Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
8f0bb5ae
Commit
8f0bb5ae
authored
Feb 06, 2012
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'wireless-next' of
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi
parents
b9d90578
6fe7dd0d
Changes
30
Show whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
1837 additions
and
1776 deletions
+1837
-1776
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-1000.c
+2
-4
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-2000.c
+1
-3
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-5000.c
+1
-5
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
+4
-6
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+4
-4
drivers/net/wireless/iwlwifi/iwl-agn-tt.c
drivers/net/wireless/iwlwifi/iwl-agn-tt.c
+7
-7
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.c
+30
-683
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-agn.h
+1
-2
drivers/net/wireless/iwlwifi/iwl-bus.h
drivers/net/wireless/iwlwifi/iwl-bus.h
+0
-64
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.c
+2
-126
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-core.h
+0
-6
drivers/net/wireless/iwlwifi/iwl-debug.h
drivers/net/wireless/iwlwifi/iwl-debug.h
+8
-8
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-debugfs.c
+3
-3
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-dev.h
+0
-109
drivers/net/wireless/iwlwifi/iwl-eeprom.c
drivers/net/wireless/iwlwifi/iwl-eeprom.c
+31
-34
drivers/net/wireless/iwlwifi/iwl-io.c
drivers/net/wireless/iwlwifi/iwl-io.c
+97
-96
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl-io.h
+30
-30
drivers/net/wireless/iwlwifi/iwl-led.c
drivers/net/wireless/iwlwifi/iwl-led.c
+5
-4
drivers/net/wireless/iwlwifi/iwl-mac80211.c
drivers/net/wireless/iwlwifi/iwl-mac80211.c
+19
-17
drivers/net/wireless/iwlwifi/iwl-pci.c
drivers/net/wireless/iwlwifi/iwl-pci.c
+34
-195
drivers/net/wireless/iwlwifi/iwl-power.c
drivers/net/wireless/iwlwifi/iwl-power.c
+1
-1
drivers/net/wireless/iwlwifi/iwl-shared.h
drivers/net/wireless/iwlwifi/iwl-shared.h
+0
-2
drivers/net/wireless/iwlwifi/iwl-testmode.c
drivers/net/wireless/iwlwifi/iwl-testmode.c
+25
-11
drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
+13
-5
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+55
-48
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
+29
-26
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+536
-125
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/iwl-trans.h
+85
-48
drivers/net/wireless/iwlwifi/iwl-ucode.c
drivers/net/wireless/iwlwifi/iwl-ucode.c
+636
-104
drivers/net/wireless/iwlwifi/iwl-ucode.h
drivers/net/wireless/iwlwifi/iwl-ucode.h
+178
-0
No files found.
drivers/net/wireless/iwlwifi/iwl-1000.c
View file @
8f0bb5ae
...
...
@@ -84,13 +84,13 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
static
void
iwl1000_nic_config
(
struct
iwl_priv
*
priv
)
{
/* set CSR_HW_CONFIG_REG for uCode use */
iwl_set_bit
(
bu
s
(
priv
),
CSR_HW_IF_CONFIG_REG
,
iwl_set_bit
(
tran
s
(
priv
),
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI
|
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI
);
/* Setting digital SVR for 1000 card to 1.32V */
/* locking is acquired in iwl_set_bits_mask_prph() function */
iwl_set_bits_mask_prph
(
bu
s
(
priv
),
APMG_DIGITAL_SVR_REG
,
iwl_set_bits_mask_prph
(
tran
s
(
priv
),
APMG_DIGITAL_SVR_REG
,
APMG_SVR_DIGITAL_VOLTAGE_1_32
,
~
APMG_SVR_VOLTAGE_CONFIG_BIT_MSK
);
}
...
...
@@ -128,8 +128,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_params
->
num_of_queues
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
bcast_sta_id
=
IWLAGN_BROADCAST_ID
;
hw_params
(
priv
).
max_data_size
=
IWLAGN_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWLAGN_RTC_INST_SIZE
;
...
...
drivers/net/wireless/iwlwifi/iwl-2000.c
View file @
8f0bb5ae
...
...
@@ -87,7 +87,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
iwl_rf_config
(
priv
);
if
(
cfg
(
priv
)
->
iq_invert
)
iwl_set_bit
(
bu
s
(
priv
),
CSR_GP_DRIVER_REG
,
iwl_set_bit
(
tran
s
(
priv
),
CSR_GP_DRIVER_REG
,
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER
);
}
...
...
@@ -124,8 +124,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_params
->
num_of_queues
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
bcast_sta_id
=
IWLAGN_BROADCAST_ID
;
hw_params
(
priv
).
max_data_size
=
IWL60_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWL60_RTC_INST_SIZE
;
...
...
drivers/net/wireless/iwlwifi/iwl-5000.c
View file @
8f0bb5ae
...
...
@@ -73,7 +73,7 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
* (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back.
*/
iwl_set_bits_mask_prph
(
bu
s
(
priv
),
APMG_PS_CTRL_REG
,
iwl_set_bits_mask_prph
(
tran
s
(
priv
),
APMG_PS_CTRL_REG
,
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS
,
~
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS
);
...
...
@@ -170,8 +170,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_params
->
num_of_queues
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
bcast_sta_id
=
IWLAGN_BROADCAST_ID
;
hw_params
(
priv
).
max_data_size
=
IWLAGN_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWLAGN_RTC_INST_SIZE
;
...
...
@@ -199,8 +197,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_params
->
num_of_queues
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
bcast_sta_id
=
IWLAGN_BROADCAST_ID
;
hw_params
(
priv
).
max_data_size
=
IWLAGN_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWLAGN_RTC_INST_SIZE
;
...
...
drivers/net/wireless/iwlwifi/iwl-6000.c
View file @
8f0bb5ae
...
...
@@ -82,7 +82,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv)
{
/* Indicate calibration version to uCode. */
if
(
iwl_eeprom_calib_version
(
priv
->
shrd
)
>=
6
)
iwl_set_bit
(
bu
s
(
priv
),
CSR_GP_DRIVER_REG
,
iwl_set_bit
(
tran
s
(
priv
),
CSR_GP_DRIVER_REG
,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6
);
}
...
...
@@ -90,9 +90,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
{
/* Indicate calibration version to uCode. */
if
(
iwl_eeprom_calib_version
(
priv
->
shrd
)
>=
6
)
iwl_set_bit
(
bu
s
(
priv
),
CSR_GP_DRIVER_REG
,
iwl_set_bit
(
tran
s
(
priv
),
CSR_GP_DRIVER_REG
,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6
);
iwl_set_bit
(
bu
s
(
priv
),
CSR_GP_DRIVER_REG
,
iwl_set_bit
(
tran
s
(
priv
),
CSR_GP_DRIVER_REG
,
CSR_GP_DRIVER_REG_BIT_6050_1x2
);
}
...
...
@@ -104,7 +104,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
/* no locking required for register write */
if
(
cfg
(
priv
)
->
pa_type
==
IWL_PA_INTERNAL
)
{
/* 2x2 IPA phy type */
iwl_write32
(
bu
s
(
priv
),
CSR_GP_DRIVER_REG
,
iwl_write32
(
tran
s
(
priv
),
CSR_GP_DRIVER_REG
,
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA
);
}
/* do additional nic configuration if needed */
...
...
@@ -145,8 +145,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_params
->
num_of_queues
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
bcast_sta_id
=
IWLAGN_BROADCAST_ID
;
hw_params
(
priv
).
max_data_size
=
IWL60_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWL60_RTC_INST_SIZE
;
...
...
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
View file @
8f0bb5ae
...
...
@@ -628,16 +628,16 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
if
(
flags
&
(
SW_CARD_DISABLED
|
HW_CARD_DISABLED
|
CT_CARD_DISABLED
))
{
iwl_write32
(
bu
s
(
priv
),
CSR_UCODE_DRV_GP1_SET
,
iwl_write32
(
tran
s
(
priv
),
CSR_UCODE_DRV_GP1_SET
,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED
);
iwl_write_direct32
(
bu
s
(
priv
),
HBUS_TARG_MBX_C
,
iwl_write_direct32
(
tran
s
(
priv
),
HBUS_TARG_MBX_C
,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED
);
if
(
!
(
flags
&
RXON_CARD_DISABLED
))
{
iwl_write32
(
bu
s
(
priv
),
CSR_UCODE_DRV_GP1_CLR
,
iwl_write32
(
tran
s
(
priv
),
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED
);
iwl_write_direct32
(
bu
s
(
priv
),
HBUS_TARG_MBX_C
,
iwl_write_direct32
(
tran
s
(
priv
),
HBUS_TARG_MBX_C
,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED
);
}
if
(
flags
&
CT_CARD_DISABLED
)
...
...
drivers/net/wireless/iwlwifi/iwl-agn-tt.c
View file @
8f0bb5ae
...
...
@@ -178,19 +178,19 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
if
(
tt
->
state
==
IWL_TI_CT_KILL
)
{
if
(
priv
->
thermal_throttle
.
ct_kill_toggle
)
{
iwl_write32
(
bu
s
(
priv
),
CSR_UCODE_DRV_GP1_CLR
,
iwl_write32
(
tran
s
(
priv
),
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT
);
priv
->
thermal_throttle
.
ct_kill_toggle
=
false
;
}
else
{
iwl_write32
(
bu
s
(
priv
),
CSR_UCODE_DRV_GP1_SET
,
iwl_write32
(
tran
s
(
priv
),
CSR_UCODE_DRV_GP1_SET
,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT
);
priv
->
thermal_throttle
.
ct_kill_toggle
=
true
;
}
iwl_read32
(
bu
s
(
priv
),
CSR_UCODE_DRV_GP1
);
spin_lock_irqsave
(
&
bu
s
(
priv
)
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
bu
s
(
priv
)))
iwl_release_nic_access
(
bu
s
(
priv
));
spin_unlock_irqrestore
(
&
bu
s
(
priv
)
->
reg_lock
,
flags
);
iwl_read32
(
tran
s
(
priv
),
CSR_UCODE_DRV_GP1
);
spin_lock_irqsave
(
&
tran
s
(
priv
)
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
tran
s
(
priv
)))
iwl_release_nic_access
(
tran
s
(
priv
));
spin_unlock_irqrestore
(
&
tran
s
(
priv
)
->
reg_lock
,
flags
);
/* Reschedule the ct_kill timer to occur in
* CT_KILL_EXIT_DURATION seconds to ensure we get a
...
...
drivers/net/wireless/iwlwifi/iwl-agn.c
View file @
8f0bb5ae
...
...
@@ -34,7 +34,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
...
...
@@ -42,6 +41,7 @@
#include <asm/div64.h>
#include "iwl-ucode.h"
#include "iwl-eeprom.h"
#include "iwl-wifi.h"
#include "iwl-dev.h"
...
...
@@ -328,14 +328,14 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
ptr
=
base
+
(
4
*
sizeof
(
u32
))
+
(
start_idx
*
3
*
sizeof
(
u32
));
/* Make sure device is powered up for SRAM reads */
spin_lock_irqsave
(
&
bu
s
(
priv
)
->
reg_lock
,
reg_flags
);
if
(
iwl_grab_nic_access
(
bu
s
(
priv
)))
{
spin_unlock_irqrestore
(
&
bu
s
(
priv
)
->
reg_lock
,
reg_flags
);
spin_lock_irqsave
(
&
tran
s
(
priv
)
->
reg_lock
,
reg_flags
);
if
(
iwl_grab_nic_access
(
tran
s
(
priv
)))
{
spin_unlock_irqrestore
(
&
tran
s
(
priv
)
->
reg_lock
,
reg_flags
);
return
;
}
/* Set starting address; reads will auto-increment */
iwl_write32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RADDR
,
ptr
);
iwl_write32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RADDR
,
ptr
);
rmb
();
/*
...
...
@@ -352,19 +352,19 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
* place event id # at far right for easier visual parsing.
*/
for
(
i
=
0
;
i
<
num_events
;
i
++
)
{
ev
=
iwl_read32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
time
=
iwl_read32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
ev
=
iwl_read32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
time
=
iwl_read32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
if
(
mode
==
0
)
{
trace_iwlwifi_dev_ucode_cont_event
(
priv
,
0
,
time
,
ev
);
}
else
{
data
=
iwl_read32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
data
=
iwl_read32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
trace_iwlwifi_dev_ucode_cont_event
(
priv
,
time
,
data
,
ev
);
}
}
/* Allow device to power down */
iwl_release_nic_access
(
bu
s
(
priv
));
spin_unlock_irqrestore
(
&
bu
s
(
priv
)
->
reg_lock
,
reg_flags
);
iwl_release_nic_access
(
tran
s
(
priv
));
spin_unlock_irqrestore
(
&
tran
s
(
priv
)
->
reg_lock
,
reg_flags
);
}
static
void
iwl_continuous_event_trace
(
struct
iwl_priv
*
priv
)
...
...
@@ -383,7 +383,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
base
=
priv
->
shrd
->
device_pointers
.
log_event_table
;
if
(
iwlagn_hw_valid_rtc_data_addr
(
base
))
{
iwl_read_targ_mem_words
(
bu
s
(
priv
),
base
,
&
read
,
sizeof
(
read
));
iwl_read_targ_mem_words
(
tran
s
(
priv
),
base
,
&
read
,
sizeof
(
read
));
capacity
=
read
.
capacity
;
mode
=
read
.
mode
;
...
...
@@ -490,7 +490,7 @@ static void iwl_bg_tx_flush(struct work_struct *work)
iwlagn_dev_txfifo_flush
(
priv
,
IWL_DROP_ALL
);
}
static
void
iwl_init_context
(
struct
iwl_priv
*
priv
,
u32
ucode_flags
)
void
iwl_init_context
(
struct
iwl_priv
*
priv
,
u32
ucode_flags
)
{
int
i
;
...
...
@@ -513,6 +513,7 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
qos_cmd
=
REPLY_QOS_PARAM
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
ap_sta_id
=
IWL_AP_ID
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
wep_key_cmd
=
REPLY_WEPKEY
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
bcast_sta_id
=
IWLAGN_BROADCAST_ID
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
exclusive_interface_modes
=
BIT
(
NL80211_IFTYPE_ADHOC
);
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
interface_modes
=
...
...
@@ -547,609 +548,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
BUILD_BUG_ON
(
NUM_IWL_RXON_CTX
!=
2
);
}
static
void
iwl_ucode_callback
(
const
struct
firmware
*
ucode_raw
,
void
*
context
);
#define UCODE_EXPERIMENTAL_INDEX 100
#define UCODE_EXPERIMENTAL_TAG "exp"
static
int
__must_check
iwl_request_firmware
(
struct
iwl_priv
*
priv
,
bool
first
)
{
const
char
*
name_pre
=
cfg
(
priv
)
->
fw_name_pre
;
char
tag
[
8
];
if
(
first
)
{
#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
priv
->
fw_index
=
UCODE_EXPERIMENTAL_INDEX
;
strcpy
(
tag
,
UCODE_EXPERIMENTAL_TAG
);
}
else
if
(
priv
->
fw_index
==
UCODE_EXPERIMENTAL_INDEX
)
{
#endif
priv
->
fw_index
=
cfg
(
priv
)
->
ucode_api_max
;
sprintf
(
tag
,
"%d"
,
priv
->
fw_index
);
}
else
{
priv
->
fw_index
--
;
sprintf
(
tag
,
"%d"
,
priv
->
fw_index
);
}
if
(
priv
->
fw_index
<
cfg
(
priv
)
->
ucode_api_min
)
{
IWL_ERR
(
priv
,
"no suitable firmware found!
\n
"
);
return
-
ENOENT
;
}
sprintf
(
priv
->
firmware_name
,
"%s%s%s"
,
name_pre
,
tag
,
".ucode"
);
IWL_DEBUG_INFO
(
priv
,
"attempting to load firmware %s'%s'
\n
"
,
(
priv
->
fw_index
==
UCODE_EXPERIMENTAL_INDEX
)
?
"EXPERIMENTAL "
:
""
,
priv
->
firmware_name
);
return
request_firmware_nowait
(
THIS_MODULE
,
1
,
priv
->
firmware_name
,
bus
(
priv
)
->
dev
,
GFP_KERNEL
,
priv
,
iwl_ucode_callback
);
}
struct
iwlagn_firmware_pieces
{
const
void
*
inst
,
*
data
,
*
init
,
*
init_data
,
*
wowlan_inst
,
*
wowlan_data
;
size_t
inst_size
,
data_size
,
init_size
,
init_data_size
,
wowlan_inst_size
,
wowlan_data_size
;
u32
build
;
u32
init_evtlog_ptr
,
init_evtlog_size
,
init_errlog_ptr
;
u32
inst_evtlog_ptr
,
inst_evtlog_size
,
inst_errlog_ptr
;
};
static
int
iwlagn_load_legacy_firmware
(
struct
iwl_priv
*
priv
,
const
struct
firmware
*
ucode_raw
,
struct
iwlagn_firmware_pieces
*
pieces
)
{
struct
iwl_ucode_header
*
ucode
=
(
void
*
)
ucode_raw
->
data
;
u32
api_ver
,
hdr_size
;
const
u8
*
src
;
priv
->
ucode_ver
=
le32_to_cpu
(
ucode
->
ver
);
api_ver
=
IWL_UCODE_API
(
priv
->
ucode_ver
);
switch
(
api_ver
)
{
default:
hdr_size
=
28
;
if
(
ucode_raw
->
size
<
hdr_size
)
{
IWL_ERR
(
priv
,
"File size too small!
\n
"
);
return
-
EINVAL
;
}
pieces
->
build
=
le32_to_cpu
(
ucode
->
u
.
v2
.
build
);
pieces
->
inst_size
=
le32_to_cpu
(
ucode
->
u
.
v2
.
inst_size
);
pieces
->
data_size
=
le32_to_cpu
(
ucode
->
u
.
v2
.
data_size
);
pieces
->
init_size
=
le32_to_cpu
(
ucode
->
u
.
v2
.
init_size
);
pieces
->
init_data_size
=
le32_to_cpu
(
ucode
->
u
.
v2
.
init_data_size
);
src
=
ucode
->
u
.
v2
.
data
;
break
;
case
0
:
case
1
:
case
2
:
hdr_size
=
24
;
if
(
ucode_raw
->
size
<
hdr_size
)
{
IWL_ERR
(
priv
,
"File size too small!
\n
"
);
return
-
EINVAL
;
}
pieces
->
build
=
0
;
pieces
->
inst_size
=
le32_to_cpu
(
ucode
->
u
.
v1
.
inst_size
);
pieces
->
data_size
=
le32_to_cpu
(
ucode
->
u
.
v1
.
data_size
);
pieces
->
init_size
=
le32_to_cpu
(
ucode
->
u
.
v1
.
init_size
);
pieces
->
init_data_size
=
le32_to_cpu
(
ucode
->
u
.
v1
.
init_data_size
);
src
=
ucode
->
u
.
v1
.
data
;
break
;
}
/* Verify size of file vs. image size info in file's header */
if
(
ucode_raw
->
size
!=
hdr_size
+
pieces
->
inst_size
+
pieces
->
data_size
+
pieces
->
init_size
+
pieces
->
init_data_size
)
{
IWL_ERR
(
priv
,
"uCode file size %d does not match expected size
\n
"
,
(
int
)
ucode_raw
->
size
);
return
-
EINVAL
;
}
pieces
->
inst
=
src
;
src
+=
pieces
->
inst_size
;
pieces
->
data
=
src
;
src
+=
pieces
->
data_size
;
pieces
->
init
=
src
;
src
+=
pieces
->
init_size
;
pieces
->
init_data
=
src
;
src
+=
pieces
->
init_data_size
;
return
0
;
}
static
int
iwlagn_load_firmware
(
struct
iwl_priv
*
priv
,
const
struct
firmware
*
ucode_raw
,
struct
iwlagn_firmware_pieces
*
pieces
,
struct
iwlagn_ucode_capabilities
*
capa
)
{
struct
iwl_tlv_ucode_header
*
ucode
=
(
void
*
)
ucode_raw
->
data
;
struct
iwl_ucode_tlv
*
tlv
;
size_t
len
=
ucode_raw
->
size
;
const
u8
*
data
;
int
wanted_alternative
=
iwlagn_mod_params
.
wanted_ucode_alternative
;
int
tmp
;
u64
alternatives
;
u32
tlv_len
;
enum
iwl_ucode_tlv_type
tlv_type
;
const
u8
*
tlv_data
;
if
(
len
<
sizeof
(
*
ucode
))
{
IWL_ERR
(
priv
,
"uCode has invalid length: %zd
\n
"
,
len
);
return
-
EINVAL
;
}
if
(
ucode
->
magic
!=
cpu_to_le32
(
IWL_TLV_UCODE_MAGIC
))
{
IWL_ERR
(
priv
,
"invalid uCode magic: 0X%x
\n
"
,
le32_to_cpu
(
ucode
->
magic
));
return
-
EINVAL
;
}
/*
* Check which alternatives are present, and "downgrade"
* when the chosen alternative is not present, warning
* the user when that happens. Some files may not have
* any alternatives, so don't warn in that case.
*/
alternatives
=
le64_to_cpu
(
ucode
->
alternatives
);
tmp
=
wanted_alternative
;
if
(
wanted_alternative
>
63
)
wanted_alternative
=
63
;
while
(
wanted_alternative
&&
!
(
alternatives
&
BIT
(
wanted_alternative
)))
wanted_alternative
--
;
if
(
wanted_alternative
&&
wanted_alternative
!=
tmp
)
IWL_WARN
(
priv
,
"uCode alternative %d not available, choosing %d
\n
"
,
tmp
,
wanted_alternative
);
priv
->
ucode_ver
=
le32_to_cpu
(
ucode
->
ver
);
pieces
->
build
=
le32_to_cpu
(
ucode
->
build
);
data
=
ucode
->
data
;
len
-=
sizeof
(
*
ucode
);
while
(
len
>=
sizeof
(
*
tlv
))
{
u16
tlv_alt
;
len
-=
sizeof
(
*
tlv
);
tlv
=
(
void
*
)
data
;
tlv_len
=
le32_to_cpu
(
tlv
->
length
);
tlv_type
=
le16_to_cpu
(
tlv
->
type
);
tlv_alt
=
le16_to_cpu
(
tlv
->
alternative
);
tlv_data
=
tlv
->
data
;
if
(
len
<
tlv_len
)
{
IWL_ERR
(
priv
,
"invalid TLV len: %zd/%u
\n
"
,
len
,
tlv_len
);
return
-
EINVAL
;
}
len
-=
ALIGN
(
tlv_len
,
4
);
data
+=
sizeof
(
*
tlv
)
+
ALIGN
(
tlv_len
,
4
);
/*
* Alternative 0 is always valid.
*
* Skip alternative TLVs that are not selected.
*/
if
(
tlv_alt
!=
0
&&
tlv_alt
!=
wanted_alternative
)
continue
;
switch
(
tlv_type
)
{
case
IWL_UCODE_TLV_INST
:
pieces
->
inst
=
tlv_data
;
pieces
->
inst_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_DATA
:
pieces
->
data
=
tlv_data
;
pieces
->
data_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_INIT
:
pieces
->
init
=
tlv_data
;
pieces
->
init_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_INIT_DATA
:
pieces
->
init_data
=
tlv_data
;
pieces
->
init_data_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_BOOT
:
IWL_ERR
(
priv
,
"Found unexpected BOOT ucode
\n
"
);
break
;
case
IWL_UCODE_TLV_PROBE_MAX_LEN
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
capa
->
max_probe_length
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_PAN
:
if
(
tlv_len
)
goto
invalid_tlv_len
;
capa
->
flags
|=
IWL_UCODE_TLV_FLAGS_PAN
;
break
;
case
IWL_UCODE_TLV_FLAGS
:
/* must be at least one u32 */
if
(
tlv_len
<
sizeof
(
u32
))
goto
invalid_tlv_len
;
/* and a proper number of u32s */
if
(
tlv_len
%
sizeof
(
u32
))
goto
invalid_tlv_len
;
/*
* This driver only reads the first u32 as
* right now no more features are defined,
* if that changes then either the driver
* will not work with the new firmware, or
* it'll not take advantage of new features.
*/
capa
->
flags
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_INIT_EVTLOG_PTR
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
init_evtlog_ptr
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_INIT_EVTLOG_SIZE
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
init_evtlog_size
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_INIT_ERRLOG_PTR
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
init_errlog_ptr
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_RUNT_EVTLOG_PTR
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
inst_evtlog_ptr
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
inst_evtlog_size
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_RUNT_ERRLOG_PTR
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
inst_errlog_ptr
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_ENHANCE_SENS_TBL
:
if
(
tlv_len
)
goto
invalid_tlv_len
;
priv
->
enhance_sensitivity_table
=
true
;
break
;
case
IWL_UCODE_TLV_WOWLAN_INST
:
pieces
->
wowlan_inst
=
tlv_data
;
pieces
->
wowlan_inst_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_WOWLAN_DATA
:
pieces
->
wowlan_data
=
tlv_data
;
pieces
->
wowlan_data_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_PHY_CALIBRATION_SIZE
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
capa
->
standard_phy_calibration_size
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
default:
IWL_DEBUG_INFO
(
priv
,
"unknown TLV: %d
\n
"
,
tlv_type
);
break
;
}
}
if
(
len
)
{
IWL_ERR
(
priv
,
"invalid TLV after parsing: %zd
\n
"
,
len
);
iwl_print_hex_dump
(
priv
,
IWL_DL_FW
,
(
u8
*
)
data
,
len
);
return
-
EINVAL
;
}
return
0
;
invalid_tlv_len:
IWL_ERR
(
priv
,
"TLV %d has invalid size: %u
\n
"
,
tlv_type
,
tlv_len
);
iwl_print_hex_dump
(
priv
,
IWL_DL_FW
,
tlv_data
,
tlv_len
);
return
-
EINVAL
;
}
/**
* iwl_ucode_callback - callback when firmware was loaded
*
* If loaded successfully, copies the firmware into buffers
* for the card to fetch (via DMA).
*/
static
void
iwl_ucode_callback
(
const
struct
firmware
*
ucode_raw
,
void
*
context
)
{
struct
iwl_priv
*
priv
=
context
;
struct
iwl_ucode_header
*
ucode
;
int
err
;
struct
iwlagn_firmware_pieces
pieces
;
const
unsigned
int
api_max
=
cfg
(
priv
)
->
ucode_api_max
;
unsigned
int
api_ok
=
cfg
(
priv
)
->
ucode_api_ok
;
const
unsigned
int
api_min
=
cfg
(
priv
)
->
ucode_api_min
;
u32
api_ver
;
char
buildstr
[
25
];
u32
build
;
struct
iwlagn_ucode_capabilities
ucode_capa
=
{
.
max_probe_length
=
200
,
.
standard_phy_calibration_size
=
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE
,
};
if
(
!
api_ok
)
api_ok
=
api_max
;
memset
(
&
pieces
,
0
,
sizeof
(
pieces
));
if
(
!
ucode_raw
)
{
if
(
priv
->
fw_index
<=
api_ok
)
IWL_ERR
(
priv
,
"request for firmware file '%s' failed.
\n
"
,
priv
->
firmware_name
);
goto
try_again
;
}
IWL_DEBUG_INFO
(
priv
,
"Loaded firmware file '%s' (%zd bytes).
\n
"
,
priv
->
firmware_name
,
ucode_raw
->
size
);
/* Make sure that we got at least the API version number */
if
(
ucode_raw
->
size
<
4
)
{
IWL_ERR
(
priv
,
"File size way too small!
\n
"
);
goto
try_again
;
}
/* Data from ucode file: header followed by uCode images */
ucode
=
(
struct
iwl_ucode_header
*
)
ucode_raw
->
data
;
if
(
ucode
->
ver
)
err
=
iwlagn_load_legacy_firmware
(
priv
,
ucode_raw
,
&
pieces
);
else
err
=
iwlagn_load_firmware
(
priv
,
ucode_raw
,
&
pieces
,
&
ucode_capa
);
if
(
err
)
goto
try_again
;
api_ver
=
IWL_UCODE_API
(
priv
->
ucode_ver
);
build
=
pieces
.
build
;
/*
* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
* on the API version read from firmware header from here on forward
*/
/* no api version check required for experimental uCode */
if
(
priv
->
fw_index
!=
UCODE_EXPERIMENTAL_INDEX
)
{
if
(
api_ver
<
api_min
||
api_ver
>
api_max
)
{
IWL_ERR
(
priv
,
"Driver unable to support your firmware API. "
"Driver supports v%u, firmware is v%u.
\n
"
,
api_max
,
api_ver
);
goto
try_again
;
}
if
(
api_ver
<
api_ok
)
{
if
(
api_ok
!=
api_max
)
IWL_ERR
(
priv
,
"Firmware has old API version, "
"expected v%u through v%u, got v%u.
\n
"
,
api_ok
,
api_max
,
api_ver
);
else
IWL_ERR
(
priv
,
"Firmware has old API version, "
"expected v%u, got v%u.
\n
"
,
api_max
,
api_ver
);
IWL_ERR
(
priv
,
"New firmware can be obtained from "
"http://www.intellinuxwireless.org/.
\n
"
);
}
}
if
(
build
)
sprintf
(
buildstr
,
" build %u%s"
,
build
,
(
priv
->
fw_index
==
UCODE_EXPERIMENTAL_INDEX
)
?
" (EXP)"
:
""
);
else
buildstr
[
0
]
=
'\0'
;
IWL_INFO
(
priv
,
"loaded firmware version %u.%u.%u.%u%s
\n
"
,
IWL_UCODE_MAJOR
(
priv
->
ucode_ver
),
IWL_UCODE_MINOR
(
priv
->
ucode_ver
),
IWL_UCODE_API
(
priv
->
ucode_ver
),
IWL_UCODE_SERIAL
(
priv
->
ucode_ver
),
buildstr
);
snprintf
(
priv
->
hw
->
wiphy
->
fw_version
,
sizeof
(
priv
->
hw
->
wiphy
->
fw_version
),
"%u.%u.%u.%u%s"
,
IWL_UCODE_MAJOR
(
priv
->
ucode_ver
),
IWL_UCODE_MINOR
(
priv
->
ucode_ver
),
IWL_UCODE_API
(
priv
->
ucode_ver
),
IWL_UCODE_SERIAL
(
priv
->
ucode_ver
),
buildstr
);
/*
* For any of the failures below (before allocating pci memory)
* we will try to load a version with a smaller API -- maybe the
* user just got a corrupted version of the latest API.
*/
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr ucode version raw = 0x%x
\n
"
,
priv
->
ucode_ver
);
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr runtime inst size = %Zd
\n
"
,
pieces
.
inst_size
);
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr runtime data size = %Zd
\n
"
,
pieces
.
data_size
);
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr init inst size = %Zd
\n
"
,
pieces
.
init_size
);
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr init data size = %Zd
\n
"
,
pieces
.
init_data_size
);
/* Verify that uCode images will fit in card's SRAM */
if
(
pieces
.
inst_size
>
hw_params
(
priv
).
max_inst_size
)
{
IWL_ERR
(
priv
,
"uCode instr len %Zd too large to fit in
\n
"
,
pieces
.
inst_size
);
goto
try_again
;
}
if
(
pieces
.
data_size
>
hw_params
(
priv
).
max_data_size
)
{
IWL_ERR
(
priv
,
"uCode data len %Zd too large to fit in
\n
"
,
pieces
.
data_size
);
goto
try_again
;
}
if
(
pieces
.
init_size
>
hw_params
(
priv
).
max_inst_size
)
{
IWL_ERR
(
priv
,
"uCode init instr len %Zd too large to fit in
\n
"
,
pieces
.
init_size
);
goto
try_again
;
}
if
(
pieces
.
init_data_size
>
hw_params
(
priv
).
max_data_size
)
{
IWL_ERR
(
priv
,
"uCode init data len %Zd too large to fit in
\n
"
,
pieces
.
init_data_size
);
goto
try_again
;
}
/* Allocate ucode buffers for card's bus-master loading ... */
/* Runtime instructions and 2 copies of data:
* 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */
if
(
iwl_alloc_fw_desc
(
bus
(
priv
),
&
trans
(
priv
)
->
ucode_rt
.
code
,
pieces
.
inst
,
pieces
.
inst_size
))
goto
err_pci_alloc
;
if
(
iwl_alloc_fw_desc
(
bus
(
priv
),
&
trans
(
priv
)
->
ucode_rt
.
data
,
pieces
.
data
,
pieces
.
data_size
))
goto
err_pci_alloc
;
/* Initialization instructions and data */
if
(
pieces
.
init_size
&&
pieces
.
init_data_size
)
{
if
(
iwl_alloc_fw_desc
(
bus
(
priv
),
&
trans
(
priv
)
->
ucode_init
.
code
,
pieces
.
init
,
pieces
.
init_size
))
goto
err_pci_alloc
;
if
(
iwl_alloc_fw_desc
(
bus
(
priv
),
&
trans
(
priv
)
->
ucode_init
.
data
,
pieces
.
init_data
,
pieces
.
init_data_size
))
goto
err_pci_alloc
;
}
/* WoWLAN instructions and data */
if
(
pieces
.
wowlan_inst_size
&&
pieces
.
wowlan_data_size
)
{
if
(
iwl_alloc_fw_desc
(
bus
(
priv
),
&
trans
(
priv
)
->
ucode_wowlan
.
code
,
pieces
.
wowlan_inst
,
pieces
.
wowlan_inst_size
))
goto
err_pci_alloc
;
if
(
iwl_alloc_fw_desc
(
bus
(
priv
),
&
trans
(
priv
)
->
ucode_wowlan
.
data
,
pieces
.
wowlan_data
,
pieces
.
wowlan_data_size
))
goto
err_pci_alloc
;
}
/* Now that we can no longer fail, copy information */
/*
* The (size - 16) / 12 formula is based on the information recorded
* for each event, which is of mode 1 (including timestamp) for all
* new microcodes that include this information.
*/
priv
->
init_evtlog_ptr
=
pieces
.
init_evtlog_ptr
;
if
(
pieces
.
init_evtlog_size
)
priv
->
init_evtlog_size
=
(
pieces
.
init_evtlog_size
-
16
)
/
12
;
else
priv
->
init_evtlog_size
=
cfg
(
priv
)
->
base_params
->
max_event_log_size
;
priv
->
init_errlog_ptr
=
pieces
.
init_errlog_ptr
;
priv
->
inst_evtlog_ptr
=
pieces
.
inst_evtlog_ptr
;
if
(
pieces
.
inst_evtlog_size
)
priv
->
inst_evtlog_size
=
(
pieces
.
inst_evtlog_size
-
16
)
/
12
;
else
priv
->
inst_evtlog_size
=
cfg
(
priv
)
->
base_params
->
max_event_log_size
;
priv
->
inst_errlog_ptr
=
pieces
.
inst_errlog_ptr
;
#ifndef CONFIG_IWLWIFI_P2P
ucode_capa
.
flags
&=
~
IWL_UCODE_TLV_FLAGS_PAN
;
#endif
priv
->
new_scan_threshold_behaviour
=
!!
(
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_NEWSCAN
);
if
(
!
(
cfg
(
priv
)
->
sku
&
EEPROM_SKU_CAP_IPAN_ENABLE
))
ucode_capa
.
flags
&=
~
IWL_UCODE_TLV_FLAGS_PAN
;
/*
* if not PAN, then don't support P2P -- might be a uCode
* packaging bug or due to the eeprom check above
*/
if
(
!
(
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_PAN
))
ucode_capa
.
flags
&=
~
IWL_UCODE_TLV_FLAGS_P2P
;
if
(
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_PAN
)
{
priv
->
sta_key_max_num
=
STA_KEY_MAX_NUM_PAN
;
priv
->
shrd
->
cmd_queue
=
IWL_IPAN_CMD_QUEUE_NUM
;
}
else
{
priv
->
sta_key_max_num
=
STA_KEY_MAX_NUM
;
priv
->
shrd
->
cmd_queue
=
IWL_DEFAULT_CMD_QUEUE_NUM
;
}
/*
* figure out the offset of chain noise reset and gain commands
* base on the size of standard phy calibration commands table size
*/
if
(
ucode_capa
.
standard_phy_calibration_size
>
IWL_MAX_PHY_CALIBRATE_TBL_SIZE
)
ucode_capa
.
standard_phy_calibration_size
=
IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE
;
priv
->
phy_calib_chain_noise_reset_cmd
=
ucode_capa
.
standard_phy_calibration_size
;
priv
->
phy_calib_chain_noise_gain_cmd
=
ucode_capa
.
standard_phy_calibration_size
+
1
;
/* initialize all valid contexts */
iwl_init_context
(
priv
,
ucode_capa
.
flags
);
/**************************************************
* This is still part of probe() in a sense...
*
* 9. Setup and register with mac80211 and debugfs
**************************************************/
err
=
iwlagn_mac_setup_register
(
priv
,
&
ucode_capa
);
if
(
err
)
goto
out_unbind
;
err
=
iwl_dbgfs_register
(
priv
,
DRV_NAME
);
if
(
err
)
IWL_ERR
(
priv
,
"failed to create debugfs files. Ignoring error: %d
\n
"
,
err
);
/* We have our copies now, allow OS release its copies */
release_firmware
(
ucode_raw
);
complete
(
&
priv
->
firmware_loading_complete
);
return
;
try_again:
/* try next, if any */
if
(
iwl_request_firmware
(
priv
,
false
))
goto
out_unbind
;
release_firmware
(
ucode_raw
);
return
;
err_pci_alloc:
IWL_ERR
(
priv
,
"failed to allocate pci memory
\n
"
);
iwl_dealloc_ucode
(
trans
(
priv
));
out_unbind:
complete
(
&
priv
->
firmware_loading_complete
);
device_release_driver
(
bus
(
priv
)
->
dev
);
release_firmware
(
ucode_raw
);
}
static
void
iwl_rf_kill_ct_config
(
struct
iwl_priv
*
priv
)
{
struct
iwl_ct_kill_config
cmd
;
...
...
@@ -1158,7 +556,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
int
ret
=
0
;
spin_lock_irqsave
(
&
priv
->
shrd
->
lock
,
flags
);
iwl_write32
(
bu
s
(
priv
),
CSR_UCODE_DRV_GP1_CLR
,
iwl_write32
(
tran
s
(
priv
),
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT
);
spin_unlock_irqrestore
(
&
priv
->
shrd
->
lock
,
flags
);
priv
->
thermal_throttle
.
ct_kill_toggle
=
false
;
...
...
@@ -1243,9 +641,6 @@ int iwl_alive_start(struct iwl_priv *priv)
int
ret
=
0
;
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
IWL_RXON_CTX_BSS
];
/*TODO: this should go to the transport layer */
iwl_reset_ict
(
trans
(
priv
));
IWL_DEBUG_INFO
(
priv
,
"Runtime Alive received.
\n
"
);
/* After the ALIVE response, we can send host commands to the uCode */
...
...
@@ -1692,13 +1087,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
#endif
}
static
u32
iwl_hw_detect
(
struct
iwl_priv
*
priv
)
{
return
iwl_read32
(
bus
(
priv
),
CSR_HW_REV
);
}
/* Size of one Rx buffer in host DRAM */
#define IWL_RX_BUF_SIZE_4K (4 * 1024)
#define IWL_RX_BUF_SIZE_8K (8 * 1024)
...
...
@@ -1730,32 +1118,32 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
static
void
iwl_debug_config
(
struct
iwl_priv
*
priv
)
{
dev_printk
(
KERN_INFO
,
bu
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_DEBUG "
dev_printk
(
KERN_INFO
,
tran
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_DEBUG "
#ifdef CONFIG_IWLWIFI_DEBUG
"enabled
\n
"
);
#else
"disabled
\n
"
);
#endif
dev_printk
(
KERN_INFO
,
bu
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_DEBUGFS "
dev_printk
(
KERN_INFO
,
tran
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_DEBUGFS "
#ifdef CONFIG_IWLWIFI_DEBUGFS
"enabled
\n
"
);
#else
"disabled
\n
"
);
#endif
dev_printk
(
KERN_INFO
,
bu
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_DEVICE_TRACING "
dev_printk
(
KERN_INFO
,
tran
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_DEVICE_TRACING "
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
"enabled
\n
"
);
#else
"disabled
\n
"
);
#endif
dev_printk
(
KERN_INFO
,
bu
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_DEVICE_TESTMODE "
dev_printk
(
KERN_INFO
,
tran
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_DEVICE_TESTMODE "
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
"enabled
\n
"
);
#else
"disabled
\n
"
);
#endif
dev_printk
(
KERN_INFO
,
bu
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_P2P "
dev_printk
(
KERN_INFO
,
tran
s
(
priv
)
->
dev
,
"CONFIG_IWLWIFI_P2P "
#ifdef CONFIG_IWLWIFI_P2P
"enabled
\n
"
);
#else
...
...
@@ -1770,7 +1158,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
struct
iwl_priv
*
priv
;
struct
ieee80211_hw
*
hw
;
u16
num_mac
;
u32
hw_rev
;
/************************
* 1. Allocating HW data
...
...
@@ -1783,22 +1170,14 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
}
priv
=
hw
->
priv
;
priv
->
shrd
=
&
priv
->
_shrd
;
bus
->
shrd
=
priv
->
shrd
;
priv
->
shrd
->
bus
=
bus
;
priv
->
shrd
=
bus
->
shrd
;
priv
->
shrd
->
priv
=
priv
;
priv
->
shrd
->
trans
=
trans_ops
->
alloc
(
priv
->
shrd
);
if
(
priv
->
shrd
->
trans
==
NULL
)
{
err
=
-
ENOMEM
;
goto
out_free_traffic_mem
;
}
/* At this point both hw and priv are allocated. */
SET_IEEE80211_DEV
(
hw
,
bu
s
(
priv
)
->
dev
);
SET_IEEE80211_DEV
(
hw
,
tran
s
(
priv
)
->
dev
);
/* what debugging capabilities we have */
/*
show
what debugging capabilities we have */
iwl_debug_config
(
priv
);
IWL_DEBUG_INFO
(
priv
,
"*** LOAD DRIVER ***
\n
"
);
...
...
@@ -1821,41 +1200,29 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
/* these spin locks will be used in apm_ops.init and EEPROM access
* we should init now
*/
spin_lock_init
(
&
bu
s
(
priv
)
->
reg_lock
);
spin_lock_init
(
&
tran
s
(
priv
)
->
reg_lock
);
spin_lock_init
(
&
priv
->
shrd
->
lock
);
/*
* stop and reset the on-board processor just in case it is in a
* strange state ... like being left stranded by a primary kernel
* and this is now the kdump kernel trying to start up
*/
iwl_write32
(
bus
(
priv
),
CSR_RESET
,
CSR_RESET_REG_FLAG_NEVO_RESET
);
/***********************
* 3. Read REV register
***********************/
hw_rev
=
iwl_hw_detect
(
priv
);
IWL_INFO
(
priv
,
"Detected %s, REV=0x%X
\n
"
,
cfg
(
priv
)
->
name
,
hw_rev
);
cfg
(
priv
)
->
name
,
trans
(
priv
)
->
hw_rev
);
err
=
iwl_trans_
request_irq
(
trans
(
priv
));
err
=
iwl_trans_
start_hw
(
trans
(
priv
));
if
(
err
)
goto
out_free_trans
;
if
(
iwl_trans_prepare_card_hw
(
trans
(
priv
)))
{
err
=
-
EIO
;
IWL_WARN
(
priv
,
"Failed, HW not ready
\n
"
);
goto
out_free_trans
;
}
goto
out_free_traffic_mem
;
/*****************
* 4. Read EEPROM
*****************/
/* Read the EEPROM */
err
=
iwl_eeprom_init
(
priv
,
hw_rev
);
err
=
iwl_eeprom_init
(
priv
,
trans
(
priv
)
->
hw_rev
);
/* Reset chip to save power until we load uCode during "up". */
iwl_trans_stop_hw
(
trans
(
priv
));
if
(
err
)
{
IWL_ERR
(
priv
,
"Unable to init EEPROM
\n
"
);
goto
out_free_tra
ns
;
goto
out_free_tra
ffic_mem
;
}
err
=
iwl_eeprom_check_version
(
priv
);
if
(
err
)
...
...
@@ -1903,22 +1270,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
iwl_setup_rx_handlers
(
priv
);
iwl_testmode_init
(
priv
);
/*********************************************
* 8. Enable interrupts
*********************************************/
iwl_enable_rfkill_int
(
priv
);
/* If platform's RF_KILL switch is NOT set to KILL */
if
(
iwl_read32
(
bus
(
priv
),
CSR_GP_CNTRL
)
&
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW
)
clear_bit
(
STATUS_RF_KILL_HW
,
&
priv
->
shrd
->
status
);
else
set_bit
(
STATUS_RF_KILL_HW
,
&
priv
->
shrd
->
status
);
wiphy_rfkill_set_hw_state
(
priv
->
hw
->
wiphy
,
test_bit
(
STATUS_RF_KILL_HW
,
&
priv
->
shrd
->
status
));
iwl_power_initialize
(
priv
);
iwl_tt_initialize
(
priv
);
...
...
@@ -1936,8 +1287,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
iwl_uninit_drv
(
priv
);
out_free_eeprom:
iwl_eeprom_free
(
priv
->
shrd
);
out_free_trans:
iwl_trans_free
(
trans
(
priv
));
out_free_traffic_mem:
iwl_free_traffic_mem
(
priv
);
ieee80211_free_hw
(
priv
->
hw
);
...
...
@@ -1981,8 +1330,6 @@ void __devexit iwl_remove(struct iwl_priv * priv)
priv
->
shrd
->
workqueue
=
NULL
;
iwl_free_traffic_mem
(
priv
);
iwl_trans_free
(
trans
(
priv
));
iwl_uninit_drv
(
priv
);
dev_kfree_skb
(
priv
->
beacon_skb
);
...
...
drivers/net/wireless/iwlwifi/iwl-agn.h
View file @
8f0bb5ae
...
...
@@ -73,8 +73,6 @@ struct iwlagn_ucode_capabilities {
extern
struct
ieee80211_ops
iwlagn_hw_ops
;
int
iwl_reset_ict
(
struct
iwl_trans
*
trans
);
static
inline
void
iwl_set_calib_hdr
(
struct
iwl_calib_hdr
*
hdr
,
u8
cmd
)
{
hdr
->
op_code
=
cmd
;
...
...
@@ -109,6 +107,7 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
int
iwlagn_rx_calib_result
(
struct
iwl_priv
*
priv
,
struct
iwl_rx_mem_buffer
*
rxb
,
struct
iwl_device_cmd
*
cmd
);
void
iwl_init_context
(
struct
iwl_priv
*
priv
,
u32
ucode_flags
);
/* lib */
int
iwlagn_send_tx_power
(
struct
iwl_priv
*
priv
);
...
...
drivers/net/wireless/iwlwifi/iwl-bus.h
View file @
8f0bb5ae
...
...
@@ -118,88 +118,24 @@
struct
iwl_shared
;
struct
iwl_bus
;
/**
* struct iwl_bus_ops - bus specific operations
* @get_pm_support: must returns true if the bus can go to sleep
* @apm_config: will be called during the config of the APM
* @get_hw_id_string: prints the hw_id in the provided buffer
* @get_hw_id: get hw_id in u32
* @write8: write a byte to register at offset ofs
* @write32: write a dword to register at offset ofs
* @wread32: read a dword at register at offset ofs
*/
struct
iwl_bus_ops
{
bool
(
*
get_pm_support
)(
struct
iwl_bus
*
bus
);
void
(
*
apm_config
)(
struct
iwl_bus
*
bus
);
void
(
*
get_hw_id_string
)(
struct
iwl_bus
*
bus
,
char
buf
[],
int
buf_len
);
u32
(
*
get_hw_id
)(
struct
iwl_bus
*
bus
);
void
(
*
write8
)(
struct
iwl_bus
*
bus
,
u32
ofs
,
u8
val
);
void
(
*
write32
)(
struct
iwl_bus
*
bus
,
u32
ofs
,
u32
val
);
u32
(
*
read32
)(
struct
iwl_bus
*
bus
,
u32
ofs
);
};
/**
* struct iwl_bus - bus common data
*
* This data is common to all bus layer implementations.
*
* @dev - pointer to struct device * that represents the device
* @ops - pointer to iwl_bus_ops
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
* NB: for the time being this needs to be set by the upper layer since
* it allocates the shared data
* @irq - the irq number for the device
* @reg_lock - protect hw register access
*/
struct
iwl_bus
{
struct
device
*
dev
;
const
struct
iwl_bus_ops
*
ops
;
struct
iwl_shared
*
shrd
;
unsigned
int
irq
;
spinlock_t
reg_lock
;
/* pointer to bus specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char
bus_specific
[
0
]
__attribute__
((
__aligned__
(
sizeof
(
void
*
))));
};
static
inline
bool
bus_get_pm_support
(
struct
iwl_bus
*
bus
)
{
return
bus
->
ops
->
get_pm_support
(
bus
);
}
static
inline
void
bus_apm_config
(
struct
iwl_bus
*
bus
)
{
bus
->
ops
->
apm_config
(
bus
);
}
static
inline
void
bus_get_hw_id_string
(
struct
iwl_bus
*
bus
,
char
buf
[],
int
buf_len
)
{
bus
->
ops
->
get_hw_id_string
(
bus
,
buf
,
buf_len
);
}
static
inline
u32
bus_get_hw_id
(
struct
iwl_bus
*
bus
)
{
return
bus
->
ops
->
get_hw_id
(
bus
);
}
static
inline
void
bus_write8
(
struct
iwl_bus
*
bus
,
u32
ofs
,
u8
val
)
{
bus
->
ops
->
write8
(
bus
,
ofs
,
val
);
}
static
inline
void
bus_write32
(
struct
iwl_bus
*
bus
,
u32
ofs
,
u32
val
)
{
bus
->
ops
->
write32
(
bus
,
ofs
,
val
);
}
static
inline
u32
bus_read32
(
struct
iwl_bus
*
bus
,
u32
ofs
)
{
return
bus
->
ops
->
read32
(
bus
,
ofs
);
}
/*****************************************************
* Bus layer registration functions
******************************************************/
...
...
drivers/net/wireless/iwlwifi/iwl-core.c
View file @
8f0bb5ae
...
...
@@ -203,10 +203,9 @@ int iwl_init_geos(struct iwl_priv *priv)
if
((
priv
->
bands
[
IEEE80211_BAND_5GHZ
].
n_channels
==
0
)
&&
cfg
(
priv
)
->
sku
&
EEPROM_SKU_CAP_BAND_52GHZ
)
{
char
buf
[
32
];
bus_get_hw_id_string
(
bus
(
priv
),
buf
,
sizeof
(
buf
));
IWL_INFO
(
priv
,
"Incorrectly detected BG card as ABG. "
"Please send your %s to maintainer.
\n
"
,
buf
);
"Please send your %s to maintainer.
\n
"
,
trans
(
priv
)
->
hw_id_str
);
cfg
(
priv
)
->
sku
&=
~
EEPROM_SKU_CAP_BAND_52GHZ
;
}
...
...
@@ -883,129 +882,6 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
}
}
static
int
iwl_apm_stop_master
(
struct
iwl_priv
*
priv
)
{
int
ret
=
0
;
/* stop device's busmaster DMA activity */
iwl_set_bit
(
bus
(
priv
),
CSR_RESET
,
CSR_RESET_REG_FLAG_STOP_MASTER
);
ret
=
iwl_poll_bit
(
bus
(
priv
),
CSR_RESET
,
CSR_RESET_REG_FLAG_MASTER_DISABLED
,
CSR_RESET_REG_FLAG_MASTER_DISABLED
,
100
);
if
(
ret
)
IWL_WARN
(
priv
,
"Master Disable Timed Out, 100 usec
\n
"
);
IWL_DEBUG_INFO
(
priv
,
"stop master
\n
"
);
return
ret
;
}
void
iwl_apm_stop
(
struct
iwl_priv
*
priv
)
{
IWL_DEBUG_INFO
(
priv
,
"Stop card, put in low power state
\n
"
);
clear_bit
(
STATUS_DEVICE_ENABLED
,
&
priv
->
shrd
->
status
);
/* Stop device's DMA activity */
iwl_apm_stop_master
(
priv
);
/* Reset the entire device */
iwl_set_bit
(
bus
(
priv
),
CSR_RESET
,
CSR_RESET_REG_FLAG_SW_RESET
);
udelay
(
10
);
/*
* Clear "initialization complete" bit to move adapter from
* D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/
iwl_clear_bit
(
bus
(
priv
),
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_INIT_DONE
);
}
/*
* Start up NIC's basic functionality after it has been reset
* (e.g. after platform boot, or shutdown via iwl_apm_stop())
* NOTE: This does not load uCode nor start the embedded processor
*/
int
iwl_apm_init
(
struct
iwl_priv
*
priv
)
{
int
ret
=
0
;
IWL_DEBUG_INFO
(
priv
,
"Init card's basic functions
\n
"
);
/*
* Use "set_bit" below rather than "write", to preserve any hardware
* bits already set by default after reset.
*/
/* Disable L0S exit timer (platform NMI Work/Around) */
iwl_set_bit
(
bus
(
priv
),
CSR_GIO_CHICKEN_BITS
,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER
);
/*
* Disable L0s without affecting L1;
* don't wait for ICH L0s (ICH bug W/A)
*/
iwl_set_bit
(
bus
(
priv
),
CSR_GIO_CHICKEN_BITS
,
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX
);
/* Set FH wait threshold to maximum (HW error during stress W/A) */
iwl_set_bit
(
bus
(
priv
),
CSR_DBG_HPET_MEM_REG
,
CSR_DBG_HPET_MEM_REG_VAL
);
/*
* Enable HAP INTA (interrupt from management bus) to
* wake device's PCI Express link L1a -> L0s
*/
iwl_set_bit
(
bus
(
priv
),
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A
);
bus_apm_config
(
bus
(
priv
));
/* Configure analog phase-lock-loop before activating to D0A */
if
(
cfg
(
priv
)
->
base_params
->
pll_cfg_val
)
iwl_set_bit
(
bus
(
priv
),
CSR_ANA_PLL_CFG
,
cfg
(
priv
)
->
base_params
->
pll_cfg_val
);
/*
* Set "initialization complete" bit to move adapter from
* D0U* --> D0A* (powered-up active) state.
*/
iwl_set_bit
(
bus
(
priv
),
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_INIT_DONE
);
/*
* Wait for clock stabilization; once stabilized, access to
* device-internal resources is supported, e.g. iwl_write_prph()
* and accesses to uCode SRAM.
*/
ret
=
iwl_poll_bit
(
bus
(
priv
),
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
,
25000
);
if
(
ret
<
0
)
{
IWL_DEBUG_INFO
(
priv
,
"Failed to init the card
\n
"
);
goto
out
;
}
/*
* Enable DMA clock and wait for it to stabilize.
*
* Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
* do not disable clocks. This preserves any hardware bits already
* set by default in "CLK_CTRL_REG" after reset.
*/
iwl_write_prph
(
bus
(
priv
),
APMG_CLK_EN_REG
,
APMG_CLK_VAL_DMA_CLK_RQT
);
udelay
(
20
);
/* Disable L1-Active */
iwl_set_bits_prph
(
bus
(
priv
),
APMG_PCIDEV_STT_REG
,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS
);
set_bit
(
STATUS_DEVICE_ENABLED
,
&
priv
->
shrd
->
status
);
out:
return
ret
;
}
int
iwl_set_tx_power
(
struct
iwl_priv
*
priv
,
s8
tx_power
,
bool
force
)
{
int
ret
;
...
...
drivers/net/wireless/iwlwifi/iwl-core.h
View file @
8f0bb5ae
...
...
@@ -297,12 +297,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
cfg
(
priv
)
->
bt_params
->
advanced_bt_coexist
;
}
static
inline
void
iwl_enable_rfkill_int
(
struct
iwl_priv
*
priv
)
{
IWL_DEBUG_ISR
(
priv
,
"Enabling rfkill interrupt
\n
"
);
iwl_write32
(
bus
(
priv
),
CSR_INT_MASK
,
CSR_INT_BIT_RF_KILL
);
}
extern
bool
bt_siso_mode
;
#endif
/* __iwl_core_h__ */
drivers/net/wireless/iwlwifi/iwl-debug.h
View file @
8f0bb5ae
...
...
@@ -35,10 +35,10 @@
struct
iwl_priv
;
/*No matter what is m (priv, bus, trans), this will work */
#define IWL_ERR(m, f, a...) dev_err(
bu
s(m)->dev, f, ## a)
#define IWL_WARN(m, f, a...) dev_warn(
bu
s(m)->dev, f, ## a)
#define IWL_INFO(m, f, a...) dev_info(
bu
s(m)->dev, f, ## a)
#define IWL_CRIT(m, f, a...) dev_crit(
bu
s(m)->dev, f, ## a)
#define IWL_ERR(m, f, a...) dev_err(
tran
s(m)->dev, f, ## a)
#define IWL_WARN(m, f, a...) dev_warn(
tran
s(m)->dev, f, ## a)
#define IWL_INFO(m, f, a...) dev_info(
tran
s(m)->dev, f, ## a)
#define IWL_CRIT(m, f, a...) dev_crit(
tran
s(m)->dev, f, ## a)
#define iwl_print_hex_error(m, p, len) \
do { \
...
...
@@ -50,7 +50,7 @@ do { \
#define IWL_DEBUG(m, level, fmt, ...) \
do { \
if (iwl_get_debug_level((m)->shrd) & (level)) \
dev_err(
bu
s(m)->dev, "%c %s " fmt, \
dev_err(
tran
s(m)->dev, "%c %s " fmt, \
in_interrupt() ? 'I' : 'U', __func__, \
##__VA_ARGS__); \
} while (0)
...
...
@@ -59,7 +59,7 @@ do { \
do { \
if (iwl_get_debug_level((m)->shrd) & (level) && \
net_ratelimit()) \
dev_err(
bu
s(m)->dev, "%c %s " fmt, \
dev_err(
tran
s(m)->dev, "%c %s " fmt, \
in_interrupt() ? 'I' : 'U', __func__, \
##__VA_ARGS__); \
} while (0)
...
...
@@ -74,12 +74,12 @@ do { \
#define IWL_DEBUG_QUIET_RFKILL(p, fmt, ...) \
do { \
if (!iwl_is_rfkill(p->shrd)) \
dev_err(
bu
s(p)->dev, "%s%c %s " fmt, \
dev_err(
tran
s(p)->dev, "%s%c %s " fmt, \
"", \
in_interrupt() ? 'I' : 'U', __func__, \
##__VA_ARGS__); \
else if (iwl_get_debug_level(p->shrd) & IWL_DL_RADIO) \
dev_err(
bu
s(p)->dev, "%s%c %s " fmt, \
dev_err(
tran
s(p)->dev, "%s%c %s " fmt, \
"(RFKILL) ", \
in_interrupt() ? 'I' : 'U', __func__, \
##__VA_ARGS__); \
...
...
drivers/net/wireless/iwlwifi/iwl-debugfs.c
View file @
8f0bb5ae
...
...
@@ -263,7 +263,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
sram
=
priv
->
dbgfs_sram_offset
&
~
0x3
;
/* read the first u32 from sram */
val
=
iwl_read_targ_mem
(
bu
s
(
priv
),
sram
);
val
=
iwl_read_targ_mem
(
tran
s
(
priv
),
sram
);
for
(;
len
;
len
--
)
{
/* put the address at the start of every line */
...
...
@@ -282,7 +282,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
if
(
++
offset
==
4
)
{
sram
+=
4
;
offset
=
0
;
val
=
iwl_read_targ_mem
(
bu
s
(
priv
),
sram
);
val
=
iwl_read_targ_mem
(
tran
s
(
priv
),
sram
);
}
/* put in extra spaces and split lines for human readability */
...
...
@@ -2055,7 +2055,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
const
size_t
bufsz
=
sizeof
(
buf
);
u32
pwrsave_status
;
pwrsave_status
=
iwl_read32
(
bu
s
(
priv
),
CSR_GP_CNTRL
)
&
pwrsave_status
=
iwl_read32
(
tran
s
(
priv
),
CSR_GP_CNTRL
)
&
CSR_GP_REG_POWER_SAVE_STATUS_MSK
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"Power Save Status: "
);
...
...
drivers/net/wireless/iwlwifi/iwl-dev.h
View file @
8f0bb5ae
...
...
@@ -292,114 +292,6 @@ struct iwl_vif_priv {
u8
ibss_bssid_sta_id
;
};
/* v1/v2 uCode file layout */
struct
iwl_ucode_header
{
__le32
ver
;
/* major/minor/API/serial */
union
{
struct
{
__le32
inst_size
;
/* bytes of runtime code */
__le32
data_size
;
/* bytes of runtime data */
__le32
init_size
;
/* bytes of init code */
__le32
init_data_size
;
/* bytes of init data */
__le32
boot_size
;
/* bytes of bootstrap code */
u8
data
[
0
];
/* in same order as sizes */
}
v1
;
struct
{
__le32
build
;
/* build number */
__le32
inst_size
;
/* bytes of runtime code */
__le32
data_size
;
/* bytes of runtime data */
__le32
init_size
;
/* bytes of init code */
__le32
init_data_size
;
/* bytes of init data */
__le32
boot_size
;
/* bytes of bootstrap code */
u8
data
[
0
];
/* in same order as sizes */
}
v2
;
}
u
;
};
/*
* new TLV uCode file layout
*
* The new TLV file format contains TLVs, that each specify
* some piece of data. To facilitate "groups", for example
* different instruction image with different capabilities,
* bundled with the same init image, an alternative mechanism
* is provided:
* When the alternative field is 0, that means that the item
* is always valid. When it is non-zero, then it is only
* valid in conjunction with items of the same alternative,
* in which case the driver (user) selects one alternative
* to use.
*/
enum
iwl_ucode_tlv_type
{
IWL_UCODE_TLV_INVALID
=
0
,
/* unused */
IWL_UCODE_TLV_INST
=
1
,
IWL_UCODE_TLV_DATA
=
2
,
IWL_UCODE_TLV_INIT
=
3
,
IWL_UCODE_TLV_INIT_DATA
=
4
,
IWL_UCODE_TLV_BOOT
=
5
,
IWL_UCODE_TLV_PROBE_MAX_LEN
=
6
,
/* a u32 value */
IWL_UCODE_TLV_PAN
=
7
,
IWL_UCODE_TLV_RUNT_EVTLOG_PTR
=
8
,
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE
=
9
,
IWL_UCODE_TLV_RUNT_ERRLOG_PTR
=
10
,
IWL_UCODE_TLV_INIT_EVTLOG_PTR
=
11
,
IWL_UCODE_TLV_INIT_EVTLOG_SIZE
=
12
,
IWL_UCODE_TLV_INIT_ERRLOG_PTR
=
13
,
IWL_UCODE_TLV_ENHANCE_SENS_TBL
=
14
,
IWL_UCODE_TLV_PHY_CALIBRATION_SIZE
=
15
,
IWL_UCODE_TLV_WOWLAN_INST
=
16
,
IWL_UCODE_TLV_WOWLAN_DATA
=
17
,
IWL_UCODE_TLV_FLAGS
=
18
,
};
/**
* enum iwl_ucode_tlv_flag - ucode API flags
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
* was a separate TLV but moved here to save space.
* @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
* treats good CRC threshold as a boolean
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
*/
enum
iwl_ucode_tlv_flag
{
IWL_UCODE_TLV_FLAGS_PAN
=
BIT
(
0
),
IWL_UCODE_TLV_FLAGS_NEWSCAN
=
BIT
(
1
),
IWL_UCODE_TLV_FLAGS_MFP
=
BIT
(
2
),
IWL_UCODE_TLV_FLAGS_P2P
=
BIT
(
3
),
};
struct
iwl_ucode_tlv
{
__le16
type
;
/* see above */
__le16
alternative
;
/* see comment */
__le32
length
;
/* not including type/length fields */
u8
data
[
0
];
}
__packed
;
#define IWL_TLV_UCODE_MAGIC 0x0a4c5749
struct
iwl_tlv_ucode_header
{
/*
* The TLV style ucode header is distinguished from
* the v1/v2 style header by first four bytes being
* zero, as such is an invalid combination of
* major/minor/API/serial versions.
*/
__le32
zero
;
__le32
magic
;
u8
human_readable
[
64
];
__le32
ver
;
/* major/minor/API/serial */
__le32
build
;
__le64
alternatives
;
/* bitmask of valid alternatives */
/*
* The data contained herein has a TLV layout,
* see above for the TLV header and types.
* Note that each TLV is padded to a length
* that is a multiple of 4 for alignment.
*/
u8
data
[
0
];
};
struct
iwl_sensitivity_ranges
{
u16
min_nrg_cck
;
u16
max_nrg_cck
;
...
...
@@ -821,7 +713,6 @@ struct iwl_wipan_noa_data {
struct
iwl_priv
{
/*data shared among all the driver's layers */
struct
iwl_shared
_shrd
;
struct
iwl_shared
*
shrd
;
/* ieee device used by generic ieee processing code */
...
...
drivers/net/wireless/iwlwifi/iwl-eeprom.c
View file @
8f0bb5ae
...
...
@@ -156,16 +156,16 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus)
for
(
count
=
0
;
count
<
EEPROM_SEM_RETRY_LIMIT
;
count
++
)
{
/* Request semaphore */
iwl_set_bit
(
bus
,
CSR_HW_IF_CONFIG_REG
,
iwl_set_bit
(
trans
(
bus
)
,
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM
);
/* See if we got it */
ret
=
iwl_poll_bit
(
bus
,
CSR_HW_IF_CONFIG_REG
,
ret
=
iwl_poll_bit
(
trans
(
bus
)
,
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM
,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM
,
EEPROM_SEM_TIMEOUT
);
if
(
ret
>=
0
)
{
IWL_DEBUG_EEPROM
(
bus
,
IWL_DEBUG_EEPROM
(
trans
(
bus
)
,
"Acquired semaphore after %d tries.
\n
"
,
count
+
1
);
return
ret
;
...
...
@@ -177,14 +177,15 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus)
static
void
iwl_eeprom_release_semaphore
(
struct
iwl_bus
*
bus
)
{
iwl_clear_bit
(
bus
,
CSR_HW_IF_CONFIG_REG
,
iwl_clear_bit
(
trans
(
bus
)
,
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM
);
}
static
int
iwl_eeprom_verify_signature
(
struct
iwl_trans
*
trans
)
{
u32
gp
=
iwl_read32
(
bus
(
trans
),
CSR_EEPROM_GP
)
&
CSR_EEPROM_GP_VALID_MSK
;
u32
gp
=
iwl_read32
(
trans
,
CSR_EEPROM_GP
)
&
CSR_EEPROM_GP_VALID_MSK
;
int
ret
=
0
;
IWL_DEBUG_EEPROM
(
trans
,
"EEPROM signature=0x%08x
\n
"
,
gp
);
...
...
@@ -305,13 +306,13 @@ void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac)
static
void
iwl_set_otp_access
(
struct
iwl_bus
*
bus
,
enum
iwl_access_mode
mode
)
{
iwl_read32
(
bus
,
CSR_OTP_GP_REG
);
iwl_read32
(
trans
(
bus
)
,
CSR_OTP_GP_REG
);
if
(
mode
==
IWL_OTP_ACCESS_ABSOLUTE
)
iwl_clear_bit
(
bus
,
CSR_OTP_GP_REG
,
iwl_clear_bit
(
trans
(
bus
)
,
CSR_OTP_GP_REG
,
CSR_OTP_GP_REG_OTP_ACCESS_MODE
);
else
iwl_set_bit
(
bus
,
CSR_OTP_GP_REG
,
iwl_set_bit
(
trans
(
bus
)
,
CSR_OTP_GP_REG
,
CSR_OTP_GP_REG_OTP_ACCESS_MODE
);
}
...
...
@@ -332,7 +333,7 @@ static int iwl_get_nvm_type(struct iwl_bus *bus, u32 hw_rev)
nvm_type
=
NVM_DEVICE_TYPE_EEPROM
;
break
;
default:
otpgp
=
iwl_read32
(
bus
,
CSR_OTP_GP_REG
);
otpgp
=
iwl_read32
(
trans
(
bus
)
,
CSR_OTP_GP_REG
);
if
(
otpgp
&
CSR_OTP_GP_REG_DEVICE_SELECT
)
nvm_type
=
NVM_DEVICE_TYPE_OTP
;
else
...
...
@@ -347,22 +348,22 @@ static int iwl_init_otp_access(struct iwl_bus *bus)
int
ret
;
/* Enable 40MHz radio clock */
iwl_write32
(
bus
,
CSR_GP_CNTRL
,
iwl_read32
(
bus
,
CSR_GP_CNTRL
)
|
iwl_write32
(
trans
(
bus
)
,
CSR_GP_CNTRL
,
iwl_read32
(
trans
(
bus
)
,
CSR_GP_CNTRL
)
|
CSR_GP_CNTRL_REG_FLAG_INIT_DONE
);
/* wait for clock to be ready */
ret
=
iwl_poll_bit
(
bus
,
CSR_GP_CNTRL
,
ret
=
iwl_poll_bit
(
trans
(
bus
)
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
,
25000
);
if
(
ret
<
0
)
IWL_ERR
(
bus
,
"Time out access OTP
\n
"
);
else
{
iwl_set_bits_prph
(
bus
,
APMG_PS_CTRL_REG
,
iwl_set_bits_prph
(
trans
(
bus
)
,
APMG_PS_CTRL_REG
,
APMG_PS_CTRL_VAL_RESET_REQ
);
udelay
(
5
);
iwl_clear_bits_prph
(
bus
,
APMG_PS_CTRL_REG
,
iwl_clear_bits_prph
(
trans
(
bus
)
,
APMG_PS_CTRL_REG
,
APMG_PS_CTRL_VAL_RESET_REQ
);
/*
...
...
@@ -370,7 +371,7 @@ static int iwl_init_otp_access(struct iwl_bus *bus)
* this is only applicable for HW with OTP shadow RAM
*/
if
(
cfg
(
bus
)
->
base_params
->
shadow_ram_support
)
iwl_set_bit
(
bus
,
CSR_DBG_LINK_PWR_MGMT_REG
,
iwl_set_bit
(
trans
(
bus
)
,
CSR_DBG_LINK_PWR_MGMT_REG
,
CSR_RESET_LINK_PWR_MGMT_DISABLED
);
}
return
ret
;
...
...
@@ -382,9 +383,9 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data)
u32
r
;
u32
otpgp
;
iwl_write32
(
bus
,
CSR_EEPROM_REG
,
iwl_write32
(
trans
(
bus
)
,
CSR_EEPROM_REG
,
CSR_EEPROM_REG_MSK_ADDR
&
(
addr
<<
1
));
ret
=
iwl_poll_bit
(
bus
,
CSR_EEPROM_REG
,
ret
=
iwl_poll_bit
(
trans
(
bus
)
,
CSR_EEPROM_REG
,
CSR_EEPROM_REG_READ_VALID_MSK
,
CSR_EEPROM_REG_READ_VALID_MSK
,
IWL_EEPROM_ACCESS_TIMEOUT
);
...
...
@@ -392,13 +393,13 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data)
IWL_ERR
(
bus
,
"Time out reading OTP[%d]
\n
"
,
addr
);
return
ret
;
}
r
=
iwl_read32
(
bus
,
CSR_EEPROM_REG
);
r
=
iwl_read32
(
trans
(
bus
)
,
CSR_EEPROM_REG
);
/* check for ECC errors: */
otpgp
=
iwl_read32
(
bus
,
CSR_OTP_GP_REG
);
otpgp
=
iwl_read32
(
trans
(
bus
)
,
CSR_OTP_GP_REG
);
if
(
otpgp
&
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK
)
{
/* stop in this case */
/* set the uncorrectable OTP ECC bit for acknowledgement */
iwl_set_bit
(
bus
,
CSR_OTP_GP_REG
,
iwl_set_bit
(
trans
(
bus
)
,
CSR_OTP_GP_REG
,
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK
);
IWL_ERR
(
bus
,
"Uncorrectable OTP ECC error, abort OTP read
\n
"
);
return
-
EINVAL
;
...
...
@@ -406,7 +407,7 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data)
if
(
otpgp
&
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK
)
{
/* continue in this case */
/* set the correctable OTP ECC bit for acknowledgement */
iwl_set_bit
(
bus
,
CSR_OTP_GP_REG
,
iwl_set_bit
(
trans
(
bus
)
,
CSR_OTP_GP_REG
,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK
);
IWL_ERR
(
bus
,
"Correctable OTP ECC error, continue read
\n
"
);
}
...
...
@@ -656,7 +657,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
{
struct
iwl_shared
*
shrd
=
priv
->
shrd
;
__le16
*
e
;
u32
gp
=
iwl_read32
(
bu
s
(
priv
),
CSR_EEPROM_GP
);
u32
gp
=
iwl_read32
(
tran
s
(
priv
),
CSR_EEPROM_GP
);
int
sz
;
int
ret
;
u16
addr
;
...
...
@@ -676,8 +677,6 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
}
e
=
(
__le16
*
)
shrd
->
eeprom
;
iwl_apm_init
(
priv
);
ret
=
iwl_eeprom_verify_signature
(
trans
(
priv
));
if
(
ret
<
0
)
{
IWL_ERR
(
priv
,
"EEPROM not found, EEPROM_GP=0x%08x
\n
"
,
gp
);
...
...
@@ -701,11 +700,11 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
ret
=
-
ENOENT
;
goto
done
;
}
iwl_write32
(
bu
s
(
priv
),
CSR_EEPROM_GP
,
iwl_read32
(
bu
s
(
priv
),
CSR_EEPROM_GP
)
&
iwl_write32
(
tran
s
(
priv
),
CSR_EEPROM_GP
,
iwl_read32
(
tran
s
(
priv
),
CSR_EEPROM_GP
)
&
~
CSR_EEPROM_GP_IF_OWNER_MSK
);
iwl_set_bit
(
bu
s
(
priv
),
CSR_OTP_GP_REG
,
iwl_set_bit
(
tran
s
(
priv
),
CSR_OTP_GP_REG
,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK
|
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK
);
/* traversing the linked list if no shadow ram supported */
...
...
@@ -730,10 +729,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
for
(
addr
=
0
;
addr
<
sz
;
addr
+=
sizeof
(
u16
))
{
u32
r
;
iwl_write32
(
bu
s
(
priv
),
CSR_EEPROM_REG
,
iwl_write32
(
tran
s
(
priv
),
CSR_EEPROM_REG
,
CSR_EEPROM_REG_MSK_ADDR
&
(
addr
<<
1
));
ret
=
iwl_poll_bit
(
bu
s
(
priv
),
CSR_EEPROM_REG
,
ret
=
iwl_poll_bit
(
tran
s
(
priv
),
CSR_EEPROM_REG
,
CSR_EEPROM_REG_READ_VALID_MSK
,
CSR_EEPROM_REG_READ_VALID_MSK
,
IWL_EEPROM_ACCESS_TIMEOUT
);
...
...
@@ -741,7 +740,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
IWL_ERR
(
priv
,
"Time out reading EEPROM[%d]
\n
"
,
addr
);
goto
done
;
}
r
=
iwl_read32
(
bu
s
(
priv
),
CSR_EEPROM_REG
);
r
=
iwl_read32
(
tran
s
(
priv
),
CSR_EEPROM_REG
);
e
[
addr
/
2
]
=
cpu_to_le16
(
r
>>
16
);
}
}
...
...
@@ -758,8 +757,6 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
err:
if
(
ret
)
iwl_eeprom_free
(
priv
->
shrd
);
/* Reset chip to save power until we load uCode during "up". */
iwl_apm_stop
(
priv
);
alloc_err:
return
ret
;
}
...
...
@@ -1072,7 +1069,7 @@ void iwl_rf_config(struct iwl_priv *priv)
/* write radio config values to register */
if
(
EEPROM_RF_CFG_TYPE_MSK
(
radio_cfg
)
<=
EEPROM_RF_CONFIG_TYPE_MAX
)
{
iwl_set_bit
(
bu
s
(
priv
),
CSR_HW_IF_CONFIG_REG
,
iwl_set_bit
(
tran
s
(
priv
),
CSR_HW_IF_CONFIG_REG
,
EEPROM_RF_CFG_TYPE_MSK
(
radio_cfg
)
|
EEPROM_RF_CFG_STEP_MSK
(
radio_cfg
)
|
EEPROM_RF_CFG_DASH_MSK
(
radio_cfg
));
...
...
@@ -1084,7 +1081,7 @@ void iwl_rf_config(struct iwl_priv *priv)
WARN_ON
(
1
);
/* set CSR_HW_CONFIG_REG for uCode use */
iwl_set_bit
(
bu
s
(
priv
),
CSR_HW_IF_CONFIG_REG
,
iwl_set_bit
(
tran
s
(
priv
),
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI
|
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI
);
}
drivers/net/wireless/iwlwifi/iwl-io.c
View file @
8f0bb5ae
...
...
@@ -34,41 +34,41 @@
#define IWL_POLL_INTERVAL 10
/* microseconds */
static
inline
void
__iwl_set_bit
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
)
static
inline
void
__iwl_set_bit
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
)
{
iwl_write32
(
bus
,
reg
,
iwl_read32
(
bu
s
,
reg
)
|
mask
);
iwl_write32
(
trans
,
reg
,
iwl_read32
(
tran
s
,
reg
)
|
mask
);
}
static
inline
void
__iwl_clear_bit
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
)
static
inline
void
__iwl_clear_bit
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
)
{
iwl_write32
(
bus
,
reg
,
iwl_read32
(
bu
s
,
reg
)
&
~
mask
);
iwl_write32
(
trans
,
reg
,
iwl_read32
(
tran
s
,
reg
)
&
~
mask
);
}
void
iwl_set_bit
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
)
void
iwl_set_bit
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
__iwl_set_bit
(
bu
s
,
reg
,
mask
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
__iwl_set_bit
(
tran
s
,
reg
,
mask
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
}
void
iwl_clear_bit
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
)
void
iwl_clear_bit
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
__iwl_clear_bit
(
bu
s
,
reg
,
mask
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
__iwl_clear_bit
(
tran
s
,
reg
,
mask
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
}
int
iwl_poll_bit
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
int
iwl_poll_bit
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
bits
,
u32
mask
,
int
timeout
)
{
int
t
=
0
;
do
{
if
((
iwl_read32
(
bu
s
,
addr
)
&
mask
)
==
(
bits
&
mask
))
if
((
iwl_read32
(
tran
s
,
addr
)
&
mask
)
==
(
bits
&
mask
))
return
t
;
udelay
(
IWL_POLL_INTERVAL
);
t
+=
IWL_POLL_INTERVAL
;
...
...
@@ -77,14 +77,15 @@ int iwl_poll_bit(struct iwl_bus *bus, u32 addr,
return
-
ETIMEDOUT
;
}
int
iwl_grab_nic_access_silent
(
struct
iwl_
bus
*
bu
s
)
int
iwl_grab_nic_access_silent
(
struct
iwl_
trans
*
tran
s
)
{
int
ret
;
lockdep_assert_held
(
&
bu
s
->
reg_lock
);
lockdep_assert_held
(
&
tran
s
->
reg_lock
);
/* this bit wakes up the NIC */
__iwl_set_bit
(
bus
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
__iwl_set_bit
(
trans
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
/*
* These bits say the device is running, and should keep running for
...
...
@@ -105,70 +106,70 @@ int iwl_grab_nic_access_silent(struct iwl_bus *bus)
* 5000 series and later (including 1000 series) have non-volatile SRAM,
* and do not save/restore SRAM when power cycling.
*/
ret
=
iwl_poll_bit
(
bu
s
,
CSR_GP_CNTRL
,
ret
=
iwl_poll_bit
(
tran
s
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN
,
(
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
|
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP
),
15000
);
if
(
ret
<
0
)
{
iwl_write32
(
bu
s
,
CSR_RESET
,
CSR_RESET_REG_FLAG_FORCE_NMI
);
iwl_write32
(
tran
s
,
CSR_RESET
,
CSR_RESET_REG_FLAG_FORCE_NMI
);
return
-
EIO
;
}
return
0
;
}
int
iwl_grab_nic_access
(
struct
iwl_
bus
*
bu
s
)
int
iwl_grab_nic_access
(
struct
iwl_
trans
*
tran
s
)
{
int
ret
=
iwl_grab_nic_access_silent
(
bu
s
);
int
ret
=
iwl_grab_nic_access_silent
(
tran
s
);
if
(
ret
)
{
u32
val
=
iwl_read32
(
bu
s
,
CSR_GP_CNTRL
);
IWL_ERR
(
bu
s
,
u32
val
=
iwl_read32
(
tran
s
,
CSR_GP_CNTRL
);
IWL_ERR
(
tran
s
,
"MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X
\n
"
,
val
);
}
return
ret
;
}
void
iwl_release_nic_access
(
struct
iwl_
bus
*
bu
s
)
void
iwl_release_nic_access
(
struct
iwl_
trans
*
tran
s
)
{
lockdep_assert_held
(
&
bu
s
->
reg_lock
);
__iwl_clear_bit
(
bu
s
,
CSR_GP_CNTRL
,
lockdep_assert_held
(
&
tran
s
->
reg_lock
);
__iwl_clear_bit
(
tran
s
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
}
u32
iwl_read_direct32
(
struct
iwl_
bus
*
bu
s
,
u32
reg
)
u32
iwl_read_direct32
(
struct
iwl_
trans
*
tran
s
,
u32
reg
)
{
u32
value
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
value
=
iwl_read32
(
bu
s
,
reg
);
iwl_release_nic_access
(
bu
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
tran
s
);
value
=
iwl_read32
(
tran
s
,
reg
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
return
value
;
}
void
iwl_write_direct32
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
value
)
void
iwl_write_direct32
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
value
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
bu
s
))
{
iwl_write32
(
bu
s
,
reg
,
value
);
iwl_release_nic_access
(
bu
s
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
tran
s
))
{
iwl_write32
(
tran
s
,
reg
,
value
);
iwl_release_nic_access
(
tran
s
);
}
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
}
int
iwl_poll_direct_bit
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
u32
mask
,
int
iwl_poll_direct_bit
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
mask
,
int
timeout
)
{
int
t
=
0
;
do
{
if
((
iwl_read_direct32
(
bu
s
,
addr
)
&
mask
)
==
mask
)
if
((
iwl_read_direct32
(
tran
s
,
addr
)
&
mask
)
==
mask
)
return
t
;
udelay
(
IWL_POLL_INTERVAL
);
t
+=
IWL_POLL_INTERVAL
;
...
...
@@ -177,135 +178,135 @@ int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask,
return
-
ETIMEDOUT
;
}
static
inline
u32
__iwl_read_prph
(
struct
iwl_
bus
*
bu
s
,
u32
reg
)
static
inline
u32
__iwl_read_prph
(
struct
iwl_
trans
*
tran
s
,
u32
reg
)
{
iwl_write32
(
bu
s
,
HBUS_TARG_PRPH_RADDR
,
reg
|
(
3
<<
24
));
iwl_write32
(
tran
s
,
HBUS_TARG_PRPH_RADDR
,
reg
|
(
3
<<
24
));
rmb
();
return
iwl_read32
(
bu
s
,
HBUS_TARG_PRPH_RDAT
);
return
iwl_read32
(
tran
s
,
HBUS_TARG_PRPH_RDAT
);
}
static
inline
void
__iwl_write_prph
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
u32
val
)
static
inline
void
__iwl_write_prph
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
val
)
{
iwl_write32
(
bu
s
,
HBUS_TARG_PRPH_WADDR
,
iwl_write32
(
tran
s
,
HBUS_TARG_PRPH_WADDR
,
((
addr
&
0x0000FFFF
)
|
(
3
<<
24
)));
wmb
();
iwl_write32
(
bu
s
,
HBUS_TARG_PRPH_WDAT
,
val
);
iwl_write32
(
tran
s
,
HBUS_TARG_PRPH_WDAT
,
val
);
}
u32
iwl_read_prph
(
struct
iwl_
bus
*
bu
s
,
u32
reg
)
u32
iwl_read_prph
(
struct
iwl_
trans
*
tran
s
,
u32
reg
)
{
unsigned
long
flags
;
u32
val
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
val
=
__iwl_read_prph
(
bu
s
,
reg
);
iwl_release_nic_access
(
bu
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
tran
s
);
val
=
__iwl_read_prph
(
tran
s
,
reg
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
return
val
;
}
void
iwl_write_prph
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
u32
val
)
void
iwl_write_prph
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
val
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
bu
s
))
{
__iwl_write_prph
(
bu
s
,
addr
,
val
);
iwl_release_nic_access
(
bu
s
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
tran
s
))
{
__iwl_write_prph
(
tran
s
,
addr
,
val
);
iwl_release_nic_access
(
tran
s
);
}
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
}
void
iwl_set_bits_prph
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
)
void
iwl_set_bits_prph
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
__iwl_write_prph
(
bus
,
reg
,
__iwl_read_prph
(
bu
s
,
reg
)
|
mask
);
iwl_release_nic_access
(
bu
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
tran
s
);
__iwl_write_prph
(
trans
,
reg
,
__iwl_read_prph
(
tran
s
,
reg
)
|
mask
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
}
void
iwl_set_bits_mask_prph
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
void
iwl_set_bits_mask_prph
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
bits
,
u32
mask
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
__iwl_write_prph
(
bu
s
,
reg
,
(
__iwl_read_prph
(
bu
s
,
reg
)
&
mask
)
|
bits
);
iwl_release_nic_access
(
bu
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
tran
s
);
__iwl_write_prph
(
tran
s
,
reg
,
(
__iwl_read_prph
(
tran
s
,
reg
)
&
mask
)
|
bits
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
}
void
iwl_clear_bits_prph
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
)
void
iwl_clear_bits_prph
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
)
{
unsigned
long
flags
;
u32
val
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
val
=
__iwl_read_prph
(
bu
s
,
reg
);
__iwl_write_prph
(
bu
s
,
reg
,
(
val
&
~
mask
));
iwl_release_nic_access
(
bu
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
tran
s
);
val
=
__iwl_read_prph
(
tran
s
,
reg
);
__iwl_write_prph
(
tran
s
,
reg
,
(
val
&
~
mask
));
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
}
void
_iwl_read_targ_mem_words
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
void
_iwl_read_targ_mem_words
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
void
*
buf
,
int
words
)
{
unsigned
long
flags
;
int
offs
;
u32
*
vals
=
buf
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
tran
s
);
iwl_write32
(
bu
s
,
HBUS_TARG_MEM_RADDR
,
addr
);
iwl_write32
(
tran
s
,
HBUS_TARG_MEM_RADDR
,
addr
);
rmb
();
for
(
offs
=
0
;
offs
<
words
;
offs
++
)
vals
[
offs
]
=
iwl_read32
(
bu
s
,
HBUS_TARG_MEM_RDAT
);
vals
[
offs
]
=
iwl_read32
(
tran
s
,
HBUS_TARG_MEM_RDAT
);
iwl_release_nic_access
(
bu
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
}
u32
iwl_read_targ_mem
(
struct
iwl_
bus
*
bu
s
,
u32
addr
)
u32
iwl_read_targ_mem
(
struct
iwl_
trans
*
tran
s
,
u32
addr
)
{
u32
value
;
_iwl_read_targ_mem_words
(
bu
s
,
addr
,
&
value
,
1
);
_iwl_read_targ_mem_words
(
tran
s
,
addr
,
&
value
,
1
);
return
value
;
}
int
_iwl_write_targ_mem_words
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
int
_iwl_write_targ_mem_words
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
void
*
buf
,
int
words
)
{
unsigned
long
flags
;
int
offs
,
result
=
0
;
u32
*
vals
=
buf
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
bu
s
))
{
iwl_write32
(
bu
s
,
HBUS_TARG_MEM_WADDR
,
addr
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
tran
s
))
{
iwl_write32
(
tran
s
,
HBUS_TARG_MEM_WADDR
,
addr
);
wmb
();
for
(
offs
=
0
;
offs
<
words
;
offs
++
)
iwl_write32
(
bu
s
,
HBUS_TARG_MEM_WDAT
,
vals
[
offs
]);
iwl_release_nic_access
(
bu
s
);
iwl_write32
(
tran
s
,
HBUS_TARG_MEM_WDAT
,
vals
[
offs
]);
iwl_release_nic_access
(
tran
s
);
}
else
result
=
-
EBUSY
;
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
return
result
;
}
int
iwl_write_targ_mem
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
u32
val
)
int
iwl_write_targ_mem
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
val
)
{
return
_iwl_write_targ_mem_words
(
bu
s
,
addr
,
&
val
,
1
);
return
_iwl_write_targ_mem_words
(
tran
s
,
addr
,
&
val
,
1
);
}
drivers/net/wireless/iwlwifi/iwl-io.h
View file @
8f0bb5ae
...
...
@@ -31,63 +31,63 @@
#include "iwl-devtrace.h"
#include "iwl-shared.h"
#include "iwl-
bu
s.h"
#include "iwl-
tran
s.h"
static
inline
void
iwl_write8
(
struct
iwl_
bus
*
bu
s
,
u32
ofs
,
u8
val
)
static
inline
void
iwl_write8
(
struct
iwl_
trans
*
tran
s
,
u32
ofs
,
u8
val
)
{
trace_iwlwifi_dev_iowrite8
(
priv
(
bu
s
),
ofs
,
val
);
bus_write8
(
bu
s
,
ofs
,
val
);
trace_iwlwifi_dev_iowrite8
(
priv
(
tran
s
),
ofs
,
val
);
iwl_trans_write8
(
tran
s
,
ofs
,
val
);
}
static
inline
void
iwl_write32
(
struct
iwl_
bus
*
bu
s
,
u32
ofs
,
u32
val
)
static
inline
void
iwl_write32
(
struct
iwl_
trans
*
tran
s
,
u32
ofs
,
u32
val
)
{
trace_iwlwifi_dev_iowrite32
(
priv
(
bu
s
),
ofs
,
val
);
bus_write32
(
bu
s
,
ofs
,
val
);
trace_iwlwifi_dev_iowrite32
(
priv
(
tran
s
),
ofs
,
val
);
iwl_trans_write32
(
tran
s
,
ofs
,
val
);
}
static
inline
u32
iwl_read32
(
struct
iwl_
bus
*
bu
s
,
u32
ofs
)
static
inline
u32
iwl_read32
(
struct
iwl_
trans
*
tran
s
,
u32
ofs
)
{
u32
val
=
bus_read32
(
bu
s
,
ofs
);
trace_iwlwifi_dev_ioread32
(
priv
(
bu
s
),
ofs
,
val
);
u32
val
=
iwl_trans_read32
(
tran
s
,
ofs
);
trace_iwlwifi_dev_ioread32
(
priv
(
tran
s
),
ofs
,
val
);
return
val
;
}
void
iwl_set_bit
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
);
void
iwl_clear_bit
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
);
void
iwl_set_bit
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
);
void
iwl_clear_bit
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
);
int
iwl_poll_bit
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
int
iwl_poll_bit
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
bits
,
u32
mask
,
int
timeout
);
int
iwl_poll_direct_bit
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
u32
mask
,
int
iwl_poll_direct_bit
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
mask
,
int
timeout
);
int
iwl_grab_nic_access_silent
(
struct
iwl_
bus
*
bu
s
);
int
iwl_grab_nic_access
(
struct
iwl_
bus
*
bu
s
);
void
iwl_release_nic_access
(
struct
iwl_
bus
*
bu
s
);
int
iwl_grab_nic_access_silent
(
struct
iwl_
trans
*
tran
s
);
int
iwl_grab_nic_access
(
struct
iwl_
trans
*
tran
s
);
void
iwl_release_nic_access
(
struct
iwl_
trans
*
tran
s
);
u32
iwl_read_direct32
(
struct
iwl_
bus
*
bu
s
,
u32
reg
);
void
iwl_write_direct32
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
value
);
u32
iwl_read_direct32
(
struct
iwl_
trans
*
tran
s
,
u32
reg
);
void
iwl_write_direct32
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
value
);
u32
iwl_read_prph
(
struct
iwl_
bus
*
bu
s
,
u32
reg
);
void
iwl_write_prph
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
u32
val
);
void
iwl_set_bits_prph
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
);
void
iwl_set_bits_mask_prph
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
iwl_read_prph
(
struct
iwl_
trans
*
tran
s
,
u32
reg
);
void
iwl_write_prph
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
val
);
void
iwl_set_bits_prph
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
);
void
iwl_set_bits_mask_prph
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
bits
,
u32
mask
);
void
iwl_clear_bits_prph
(
struct
iwl_
bus
*
bu
s
,
u32
reg
,
u32
mask
);
void
iwl_clear_bits_prph
(
struct
iwl_
trans
*
tran
s
,
u32
reg
,
u32
mask
);
void
_iwl_read_targ_mem_words
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
void
_iwl_read_targ_mem_words
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
void
*
buf
,
int
words
);
#define iwl_read_targ_mem_words(
bu
s, addr, buf, bufsize) \
#define iwl_read_targ_mem_words(
tran
s, addr, buf, bufsize) \
do { \
BUILD_BUG_ON((bufsize) % sizeof(u32)); \
_iwl_read_targ_mem_words(
bu
s, addr, buf, \
_iwl_read_targ_mem_words(
tran
s, addr, buf, \
(bufsize) / sizeof(u32));\
} while (0)
int
_iwl_write_targ_mem_words
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
int
_iwl_write_targ_mem_words
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
void
*
buf
,
int
words
);
u32
iwl_read_targ_mem
(
struct
iwl_
bus
*
bu
s
,
u32
addr
);
int
iwl_write_targ_mem
(
struct
iwl_
bus
*
bu
s
,
u32
addr
,
u32
val
);
u32
iwl_read_targ_mem
(
struct
iwl_
trans
*
tran
s
,
u32
addr
);
int
iwl_write_targ_mem
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
val
);
#endif
drivers/net/wireless/iwlwifi/iwl-led.c
View file @
8f0bb5ae
...
...
@@ -71,7 +71,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {
/* Set led register off */
void
iwlagn_led_enable
(
struct
iwl_priv
*
priv
)
{
iwl_write32
(
bu
s
(
priv
),
CSR_LED_REG
,
CSR_LED_REG_TRUN_ON
);
iwl_write32
(
tran
s
(
priv
),
CSR_LED_REG
,
CSR_LED_REG_TRUN_ON
);
}
/*
...
...
@@ -107,9 +107,10 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
};
u32
reg
;
reg
=
iwl_read32
(
bu
s
(
priv
),
CSR_LED_REG
);
reg
=
iwl_read32
(
tran
s
(
priv
),
CSR_LED_REG
);
if
(
reg
!=
(
reg
&
CSR_LED_BSM_CTRL_MSK
))
iwl_write32
(
bus
(
priv
),
CSR_LED_REG
,
reg
&
CSR_LED_BSM_CTRL_MSK
);
iwl_write32
(
trans
(
priv
),
CSR_LED_REG
,
reg
&
CSR_LED_BSM_CTRL_MSK
);
return
iwl_trans_send_cmd
(
trans
(
priv
),
&
cmd
);
}
...
...
@@ -206,7 +207,7 @@ void iwl_leds_init(struct iwl_priv *priv)
break
;
}
ret
=
led_classdev_register
(
bu
s
(
priv
)
->
dev
,
&
priv
->
led
);
ret
=
led_classdev_register
(
tran
s
(
priv
)
->
dev
,
&
priv
->
led
);
if
(
ret
)
{
kfree
(
priv
->
led
.
name
);
return
;
...
...
drivers/net/wireless/iwlwifi/iwl-mac80211.c
View file @
8f0bb5ae
...
...
@@ -35,7 +35,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
...
...
@@ -43,6 +42,7 @@
#include <asm/div64.h>
#include "iwl-ucode.h"
#include "iwl-eeprom.h"
#include "iwl-wifi.h"
#include "iwl-dev.h"
...
...
@@ -196,7 +196,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
WIPHY_FLAG_IBSS_RSN
;
if
(
trans
(
priv
)
->
ucode_wowlan
.
code
.
len
&&
device_can_wakeup
(
bu
s
(
priv
)
->
dev
))
{
device_can_wakeup
(
tran
s
(
priv
)
->
dev
))
{
hw
->
wiphy
->
wowlan
.
flags
=
WIPHY_WOWLAN_MAGIC_PKT
|
WIPHY_WOWLAN_DISCONNECT
|
WIPHY_WOWLAN_EAP_IDENTITY_REQ
|
...
...
@@ -234,7 +234,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
priv
->
hw
->
wiphy
->
bands
[
IEEE80211_BAND_5GHZ
]
=
&
priv
->
bands
[
IEEE80211_BAND_5GHZ
];
hw
->
wiphy
->
hw_version
=
bus_get_hw_id
(
bus
(
priv
))
;
hw
->
wiphy
->
hw_version
=
trans
(
priv
)
->
hw_id
;
iwl_leds_init
(
priv
);
...
...
@@ -346,9 +346,10 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
flush_workqueue
(
priv
->
shrd
->
workqueue
);
/* User space software may expect getting rfkill changes
* even if interface is down */
iwl_write32
(
bus
(
priv
),
CSR_INT
,
0xFFFFFFFF
);
iwl_enable_rfkill_int
(
priv
);
* even if interface is down, trans->down will leave the RF
* kill interrupt enabled
*/
iwl_trans_stop_hw
(
trans
(
priv
));
IWL_DEBUG_MAC80211
(
priv
,
"leave
\n
"
);
}
...
...
@@ -405,10 +406,10 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
if
(
ret
)
goto
error
;
device_set_wakeup_enable
(
bu
s
(
priv
)
->
dev
,
true
);
device_set_wakeup_enable
(
tran
s
(
priv
)
->
dev
,
true
);
/* Now let the ucode operate on its own */
iwl_write32
(
bu
s
(
priv
),
CSR_UCODE_DRV_GP1_SET
,
iwl_write32
(
tran
s
(
priv
),
CSR_UCODE_DRV_GP1_SET
,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE
);
goto
out
;
...
...
@@ -436,19 +437,19 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
IWL_DEBUG_MAC80211
(
priv
,
"enter
\n
"
);
mutex_lock
(
&
priv
->
shrd
->
mutex
);
iwl_write32
(
bu
s
(
priv
),
CSR_UCODE_DRV_GP1_CLR
,
iwl_write32
(
tran
s
(
priv
),
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE
);
base
=
priv
->
shrd
->
device_pointers
.
error_event_table
;
if
(
iwlagn_hw_valid_rtc_data_addr
(
base
))
{
spin_lock_irqsave
(
&
bu
s
(
priv
)
->
reg_lock
,
flags
);
ret
=
iwl_grab_nic_access_silent
(
bu
s
(
priv
));
spin_lock_irqsave
(
&
tran
s
(
priv
)
->
reg_lock
,
flags
);
ret
=
iwl_grab_nic_access_silent
(
tran
s
(
priv
));
if
(
ret
==
0
)
{
iwl_write32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RADDR
,
base
);
status
=
iwl_read32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
iwl_release_nic_access
(
bu
s
(
priv
));
iwl_write32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RADDR
,
base
);
status
=
iwl_read32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
iwl_release_nic_access
(
tran
s
(
priv
));
}
spin_unlock_irqrestore
(
&
bu
s
(
priv
)
->
reg_lock
,
flags
);
spin_unlock_irqrestore
(
&
tran
s
(
priv
)
->
reg_lock
,
flags
);
#ifdef CONFIG_IWLWIFI_DEBUGFS
if
(
ret
==
0
)
{
...
...
@@ -460,7 +461,8 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
if
(
priv
->
wowlan_sram
)
_iwl_read_targ_mem_words
(
bus
(
priv
),
0x800000
,
priv
->
wowlan_sram
,
trans
(
priv
),
0x800000
,
priv
->
wowlan_sram
,
trans
->
ucode_wowlan
.
data
.
len
/
4
);
}
#endif
...
...
@@ -471,7 +473,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
priv
->
shrd
->
wowlan
=
false
;
device_set_wakeup_enable
(
bu
s
(
priv
)
->
dev
,
false
);
device_set_wakeup_enable
(
tran
s
(
priv
)
->
dev
,
false
);
iwlagn_prepare_restart
(
priv
);
...
...
drivers/net/wireless/iwlwifi/iwl-pci.c
View file @
8f0bb5ae
...
...
@@ -71,112 +71,6 @@
#include "iwl-csr.h"
#include "iwl-cfg.h"
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041
#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
struct
iwl_pci_bus
{
/* basic pci-network driver stuff */
struct
pci_dev
*
pci_dev
;
/* pci hardware address support */
void
__iomem
*
hw_base
;
};
#define IWL_BUS_GET_PCI_BUS(_iwl_bus) \
((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific))
#define IWL_BUS_GET_PCI_DEV(_iwl_bus) \
((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev)
static
u16
iwl_pciexp_link_ctrl
(
struct
iwl_bus
*
bus
)
{
int
pos
;
u16
pci_lnk_ctl
;
struct
pci_dev
*
pci_dev
=
IWL_BUS_GET_PCI_DEV
(
bus
);
pos
=
pci_pcie_cap
(
pci_dev
);
pci_read_config_word
(
pci_dev
,
pos
+
PCI_EXP_LNKCTL
,
&
pci_lnk_ctl
);
return
pci_lnk_ctl
;
}
static
bool
iwl_pci_is_pm_supported
(
struct
iwl_bus
*
bus
)
{
u16
lctl
=
iwl_pciexp_link_ctrl
(
bus
);
return
!
(
lctl
&
PCI_CFG_LINK_CTRL_VAL_L0S_EN
);
}
static
void
iwl_pci_apm_config
(
struct
iwl_bus
*
bus
)
{
/*
* HW bug W/A for instability in PCIe bus L0S->L1 transition.
* Check if BIOS (or OS) enabled L1-ASPM on this device.
* If so (likely), disable L0S, so device moves directly L0->L1;
* costs negligible amount of power savings.
* If not (unlikely), enable L0S, so there is at least some
* power savings, even without L1.
*/
u16
lctl
=
iwl_pciexp_link_ctrl
(
bus
);
if
((
lctl
&
PCI_CFG_LINK_CTRL_VAL_L1_EN
)
==
PCI_CFG_LINK_CTRL_VAL_L1_EN
)
{
/* L1-ASPM enabled; disable(!) L0S */
iwl_set_bit
(
bus
,
CSR_GIO_REG
,
CSR_GIO_REG_VAL_L0S_ENABLED
);
dev_printk
(
KERN_INFO
,
bus
->
dev
,
"L1 Enabled; Disabling L0S
\n
"
);
}
else
{
/* L1-ASPM disabled; enable(!) L0S */
iwl_clear_bit
(
bus
,
CSR_GIO_REG
,
CSR_GIO_REG_VAL_L0S_ENABLED
);
dev_printk
(
KERN_INFO
,
bus
->
dev
,
"L1 Disabled; Enabling L0S
\n
"
);
}
}
static
void
iwl_pci_get_hw_id_string
(
struct
iwl_bus
*
bus
,
char
buf
[],
int
buf_len
)
{
struct
pci_dev
*
pci_dev
=
IWL_BUS_GET_PCI_DEV
(
bus
);
snprintf
(
buf
,
buf_len
,
"PCI ID: 0x%04X:0x%04X"
,
pci_dev
->
device
,
pci_dev
->
subsystem_device
);
}
static
u32
iwl_pci_get_hw_id
(
struct
iwl_bus
*
bus
)
{
struct
pci_dev
*
pci_dev
=
IWL_BUS_GET_PCI_DEV
(
bus
);
return
(
pci_dev
->
device
<<
16
)
+
pci_dev
->
subsystem_device
;
}
static
void
iwl_pci_write8
(
struct
iwl_bus
*
bus
,
u32
ofs
,
u8
val
)
{
iowrite8
(
val
,
IWL_BUS_GET_PCI_BUS
(
bus
)
->
hw_base
+
ofs
);
}
static
void
iwl_pci_write32
(
struct
iwl_bus
*
bus
,
u32
ofs
,
u32
val
)
{
iowrite32
(
val
,
IWL_BUS_GET_PCI_BUS
(
bus
)
->
hw_base
+
ofs
);
}
static
u32
iwl_pci_read32
(
struct
iwl_bus
*
bus
,
u32
ofs
)
{
u32
val
=
ioread32
(
IWL_BUS_GET_PCI_BUS
(
bus
)
->
hw_base
+
ofs
);
return
val
;
}
static
const
struct
iwl_bus_ops
bus_ops_pci
=
{
.
get_pm_support
=
iwl_pci_is_pm_supported
,
.
apm_config
=
iwl_pci_apm_config
,
.
get_hw_id_string
=
iwl_pci_get_hw_id_string
,
.
get_hw_id
=
iwl_pci_get_hw_id
,
.
write8
=
iwl_pci_write8
,
.
write32
=
iwl_pci_write32
,
.
read32
=
iwl_pci_read32
,
};
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
...
...
@@ -362,112 +256,61 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
};
MODULE_DEVICE_TABLE
(
pci
,
iwl_hw_card_ids
);
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041
static
int
iwl_pci_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
struct
iwl_cfg
*
cfg
=
(
struct
iwl_cfg
*
)(
ent
->
driver_data
);
struct
iwl_bus
*
bus
;
struct
iwl_pci_bus
*
pci_bus
;
u16
pci_cmd
;
int
err
;
bus
=
kzalloc
(
sizeof
(
*
bus
)
+
sizeof
(
*
pci_bus
)
,
GFP_KERNEL
);
bus
=
kzalloc
(
sizeof
(
*
bus
),
GFP_KERNEL
);
if
(
!
bus
)
{
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
"Couldn't allocate iwl_pci_bus"
);
err
=
-
ENOMEM
;
goto
out_no_pci
;
return
-
ENOMEM
;
}
pci_bus
=
IWL_BUS_GET_PCI_BUS
(
bus
);
pci_bus
->
pci_dev
=
pdev
;
pci_set_drvdata
(
pdev
,
bus
);
/* W/A - seems to solve weird behavior. We need to remove this if we
* don't want to stay in L1 all the time. This wastes a lot of power */
pci_disable_link_state
(
pdev
,
PCIE_LINK_STATE_L0S
|
PCIE_LINK_STATE_L1
|
PCIE_LINK_STATE_CLKPM
);
if
(
pci_enable_device
(
pdev
))
{
err
=
-
ENODEV
;
goto
out_no_pci
;
bus
->
shrd
=
kzalloc
(
sizeof
(
*
bus
->
shrd
),
GFP_KERNEL
);
if
(
!
bus
->
shrd
)
{
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
"Couldn't allocate iwl_shared"
);
err
=
-
ENOMEM
;
goto
out_free_bus
;
}
pci_set_master
(
pdev
);
err
=
pci_set_dma_mask
(
pdev
,
DMA_BIT_MASK
(
36
));
if
(
!
err
)
err
=
pci_set_consistent_dma_mask
(
pdev
,
DMA_BIT_MASK
(
36
));
if
(
err
)
{
err
=
pci_set_dma_mask
(
pdev
,
DMA_BIT_MASK
(
32
));
if
(
!
err
)
err
=
pci_set_consistent_dma_mask
(
pdev
,
DMA_BIT_MASK
(
32
));
/* both attempts failed: */
if
(
err
)
{
dev_printk
(
KERN_ERR
,
bus
->
dev
,
"No suitable DMA available.
\n
"
);
goto
out_pci_disable_device
;
}
}
bus
->
shrd
->
bus
=
bus
;
err
=
pci_request_regions
(
pdev
,
DRV_NAME
);
if
(
err
)
{
dev_printk
(
KERN_ERR
,
bus
->
dev
,
"pci_request_regions failed"
);
goto
out_pci_disable_device
;
}
pci_set_drvdata
(
pdev
,
bus
);
pci_bus
->
hw_base
=
pci_iomap
(
pdev
,
0
,
0
);
if
(
!
pci_bus
->
hw_base
)
{
dev_printk
(
KERN_ERR
,
bus
->
dev
,
"pci_iomap failed"
);
err
=
-
ENO
DEV
;
goto
out_
pci_release_region
s
;
#ifdef CONFIG_IWLWIFI_IDI
trans
(
bus
)
=
iwl_trans_idi_alloc
(
bus
->
shrd
,
pdev
,
ent
);
if
(
trans
(
bus
)
==
NULL
)
{
err
=
-
ENO
MEM
;
goto
out_
free_bu
s
;
}
dev_printk
(
KERN_INFO
,
&
pdev
->
dev
,
"pci_resource_len = 0x%08llx
\n
"
,
(
unsigned
long
long
)
pci_resource_len
(
pdev
,
0
));
dev_printk
(
KERN_INFO
,
&
pdev
->
dev
,
"pci_resource_base = %p
\n
"
,
pci_bus
->
hw_base
);
dev_printk
(
KERN_INFO
,
&
pdev
->
dev
,
"HW Revision ID = 0x%X
\n
"
,
pdev
->
revision
);
/* We disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte
(
pdev
,
PCI_CFG_RETRY_TIMEOUT
,
0x00
);
err
=
pci_enable_msi
(
pdev
);
if
(
err
)
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
"pci_enable_msi failed(0X%x)"
,
err
);
/* TODO: Move this away, not needed if not MSI */
/* enable rfkill interrupt: hw bug w/a */
pci_read_config_word
(
pdev
,
PCI_COMMAND
,
&
pci_cmd
);
if
(
pci_cmd
&
PCI_COMMAND_INTX_DISABLE
)
{
pci_cmd
&=
~
PCI_COMMAND_INTX_DISABLE
;
pci_write_config_word
(
pdev
,
PCI_COMMAND
,
pci_cmd
);
err
=
iwl_probe
(
bus
,
&
trans_ops_idi
,
cfg
);
#else
trans
(
bus
)
=
iwl_trans_pcie_alloc
(
bus
->
shrd
,
pdev
,
ent
);
if
(
trans
(
bus
)
==
NULL
)
{
err
=
-
ENOMEM
;
goto
out_free_bus
;
}
bus
->
dev
=
&
pdev
->
dev
;
bus
->
irq
=
pdev
->
irq
;
bus
->
ops
=
&
bus_ops_pci
;
err
=
iwl_probe
(
bus
,
&
trans_ops_pcie
,
cfg
);
#endif
if
(
err
)
goto
out_disable_msi
;
goto
out_free_trans
;
return
0
;
out_disable_msi:
pci_disable_msi
(
pdev
);
pci_iounmap
(
pdev
,
pci_bus
->
hw_base
);
out_pci_release_regions:
out_free_trans:
iwl_trans_free
(
trans
(
bus
));
pci_set_drvdata
(
pdev
,
NULL
);
pci_release_regions
(
pdev
);
out_pci_disable_device:
pci_disable_device
(
pdev
);
out_no_pci:
out_free_bus:
kfree
(
bus
->
shrd
);
kfree
(
bus
);
return
err
;
}
...
...
@@ -475,18 +318,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static
void
__devexit
iwl_pci_remove
(
struct
pci_dev
*
pdev
)
{
struct
iwl_bus
*
bus
=
pci_get_drvdata
(
pdev
);
struct
iwl_pci_bus
*
pci_bus
=
IWL_BUS_GET_PCI_BUS
(
bus
);
struct
pci_dev
*
pci_dev
=
IWL_BUS_GET_PCI_DEV
(
bus
);
struct
iwl_shared
*
shrd
=
bus
->
shrd
;
iwl_remove
(
shrd
->
priv
);
iwl_trans_free
(
shrd
->
trans
);
pci_disable_msi
(
pci_dev
);
pci_iounmap
(
pci_dev
,
pci_bus
->
hw_base
);
pci_release_regions
(
pci_dev
);
pci_disable_device
(
pci_dev
);
pci_set_drvdata
(
pci_dev
,
NULL
);
pci_set_drvdata
(
pdev
,
NULL
);
kfree
(
bus
->
shrd
);
kfree
(
bus
);
}
...
...
drivers/net/wireless/iwlwifi/iwl-power.c
View file @
8f0bb5ae
...
...
@@ -436,7 +436,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
/* initialize to default */
void
iwl_power_initialize
(
struct
iwl_priv
*
priv
)
{
priv
->
power_data
.
bus_pm
=
bus_get_pm_support
(
bus
(
priv
))
;
priv
->
power_data
.
bus_pm
=
trans
(
priv
)
->
pm_support
;
priv
->
power_data
.
debug_sleep_level_override
=
-
1
;
...
...
drivers/net/wireless/iwlwifi/iwl-shared.h
View file @
8f0bb5ae
...
...
@@ -543,8 +543,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);
void
iwl_set_hw_rfkill_state
(
struct
iwl_priv
*
priv
,
bool
state
);
void
iwl_nic_config
(
struct
iwl_priv
*
priv
);
void
iwl_free_skb
(
struct
iwl_priv
*
priv
,
struct
sk_buff
*
skb
);
void
iwl_apm_stop
(
struct
iwl_priv
*
priv
);
int
iwl_apm_init
(
struct
iwl_priv
*
priv
);
void
iwlagn_fw_error
(
struct
iwl_priv
*
priv
,
bool
ondemand
);
const
char
*
get_cmd_string
(
u8
cmd
);
bool
iwl_check_for_ct_kill
(
struct
iwl_priv
*
priv
);
...
...
drivers/net/wireless/iwlwifi/iwl-testmode.c
View file @
8f0bb5ae
...
...
@@ -79,6 +79,7 @@
#include "iwl-testmode.h"
#include "iwl-trans.h"
#include "iwl-bus.h"
#include "iwl-fh.h"
/* The TLVs used in the gnl message policy between the kernel module and
* user space application. iwl_testmode_gnl_msg_policy is to be carried
...
...
@@ -208,7 +209,7 @@ static void iwl_trace_cleanup(struct iwl_priv *priv)
if
(
priv
->
testmode_trace
.
trace_enabled
)
{
if
(
priv
->
testmode_trace
.
cpu_addr
&&
priv
->
testmode_trace
.
dma_addr
)
dma_free_coherent
(
bu
s
(
priv
)
->
dev
,
dma_free_coherent
(
tran
s
(
priv
)
->
dev
,
priv
->
testmode_trace
.
total_size
,
priv
->
testmode_trace
.
cpu_addr
,
priv
->
testmode_trace
.
dma_addr
);
...
...
@@ -288,7 +289,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
static
int
iwl_testmode_reg
(
struct
ieee80211_hw
*
hw
,
struct
nlattr
**
tb
)
{
struct
iwl_priv
*
priv
=
hw
->
priv
;
u32
ofs
,
val32
;
u32
ofs
,
val32
,
cmd
;
u8
val8
;
struct
sk_buff
*
skb
;
int
status
=
0
;
...
...
@@ -300,9 +301,22 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
ofs
=
nla_get_u32
(
tb
[
IWL_TM_ATTR_REG_OFFSET
]);
IWL_INFO
(
priv
,
"testmode register access command offset 0x%x
\n
"
,
ofs
);
switch
(
nla_get_u32
(
tb
[
IWL_TM_ATTR_COMMAND
]))
{
/* Allow access only to FH/CSR/HBUS in direct mode.
Since we don't have the upper bounds for the CSR and HBUS segments,
we will use only the upper bound of FH for sanity check. */
cmd
=
nla_get_u32
(
tb
[
IWL_TM_ATTR_COMMAND
]);
if
((
cmd
==
IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32
||
cmd
==
IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32
||
cmd
==
IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8
)
&&
(
ofs
>=
FH_MEM_UPPER_BOUND
))
{
IWL_DEBUG_INFO
(
priv
,
"offset out of segment (0x0 - 0x%x)
\n
"
,
FH_MEM_UPPER_BOUND
);
return
-
EINVAL
;
}
switch
(
cmd
)
{
case
IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32
:
val32
=
iwl_read_direct32
(
bu
s
(
priv
),
ofs
);
val32
=
iwl_read_direct32
(
tran
s
(
priv
),
ofs
);
IWL_INFO
(
priv
,
"32bit value to read 0x%x
\n
"
,
val32
);
skb
=
cfg80211_testmode_alloc_reply_skb
(
hw
->
wiphy
,
20
);
...
...
@@ -324,7 +338,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
}
else
{
val32
=
nla_get_u32
(
tb
[
IWL_TM_ATTR_REG_VALUE32
]);
IWL_INFO
(
priv
,
"32bit value to write 0x%x
\n
"
,
val32
);
iwl_write_direct32
(
bu
s
(
priv
),
ofs
,
val32
);
iwl_write_direct32
(
tran
s
(
priv
),
ofs
,
val32
);
}
break
;
case
IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8
:
...
...
@@ -334,11 +348,11 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
}
else
{
val8
=
nla_get_u8
(
tb
[
IWL_TM_ATTR_REG_VALUE8
]);
IWL_INFO
(
priv
,
"8bit value to write 0x%x
\n
"
,
val8
);
iwl_write8
(
bu
s
(
priv
),
ofs
,
val8
);
iwl_write8
(
tran
s
(
priv
),
ofs
,
val8
);
}
break
;
case
IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32
:
val32
=
iwl_read_prph
(
bu
s
(
priv
),
ofs
);
val32
=
iwl_read_prph
(
tran
s
(
priv
),
ofs
);
IWL_INFO
(
priv
,
"32bit value to read 0x%x
\n
"
,
val32
);
skb
=
cfg80211_testmode_alloc_reply_skb
(
hw
->
wiphy
,
20
);
...
...
@@ -360,7 +374,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
}
else
{
val32
=
nla_get_u32
(
tb
[
IWL_TM_ATTR_REG_VALUE32
]);
IWL_INFO
(
priv
,
"32bit value to write 0x%x
\n
"
,
val32
);
iwl_write_prph
(
bu
s
(
priv
),
ofs
,
val32
);
iwl_write_prph
(
tran
s
(
priv
),
ofs
,
val32
);
}
break
;
default:
...
...
@@ -536,7 +550,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
break
;
case
IWL_TM_CMD_APP2DEV_GET_DEVICE_ID
:
devid
=
bus_get_hw_id
(
bus
(
priv
))
;
devid
=
trans
(
priv
)
->
hw_id
;
IWL_INFO
(
priv
,
"hw version: 0x%x
\n
"
,
devid
);
skb
=
cfg80211_testmode_alloc_reply_skb
(
hw
->
wiphy
,
20
);
...
...
@@ -615,7 +629,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
struct
iwl_priv
*
priv
=
hw
->
priv
;
struct
sk_buff
*
skb
;
int
status
=
0
;
struct
device
*
dev
=
bu
s
(
priv
)
->
dev
;
struct
device
*
dev
=
tran
s
(
priv
)
->
dev
;
switch
(
nla_get_u32
(
tb
[
IWL_TM_ATTR_COMMAND
]))
{
case
IWL_TM_CMD_APP2DEV_BEGIN_TRACE
:
...
...
@@ -814,7 +828,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb)
IWL_ERR
(
priv
,
"Error allocating memory
\n
"
);
return
-
ENOMEM
;
}
_iwl_read_targ_mem_words
(
bu
s
(
priv
),
ofs
,
_iwl_read_targ_mem_words
(
tran
s
(
priv
),
ofs
,
priv
->
testmode_sram
.
buff_addr
,
priv
->
testmode_sram
.
buff_size
/
4
);
priv
->
testmode_sram
.
num_chunks
=
...
...
drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
View file @
8f0bb5ae
...
...
@@ -201,6 +201,7 @@ struct iwl_tx_queue {
* @rxq: all the RX queue data
* @rx_replenish: work that will be called when buffers need to be allocated
* @trans: pointer to the generic transport area
* @irq_requested: true when the irq has been requested
* @scd_base_addr: scheduler sram base address in SRAM
* @scd_bc_tbls: pointer to the byte count table of the scheduler
* @kw: keep warm address
...
...
@@ -211,6 +212,8 @@ struct iwl_tx_queue {
* @txq_ctx_active_msk: what queue is active
* queue_stopped: tracks what queue is stopped
* queue_stop_count: tracks what SW queue is stopped
* @pci_dev: basic pci-network driver stuff
* @hw_base: pci hardware address support
*/
struct
iwl_trans_pcie
{
struct
iwl_rx_queue
rxq
;
...
...
@@ -223,6 +226,7 @@ struct iwl_trans_pcie {
int
ict_index
;
u32
inta
;
bool
use_ict
;
bool
irq_requested
;
struct
tasklet_struct
irq_tasklet
;
struct
isr_statistics
isr_stats
;
...
...
@@ -241,6 +245,10 @@ struct iwl_trans_pcie {
#define IWL_MAX_HW_QUEUES 32
unsigned
long
queue_stopped
[
BITS_TO_LONGS
(
IWL_MAX_HW_QUEUES
)];
atomic_t
queue_stop_count
[
4
];
/* PCI bus related data */
struct
pci_dev
*
pci_dev
;
void
__iomem
*
hw_base
;
};
#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
...
...
@@ -258,7 +266,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
/*****************************************************
* ICT
******************************************************/
int
iwl_reset_ict
(
struct
iwl_trans
*
trans
);
void
iwl_reset_ict
(
struct
iwl_trans
*
trans
);
void
iwl_disable_ict
(
struct
iwl_trans
*
trans
);
int
iwl_alloc_isr_ict
(
struct
iwl_trans
*
trans
);
void
iwl_free_isr_ict
(
struct
iwl_trans
*
trans
);
...
...
@@ -311,12 +319,12 @@ static inline void iwl_disable_interrupts(struct iwl_trans *trans)
clear_bit
(
STATUS_INT_ENABLED
,
&
trans
->
shrd
->
status
);
/* disable interrupts from uCode/NIC to host */
iwl_write32
(
bus
(
trans
)
,
CSR_INT_MASK
,
0x00000000
);
iwl_write32
(
trans
,
CSR_INT_MASK
,
0x00000000
);
/* acknowledge/clear/reset any interrupts still pending
* from uCode or flow handler (Rx/Tx DMA) */
iwl_write32
(
bus
(
trans
)
,
CSR_INT
,
0xffffffff
);
iwl_write32
(
bus
(
trans
)
,
CSR_FH_INT_STATUS
,
0xffffffff
);
iwl_write32
(
trans
,
CSR_INT
,
0xffffffff
);
iwl_write32
(
trans
,
CSR_FH_INT_STATUS
,
0xffffffff
);
IWL_DEBUG_ISR
(
trans
,
"Disabled interrupts
\n
"
);
}
...
...
@@ -327,7 +335,7 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
IWL_DEBUG_ISR
(
trans
,
"Enabling interrupts
\n
"
);
set_bit
(
STATUS_INT_ENABLED
,
&
trans
->
shrd
->
status
);
iwl_write32
(
bus
(
trans
)
,
CSR_INT_MASK
,
trans_pcie
->
inta_mask
);
iwl_write32
(
trans
,
CSR_INT_MASK
,
trans_pcie
->
inta_mask
);
}
/*
...
...
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
View file @
8f0bb5ae
...
...
@@ -35,6 +35,10 @@
#include "iwl-io.h"
#include "iwl-trans-pcie-int.h"
#ifdef CONFIG_IWLWIFI_IDI
#include "iwl-amfh.h"
#endif
/******************************************************************************
*
* RX path functions
...
...
@@ -140,30 +144,30 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
/* shadow register enabled */
/* Device expects a multiple of 8 */
q
->
write_actual
=
(
q
->
write
&
~
0x7
);
iwl_write32
(
bus
(
trans
)
,
FH_RSCSR_CHNL0_WPTR
,
q
->
write_actual
);
iwl_write32
(
trans
,
FH_RSCSR_CHNL0_WPTR
,
q
->
write_actual
);
}
else
{
/* If power-saving is in use, make sure device is awake */
if
(
test_bit
(
STATUS_POWER_PMI
,
&
trans
->
shrd
->
status
))
{
reg
=
iwl_read32
(
bus
(
trans
)
,
CSR_UCODE_DRV_GP1
);
reg
=
iwl_read32
(
trans
,
CSR_UCODE_DRV_GP1
);
if
(
reg
&
CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP
)
{
IWL_DEBUG_INFO
(
trans
,
"Rx queue requesting wakeup,"
" GP1 = 0x%x
\n
"
,
reg
);
iwl_set_bit
(
bus
(
trans
)
,
CSR_GP_CNTRL
,
iwl_set_bit
(
trans
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
goto
exit_unlock
;
}
q
->
write_actual
=
(
q
->
write
&
~
0x7
);
iwl_write_direct32
(
bus
(
trans
)
,
FH_RSCSR_CHNL0_WPTR
,
iwl_write_direct32
(
trans
,
FH_RSCSR_CHNL0_WPTR
,
q
->
write_actual
);
/* Else device is assumed to be awake */
}
else
{
/* Device expects a multiple of 8 */
q
->
write_actual
=
(
q
->
write
&
~
0x7
);
iwl_write_direct32
(
bus
(
trans
)
,
FH_RSCSR_CHNL0_WPTR
,
iwl_write_direct32
(
trans
,
FH_RSCSR_CHNL0_WPTR
,
q
->
write_actual
);
}
}
...
...
@@ -308,7 +312,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
BUG_ON
(
rxb
->
page
);
rxb
->
page
=
page
;
/* Get physical address of the RB */
rxb
->
page_dma
=
dma_map_page
(
bus
(
trans
)
->
dev
,
page
,
0
,
rxb
->
page_dma
=
dma_map_page
(
trans
->
dev
,
page
,
0
,
PAGE_SIZE
<<
hw_params
(
trans
).
rx_page_order
,
DMA_FROM_DEVICE
);
/* dma address must be no more than 36 bits */
...
...
@@ -414,7 +418,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
rxq
->
queue
[
i
]
=
NULL
;
dma_unmap_page
(
bus
(
trans
)
->
dev
,
rxb
->
page_dma
,
dma_unmap_page
(
trans
->
dev
,
rxb
->
page_dma
,
PAGE_SIZE
<<
hw_params
(
trans
).
rx_page_order
,
DMA_FROM_DEVICE
);
pkt
=
rxb_addr
(
rxb
);
...
...
@@ -485,7 +489,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
* rx_free list for reuse later. */
spin_lock_irqsave
(
&
rxq
->
lock
,
flags
);
if
(
rxb
->
page
!=
NULL
)
{
rxb
->
page_dma
=
dma_map_page
(
bus
(
trans
)
->
dev
,
rxb
->
page
,
rxb
->
page_dma
=
dma_map_page
(
trans
->
dev
,
rxb
->
page
,
0
,
PAGE_SIZE
<<
hw_params
(
trans
).
rx_page_order
,
DMA_FROM_DEVICE
);
...
...
@@ -612,7 +616,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
return
;
}
iwl_read_targ_mem_words
(
bu
s
(
priv
),
base
,
&
table
,
sizeof
(
table
));
iwl_read_targ_mem_words
(
tran
s
(
priv
),
base
,
&
table
,
sizeof
(
table
));
if
(
ERROR_START_OFFSET
<=
table
.
valid
*
ERROR_ELEM_SIZE
)
{
IWL_ERR
(
trans
,
"Start IWL Error Log Dump:
\n
"
);
...
...
@@ -673,9 +677,9 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
struct
iwl_priv
*
priv
=
priv
(
trans
);
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
if
(
cfg
(
priv
)
->
internal_wimax_coex
&&
(
!
(
iwl_read_prph
(
bus
(
trans
)
,
APMG_CLK_CTRL_REG
)
&
(
!
(
iwl_read_prph
(
trans
,
APMG_CLK_CTRL_REG
)
&
APMS_CLK_VAL_MRB_FUNC_MODE
)
||
(
iwl_read_prph
(
bus
(
trans
)
,
APMG_PS_CTRL_REG
)
&
(
iwl_read_prph
(
trans
,
APMG_PS_CTRL_REG
)
&
APMG_PS_CTRL_VAL_RESET_REQ
)))
{
/*
* Keep the restart process from trying to send host
...
...
@@ -741,18 +745,18 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
ptr
=
base
+
EVENT_START_OFFSET
+
(
start_idx
*
event_size
);
/* Make sure device is powered up for SRAM reads */
spin_lock_irqsave
(
&
bus
(
trans
)
->
reg_lock
,
reg_flags
);
iwl_grab_nic_access
(
bus
(
trans
)
);
spin_lock_irqsave
(
&
trans
->
reg_lock
,
reg_flags
);
iwl_grab_nic_access
(
trans
);
/* Set starting address; reads will auto-increment */
iwl_write32
(
bus
(
trans
)
,
HBUS_TARG_MEM_RADDR
,
ptr
);
iwl_write32
(
trans
,
HBUS_TARG_MEM_RADDR
,
ptr
);
rmb
();
/* "time" is actually "data" for mode 0 (no timestamp).
* place event id # at far right for easier visual parsing. */
for
(
i
=
0
;
i
<
num_events
;
i
++
)
{
ev
=
iwl_read32
(
bus
(
trans
)
,
HBUS_TARG_MEM_RDAT
);
time
=
iwl_read32
(
bus
(
trans
)
,
HBUS_TARG_MEM_RDAT
);
ev
=
iwl_read32
(
trans
,
HBUS_TARG_MEM_RDAT
);
time
=
iwl_read32
(
trans
,
HBUS_TARG_MEM_RDAT
);
if
(
mode
==
0
)
{
/* data, ev */
if
(
bufsz
)
{
...
...
@@ -766,7 +770,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
time
,
ev
);
}
}
else
{
data
=
iwl_read32
(
bus
(
trans
)
,
HBUS_TARG_MEM_RDAT
);
data
=
iwl_read32
(
trans
,
HBUS_TARG_MEM_RDAT
);
if
(
bufsz
)
{
pos
+=
scnprintf
(
*
buf
+
pos
,
bufsz
-
pos
,
"EVT_LOGT:%010u:0x%08x:%04u
\n
"
,
...
...
@@ -781,8 +785,8 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
}
/* Allow device to power down */
iwl_release_nic_access
(
bus
(
trans
)
);
spin_unlock_irqrestore
(
&
bus
(
trans
)
->
reg_lock
,
reg_flags
);
iwl_release_nic_access
(
trans
);
spin_unlock_irqrestore
(
&
trans
->
reg_lock
,
reg_flags
);
return
pos
;
}
...
...
@@ -859,10 +863,10 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
}
/* event log header */
capacity
=
iwl_read_targ_mem
(
bus
(
trans
)
,
base
);
mode
=
iwl_read_targ_mem
(
bus
(
trans
)
,
base
+
(
1
*
sizeof
(
u32
)));
num_wraps
=
iwl_read_targ_mem
(
bus
(
trans
)
,
base
+
(
2
*
sizeof
(
u32
)));
next_entry
=
iwl_read_targ_mem
(
bus
(
trans
)
,
base
+
(
3
*
sizeof
(
u32
)));
capacity
=
iwl_read_targ_mem
(
trans
,
base
);
mode
=
iwl_read_targ_mem
(
trans
,
base
+
(
1
*
sizeof
(
u32
)));
num_wraps
=
iwl_read_targ_mem
(
trans
,
base
+
(
2
*
sizeof
(
u32
)));
next_entry
=
iwl_read_targ_mem
(
trans
,
base
+
(
3
*
sizeof
(
u32
)));
if
(
capacity
>
logsize
)
{
IWL_ERR
(
trans
,
"Log capacity %d is bogus, limit to %d "
...
...
@@ -958,7 +962,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
* hardware bugs here by ACKing all the possible interrupts so that
* interrupt coalescing can still be achieved.
*/
iwl_write32
(
bus
(
trans
)
,
CSR_INT
,
iwl_write32
(
trans
,
CSR_INT
,
trans_pcie
->
inta
|
~
trans_pcie
->
inta_mask
);
inta
=
trans_pcie
->
inta
;
...
...
@@ -966,7 +970,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
#ifdef CONFIG_IWLWIFI_DEBUG
if
(
iwl_get_debug_level
(
trans
->
shrd
)
&
IWL_DL_ISR
)
{
/* just for debug */
inta_mask
=
iwl_read32
(
bus
(
trans
)
,
CSR_INT_MASK
);
inta_mask
=
iwl_read32
(
trans
,
CSR_INT_MASK
);
IWL_DEBUG_ISR
(
trans
,
"inta 0x%08x, enabled 0x%08x
\n
"
,
inta
,
inta_mask
);
}
...
...
@@ -1014,7 +1018,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
/* HW RF KILL switch toggled */
if
(
inta
&
CSR_INT_BIT_RF_KILL
)
{
int
hw_rf_kill
=
0
;
if
(
!
(
iwl_read32
(
bus
(
trans
)
,
CSR_GP_CNTRL
)
&
if
(
!
(
iwl_read32
(
trans
,
CSR_GP_CNTRL
)
&
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW
))
hw_rf_kill
=
1
;
...
...
@@ -1078,12 +1082,12 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
IWL_DEBUG_ISR
(
trans
,
"Rx interrupt
\n
"
);
if
(
inta
&
(
CSR_INT_BIT_FH_RX
|
CSR_INT_BIT_SW_RX
))
{
handled
|=
(
CSR_INT_BIT_FH_RX
|
CSR_INT_BIT_SW_RX
);
iwl_write32
(
bus
(
trans
)
,
CSR_FH_INT_STATUS
,
iwl_write32
(
trans
,
CSR_FH_INT_STATUS
,
CSR_FH_INT_RX_MASK
);
}
if
(
inta
&
CSR_INT_BIT_RX_PERIODIC
)
{
handled
|=
CSR_INT_BIT_RX_PERIODIC
;
iwl_write32
(
bus
(
trans
)
,
iwl_write32
(
trans
,
CSR_INT
,
CSR_INT_BIT_RX_PERIODIC
);
}
/* Sending RX interrupt require many steps to be done in the
...
...
@@ -1098,10 +1102,13 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
*/
/* Disable periodic interrupt; we use it as just a one-shot. */
iwl_write8
(
bus
(
trans
)
,
CSR_INT_PERIODIC_REG
,
iwl_write8
(
trans
,
CSR_INT_PERIODIC_REG
,
CSR_INT_PERIODIC_DIS
);
#ifdef CONFIG_IWLWIFI_IDI
iwl_amfh_rx_handler
();
#else
iwl_rx_handle
(
trans
);
#endif
/*
* Enable periodic interrupt in 8 msec only if we received
* real RX interrupt (instead of just periodic int), to catch
...
...
@@ -1110,7 +1117,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
* to extend the periodic interrupt; one-shot is enough.
*/
if
(
inta
&
(
CSR_INT_BIT_FH_RX
|
CSR_INT_BIT_SW_RX
))
iwl_write8
(
bus
(
trans
)
,
CSR_INT_PERIODIC_REG
,
iwl_write8
(
trans
,
CSR_INT_PERIODIC_REG
,
CSR_INT_PERIODIC_ENA
);
isr_stats
->
rx
++
;
...
...
@@ -1118,7 +1125,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
/* This "Tx" DMA channel is used only for loading uCode */
if
(
inta
&
CSR_INT_BIT_FH_TX
)
{
iwl_write32
(
bus
(
trans
)
,
CSR_FH_INT_STATUS
,
CSR_FH_INT_TX_MASK
);
iwl_write32
(
trans
,
CSR_FH_INT_STATUS
,
CSR_FH_INT_TX_MASK
);
IWL_DEBUG_ISR
(
trans
,
"uCode load interrupt
\n
"
);
isr_stats
->
tx
++
;
handled
|=
CSR_INT_BIT_FH_TX
;
...
...
@@ -1142,8 +1149,10 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans
->
shrd
->
status
))
iwl_enable_interrupts
(
trans
);
/* Re-enable RF_KILL if it occurred */
else
if
(
handled
&
CSR_INT_BIT_RF_KILL
)
iwl_enable_rfkill_int
(
priv
(
trans
));
else
if
(
handled
&
CSR_INT_BIT_RF_KILL
)
{
IWL_DEBUG_ISR
(
trans
,
"Enabling rfkill interrupt
\n
"
);
iwl_write32
(
trans
,
CSR_INT_MASK
,
CSR_INT_BIT_RF_KILL
);
}
}
/******************************************************************************
...
...
@@ -1164,7 +1173,7 @@ void iwl_free_isr_ict(struct iwl_trans *trans)
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
if
(
trans_pcie
->
ict_tbl
)
{
dma_free_coherent
(
bus
(
trans
)
->
dev
,
ICT_SIZE
,
dma_free_coherent
(
trans
->
dev
,
ICT_SIZE
,
trans_pcie
->
ict_tbl
,
trans_pcie
->
ict_tbl_dma
);
trans_pcie
->
ict_tbl
=
NULL
;
...
...
@@ -1184,7 +1193,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
trans_pcie
->
ict_tbl
=
dma_alloc_coherent
(
bus
(
trans
)
->
dev
,
ICT_SIZE
,
dma_alloc_coherent
(
trans
->
dev
,
ICT_SIZE
,
&
trans_pcie
->
ict_tbl_dma
,
GFP_KERNEL
);
if
(
!
trans_pcie
->
ict_tbl
)
...
...
@@ -1213,7 +1222,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
/* Device is going up inform it about using ICT interrupt table,
* also we need to tell the driver to start using ICT interrupt.
*/
int
iwl_reset_ict
(
struct
iwl_trans
*
trans
)
void
iwl_reset_ict
(
struct
iwl_trans
*
trans
)
{
u32
val
;
unsigned
long
flags
;
...
...
@@ -1221,7 +1230,7 @@ int iwl_reset_ict(struct iwl_trans *trans)
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
if
(
!
trans_pcie
->
ict_tbl
)
return
0
;
return
;
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
iwl_disable_interrupts
(
trans
);
...
...
@@ -1235,14 +1244,12 @@ int iwl_reset_ict(struct iwl_trans *trans)
IWL_DEBUG_ISR
(
trans
,
"CSR_DRAM_INT_TBL_REG =0x%x
\n
"
,
val
);
iwl_write32
(
bus
(
trans
)
,
CSR_DRAM_INT_TBL_REG
,
val
);
iwl_write32
(
trans
,
CSR_DRAM_INT_TBL_REG
,
val
);
trans_pcie
->
use_ict
=
true
;
trans_pcie
->
ict_index
=
0
;
iwl_write32
(
bus
(
trans
)
,
CSR_INT
,
trans_pcie
->
inta_mask
);
iwl_write32
(
trans
,
CSR_INT
,
trans_pcie
->
inta_mask
);
iwl_enable_interrupts
(
trans
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
return
0
;
}
/* Device is going down disable ict interrupt usage */
...
...
@@ -1280,11 +1287,11 @@ static irqreturn_t iwl_isr(int irq, void *data)
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here. */
inta_mask
=
iwl_read32
(
bus
(
trans
)
,
CSR_INT_MASK
);
/* just for debug */
iwl_write32
(
bus
(
trans
)
,
CSR_INT_MASK
,
0x00000000
);
inta_mask
=
iwl_read32
(
trans
,
CSR_INT_MASK
);
/* just for debug */
iwl_write32
(
trans
,
CSR_INT_MASK
,
0x00000000
);
/* Discover which interrupts are active/pending */
inta
=
iwl_read32
(
bus
(
trans
)
,
CSR_INT
);
inta
=
iwl_read32
(
trans
,
CSR_INT
);
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
...
...
@@ -1303,7 +1310,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
#ifdef CONFIG_IWLWIFI_DEBUG
if
(
iwl_get_debug_level
(
trans
->
shrd
)
&
(
IWL_DL_ISR
))
{
inta_fh
=
iwl_read32
(
bus
(
trans
)
,
CSR_FH_INT_STATUS
);
inta_fh
=
iwl_read32
(
trans
,
CSR_FH_INT_STATUS
);
IWL_DEBUG_ISR
(
trans
,
"ISR inta 0x%08x, enabled 0x%08x, "
"fh 0x%08x
\n
"
,
inta
,
inta_mask
,
inta_fh
);
}
...
...
@@ -1369,8 +1376,8 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here.
*/
inta_mask
=
iwl_read32
(
bus
(
trans
)
,
CSR_INT_MASK
);
/* just for debug */
iwl_write32
(
bus
(
trans
)
,
CSR_INT_MASK
,
0x00000000
);
inta_mask
=
iwl_read32
(
trans
,
CSR_INT_MASK
);
/* just for debug */
iwl_write32
(
trans
,
CSR_INT_MASK
,
0x00000000
);
/* Ignore interrupt if there's nothing in NIC to service.
...
...
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
View file @
8f0bb5ae
...
...
@@ -100,7 +100,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
if
(
hw_params
(
trans
).
shadow_reg_enable
)
{
/* shadow register enabled */
iwl_write32
(
bus
(
trans
)
,
HBUS_TARG_WRPTR
,
iwl_write32
(
trans
,
HBUS_TARG_WRPTR
,
txq
->
q
.
write_ptr
|
(
txq_id
<<
8
));
}
else
{
/* if we're trying to save power */
...
...
@@ -108,18 +108,18 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
/* wake up nic if it's powered down ...
* uCode will wake up, and interrupt us again, so next
* time we'll skip this part. */
reg
=
iwl_read32
(
bus
(
trans
)
,
CSR_UCODE_DRV_GP1
);
reg
=
iwl_read32
(
trans
,
CSR_UCODE_DRV_GP1
);
if
(
reg
&
CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP
)
{
IWL_DEBUG_INFO
(
trans
,
"Tx queue %d requesting wakeup,"
" GP1 = 0x%x
\n
"
,
txq_id
,
reg
);
iwl_set_bit
(
bus
(
trans
)
,
CSR_GP_CNTRL
,
iwl_set_bit
(
trans
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
return
;
}
iwl_write_direct32
(
bus
(
trans
)
,
HBUS_TARG_WRPTR
,
iwl_write_direct32
(
trans
,
HBUS_TARG_WRPTR
,
txq
->
q
.
write_ptr
|
(
txq_id
<<
8
));
/*
...
...
@@ -128,7 +128,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
* trying to tx (during RFKILL, we're not trying to tx).
*/
}
else
iwl_write32
(
bus
(
trans
)
,
HBUS_TARG_WRPTR
,
iwl_write32
(
trans
,
HBUS_TARG_WRPTR
,
txq
->
q
.
write_ptr
|
(
txq_id
<<
8
));
}
txq
->
need_update
=
0
;
...
...
@@ -190,14 +190,14 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
/* Unmap tx_cmd */
if
(
num_tbs
)
dma_unmap_single
(
bus
(
trans
)
->
dev
,
dma_unmap_single
(
trans
->
dev
,
dma_unmap_addr
(
meta
,
mapping
),
dma_unmap_len
(
meta
,
len
),
DMA_BIDIRECTIONAL
);
/* Unmap chunks, if any. */
for
(
i
=
1
;
i
<
num_tbs
;
i
++
)
dma_unmap_single
(
bus
(
trans
)
->
dev
,
iwl_tfd_tb_get_addr
(
tfd
,
i
),
dma_unmap_single
(
trans
->
dev
,
iwl_tfd_tb_get_addr
(
tfd
,
i
),
iwl_tfd_tb_get_len
(
tfd
,
i
),
dma_dir
);
}
...
...
@@ -383,14 +383,14 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid,
tbl_dw_addr
=
trans_pcie
->
scd_base_addr
+
SCD_TRANS_TBL_OFFSET_QUEUE
(
txq_id
);
tbl_dw
=
iwl_read_targ_mem
(
bus
(
trans
)
,
tbl_dw_addr
);
tbl_dw
=
iwl_read_targ_mem
(
trans
,
tbl_dw_addr
);
if
(
txq_id
&
0x1
)
tbl_dw
=
(
scd_q2ratid
<<
16
)
|
(
tbl_dw
&
0x0000FFFF
);
else
tbl_dw
=
scd_q2ratid
|
(
tbl_dw
&
0xFFFF0000
);
iwl_write_targ_mem
(
bus
(
trans
)
,
tbl_dw_addr
,
tbl_dw
);
iwl_write_targ_mem
(
trans
,
tbl_dw_addr
,
tbl_dw
);
return
0
;
}
...
...
@@ -399,7 +399,7 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id)
{
/* Simply stop the queue, but don't change any configuration;
* the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
iwl_write_prph
(
bus
(
trans
)
,
iwl_write_prph
(
trans
,
SCD_QUEUE_STATUS_BITS
(
txq_id
),
(
0
<<
SCD_QUEUE_STTS_REG_POS_ACTIVE
)
|
(
1
<<
SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN
));
...
...
@@ -409,9 +409,9 @@ void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
int
txq_id
,
u32
index
)
{
IWL_DEBUG_TX_QUEUES
(
trans
,
"Q %d WrPtr: %d"
,
txq_id
,
index
&
0xff
);
iwl_write_direct32
(
bus
(
trans
)
,
HBUS_TARG_WRPTR
,
iwl_write_direct32
(
trans
,
HBUS_TARG_WRPTR
,
(
index
&
0xff
)
|
(
txq_id
<<
8
));
iwl_write_prph
(
bus
(
trans
)
,
SCD_QUEUE_RDPTR
(
txq_id
),
index
);
iwl_write_prph
(
trans
,
SCD_QUEUE_RDPTR
(
txq_id
),
index
);
}
void
iwl_trans_tx_queue_set_status
(
struct
iwl_trans
*
trans
,
...
...
@@ -423,7 +423,7 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
int
active
=
test_bit
(
txq_id
,
&
trans_pcie
->
txq_ctx_active_msk
)
?
1
:
0
;
iwl_write_prph
(
bus
(
trans
)
,
SCD_QUEUE_STATUS_BITS
(
txq_id
),
iwl_write_prph
(
trans
,
SCD_QUEUE_STATUS_BITS
(
txq_id
),
(
active
<<
SCD_QUEUE_STTS_REG_POS_ACTIVE
)
|
(
tx_fifo_id
<<
SCD_QUEUE_STTS_REG_POS_TXF
)
|
(
1
<<
SCD_QUEUE_STTS_REG_POS_WSL
)
|
...
...
@@ -431,9 +431,12 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
txq
->
sched_retry
=
scd_retry
;
IWL_DEBUG_TX_QUEUES
(
trans
,
"%s %s Queue %d on FIFO %d
\n
"
,
active
?
"Activate"
:
"Deactivate
"
,
if
(
active
)
IWL_DEBUG_TX_QUEUES
(
trans
,
"Activate %s Queue %d on FIFO %d
\n
"
,
scd_retry
?
"BA"
:
"AC/CMD"
,
txq_id
,
tx_fifo_id
);
else
IWL_DEBUG_TX_QUEUES
(
trans
,
"Deactivate %s Queue %d
\n
"
,
scd_retry
?
"BA"
:
"AC/CMD"
,
txq_id
);
}
static
inline
int
get_fifo_from_tid
(
struct
iwl_trans_pcie
*
trans_pcie
,
...
...
@@ -498,10 +501,10 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
iwlagn_tx_queue_set_q2ratid
(
trans
,
ra_tid
,
txq_id
);
/* Set this queue as a chain-building queue */
iwl_set_bits_prph
(
bus
(
trans
)
,
SCD_QUEUECHAIN_SEL
,
(
1
<<
txq_id
));
iwl_set_bits_prph
(
trans
,
SCD_QUEUECHAIN_SEL
,
(
1
<<
txq_id
));
/* enable aggregations for the queue */
iwl_set_bits_prph
(
bus
(
trans
)
,
SCD_AGGR_SEL
,
(
1
<<
txq_id
));
iwl_set_bits_prph
(
trans
,
SCD_AGGR_SEL
,
(
1
<<
txq_id
));
/* Place first TFD at index corresponding to start sequence number.
* Assumes that ssn_idx is valid (!= 0xFFF) */
...
...
@@ -510,7 +513,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
iwl_trans_set_wr_ptrs
(
trans
,
txq_id
,
ssn
);
/* Set up Tx window size and frame limit for this queue */
iwl_write_targ_mem
(
bus
(
trans
)
,
trans_pcie
->
scd_base_addr
+
iwl_write_targ_mem
(
trans
,
trans_pcie
->
scd_base_addr
+
SCD_CONTEXT_QUEUE_OFFSET
(
txq_id
)
+
sizeof
(
u32
),
((
frame_limit
<<
...
...
@@ -520,7 +523,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS
)
&
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK
));
iwl_set_bits_prph
(
bus
(
trans
)
,
SCD_INTERRUPT_MASK
,
(
1
<<
txq_id
));
iwl_set_bits_prph
(
trans
,
SCD_INTERRUPT_MASK
,
(
1
<<
txq_id
));
/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
iwl_trans_tx_queue_set_status
(
trans
,
&
trans_pcie
->
txq
[
txq_id
],
...
...
@@ -584,7 +587,7 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid)
iwlagn_tx_queue_stop_scheduler
(
trans
,
txq_id
);
iwl_clear_bits_prph
(
bus
(
trans
)
,
SCD_AGGR_SEL
,
(
1
<<
txq_id
));
iwl_clear_bits_prph
(
trans
,
SCD_AGGR_SEL
,
(
1
<<
txq_id
));
trans_pcie
->
agg_txq
[
sta_id
][
tid
]
=
0
;
trans_pcie
->
txq
[
txq_id
].
q
.
read_ptr
=
0
;
...
...
@@ -592,7 +595,7 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid)
/* supposes that ssn_idx is valid (!= 0xFFF) */
iwl_trans_set_wr_ptrs
(
trans
,
txq_id
,
0
);
iwl_clear_bits_prph
(
bus
(
trans
)
,
SCD_INTERRUPT_MASK
,
(
1
<<
txq_id
));
iwl_clear_bits_prph
(
trans
,
SCD_INTERRUPT_MASK
,
(
1
<<
txq_id
));
iwl_txq_ctx_deactivate
(
trans_pcie
,
txq_id
);
iwl_trans_tx_queue_set_status
(
trans
,
&
trans_pcie
->
txq
[
txq_id
],
0
,
0
);
return
0
;
...
...
@@ -725,9 +728,9 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
le16_to_cpu
(
out_cmd
->
hdr
.
sequence
),
cmd_size
,
q
->
write_ptr
,
idx
,
trans
->
shrd
->
cmd_queue
);
phys_addr
=
dma_map_single
(
bus
(
trans
)
->
dev
,
&
out_cmd
->
hdr
,
copy_size
,
phys_addr
=
dma_map_single
(
trans
->
dev
,
&
out_cmd
->
hdr
,
copy_size
,
DMA_BIDIRECTIONAL
);
if
(
unlikely
(
dma_mapping_error
(
bus
(
trans
)
->
dev
,
phys_addr
)))
{
if
(
unlikely
(
dma_mapping_error
(
trans
->
dev
,
phys_addr
)))
{
idx
=
-
ENOMEM
;
goto
out
;
}
...
...
@@ -748,10 +751,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
continue
;
if
(
!
(
cmd
->
dataflags
[
i
]
&
IWL_HCMD_DFL_NOCOPY
))
continue
;
phys_addr
=
dma_map_single
(
bus
(
trans
)
->
dev
,
phys_addr
=
dma_map_single
(
trans
->
dev
,
(
void
*
)
cmd
->
data
[
i
],
cmd
->
len
[
i
],
DMA_BIDIRECTIONAL
);
if
(
dma_mapping_error
(
bus
(
trans
)
->
dev
,
phys_addr
))
{
if
(
dma_mapping_error
(
trans
->
dev
,
phys_addr
))
{
iwlagn_unmap_tfd
(
trans
,
out_meta
,
&
txq
->
tfds
[
q
->
write_ptr
],
DMA_BIDIRECTIONAL
);
...
...
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
View file @
8f0bb5ae
...
...
@@ -60,8 +60,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <linux/pci.h>
#include <linux/pci-aspm.h>
#include <linux/interrupt.h>
#include <linux/debugfs.h>
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/gfp.h>
...
...
@@ -72,13 +75,14 @@
#include "iwl-shared.h"
#include "iwl-eeprom.h"
#include "iwl-agn-hw.h"
#include "iwl-core.h"
static
int
iwl_trans_rx_alloc
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
struct
iwl_rx_queue
*
rxq
=
&
trans_pcie
->
rxq
;
struct
device
*
dev
=
bus
(
trans
)
->
dev
;
struct
device
*
dev
=
trans
->
dev
;
memset
(
&
trans_pcie
->
rxq
,
0
,
sizeof
(
trans_pcie
->
rxq
));
...
...
@@ -122,7 +126,7 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans)
/* In the reset function, these buffers may have been allocated
* to an SKB, so we need to unmap and free potential storage */
if
(
rxq
->
pool
[
i
].
page
!=
NULL
)
{
dma_unmap_page
(
bus
(
trans
)
->
dev
,
rxq
->
pool
[
i
].
page_dma
,
dma_unmap_page
(
trans
->
dev
,
rxq
->
pool
[
i
].
page_dma
,
PAGE_SIZE
<<
hw_params
(
trans
).
rx_page_order
,
DMA_FROM_DEVICE
);
__free_pages
(
rxq
->
pool
[
i
].
page
,
...
...
@@ -146,17 +150,17 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
rb_size
=
FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K
;
/* Stop Rx DMA */
iwl_write_direct32
(
bus
(
trans
)
,
FH_MEM_RCSR_CHNL0_CONFIG_REG
,
0
);
iwl_write_direct32
(
trans
,
FH_MEM_RCSR_CHNL0_CONFIG_REG
,
0
);
/* Reset driver's Rx queue write index */
iwl_write_direct32
(
bus
(
trans
)
,
FH_RSCSR_CHNL0_RBDCB_WPTR_REG
,
0
);
iwl_write_direct32
(
trans
,
FH_RSCSR_CHNL0_RBDCB_WPTR_REG
,
0
);
/* Tell device where to find RBD circular buffer in DRAM */
iwl_write_direct32
(
bus
(
trans
)
,
FH_RSCSR_CHNL0_RBDCB_BASE_REG
,
iwl_write_direct32
(
trans
,
FH_RSCSR_CHNL0_RBDCB_BASE_REG
,
(
u32
)(
rxq
->
bd_dma
>>
8
));
/* Tell device where in DRAM to update its Rx status */
iwl_write_direct32
(
bus
(
trans
)
,
FH_RSCSR_CHNL0_STTS_WPTR_REG
,
iwl_write_direct32
(
trans
,
FH_RSCSR_CHNL0_STTS_WPTR_REG
,
rxq
->
rb_stts_dma
>>
4
);
/* Enable Rx DMA
...
...
@@ -167,7 +171,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
* RB timeout 0x10
* 256 RBDs
*/
iwl_write_direct32
(
bus
(
trans
)
,
FH_MEM_RCSR_CHNL0_CONFIG_REG
,
iwl_write_direct32
(
trans
,
FH_MEM_RCSR_CHNL0_CONFIG_REG
,
FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL
|
FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY
|
FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL
|
...
...
@@ -177,7 +181,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
(
rfdnlog
<<
FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS
));
/* Set interrupt coalescing timer to default (2048 usecs) */
iwl_write8
(
bus
(
trans
)
,
CSR_INT_COALESCING
,
IWL_HOST_INT_TIMEOUT_DEF
);
iwl_write8
(
trans
,
CSR_INT_COALESCING
,
IWL_HOST_INT_TIMEOUT_DEF
);
}
static
int
iwl_rx_init
(
struct
iwl_trans
*
trans
)
...
...
@@ -242,13 +246,13 @@ static void iwl_trans_pcie_rx_free(struct iwl_trans *trans)
iwl_trans_rxq_free_rx_bufs
(
trans
);
spin_unlock_irqrestore
(
&
rxq
->
lock
,
flags
);
dma_free_coherent
(
bus
(
trans
)
->
dev
,
sizeof
(
__le32
)
*
RX_QUEUE_SIZE
,
dma_free_coherent
(
trans
->
dev
,
sizeof
(
__le32
)
*
RX_QUEUE_SIZE
,
rxq
->
bd
,
rxq
->
bd_dma
);
memset
(
&
rxq
->
bd_dma
,
0
,
sizeof
(
rxq
->
bd_dma
));
rxq
->
bd
=
NULL
;
if
(
rxq
->
rb_stts
)
dma_free_coherent
(
bus
(
trans
)
->
dev
,
dma_free_coherent
(
trans
->
dev
,
sizeof
(
struct
iwl_rb_status
),
rxq
->
rb_stts
,
rxq
->
rb_stts_dma
);
else
...
...
@@ -261,8 +265,8 @@ static int iwl_trans_rx_stop(struct iwl_trans *trans)
{
/* stop Rx DMA */
iwl_write_direct32
(
bus
(
trans
)
,
FH_MEM_RCSR_CHNL0_CONFIG_REG
,
0
);
return
iwl_poll_direct_bit
(
bus
(
trans
)
,
FH_MEM_RSSR_RX_STATUS_REG
,
iwl_write_direct32
(
trans
,
FH_MEM_RCSR_CHNL0_CONFIG_REG
,
0
);
return
iwl_poll_direct_bit
(
trans
,
FH_MEM_RSSR_RX_STATUS_REG
,
FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE
,
1000
);
}
...
...
@@ -272,7 +276,7 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans,
if
(
WARN_ON
(
ptr
->
addr
))
return
-
EINVAL
;
ptr
->
addr
=
dma_alloc_coherent
(
bus
(
trans
)
->
dev
,
size
,
ptr
->
addr
=
dma_alloc_coherent
(
trans
->
dev
,
size
,
&
ptr
->
dma
,
GFP_KERNEL
);
if
(
!
ptr
->
addr
)
return
-
ENOMEM
;
...
...
@@ -286,7 +290,7 @@ static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans,
if
(
unlikely
(
!
ptr
->
addr
))
return
;
dma_free_coherent
(
bus
(
trans
)
->
dev
,
ptr
->
size
,
ptr
->
addr
,
ptr
->
dma
);
dma_free_coherent
(
trans
->
dev
,
ptr
->
size
,
ptr
->
addr
,
ptr
->
dma
);
memset
(
ptr
,
0
,
sizeof
(
*
ptr
));
}
...
...
@@ -333,7 +337,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
/* Circular buffer of transmit frame descriptors (TFDs),
* shared with device */
txq
->
tfds
=
dma_alloc_coherent
(
bus
(
trans
)
->
dev
,
tfd_sz
,
txq
->
tfds
=
dma_alloc_coherent
(
trans
->
dev
,
tfd_sz
,
&
txq
->
q
.
dma_addr
,
GFP_KERNEL
);
if
(
!
txq
->
tfds
)
{
IWL_ERR
(
trans
,
"dma_alloc_coherent(%zd) failed
\n
"
,
tfd_sz
);
...
...
@@ -389,7 +393,7 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq,
* Tell nic where to find circular buffer of Tx Frame Descriptors for
* given Tx queue, and enable the DMA channel used for that queue.
* Circular buffer (TFD queue in DRAM) physical base address */
iwl_write_direct32
(
bus
(
trans
)
,
FH_MEM_CBBC_QUEUE
(
txq_id
),
iwl_write_direct32
(
trans
,
FH_MEM_CBBC_QUEUE
(
txq_id
),
txq
->
q
.
dma_addr
>>
8
);
return
0
;
...
...
@@ -443,7 +447,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
struct
iwl_tx_queue
*
txq
=
&
trans_pcie
->
txq
[
txq_id
];
struct
device
*
dev
=
bus
(
trans
)
->
dev
;
struct
device
*
dev
=
trans
->
dev
;
int
i
;
if
(
WARN_ON
(
!
txq
))
return
;
...
...
@@ -584,10 +588,10 @@ static int iwl_tx_init(struct iwl_trans *trans)
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
/* Turn off all Tx DMA fifos */
iwl_write_prph
(
bus
(
trans
)
,
SCD_TXFACT
,
0
);
iwl_write_prph
(
trans
,
SCD_TXFACT
,
0
);
/* Tell NIC where to find the "keep warm" buffer */
iwl_write_direct32
(
bus
(
trans
)
,
FH_KW_MEM_ADDR_REG
,
iwl_write_direct32
(
trans
,
FH_KW_MEM_ADDR_REG
,
trans_pcie
->
kw
.
dma
>>
4
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
...
...
@@ -619,26 +623,194 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans)
* to set power to V_AUX, do:
if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
iwl_set_bits_mask_prph(
bus(trans)
, APMG_PS_CTRL_REG,
iwl_set_bits_mask_prph(
trans
, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
~APMG_PS_CTRL_MSK_PWR_SRC);
*/
iwl_set_bits_mask_prph
(
bus
(
trans
)
,
APMG_PS_CTRL_REG
,
iwl_set_bits_mask_prph
(
trans
,
APMG_PS_CTRL_REG
,
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN
,
~
APMG_PS_CTRL_MSK_PWR_SRC
);
}
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041
#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
static
u16
iwl_pciexp_link_ctrl
(
struct
iwl_trans
*
trans
)
{
int
pos
;
u16
pci_lnk_ctl
;
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
struct
pci_dev
*
pci_dev
=
trans_pcie
->
pci_dev
;
pos
=
pci_pcie_cap
(
pci_dev
);
pci_read_config_word
(
pci_dev
,
pos
+
PCI_EXP_LNKCTL
,
&
pci_lnk_ctl
);
return
pci_lnk_ctl
;
}
static
void
iwl_apm_config
(
struct
iwl_trans
*
trans
)
{
/*
* HW bug W/A for instability in PCIe bus L0S->L1 transition.
* Check if BIOS (or OS) enabled L1-ASPM on this device.
* If so (likely), disable L0S, so device moves directly L0->L1;
* costs negligible amount of power savings.
* If not (unlikely), enable L0S, so there is at least some
* power savings, even without L1.
*/
u16
lctl
=
iwl_pciexp_link_ctrl
(
trans
);
if
((
lctl
&
PCI_CFG_LINK_CTRL_VAL_L1_EN
)
==
PCI_CFG_LINK_CTRL_VAL_L1_EN
)
{
/* L1-ASPM enabled; disable(!) L0S */
iwl_set_bit
(
trans
,
CSR_GIO_REG
,
CSR_GIO_REG_VAL_L0S_ENABLED
);
dev_printk
(
KERN_INFO
,
trans
->
dev
,
"L1 Enabled; Disabling L0S
\n
"
);
}
else
{
/* L1-ASPM disabled; enable(!) L0S */
iwl_clear_bit
(
trans
,
CSR_GIO_REG
,
CSR_GIO_REG_VAL_L0S_ENABLED
);
dev_printk
(
KERN_INFO
,
trans
->
dev
,
"L1 Disabled; Enabling L0S
\n
"
);
}
trans
->
pm_support
=
!
(
lctl
&
PCI_CFG_LINK_CTRL_VAL_L0S_EN
);
}
/*
* Start up NIC's basic functionality after it has been reset
* (e.g. after platform boot, or shutdown via iwl_apm_stop())
* NOTE: This does not load uCode nor start the embedded processor
*/
static
int
iwl_apm_init
(
struct
iwl_trans
*
trans
)
{
int
ret
=
0
;
IWL_DEBUG_INFO
(
trans
,
"Init card's basic functions
\n
"
);
/*
* Use "set_bit" below rather than "write", to preserve any hardware
* bits already set by default after reset.
*/
/* Disable L0S exit timer (platform NMI Work/Around) */
iwl_set_bit
(
trans
,
CSR_GIO_CHICKEN_BITS
,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER
);
/*
* Disable L0s without affecting L1;
* don't wait for ICH L0s (ICH bug W/A)
*/
iwl_set_bit
(
trans
,
CSR_GIO_CHICKEN_BITS
,
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX
);
/* Set FH wait threshold to maximum (HW error during stress W/A) */
iwl_set_bit
(
trans
,
CSR_DBG_HPET_MEM_REG
,
CSR_DBG_HPET_MEM_REG_VAL
);
/*
* Enable HAP INTA (interrupt from management bus) to
* wake device's PCI Express link L1a -> L0s
*/
iwl_set_bit
(
trans
,
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A
);
iwl_apm_config
(
trans
);
/* Configure analog phase-lock-loop before activating to D0A */
if
(
cfg
(
trans
)
->
base_params
->
pll_cfg_val
)
iwl_set_bit
(
trans
,
CSR_ANA_PLL_CFG
,
cfg
(
trans
)
->
base_params
->
pll_cfg_val
);
/*
* Set "initialization complete" bit to move adapter from
* D0U* --> D0A* (powered-up active) state.
*/
iwl_set_bit
(
trans
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_INIT_DONE
);
/*
* Wait for clock stabilization; once stabilized, access to
* device-internal resources is supported, e.g. iwl_write_prph()
* and accesses to uCode SRAM.
*/
ret
=
iwl_poll_bit
(
trans
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
,
25000
);
if
(
ret
<
0
)
{
IWL_DEBUG_INFO
(
trans
,
"Failed to init the card
\n
"
);
goto
out
;
}
/*
* Enable DMA clock and wait for it to stabilize.
*
* Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
* do not disable clocks. This preserves any hardware bits already
* set by default in "CLK_CTRL_REG" after reset.
*/
iwl_write_prph
(
trans
,
APMG_CLK_EN_REG
,
APMG_CLK_VAL_DMA_CLK_RQT
);
udelay
(
20
);
/* Disable L1-Active */
iwl_set_bits_prph
(
trans
,
APMG_PCIDEV_STT_REG
,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS
);
set_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
shrd
->
status
);
out:
return
ret
;
}
static
int
iwl_apm_stop_master
(
struct
iwl_trans
*
trans
)
{
int
ret
=
0
;
/* stop device's busmaster DMA activity */
iwl_set_bit
(
trans
,
CSR_RESET
,
CSR_RESET_REG_FLAG_STOP_MASTER
);
ret
=
iwl_poll_bit
(
trans
,
CSR_RESET
,
CSR_RESET_REG_FLAG_MASTER_DISABLED
,
CSR_RESET_REG_FLAG_MASTER_DISABLED
,
100
);
if
(
ret
)
IWL_WARN
(
trans
,
"Master Disable Timed Out, 100 usec
\n
"
);
IWL_DEBUG_INFO
(
trans
,
"stop master
\n
"
);
return
ret
;
}
static
void
iwl_apm_stop
(
struct
iwl_trans
*
trans
)
{
IWL_DEBUG_INFO
(
trans
,
"Stop card, put in low power state
\n
"
);
clear_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
shrd
->
status
);
/* Stop device's DMA activity */
iwl_apm_stop_master
(
trans
);
/* Reset the entire device */
iwl_set_bit
(
trans
,
CSR_RESET
,
CSR_RESET_REG_FLAG_SW_RESET
);
udelay
(
10
);
/*
* Clear "initialization complete" bit to move adapter from
* D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/
iwl_clear_bit
(
trans
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_INIT_DONE
);
}
static
int
iwl_nic_init
(
struct
iwl_trans
*
trans
)
{
unsigned
long
flags
;
/* nic_init */
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
iwl_apm_init
(
priv
(
trans
)
);
iwl_apm_init
(
trans
);
/* Set interrupt coalescing calibration timer to default (512 usecs) */
iwl_write8
(
bus
(
trans
)
,
CSR_INT_COALESCING
,
iwl_write8
(
trans
,
CSR_INT_COALESCING
,
IWL_HOST_INT_CALIB_TIMEOUT_DEF
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
...
...
@@ -647,8 +819,10 @@ static int iwl_nic_init(struct iwl_trans *trans)
iwl_nic_config
(
priv
(
trans
));
#ifndef CONFIG_IWLWIFI_IDI
/* Allocate the RX queue, or reset if it is already allocated */
iwl_rx_init
(
trans
);
#endif
/* Allocate or reset and init all Tx and Command queues */
if
(
iwl_tx_init
(
trans
))
...
...
@@ -656,7 +830,7 @@ static int iwl_nic_init(struct iwl_trans *trans)
if
(
hw_params
(
trans
).
shadow_reg_enable
)
{
/* enable shadow regs in HW */
iwl_set_bit
(
bus
(
trans
)
,
CSR_MAC_SHADOW_REG_CTRL
,
iwl_set_bit
(
trans
,
CSR_MAC_SHADOW_REG_CTRL
,
0x800FFFFF
);
}
...
...
@@ -672,11 +846,11 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
{
int
ret
;
iwl_set_bit
(
bus
(
trans
)
,
CSR_HW_IF_CONFIG_REG
,
iwl_set_bit
(
trans
,
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY
);
/* See if we got it */
ret
=
iwl_poll_bit
(
bus
(
trans
)
,
CSR_HW_IF_CONFIG_REG
,
ret
=
iwl_poll_bit
(
trans
,
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY
,
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY
,
HW_READY_TIMEOUT
);
...
...
@@ -686,21 +860,22 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
}
/* Note: returns standard 0/-ERROR code */
static
int
iwl_
trans_pcie_
prepare_card_hw
(
struct
iwl_trans
*
trans
)
static
int
iwl_prepare_card_hw
(
struct
iwl_trans
*
trans
)
{
int
ret
;
IWL_DEBUG_INFO
(
trans
,
"iwl_trans_prepare_card_hw enter
\n
"
);
ret
=
iwl_set_hw_ready
(
trans
);
/* If the card is ready, exit 0 */
if
(
ret
>=
0
)
return
0
;
/* If HW is not ready, prepare the conditions to check again */
iwl_set_bit
(
bus
(
trans
)
,
CSR_HW_IF_CONFIG_REG
,
iwl_set_bit
(
trans
,
CSR_HW_IF_CONFIG_REG
,
CSR_HW_IF_CONFIG_REG_PREPARE
);
ret
=
iwl_poll_bit
(
bus
(
trans
)
,
CSR_HW_IF_CONFIG_REG
,
ret
=
iwl_poll_bit
(
trans
,
CSR_HW_IF_CONFIG_REG
,
~
CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE
,
CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE
,
150000
);
...
...
@@ -767,7 +942,79 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
7
,
6
,
5
,
4
,
};
static
int
iwl_trans_pcie_start_device
(
struct
iwl_trans
*
trans
)
/*
* ucode
*/
static
int
iwl_load_section
(
struct
iwl_trans
*
trans
,
const
char
*
name
,
struct
fw_desc
*
image
,
u32
dst_addr
)
{
dma_addr_t
phy_addr
=
image
->
p_addr
;
u32
byte_cnt
=
image
->
len
;
int
ret
;
trans
->
ucode_write_complete
=
0
;
iwl_write_direct32
(
trans
,
FH_TCSR_CHNL_TX_CONFIG_REG
(
FH_SRVC_CHNL
),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE
);
iwl_write_direct32
(
trans
,
FH_SRVC_CHNL_SRAM_ADDR_REG
(
FH_SRVC_CHNL
),
dst_addr
);
iwl_write_direct32
(
trans
,
FH_TFDIB_CTRL0_REG
(
FH_SRVC_CHNL
),
phy_addr
&
FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK
);
iwl_write_direct32
(
trans
,
FH_TFDIB_CTRL1_REG
(
FH_SRVC_CHNL
),
(
iwl_get_dma_hi_addr
(
phy_addr
)
<<
FH_MEM_TFDIB_REG1_ADDR_BITSHIFT
)
|
byte_cnt
);
iwl_write_direct32
(
trans
,
FH_TCSR_CHNL_TX_BUF_STS_REG
(
FH_SRVC_CHNL
),
1
<<
FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM
|
1
<<
FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX
|
FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID
);
iwl_write_direct32
(
trans
,
FH_TCSR_CHNL_TX_CONFIG_REG
(
FH_SRVC_CHNL
),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE
|
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE
|
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD
);
IWL_DEBUG_FW
(
trans
,
"%s uCode section being loaded...
\n
"
,
name
);
ret
=
wait_event_timeout
(
trans
->
shrd
->
wait_command_queue
,
trans
->
ucode_write_complete
,
5
*
HZ
);
if
(
!
ret
)
{
IWL_ERR
(
trans
,
"Could not load the %s uCode section
\n
"
,
name
);
return
-
ETIMEDOUT
;
}
return
0
;
}
static
int
iwl_load_given_ucode
(
struct
iwl_trans
*
trans
,
struct
fw_img
*
image
)
{
int
ret
=
0
;
ret
=
iwl_load_section
(
trans
,
"INST"
,
&
image
->
code
,
IWLAGN_RTC_INST_LOWER_BOUND
);
if
(
ret
)
return
ret
;
ret
=
iwl_load_section
(
trans
,
"DATA"
,
&
image
->
data
,
IWLAGN_RTC_DATA_LOWER_BOUND
);
if
(
ret
)
return
ret
;
/* Remove all resets to allow NIC to operate */
iwl_write32
(
trans
,
CSR_RESET
,
0
);
return
0
;
}
static
int
iwl_trans_pcie_start_fw
(
struct
iwl_trans
*
trans
,
struct
fw_img
*
fw
)
{
int
ret
;
struct
iwl_trans_pcie
*
trans_pcie
=
...
...
@@ -784,13 +1031,13 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
trans_pcie
->
mcast_queue
[
IWL_RXON_CTX_PAN
]
=
IWL_IPAN_MCAST_QUEUE
;
if
((
hw_params
(
trans
).
sku
&
EEPROM_SKU_CAP_AMT_ENABLE
)
&&
iwl_
trans_pcie_
prepare_card_hw
(
trans
))
{
iwl_prepare_card_hw
(
trans
))
{
IWL_WARN
(
trans
,
"Exit HW not ready
\n
"
);
return
-
EIO
;
}
/* If platform's RF_KILL switch is NOT set to KILL */
if
(
iwl_read32
(
bus
(
trans
)
,
CSR_GP_CNTRL
)
&
if
(
iwl_read32
(
trans
,
CSR_GP_CNTRL
)
&
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW
)
clear_bit
(
STATUS_RF_KILL_HW
,
&
trans
->
shrd
->
status
);
else
...
...
@@ -802,7 +1049,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
return
-
ERFKILL
;
}
iwl_write32
(
bus
(
trans
)
,
CSR_INT
,
0xFFFFFFFF
);
iwl_write32
(
trans
,
CSR_INT
,
0xFFFFFFFF
);
ret
=
iwl_nic_init
(
trans
);
if
(
ret
)
{
...
...
@@ -811,17 +1058,20 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
}
/* make sure rfkill handshake bits are cleared */
iwl_write32
(
bus
(
trans
)
,
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_SW_BIT_RFKILL
);
iwl_write32
(
bus
(
trans
)
,
CSR_UCODE_DRV_GP1_CLR
,
iwl_write32
(
trans
,
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_SW_BIT_RFKILL
);
iwl_write32
(
trans
,
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED
);
/* clear (again), then enable host interrupts */
iwl_write32
(
bus
(
trans
)
,
CSR_INT
,
0xFFFFFFFF
);
iwl_write32
(
trans
,
CSR_INT
,
0xFFFFFFFF
);
iwl_enable_interrupts
(
trans
);
/* really make sure rfkill handshake bits are cleared */
iwl_write32
(
bus
(
trans
),
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_SW_BIT_RFKILL
);
iwl_write32
(
bus
(
trans
),
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_SW_BIT_RFKILL
);
iwl_write32
(
trans
,
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_SW_BIT_RFKILL
);
iwl_write32
(
trans
,
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_SW_BIT_RFKILL
);
/* Load the given image to the HW */
iwl_load_given_ucode
(
trans
,
fw
);
return
0
;
}
...
...
@@ -832,10 +1082,10 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
*/
static
void
iwl_trans_txq_set_sched
(
struct
iwl_trans
*
trans
,
u32
mask
)
{
iwl_write_prph
(
bus
(
trans
)
,
SCD_TXFACT
,
mask
);
iwl_write_prph
(
trans
,
SCD_TXFACT
,
mask
);
}
static
void
iwl_t
rans_pcie_t
x_start
(
struct
iwl_trans
*
trans
)
static
void
iwl_tx_start
(
struct
iwl_trans
*
trans
)
{
const
struct
queue_to_fifo_ac
*
queue_to_fifo
;
struct
iwl_trans_pcie
*
trans_pcie
=
...
...
@@ -848,46 +1098,46 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
trans_pcie
->
scd_base_addr
=
iwl_read_prph
(
bus
(
trans
)
,
SCD_SRAM_BASE_ADDR
);
iwl_read_prph
(
trans
,
SCD_SRAM_BASE_ADDR
);
a
=
trans_pcie
->
scd_base_addr
+
SCD_CONTEXT_MEM_LOWER_BOUND
;
/* reset conext data memory */
for
(;
a
<
trans_pcie
->
scd_base_addr
+
SCD_CONTEXT_MEM_UPPER_BOUND
;
a
+=
4
)
iwl_write_targ_mem
(
bus
(
trans
)
,
a
,
0
);
iwl_write_targ_mem
(
trans
,
a
,
0
);
/* reset tx status memory */
for
(;
a
<
trans_pcie
->
scd_base_addr
+
SCD_TX_STTS_MEM_UPPER_BOUND
;
a
+=
4
)
iwl_write_targ_mem
(
bus
(
trans
)
,
a
,
0
);
iwl_write_targ_mem
(
trans
,
a
,
0
);
for
(;
a
<
trans_pcie
->
scd_base_addr
+
SCD_TRANS_TBL_OFFSET_QUEUE
(
hw_params
(
trans
).
max_txq_num
);
a
+=
4
)
iwl_write_targ_mem
(
bus
(
trans
)
,
a
,
0
);
iwl_write_targ_mem
(
trans
,
a
,
0
);
iwl_write_prph
(
bus
(
trans
)
,
SCD_DRAM_BASE_ADDR
,
iwl_write_prph
(
trans
,
SCD_DRAM_BASE_ADDR
,
trans_pcie
->
scd_bc_tbls
.
dma
>>
10
);
/* Enable DMA channel */
for
(
chan
=
0
;
chan
<
FH_TCSR_CHNL_NUM
;
chan
++
)
iwl_write_direct32
(
bus
(
trans
)
,
FH_TCSR_CHNL_TX_CONFIG_REG
(
chan
),
iwl_write_direct32
(
trans
,
FH_TCSR_CHNL_TX_CONFIG_REG
(
chan
),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE
|
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE
);
/* Update FH chicken bits */
reg_val
=
iwl_read_direct32
(
bus
(
trans
)
,
FH_TX_CHICKEN_BITS_REG
);
iwl_write_direct32
(
bus
(
trans
)
,
FH_TX_CHICKEN_BITS_REG
,
reg_val
=
iwl_read_direct32
(
trans
,
FH_TX_CHICKEN_BITS_REG
);
iwl_write_direct32
(
trans
,
FH_TX_CHICKEN_BITS_REG
,
reg_val
|
FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN
);
iwl_write_prph
(
bus
(
trans
)
,
SCD_QUEUECHAIN_SEL
,
iwl_write_prph
(
trans
,
SCD_QUEUECHAIN_SEL
,
SCD_QUEUECHAIN_SEL_ALL
(
trans
));
iwl_write_prph
(
bus
(
trans
)
,
SCD_AGGR_SEL
,
0
);
iwl_write_prph
(
trans
,
SCD_AGGR_SEL
,
0
);
/* initiate the queues */
for
(
i
=
0
;
i
<
hw_params
(
trans
).
max_txq_num
;
i
++
)
{
iwl_write_prph
(
bus
(
trans
)
,
SCD_QUEUE_RDPTR
(
i
),
0
);
iwl_write_direct32
(
bus
(
trans
)
,
HBUS_TARG_WRPTR
,
0
|
(
i
<<
8
));
iwl_write_targ_mem
(
bus
(
trans
)
,
trans_pcie
->
scd_base_addr
+
iwl_write_prph
(
trans
,
SCD_QUEUE_RDPTR
(
i
),
0
);
iwl_write_direct32
(
trans
,
HBUS_TARG_WRPTR
,
0
|
(
i
<<
8
));
iwl_write_targ_mem
(
trans
,
trans_pcie
->
scd_base_addr
+
SCD_CONTEXT_QUEUE_OFFSET
(
i
),
0
);
iwl_write_targ_mem
(
bus
(
trans
)
,
trans_pcie
->
scd_base_addr
+
iwl_write_targ_mem
(
trans
,
trans_pcie
->
scd_base_addr
+
SCD_CONTEXT_QUEUE_OFFSET
(
i
)
+
sizeof
(
u32
),
((
SCD_WIN_SIZE
<<
...
...
@@ -898,7 +1148,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK
));
}
iwl_write_prph
(
bus
(
trans
)
,
SCD_INTERRUPT_MASK
,
iwl_write_prph
(
trans
,
SCD_INTERRUPT_MASK
,
IWL_MASK
(
0
,
hw_params
(
trans
).
max_txq_num
));
/* Activate all Tx DMA/FIFO channels */
...
...
@@ -944,10 +1194,16 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
/* Enable L1-Active */
iwl_clear_bits_prph
(
bus
(
trans
)
,
APMG_PCIDEV_STT_REG
,
iwl_clear_bits_prph
(
trans
,
APMG_PCIDEV_STT_REG
,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS
);
}
static
void
iwl_trans_pcie_fw_alive
(
struct
iwl_trans
*
trans
)
{
iwl_reset_ict
(
trans
);
iwl_tx_start
(
trans
);
}
/**
* iwlagn_txq_ctx_stop - Stop all Tx DMA channels
*/
...
...
@@ -964,14 +1220,14 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
/* Stop each Tx DMA channel, and wait for it to be idle */
for
(
ch
=
0
;
ch
<
FH_TCSR_CHNL_NUM
;
ch
++
)
{
iwl_write_direct32
(
bus
(
trans
)
,
iwl_write_direct32
(
trans
,
FH_TCSR_CHNL_TX_CONFIG_REG
(
ch
),
0x0
);
if
(
iwl_poll_direct_bit
(
bus
(
trans
)
,
FH_TSSR_TX_STATUS_REG
,
if
(
iwl_poll_direct_bit
(
trans
,
FH_TSSR_TX_STATUS_REG
,
FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
(
ch
),
1000
))
IWL_ERR
(
trans
,
"Failing on timeout while stopping"
" DMA channel %d [0x%08x]"
,
ch
,
iwl_read_direct32
(
bus
(
trans
)
,
iwl_read_direct32
(
trans
,
FH_TSSR_TX_STATUS_REG
));
}
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
...
...
@@ -1010,20 +1266,21 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
*/
if
(
test_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
shrd
->
status
))
{
iwl_trans_tx_stop
(
trans
);
#ifndef CONFIG_IWLWIFI_IDI
iwl_trans_rx_stop
(
trans
);
#endif
/* Power-down device's busmaster DMA clocks */
iwl_write_prph
(
bus
(
trans
)
,
APMG_CLK_DIS_REG
,
iwl_write_prph
(
trans
,
APMG_CLK_DIS_REG
,
APMG_CLK_VAL_DMA_CLK_RQT
);
udelay
(
5
);
}
/* Make sure (redundant) we've released our request to stay awake */
iwl_clear_bit
(
bus
(
trans
)
,
CSR_GP_CNTRL
,
iwl_clear_bit
(
trans
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
/* Stop the device, and put it in low power state */
iwl_apm_stop
(
priv
(
trans
)
);
iwl_apm_stop
(
trans
);
/* Upon stop, the APM issues an interrupt if HW RF kill is set.
* Clean again the interrupt here
...
...
@@ -1033,11 +1290,11 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
/* wait to make sure we flush pending tasklet*/
synchronize_irq
(
bus
(
trans
)
->
irq
);
synchronize_irq
(
trans
->
irq
);
tasklet_kill
(
&
trans_pcie
->
irq_tasklet
);
/* stop and reset the on-board processor */
iwl_write32
(
bus
(
trans
)
,
CSR_RESET
,
CSR_RESET_REG_FLAG_NEVO_RESET
);
iwl_write32
(
trans
,
CSR_RESET
,
CSR_RESET_REG_FLAG_NEVO_RESET
);
}
static
int
iwl_trans_pcie_tx
(
struct
iwl_trans
*
trans
,
struct
sk_buff
*
skb
,
...
...
@@ -1134,10 +1391,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
/* Physical address of this Tx command's header (not MAC header!),
* within command buffer array. */
txcmd_phys
=
dma_map_single
(
bus
(
trans
)
->
dev
,
txcmd_phys
=
dma_map_single
(
trans
->
dev
,
&
dev_cmd
->
hdr
,
firstlen
,
DMA_BIDIRECTIONAL
);
if
(
unlikely
(
dma_mapping_error
(
bus
(
trans
)
->
dev
,
txcmd_phys
)))
if
(
unlikely
(
dma_mapping_error
(
trans
->
dev
,
txcmd_phys
)))
return
-
1
;
dma_unmap_addr_set
(
out_meta
,
mapping
,
txcmd_phys
);
dma_unmap_len_set
(
out_meta
,
len
,
firstlen
);
...
...
@@ -1153,10 +1410,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
* if any (802.11 null frames have no payload). */
secondlen
=
skb
->
len
-
hdr_len
;
if
(
secondlen
>
0
)
{
phys_addr
=
dma_map_single
(
bus
(
trans
)
->
dev
,
skb
->
data
+
hdr_len
,
phys_addr
=
dma_map_single
(
trans
->
dev
,
skb
->
data
+
hdr_len
,
secondlen
,
DMA_TO_DEVICE
);
if
(
unlikely
(
dma_mapping_error
(
bus
(
trans
)
->
dev
,
phys_addr
)))
{
dma_unmap_single
(
bus
(
trans
)
->
dev
,
if
(
unlikely
(
dma_mapping_error
(
trans
->
dev
,
phys_addr
)))
{
dma_unmap_single
(
trans
->
dev
,
dma_unmap_addr
(
out_meta
,
mapping
),
dma_unmap_len
(
out_meta
,
len
),
DMA_BIDIRECTIONAL
);
...
...
@@ -1174,7 +1431,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
offsetof
(
struct
iwl_tx_cmd
,
scratch
);
/* take back ownership of DMA buffer to enable update */
dma_sync_single_for_cpu
(
bus
(
trans
)
->
dev
,
txcmd_phys
,
firstlen
,
dma_sync_single_for_cpu
(
trans
->
dev
,
txcmd_phys
,
firstlen
,
DMA_BIDIRECTIONAL
);
tx_cmd
->
dram_lsb_ptr
=
cpu_to_le32
(
scratch_phys
);
tx_cmd
->
dram_msb_ptr
=
iwl_get_dma_hi_addr
(
scratch_phys
);
...
...
@@ -1188,7 +1445,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
/* Set up entry for this TFD in Tx byte-count array */
iwl_trans_txq_update_byte_cnt_tbl
(
trans
,
txq
,
le16_to_cpu
(
tx_cmd
->
len
));
dma_sync_single_for_device
(
bus
(
trans
)
->
dev
,
txcmd_phys
,
firstlen
,
dma_sync_single_for_device
(
trans
->
dev
,
txcmd_phys
,
firstlen
,
DMA_BIDIRECTIONAL
);
trace_iwlwifi_dev_tx
(
priv
(
trans
),
...
...
@@ -1218,13 +1475,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
return
0
;
}
static
void
iwl_trans_pcie_kick_nic
(
struct
iwl_trans
*
trans
)
{
/* Remove all resets to allow NIC to operate */
iwl_write32
(
bus
(
trans
),
CSR_RESET
,
0
);
}
static
int
iwl_trans_pcie_request_irq
(
struct
iwl_trans
*
trans
)
static
int
iwl_trans_pcie_start_hw
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
...
...
@@ -1232,21 +1483,62 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans)
trans_pcie
->
inta_mask
=
CSR_INI_SET_MASK
;
if
(
!
trans_pcie
->
irq_requested
)
{
tasklet_init
(
&
trans_pcie
->
irq_tasklet
,
(
void
(
*
)(
unsigned
long
))
iwl_irq_tasklet
,
(
unsigned
long
)
trans
);
iwl_alloc_isr_ict
(
trans
);
err
=
request_irq
(
bus
(
trans
)
->
irq
,
iwl_isr_ict
,
IRQF_SHARED
,
err
=
request_irq
(
trans
->
irq
,
iwl_isr_ict
,
IRQF_SHARED
,
DRV_NAME
,
trans
);
if
(
err
)
{
IWL_ERR
(
trans
,
"Error allocating IRQ %d
\n
"
,
bus
(
trans
)
->
irq
);
iwl_free_isr_ict
(
trans
);
return
er
r
;
IWL_ERR
(
trans
,
"Error allocating IRQ %d
\n
"
,
trans
->
irq
);
goto
erro
r
;
}
INIT_WORK
(
&
trans_pcie
->
rx_replenish
,
iwl_bg_rx_replenish
);
return
0
;
trans_pcie
->
irq_requested
=
true
;
}
err
=
iwl_prepare_card_hw
(
trans
);
if
(
err
)
{
IWL_ERR
(
trans
,
"Error while preparing HW: %d"
,
err
);
goto
err_free_irq
;
}
iwl_apm_init
(
trans
);
/* If platform's RF_KILL switch is NOT set to KILL */
if
(
iwl_read32
(
trans
,
CSR_GP_CNTRL
)
&
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW
)
clear_bit
(
STATUS_RF_KILL_HW
,
&
trans
->
shrd
->
status
);
else
set_bit
(
STATUS_RF_KILL_HW
,
&
trans
->
shrd
->
status
);
iwl_set_hw_rfkill_state
(
priv
(
trans
),
test_bit
(
STATUS_RF_KILL_HW
,
&
trans
->
shrd
->
status
));
return
err
;
err_free_irq:
free_irq
(
trans
->
irq
,
trans
);
error:
iwl_free_isr_ict
(
trans
);
tasklet_kill
(
&
trans_pcie
->
irq_tasklet
);
return
err
;
}
static
void
iwl_trans_pcie_stop_hw
(
struct
iwl_trans
*
trans
)
{
iwl_apm_stop
(
trans
);
iwl_write32
(
trans
,
CSR_INT
,
0xFFFFFFFF
);
/* Even if we stop the HW, we still want the RF kill interrupt */
IWL_DEBUG_ISR
(
trans
,
"Enabling rfkill interrupt
\n
"
);
iwl_write32
(
trans
,
CSR_INT_MASK
,
CSR_INT_BIT_RF_KILL
);
}
static
int
iwl_trans_pcie_reclaim
(
struct
iwl_trans
*
trans
,
int
sta_id
,
int
tid
,
...
...
@@ -1288,13 +1580,42 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
return
0
;
}
static
void
iwl_trans_pcie_write8
(
struct
iwl_trans
*
trans
,
u32
ofs
,
u8
val
)
{
iowrite8
(
val
,
IWL_TRANS_GET_PCIE_TRANS
(
trans
)
->
hw_base
+
ofs
);
}
static
void
iwl_trans_pcie_write32
(
struct
iwl_trans
*
trans
,
u32
ofs
,
u32
val
)
{
iowrite32
(
val
,
IWL_TRANS_GET_PCIE_TRANS
(
trans
)
->
hw_base
+
ofs
);
}
static
u32
iwl_trans_pcie_read32
(
struct
iwl_trans
*
trans
,
u32
ofs
)
{
u32
val
=
ioread32
(
IWL_TRANS_GET_PCIE_TRANS
(
trans
)
->
hw_base
+
ofs
);
return
val
;
}
static
void
iwl_trans_pcie_free
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
iwl_calib_free_results
(
trans
);
iwl_trans_pcie_tx_free
(
trans
);
#ifndef CONFIG_IWLWIFI_IDI
iwl_trans_pcie_rx_free
(
trans
);
free_irq
(
bus
(
trans
)
->
irq
,
trans
);
#endif
if
(
trans_pcie
->
irq_requested
==
true
)
{
free_irq
(
trans
->
irq
,
trans
);
iwl_free_isr_ict
(
trans
);
}
pci_disable_msi
(
trans_pcie
->
pci_dev
);
pci_iounmap
(
trans_pcie
->
pci_dev
,
trans_pcie
->
hw_base
);
pci_release_regions
(
trans_pcie
->
pci_dev
);
pci_disable_device
(
trans_pcie
->
pci_dev
);
trans
->
shrd
->
trans
=
NULL
;
kfree
(
trans
);
}
...
...
@@ -1314,10 +1635,10 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
* things already :-)
*/
if
(
!
trans
->
shrd
->
wowlan
)
{
iwl_apm_stop
(
priv
(
trans
)
);
iwl_apm_stop
(
trans
);
}
else
{
iwl_disable_interrupts
(
trans
);
iwl_clear_bit
(
bus
(
trans
)
,
CSR_GP_CNTRL
,
iwl_clear_bit
(
trans
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
}
...
...
@@ -1330,7 +1651,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
iwl_enable_interrupts
(
trans
);
if
(
!
(
iwl_read32
(
bus
(
trans
)
,
CSR_GP_CNTRL
)
&
if
(
!
(
iwl_read32
(
trans
,
CSR_GP_CNTRL
)
&
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW
))
hw_rfkill
=
true
;
...
...
@@ -1363,25 +1684,6 @@ static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans,
}
}
const
struct
iwl_trans_ops
trans_ops_pcie
;
static
struct
iwl_trans
*
iwl_trans_pcie_alloc
(
struct
iwl_shared
*
shrd
)
{
struct
iwl_trans
*
iwl_trans
=
kzalloc
(
sizeof
(
struct
iwl_trans
)
+
sizeof
(
struct
iwl_trans_pcie
),
GFP_KERNEL
);
if
(
iwl_trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
iwl_trans
);
iwl_trans
->
ops
=
&
trans_ops_pcie
;
iwl_trans
->
shrd
=
shrd
;
trans_pcie
->
trans
=
iwl_trans
;
spin_lock_init
(
&
iwl_trans
->
hcmd_lock
);
}
return
iwl_trans
;
}
static
void
iwl_trans_pcie_stop_queue
(
struct
iwl_trans
*
trans
,
int
txq_id
,
const
char
*
msg
)
{
...
...
@@ -1445,9 +1747,9 @@ static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt)
IWL_ERR
(
trans
,
"Current SW read_ptr %d write_ptr %d
\n
"
,
q
->
read_ptr
,
q
->
write_ptr
);
IWL_ERR
(
trans
,
"Current HW read_ptr %d write_ptr %d
\n
"
,
iwl_read_prph
(
bus
(
trans
)
,
SCD_QUEUE_RDPTR
(
cnt
))
iwl_read_prph
(
trans
,
SCD_QUEUE_RDPTR
(
cnt
))
&
(
TFD_QUEUE_SIZE_MAX
-
1
),
iwl_read_prph
(
bus
(
trans
)
,
SCD_QUEUE_WRPTR
(
cnt
)));
iwl_read_prph
(
trans
,
SCD_QUEUE_WRPTR
(
cnt
)));
return
1
;
}
...
...
@@ -1501,7 +1803,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
pos
+=
scnprintf
(
*
buf
+
pos
,
bufsz
-
pos
,
" %34s: 0X%08x
\n
"
,
get_fh_string
(
fh_tbl
[
i
]),
iwl_read_direct32
(
bus
(
trans
)
,
fh_tbl
[
i
]));
iwl_read_direct32
(
trans
,
fh_tbl
[
i
]));
}
return
pos
;
}
...
...
@@ -1510,7 +1812,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
fh_tbl
);
i
++
)
{
IWL_ERR
(
trans
,
" %34s: 0X%08x
\n
"
,
get_fh_string
(
fh_tbl
[
i
]),
iwl_read_direct32
(
bus
(
trans
)
,
fh_tbl
[
i
]));
iwl_read_direct32
(
trans
,
fh_tbl
[
i
]));
}
return
0
;
}
...
...
@@ -1580,7 +1882,7 @@ void iwl_dump_csr(struct iwl_trans *trans)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
csr_tbl
);
i
++
)
{
IWL_ERR
(
trans
,
" %25s: 0X%08x
\n
"
,
get_csr_string
(
csr_tbl
[
i
]),
iwl_read32
(
bus
(
trans
)
,
csr_tbl
[
i
]));
iwl_read32
(
trans
,
csr_tbl
[
i
]));
}
}
...
...
@@ -1901,13 +2203,12 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
#endif
/*CONFIG_IWLWIFI_DEBUGFS */
const
struct
iwl_trans_ops
trans_ops_pcie
=
{
.
alloc
=
iwl_trans_pcie_alloc
,
.
request_irq
=
iwl_trans_pcie_request_irq
,
.
start_device
=
iwl_trans_pcie_start_devic
e
,
.
prepare_card_hw
=
iwl_trans_pcie_prepare_card_h
w
,
.
start_hw
=
iwl_trans_pcie_start_hw
,
.
stop_hw
=
iwl_trans_pcie_stop_hw
,
.
fw_alive
=
iwl_trans_pcie_fw_aliv
e
,
.
start_fw
=
iwl_trans_pcie_start_f
w
,
.
stop_device
=
iwl_trans_pcie_stop_device
,
.
tx_start
=
iwl_trans_pcie_tx_start
,
.
wake_any_queue
=
iwl_trans_pcie_wake_any_queue
,
.
send_cmd
=
iwl_trans_pcie_send_cmd
,
...
...
@@ -1919,8 +2220,6 @@ const struct iwl_trans_ops trans_ops_pcie = {
.
tx_agg_alloc
=
iwl_trans_pcie_tx_agg_alloc
,
.
tx_agg_setup
=
iwl_trans_pcie_tx_agg_setup
,
.
kick_nic
=
iwl_trans_pcie_kick_nic
,
.
free
=
iwl_trans_pcie_free
,
.
stop_queue
=
iwl_trans_pcie_stop_queue
,
...
...
@@ -1933,4 +2232,116 @@ const struct iwl_trans_ops trans_ops_pcie = {
.
suspend
=
iwl_trans_pcie_suspend
,
.
resume
=
iwl_trans_pcie_resume
,
#endif
.
write8
=
iwl_trans_pcie_write8
,
.
write32
=
iwl_trans_pcie_write32
,
.
read32
=
iwl_trans_pcie_read32
,
};
struct
iwl_trans
*
iwl_trans_pcie_alloc
(
struct
iwl_shared
*
shrd
,
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
struct
iwl_trans_pcie
*
trans_pcie
;
struct
iwl_trans
*
trans
;
u16
pci_cmd
;
int
err
;
trans
=
kzalloc
(
sizeof
(
struct
iwl_trans
)
+
sizeof
(
struct
iwl_trans_pcie
),
GFP_KERNEL
);
if
(
WARN_ON
(
!
trans
))
return
NULL
;
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
trans
->
ops
=
&
trans_ops_pcie
;
trans
->
shrd
=
shrd
;
trans_pcie
->
trans
=
trans
;
spin_lock_init
(
&
trans
->
hcmd_lock
);
/* W/A - seems to solve weird behavior. We need to remove this if we
* don't want to stay in L1 all the time. This wastes a lot of power */
pci_disable_link_state
(
pdev
,
PCIE_LINK_STATE_L0S
|
PCIE_LINK_STATE_L1
|
PCIE_LINK_STATE_CLKPM
);
if
(
pci_enable_device
(
pdev
))
{
err
=
-
ENODEV
;
goto
out_no_pci
;
}
pci_set_master
(
pdev
);
err
=
pci_set_dma_mask
(
pdev
,
DMA_BIT_MASK
(
36
));
if
(
!
err
)
err
=
pci_set_consistent_dma_mask
(
pdev
,
DMA_BIT_MASK
(
36
));
if
(
err
)
{
err
=
pci_set_dma_mask
(
pdev
,
DMA_BIT_MASK
(
32
));
if
(
!
err
)
err
=
pci_set_consistent_dma_mask
(
pdev
,
DMA_BIT_MASK
(
32
));
/* both attempts failed: */
if
(
err
)
{
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
"No suitable DMA available.
\n
"
);
goto
out_pci_disable_device
;
}
}
err
=
pci_request_regions
(
pdev
,
DRV_NAME
);
if
(
err
)
{
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
"pci_request_regions failed"
);
goto
out_pci_disable_device
;
}
trans_pcie
->
hw_base
=
pci_iomap
(
pdev
,
0
,
0
);
if
(
!
trans_pcie
->
hw_base
)
{
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
"pci_iomap failed"
);
err
=
-
ENODEV
;
goto
out_pci_release_regions
;
}
dev_printk
(
KERN_INFO
,
&
pdev
->
dev
,
"pci_resource_len = 0x%08llx
\n
"
,
(
unsigned
long
long
)
pci_resource_len
(
pdev
,
0
));
dev_printk
(
KERN_INFO
,
&
pdev
->
dev
,
"pci_resource_base = %p
\n
"
,
trans_pcie
->
hw_base
);
dev_printk
(
KERN_INFO
,
&
pdev
->
dev
,
"HW Revision ID = 0x%X
\n
"
,
pdev
->
revision
);
/* We disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte
(
pdev
,
PCI_CFG_RETRY_TIMEOUT
,
0x00
);
err
=
pci_enable_msi
(
pdev
);
if
(
err
)
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
"pci_enable_msi failed(0X%x)"
,
err
);
trans
->
dev
=
&
pdev
->
dev
;
trans
->
irq
=
pdev
->
irq
;
trans_pcie
->
pci_dev
=
pdev
;
trans
->
hw_rev
=
iwl_read32
(
trans
,
CSR_HW_REV
);
trans
->
hw_id
=
(
pdev
->
device
<<
16
)
+
pdev
->
subsystem_device
;
snprintf
(
trans
->
hw_id_str
,
sizeof
(
trans
->
hw_id_str
),
"PCI ID: 0x%04X:0x%04X"
,
pdev
->
device
,
pdev
->
subsystem_device
);
/* TODO: Move this away, not needed if not MSI */
/* enable rfkill interrupt: hw bug w/a */
pci_read_config_word
(
pdev
,
PCI_COMMAND
,
&
pci_cmd
);
if
(
pci_cmd
&
PCI_COMMAND_INTX_DISABLE
)
{
pci_cmd
&=
~
PCI_COMMAND_INTX_DISABLE
;
pci_write_config_word
(
pdev
,
PCI_COMMAND
,
pci_cmd
);
}
return
trans
;
out_pci_release_regions:
pci_release_regions
(
pdev
);
out_pci_disable_device:
pci_disable_device
(
pdev
);
out_no_pci:
kfree
(
trans
);
return
NULL
;
}
drivers/net/wireless/iwlwifi/iwl-trans.h
View file @
8f0bb5ae
...
...
@@ -131,16 +131,26 @@ struct iwl_host_cmd {
u8
id
;
};
/* one for each uCode image (inst/data, boot/init/runtime) */
struct
fw_desc
{
dma_addr_t
p_addr
;
/* hardware address */
void
*
v_addr
;
/* software address */
u32
len
;
/* size in bytes */
};
struct
fw_img
{
struct
fw_desc
code
;
/* firmware code image */
struct
fw_desc
data
;
/* firmware data image */
};
/**
* struct iwl_trans_ops - transport specific operations
* @alloc: allocates the meta data (not the queues themselves)
* @request_irq: requests IRQ - will be called before the FW load in probe flow
* @start_device: allocates and inits all the resources for the transport
* layer.
* @prepare_card_hw: claim the ownership on the HW. Will be called during
* probe.
* @tx_start: starts and configures all the Tx fifo - usually done once the fw
* is alive.
* @start_hw: starts the HW- from that point on, the HW can send interrupts
* @stop_hw: stops the HW- from that point on, the HW will be in low power but
* will still issue interrupt if the HW RF kill is triggered.
* @start_fw: allocates and inits all the resources for the transport
* layer. Also kick a fw image. This handler may sleep.
* @fw_alive: called when the fw sends alive notification
* @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
* @stop_device:stops the whole device (embedded CPU put to reset)
* @send_cmd:send a host command
...
...
@@ -150,7 +160,6 @@ struct iwl_host_cmd {
* @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
* ready and a successful ADDBA response has been received.
* @tx_agg_disable: de-configure a Tx queue to send AMPDUs
* @kick_nic: remove the RESET from the embedded CPU and let it run
* @free: release all the ressource for the transport layer itself such as
* irq, tasklet etc...
* @stop_queue: stop a specific queue
...
...
@@ -160,15 +169,17 @@ struct iwl_host_cmd {
* automatically deleted.
* @suspend: stop the device unless WoWLAN is configured
* @resume: resume activity of the device
* @write8: write a u8 to a register at offset ofs from the BAR
* @write32: write a u32 to a register at offset ofs from the BAR
* @read32: read a u32 register at offset ofs from the BAR
*/
struct
iwl_trans_ops
{
struct
iwl_trans
*
(
*
alloc
)(
struct
iwl_shared
*
shrd
);
int
(
*
request_irq
)(
struct
iwl_trans
*
iwl_trans
);
int
(
*
start_
device
)(
struct
iwl_trans
*
trans
);
int
(
*
prepare_card_hw
)(
struct
iwl_trans
*
trans
);
int
(
*
start_hw
)(
struct
iwl_trans
*
iwl_trans
);
void
(
*
stop_hw
)(
struct
iwl_trans
*
iwl_trans
);
int
(
*
start_
fw
)(
struct
iwl_trans
*
trans
,
struct
fw_img
*
fw
);
void
(
*
fw_alive
)(
struct
iwl_trans
*
trans
);
void
(
*
stop_device
)(
struct
iwl_trans
*
trans
);
void
(
*
tx_start
)(
struct
iwl_trans
*
trans
);
void
(
*
wake_any_queue
)(
struct
iwl_trans
*
trans
,
enum
iwl_rxon_context_id
ctx
,
...
...
@@ -191,8 +202,6 @@ struct iwl_trans_ops {
enum
iwl_rxon_context_id
ctx
,
int
sta_id
,
int
tid
,
int
frame_limit
,
u16
ssn
);
void
(
*
kick_nic
)(
struct
iwl_trans
*
trans
);
void
(
*
free
)(
struct
iwl_trans
*
trans
);
void
(
*
stop_queue
)(
struct
iwl_trans
*
trans
,
int
q
,
const
char
*
msg
);
...
...
@@ -204,18 +213,9 @@ struct iwl_trans_ops {
int
(
*
suspend
)(
struct
iwl_trans
*
trans
);
int
(
*
resume
)(
struct
iwl_trans
*
trans
);
#endif
};
/* one for each uCode image (inst/data, boot/init/runtime) */
struct
fw_desc
{
dma_addr_t
p_addr
;
/* hardware address */
void
*
v_addr
;
/* software address */
u32
len
;
/* size in bytes */
};
struct
fw_img
{
struct
fw_desc
code
;
/* firmware code image */
struct
fw_desc
data
;
/* firmware data image */
void
(
*
write8
)(
struct
iwl_trans
*
trans
,
u32
ofs
,
u8
val
);
void
(
*
write32
)(
struct
iwl_trans
*
trans
,
u32
ofs
,
u32
val
);
u32
(
*
read32
)(
struct
iwl_trans
*
trans
,
u32
ofs
);
};
/* Opaque calibration results */
...
...
@@ -231,17 +231,31 @@ struct iwl_calib_result {
* @ops - pointer to iwl_trans_ops
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
* @hcmd_lock: protects HCMD
* @reg_lock - protect hw register access
* @dev - pointer to struct device * that represents the device
* @irq - the irq number for the device
* @hw_id: a u32 with the ID of the device / subdevice.
* Set during transport alloaction.
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
* @ucode_write_complete: indicates that the ucode has been copied.
* @ucode_rt: run time ucode image
* @ucode_init: init ucode image
* @ucode_wowlan: wake on wireless ucode image (optional)
* @nvm_device_type: indicates OTP or eeprom
* @pm_support: set to true in start_hw if link pm is supported
* @calib_results: list head for init calibration results
*/
struct
iwl_trans
{
const
struct
iwl_trans_ops
*
ops
;
struct
iwl_shared
*
shrd
;
spinlock_t
hcmd_lock
;
spinlock_t
reg_lock
;
struct
device
*
dev
;
unsigned
int
irq
;
u32
hw_rev
;
u32
hw_id
;
char
hw_id_str
[
52
];
u8
ucode_write_complete
;
/* the image write is complete */
struct
fw_img
ucode_rt
;
...
...
@@ -250,6 +264,7 @@ struct iwl_trans {
/* eeprom related variables */
int
nvm_device_type
;
bool
pm_support
;
/* init calibration results */
struct
list_head
calib_results
;
...
...
@@ -259,29 +274,31 @@ struct iwl_trans {
char
trans_specific
[
0
]
__attribute__
((
__aligned__
(
sizeof
(
void
*
))));
};
static
inline
int
iwl_trans_
request_irq
(
struct
iwl_trans
*
trans
)
static
inline
int
iwl_trans_
start_hw
(
struct
iwl_trans
*
trans
)
{
return
trans
->
ops
->
request_irq
(
trans
);
return
trans
->
ops
->
start_hw
(
trans
);
}
static
inline
int
iwl_trans_start_device
(
struct
iwl_trans
*
trans
)
static
inline
void
iwl_trans_stop_hw
(
struct
iwl_trans
*
trans
)
{
return
trans
->
ops
->
start_device
(
trans
);
trans
->
ops
->
stop_hw
(
trans
);
}
static
inline
int
iwl_trans_prepare_card_hw
(
struct
iwl_trans
*
trans
)
static
inline
void
iwl_trans_fw_alive
(
struct
iwl_trans
*
trans
)
{
return
trans
->
ops
->
prepare_card_hw
(
trans
);
trans
->
ops
->
fw_alive
(
trans
);
}
static
inline
void
iwl_trans_stop_device
(
struct
iwl_trans
*
trans
)
static
inline
int
iwl_trans_start_fw
(
struct
iwl_trans
*
trans
,
struct
fw_img
*
fw
)
{
trans
->
ops
->
stop_device
(
trans
);
might_sleep
();
return
trans
->
ops
->
start_fw
(
trans
,
fw
);
}
static
inline
void
iwl_trans_
tx_start
(
struct
iwl_trans
*
trans
)
static
inline
void
iwl_trans_
stop_device
(
struct
iwl_trans
*
trans
)
{
trans
->
ops
->
tx_start
(
trans
);
trans
->
ops
->
stop_device
(
trans
);
}
static
inline
void
iwl_trans_wake_any_queue
(
struct
iwl_trans
*
trans
,
...
...
@@ -337,11 +354,6 @@ static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans,
trans
->
ops
->
tx_agg_setup
(
trans
,
ctx
,
sta_id
,
tid
,
frame_limit
,
ssn
);
}
static
inline
void
iwl_trans_kick_nic
(
struct
iwl_trans
*
trans
)
{
trans
->
ops
->
kick_nic
(
trans
);
}
static
inline
void
iwl_trans_free
(
struct
iwl_trans
*
trans
)
{
trans
->
ops
->
free
(
trans
);
...
...
@@ -380,13 +392,24 @@ static inline int iwl_trans_resume(struct iwl_trans *trans)
}
#endif
static
inline
void
iwl_trans_write8
(
struct
iwl_trans
*
trans
,
u32
ofs
,
u8
val
)
{
trans
->
ops
->
write8
(
trans
,
ofs
,
val
);
}
static
inline
void
iwl_trans_write32
(
struct
iwl_trans
*
trans
,
u32
ofs
,
u32
val
)
{
trans
->
ops
->
write32
(
trans
,
ofs
,
val
);
}
static
inline
u32
iwl_trans_read32
(
struct
iwl_trans
*
trans
,
u32
ofs
)
{
return
trans
->
ops
->
read32
(
trans
,
ofs
);
}
/*****************************************************
*
Transport layers implementa
tions
*
Utils func
tions
******************************************************/
extern
const
struct
iwl_trans_ops
trans_ops_pcie
;
int
iwl_alloc_fw_desc
(
struct
iwl_bus
*
bus
,
struct
fw_desc
*
desc
,
const
void
*
data
,
size_t
len
);
void
iwl_dealloc_ucode
(
struct
iwl_trans
*
trans
);
int
iwl_send_calib_results
(
struct
iwl_trans
*
trans
);
...
...
@@ -394,4 +417,18 @@ int iwl_calib_set(struct iwl_trans *trans,
const
struct
iwl_calib_hdr
*
cmd
,
int
len
);
void
iwl_calib_free_results
(
struct
iwl_trans
*
trans
);
/*****************************************************
* Transport layers implementations + their allocation function
******************************************************/
struct
pci_dev
;
struct
pci_device_id
;
extern
const
struct
iwl_trans_ops
trans_ops_pcie
;
struct
iwl_trans
*
iwl_trans_pcie_alloc
(
struct
iwl_shared
*
shrd
,
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
);
extern
const
struct
iwl_trans_ops
trans_ops_idi
;
struct
iwl_trans
*
iwl_trans_idi_alloc
(
struct
iwl_shared
*
shrd
,
void
*
pdev_void
,
const
void
*
ent_void
);
#endif
/* __iwl_trans_h__ */
drivers/net/wireless/iwlwifi/iwl-ucode.c
View file @
8f0bb5ae
...
...
@@ -32,7 +32,9 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include "iwl-ucode.h"
#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-core.h"
...
...
@@ -80,29 +82,29 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
*
******************************************************************************/
static
void
iwl_free_fw_desc
(
struct
iwl_
bus
*
bu
s
,
struct
fw_desc
*
desc
)
static
void
iwl_free_fw_desc
(
struct
iwl_
trans
*
tran
s
,
struct
fw_desc
*
desc
)
{
if
(
desc
->
v_addr
)
dma_free_coherent
(
bu
s
->
dev
,
desc
->
len
,
dma_free_coherent
(
tran
s
->
dev
,
desc
->
len
,
desc
->
v_addr
,
desc
->
p_addr
);
desc
->
v_addr
=
NULL
;
desc
->
len
=
0
;
}
static
void
iwl_free_fw_img
(
struct
iwl_
bus
*
bu
s
,
struct
fw_img
*
img
)
static
void
iwl_free_fw_img
(
struct
iwl_
trans
*
tran
s
,
struct
fw_img
*
img
)
{
iwl_free_fw_desc
(
bu
s
,
&
img
->
code
);
iwl_free_fw_desc
(
bu
s
,
&
img
->
data
);
iwl_free_fw_desc
(
tran
s
,
&
img
->
code
);
iwl_free_fw_desc
(
tran
s
,
&
img
->
data
);
}
void
iwl_dealloc_ucode
(
struct
iwl_trans
*
trans
)
{
iwl_free_fw_img
(
bus
(
trans
)
,
&
trans
->
ucode_rt
);
iwl_free_fw_img
(
bus
(
trans
)
,
&
trans
->
ucode_init
);
iwl_free_fw_img
(
bus
(
trans
)
,
&
trans
->
ucode_wowlan
);
iwl_free_fw_img
(
trans
,
&
trans
->
ucode_rt
);
iwl_free_fw_img
(
trans
,
&
trans
->
ucode_init
);
iwl_free_fw_img
(
trans
,
&
trans
->
ucode_wowlan
);
}
int
iwl_alloc_fw_desc
(
struct
iwl_bus
*
bu
s
,
struct
fw_desc
*
desc
,
static
int
iwl_alloc_fw_desc
(
struct
iwl_trans
*
tran
s
,
struct
fw_desc
*
desc
,
const
void
*
data
,
size_t
len
)
{
if
(
!
len
)
{
...
...
@@ -110,7 +112,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
return
-
EINVAL
;
}
desc
->
v_addr
=
dma_alloc_coherent
(
bu
s
->
dev
,
len
,
desc
->
v_addr
=
dma_alloc_coherent
(
tran
s
->
dev
,
len
,
&
desc
->
p_addr
,
GFP_KERNEL
);
if
(
!
desc
->
v_addr
)
return
-
ENOMEM
;
...
...
@@ -120,59 +122,6 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
return
0
;
}
/*
* ucode
*/
static
int
iwl_load_section
(
struct
iwl_trans
*
trans
,
const
char
*
name
,
struct
fw_desc
*
image
,
u32
dst_addr
)
{
struct
iwl_bus
*
bus
=
bus
(
trans
);
dma_addr_t
phy_addr
=
image
->
p_addr
;
u32
byte_cnt
=
image
->
len
;
int
ret
;
trans
->
ucode_write_complete
=
0
;
iwl_write_direct32
(
bus
,
FH_TCSR_CHNL_TX_CONFIG_REG
(
FH_SRVC_CHNL
),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE
);
iwl_write_direct32
(
bus
,
FH_SRVC_CHNL_SRAM_ADDR_REG
(
FH_SRVC_CHNL
),
dst_addr
);
iwl_write_direct32
(
bus
,
FH_TFDIB_CTRL0_REG
(
FH_SRVC_CHNL
),
phy_addr
&
FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK
);
iwl_write_direct32
(
bus
,
FH_TFDIB_CTRL1_REG
(
FH_SRVC_CHNL
),
(
iwl_get_dma_hi_addr
(
phy_addr
)
<<
FH_MEM_TFDIB_REG1_ADDR_BITSHIFT
)
|
byte_cnt
);
iwl_write_direct32
(
bus
,
FH_TCSR_CHNL_TX_BUF_STS_REG
(
FH_SRVC_CHNL
),
1
<<
FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM
|
1
<<
FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX
|
FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID
);
iwl_write_direct32
(
bus
,
FH_TCSR_CHNL_TX_CONFIG_REG
(
FH_SRVC_CHNL
),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE
|
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE
|
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD
);
IWL_DEBUG_FW
(
bus
,
"%s uCode section being loaded...
\n
"
,
name
);
ret
=
wait_event_timeout
(
trans
->
shrd
->
wait_command_queue
,
trans
->
ucode_write_complete
,
5
*
HZ
);
if
(
!
ret
)
{
IWL_ERR
(
trans
,
"Could not load the %s uCode section
\n
"
,
name
);
return
-
ETIMEDOUT
;
}
return
0
;
}
static
inline
struct
fw_img
*
iwl_get_ucode_image
(
struct
iwl_trans
*
trans
,
enum
iwl_ucode_type
ucode_type
)
{
...
...
@@ -189,28 +138,6 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
return
NULL
;
}
static
int
iwl_load_given_ucode
(
struct
iwl_trans
*
trans
,
enum
iwl_ucode_type
ucode_type
)
{
int
ret
=
0
;
struct
fw_img
*
image
=
iwl_get_ucode_image
(
trans
,
ucode_type
);
if
(
!
image
)
{
IWL_ERR
(
trans
,
"Invalid ucode requested (%d)
\n
"
,
ucode_type
);
return
-
EINVAL
;
}
ret
=
iwl_load_section
(
trans
,
"INST"
,
&
image
->
code
,
IWLAGN_RTC_INST_LOWER_BOUND
);
if
(
ret
)
return
ret
;
return
iwl_load_section
(
trans
,
"DATA"
,
&
image
->
data
,
IWLAGN_RTC_DATA_LOWER_BOUND
);
}
/*
* Calibration
*/
...
...
@@ -447,7 +374,7 @@ static int iwl_alive_notify(struct iwl_trans *trans)
if
(
!
priv
->
tx_cmd_pool
)
return
-
ENOMEM
;
iwl_trans_
tx_start
(
trans
);
iwl_trans_
fw_alive
(
trans
);
for_each_context
(
priv
,
ctx
)
ctx
->
last_tx_rejected
=
false
;
...
...
@@ -470,7 +397,7 @@ static int iwl_alive_notify(struct iwl_trans *trans)
* using sample data 100 bytes apart. If these sample points are good,
* it's a pretty good bet that everything between them is good, too.
*/
static
int
iwl_verify_inst_sparse
(
struct
iwl_
bus
*
bu
s
,
static
int
iwl_verify_inst_sparse
(
struct
iwl_
trans
*
tran
s
,
struct
fw_desc
*
fw_desc
)
{
__le32
*
image
=
(
__le32
*
)
fw_desc
->
v_addr
;
...
...
@@ -478,15 +405,15 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus,
u32
val
;
u32
i
;
IWL_DEBUG_FW
(
bu
s
,
"ucode inst image size is %u
\n
"
,
len
);
IWL_DEBUG_FW
(
tran
s
,
"ucode inst image size is %u
\n
"
,
len
);
for
(
i
=
0
;
i
<
len
;
i
+=
100
,
image
+=
100
/
sizeof
(
u32
))
{
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */
iwl_write_direct32
(
bu
s
,
HBUS_TARG_MEM_RADDR
,
iwl_write_direct32
(
tran
s
,
HBUS_TARG_MEM_RADDR
,
i
+
IWLAGN_RTC_INST_LOWER_BOUND
);
val
=
iwl_read32
(
bu
s
,
HBUS_TARG_MEM_RDAT
);
val
=
iwl_read32
(
tran
s
,
HBUS_TARG_MEM_RDAT
);
if
(
val
!=
le32_to_cpu
(
*
image
))
return
-
EIO
;
}
...
...
@@ -494,7 +421,7 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus,
return
0
;
}
static
void
iwl_print_mismatch_inst
(
struct
iwl_
bus
*
bu
s
,
static
void
iwl_print_mismatch_inst
(
struct
iwl_
trans
*
tran
s
,
struct
fw_desc
*
fw_desc
)
{
__le32
*
image
=
(
__le32
*
)
fw_desc
->
v_addr
;
...
...
@@ -503,18 +430,18 @@ static void iwl_print_mismatch_inst(struct iwl_bus *bus,
u32
offs
;
int
errors
=
0
;
IWL_DEBUG_FW
(
bu
s
,
"ucode inst image size is %u
\n
"
,
len
);
IWL_DEBUG_FW
(
tran
s
,
"ucode inst image size is %u
\n
"
,
len
);
iwl_write_direct32
(
bu
s
,
HBUS_TARG_MEM_RADDR
,
iwl_write_direct32
(
tran
s
,
HBUS_TARG_MEM_RADDR
,
IWLAGN_RTC_INST_LOWER_BOUND
);
for
(
offs
=
0
;
offs
<
len
&&
errors
<
20
;
offs
+=
sizeof
(
u32
),
image
++
)
{
/* read data comes through single port, auto-incr addr */
val
=
iwl_read32
(
bu
s
,
HBUS_TARG_MEM_RDAT
);
val
=
iwl_read32
(
tran
s
,
HBUS_TARG_MEM_RDAT
);
if
(
val
!=
le32_to_cpu
(
*
image
))
{
IWL_ERR
(
bu
s
,
"uCode INST section at "
IWL_ERR
(
tran
s
,
"uCode INST section at "
"offset 0x%x, is 0x%x, s/b 0x%x
\n
"
,
offs
,
val
,
le32_to_cpu
(
*
image
));
errors
++
;
...
...
@@ -536,14 +463,14 @@ static int iwl_verify_ucode(struct iwl_trans *trans,
return
-
EINVAL
;
}
if
(
!
iwl_verify_inst_sparse
(
bus
(
trans
)
,
&
img
->
code
))
{
if
(
!
iwl_verify_inst_sparse
(
trans
,
&
img
->
code
))
{
IWL_DEBUG_FW
(
trans
,
"uCode is good in inst SRAM
\n
"
);
return
0
;
}
IWL_ERR
(
trans
,
"UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!
\n
"
);
iwl_print_mismatch_inst
(
bus
(
trans
)
,
&
img
->
code
);
iwl_print_mismatch_inst
(
trans
,
&
img
->
code
);
return
-
EIO
;
}
...
...
@@ -647,28 +574,27 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
{
struct
iwl_notification_wait
alive_wait
;
struct
iwl_alive_data
alive_data
;
struct
fw_img
*
fw
;
int
ret
;
enum
iwl_ucode_type
old_type
;
ret
=
iwl_trans_start_device
(
trans
);
if
(
ret
)
return
ret
;
iwl_init_notification_wait
(
trans
->
shrd
,
&
alive_wait
,
REPLY_ALIVE
,
iwl_alive_fn
,
&
alive_data
);
old_type
=
trans
->
shrd
->
ucode_type
;
trans
->
shrd
->
ucode_type
=
ucode_type
;
fw
=
iwl_get_ucode_image
(
trans
,
ucode_type
);
if
(
!
fw
)
return
-
EINVAL
;
ret
=
iwl_
load_given_ucode
(
trans
,
ucode_type
);
ret
=
iwl_
trans_start_fw
(
trans
,
fw
);
if
(
ret
)
{
trans
->
shrd
->
ucode_type
=
old_type
;
iwl_remove_notification
(
trans
->
shrd
,
&
alive_wait
);
return
ret
;
}
iwl_trans_kick_nic
(
trans
);
/*
* Some things may run in the background now, but we
* just wait for the ALIVE notification here.
...
...
@@ -756,3 +682,609 @@ int iwl_run_init_ucode(struct iwl_trans *trans)
iwl_trans_stop_device
(
trans
);
return
ret
;
}
static
void
iwl_ucode_callback
(
const
struct
firmware
*
ucode_raw
,
void
*
context
);
#define UCODE_EXPERIMENTAL_INDEX 100
#define UCODE_EXPERIMENTAL_TAG "exp"
int
__must_check
iwl_request_firmware
(
struct
iwl_priv
*
priv
,
bool
first
)
{
const
char
*
name_pre
=
cfg
(
priv
)
->
fw_name_pre
;
char
tag
[
8
];
if
(
first
)
{
#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
priv
->
fw_index
=
UCODE_EXPERIMENTAL_INDEX
;
strcpy
(
tag
,
UCODE_EXPERIMENTAL_TAG
);
}
else
if
(
priv
->
fw_index
==
UCODE_EXPERIMENTAL_INDEX
)
{
#endif
priv
->
fw_index
=
cfg
(
priv
)
->
ucode_api_max
;
sprintf
(
tag
,
"%d"
,
priv
->
fw_index
);
}
else
{
priv
->
fw_index
--
;
sprintf
(
tag
,
"%d"
,
priv
->
fw_index
);
}
if
(
priv
->
fw_index
<
cfg
(
priv
)
->
ucode_api_min
)
{
IWL_ERR
(
priv
,
"no suitable firmware found!
\n
"
);
return
-
ENOENT
;
}
sprintf
(
priv
->
firmware_name
,
"%s%s%s"
,
name_pre
,
tag
,
".ucode"
);
IWL_DEBUG_INFO
(
priv
,
"attempting to load firmware %s'%s'
\n
"
,
(
priv
->
fw_index
==
UCODE_EXPERIMENTAL_INDEX
)
?
"EXPERIMENTAL "
:
""
,
priv
->
firmware_name
);
return
request_firmware_nowait
(
THIS_MODULE
,
1
,
priv
->
firmware_name
,
trans
(
priv
)
->
dev
,
GFP_KERNEL
,
priv
,
iwl_ucode_callback
);
}
struct
iwlagn_firmware_pieces
{
const
void
*
inst
,
*
data
,
*
init
,
*
init_data
,
*
wowlan_inst
,
*
wowlan_data
;
size_t
inst_size
,
data_size
,
init_size
,
init_data_size
,
wowlan_inst_size
,
wowlan_data_size
;
u32
build
;
u32
init_evtlog_ptr
,
init_evtlog_size
,
init_errlog_ptr
;
u32
inst_evtlog_ptr
,
inst_evtlog_size
,
inst_errlog_ptr
;
};
static
int
iwlagn_load_legacy_firmware
(
struct
iwl_priv
*
priv
,
const
struct
firmware
*
ucode_raw
,
struct
iwlagn_firmware_pieces
*
pieces
)
{
struct
iwl_ucode_header
*
ucode
=
(
void
*
)
ucode_raw
->
data
;
u32
api_ver
,
hdr_size
;
const
u8
*
src
;
priv
->
ucode_ver
=
le32_to_cpu
(
ucode
->
ver
);
api_ver
=
IWL_UCODE_API
(
priv
->
ucode_ver
);
switch
(
api_ver
)
{
default:
hdr_size
=
28
;
if
(
ucode_raw
->
size
<
hdr_size
)
{
IWL_ERR
(
priv
,
"File size too small!
\n
"
);
return
-
EINVAL
;
}
pieces
->
build
=
le32_to_cpu
(
ucode
->
u
.
v2
.
build
);
pieces
->
inst_size
=
le32_to_cpu
(
ucode
->
u
.
v2
.
inst_size
);
pieces
->
data_size
=
le32_to_cpu
(
ucode
->
u
.
v2
.
data_size
);
pieces
->
init_size
=
le32_to_cpu
(
ucode
->
u
.
v2
.
init_size
);
pieces
->
init_data_size
=
le32_to_cpu
(
ucode
->
u
.
v2
.
init_data_size
);
src
=
ucode
->
u
.
v2
.
data
;
break
;
case
0
:
case
1
:
case
2
:
hdr_size
=
24
;
if
(
ucode_raw
->
size
<
hdr_size
)
{
IWL_ERR
(
priv
,
"File size too small!
\n
"
);
return
-
EINVAL
;
}
pieces
->
build
=
0
;
pieces
->
inst_size
=
le32_to_cpu
(
ucode
->
u
.
v1
.
inst_size
);
pieces
->
data_size
=
le32_to_cpu
(
ucode
->
u
.
v1
.
data_size
);
pieces
->
init_size
=
le32_to_cpu
(
ucode
->
u
.
v1
.
init_size
);
pieces
->
init_data_size
=
le32_to_cpu
(
ucode
->
u
.
v1
.
init_data_size
);
src
=
ucode
->
u
.
v1
.
data
;
break
;
}
/* Verify size of file vs. image size info in file's header */
if
(
ucode_raw
->
size
!=
hdr_size
+
pieces
->
inst_size
+
pieces
->
data_size
+
pieces
->
init_size
+
pieces
->
init_data_size
)
{
IWL_ERR
(
priv
,
"uCode file size %d does not match expected size
\n
"
,
(
int
)
ucode_raw
->
size
);
return
-
EINVAL
;
}
pieces
->
inst
=
src
;
src
+=
pieces
->
inst_size
;
pieces
->
data
=
src
;
src
+=
pieces
->
data_size
;
pieces
->
init
=
src
;
src
+=
pieces
->
init_size
;
pieces
->
init_data
=
src
;
src
+=
pieces
->
init_data_size
;
return
0
;
}
static
int
iwlagn_load_firmware
(
struct
iwl_priv
*
priv
,
const
struct
firmware
*
ucode_raw
,
struct
iwlagn_firmware_pieces
*
pieces
,
struct
iwlagn_ucode_capabilities
*
capa
)
{
struct
iwl_tlv_ucode_header
*
ucode
=
(
void
*
)
ucode_raw
->
data
;
struct
iwl_ucode_tlv
*
tlv
;
size_t
len
=
ucode_raw
->
size
;
const
u8
*
data
;
int
wanted_alternative
=
iwlagn_mod_params
.
wanted_ucode_alternative
;
int
tmp
;
u64
alternatives
;
u32
tlv_len
;
enum
iwl_ucode_tlv_type
tlv_type
;
const
u8
*
tlv_data
;
if
(
len
<
sizeof
(
*
ucode
))
{
IWL_ERR
(
priv
,
"uCode has invalid length: %zd
\n
"
,
len
);
return
-
EINVAL
;
}
if
(
ucode
->
magic
!=
cpu_to_le32
(
IWL_TLV_UCODE_MAGIC
))
{
IWL_ERR
(
priv
,
"invalid uCode magic: 0X%x
\n
"
,
le32_to_cpu
(
ucode
->
magic
));
return
-
EINVAL
;
}
/*
* Check which alternatives are present, and "downgrade"
* when the chosen alternative is not present, warning
* the user when that happens. Some files may not have
* any alternatives, so don't warn in that case.
*/
alternatives
=
le64_to_cpu
(
ucode
->
alternatives
);
tmp
=
wanted_alternative
;
if
(
wanted_alternative
>
63
)
wanted_alternative
=
63
;
while
(
wanted_alternative
&&
!
(
alternatives
&
BIT
(
wanted_alternative
)))
wanted_alternative
--
;
if
(
wanted_alternative
&&
wanted_alternative
!=
tmp
)
IWL_WARN
(
priv
,
"uCode alternative %d not available, choosing %d
\n
"
,
tmp
,
wanted_alternative
);
priv
->
ucode_ver
=
le32_to_cpu
(
ucode
->
ver
);
pieces
->
build
=
le32_to_cpu
(
ucode
->
build
);
data
=
ucode
->
data
;
len
-=
sizeof
(
*
ucode
);
while
(
len
>=
sizeof
(
*
tlv
))
{
u16
tlv_alt
;
len
-=
sizeof
(
*
tlv
);
tlv
=
(
void
*
)
data
;
tlv_len
=
le32_to_cpu
(
tlv
->
length
);
tlv_type
=
le16_to_cpu
(
tlv
->
type
);
tlv_alt
=
le16_to_cpu
(
tlv
->
alternative
);
tlv_data
=
tlv
->
data
;
if
(
len
<
tlv_len
)
{
IWL_ERR
(
priv
,
"invalid TLV len: %zd/%u
\n
"
,
len
,
tlv_len
);
return
-
EINVAL
;
}
len
-=
ALIGN
(
tlv_len
,
4
);
data
+=
sizeof
(
*
tlv
)
+
ALIGN
(
tlv_len
,
4
);
/*
* Alternative 0 is always valid.
*
* Skip alternative TLVs that are not selected.
*/
if
(
tlv_alt
!=
0
&&
tlv_alt
!=
wanted_alternative
)
continue
;
switch
(
tlv_type
)
{
case
IWL_UCODE_TLV_INST
:
pieces
->
inst
=
tlv_data
;
pieces
->
inst_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_DATA
:
pieces
->
data
=
tlv_data
;
pieces
->
data_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_INIT
:
pieces
->
init
=
tlv_data
;
pieces
->
init_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_INIT_DATA
:
pieces
->
init_data
=
tlv_data
;
pieces
->
init_data_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_BOOT
:
IWL_ERR
(
priv
,
"Found unexpected BOOT ucode
\n
"
);
break
;
case
IWL_UCODE_TLV_PROBE_MAX_LEN
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
capa
->
max_probe_length
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_PAN
:
if
(
tlv_len
)
goto
invalid_tlv_len
;
capa
->
flags
|=
IWL_UCODE_TLV_FLAGS_PAN
;
break
;
case
IWL_UCODE_TLV_FLAGS
:
/* must be at least one u32 */
if
(
tlv_len
<
sizeof
(
u32
))
goto
invalid_tlv_len
;
/* and a proper number of u32s */
if
(
tlv_len
%
sizeof
(
u32
))
goto
invalid_tlv_len
;
/*
* This driver only reads the first u32 as
* right now no more features are defined,
* if that changes then either the driver
* will not work with the new firmware, or
* it'll not take advantage of new features.
*/
capa
->
flags
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_INIT_EVTLOG_PTR
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
init_evtlog_ptr
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_INIT_EVTLOG_SIZE
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
init_evtlog_size
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_INIT_ERRLOG_PTR
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
init_errlog_ptr
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_RUNT_EVTLOG_PTR
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
inst_evtlog_ptr
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
inst_evtlog_size
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_RUNT_ERRLOG_PTR
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
pieces
->
inst_errlog_ptr
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
case
IWL_UCODE_TLV_ENHANCE_SENS_TBL
:
if
(
tlv_len
)
goto
invalid_tlv_len
;
priv
->
enhance_sensitivity_table
=
true
;
break
;
case
IWL_UCODE_TLV_WOWLAN_INST
:
pieces
->
wowlan_inst
=
tlv_data
;
pieces
->
wowlan_inst_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_WOWLAN_DATA
:
pieces
->
wowlan_data
=
tlv_data
;
pieces
->
wowlan_data_size
=
tlv_len
;
break
;
case
IWL_UCODE_TLV_PHY_CALIBRATION_SIZE
:
if
(
tlv_len
!=
sizeof
(
u32
))
goto
invalid_tlv_len
;
capa
->
standard_phy_calibration_size
=
le32_to_cpup
((
__le32
*
)
tlv_data
);
break
;
default:
IWL_DEBUG_INFO
(
priv
,
"unknown TLV: %d
\n
"
,
tlv_type
);
break
;
}
}
if
(
len
)
{
IWL_ERR
(
priv
,
"invalid TLV after parsing: %zd
\n
"
,
len
);
iwl_print_hex_dump
(
priv
,
IWL_DL_FW
,
(
u8
*
)
data
,
len
);
return
-
EINVAL
;
}
return
0
;
invalid_tlv_len:
IWL_ERR
(
priv
,
"TLV %d has invalid size: %u
\n
"
,
tlv_type
,
tlv_len
);
iwl_print_hex_dump
(
priv
,
IWL_DL_FW
,
tlv_data
,
tlv_len
);
return
-
EINVAL
;
}
/**
* iwl_ucode_callback - callback when firmware was loaded
*
* If loaded successfully, copies the firmware into buffers
* for the card to fetch (via DMA).
*/
static
void
iwl_ucode_callback
(
const
struct
firmware
*
ucode_raw
,
void
*
context
)
{
struct
iwl_priv
*
priv
=
context
;
struct
iwl_ucode_header
*
ucode
;
int
err
;
struct
iwlagn_firmware_pieces
pieces
;
const
unsigned
int
api_max
=
cfg
(
priv
)
->
ucode_api_max
;
unsigned
int
api_ok
=
cfg
(
priv
)
->
ucode_api_ok
;
const
unsigned
int
api_min
=
cfg
(
priv
)
->
ucode_api_min
;
u32
api_ver
;
char
buildstr
[
25
];
u32
build
;
struct
iwlagn_ucode_capabilities
ucode_capa
=
{
.
max_probe_length
=
200
,
.
standard_phy_calibration_size
=
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE
,
};
if
(
!
api_ok
)
api_ok
=
api_max
;
memset
(
&
pieces
,
0
,
sizeof
(
pieces
));
if
(
!
ucode_raw
)
{
if
(
priv
->
fw_index
<=
api_ok
)
IWL_ERR
(
priv
,
"request for firmware file '%s' failed.
\n
"
,
priv
->
firmware_name
);
goto
try_again
;
}
IWL_DEBUG_INFO
(
priv
,
"Loaded firmware file '%s' (%zd bytes).
\n
"
,
priv
->
firmware_name
,
ucode_raw
->
size
);
/* Make sure that we got at least the API version number */
if
(
ucode_raw
->
size
<
4
)
{
IWL_ERR
(
priv
,
"File size way too small!
\n
"
);
goto
try_again
;
}
/* Data from ucode file: header followed by uCode images */
ucode
=
(
struct
iwl_ucode_header
*
)
ucode_raw
->
data
;
if
(
ucode
->
ver
)
err
=
iwlagn_load_legacy_firmware
(
priv
,
ucode_raw
,
&
pieces
);
else
err
=
iwlagn_load_firmware
(
priv
,
ucode_raw
,
&
pieces
,
&
ucode_capa
);
if
(
err
)
goto
try_again
;
api_ver
=
IWL_UCODE_API
(
priv
->
ucode_ver
);
build
=
pieces
.
build
;
/*
* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
* on the API version read from firmware header from here on forward
*/
/* no api version check required for experimental uCode */
if
(
priv
->
fw_index
!=
UCODE_EXPERIMENTAL_INDEX
)
{
if
(
api_ver
<
api_min
||
api_ver
>
api_max
)
{
IWL_ERR
(
priv
,
"Driver unable to support your firmware API. "
"Driver supports v%u, firmware is v%u.
\n
"
,
api_max
,
api_ver
);
goto
try_again
;
}
if
(
api_ver
<
api_ok
)
{
if
(
api_ok
!=
api_max
)
IWL_ERR
(
priv
,
"Firmware has old API version, "
"expected v%u through v%u, got v%u.
\n
"
,
api_ok
,
api_max
,
api_ver
);
else
IWL_ERR
(
priv
,
"Firmware has old API version, "
"expected v%u, got v%u.
\n
"
,
api_max
,
api_ver
);
IWL_ERR
(
priv
,
"New firmware can be obtained from "
"http://www.intellinuxwireless.org/.
\n
"
);
}
}
if
(
build
)
sprintf
(
buildstr
,
" build %u%s"
,
build
,
(
priv
->
fw_index
==
UCODE_EXPERIMENTAL_INDEX
)
?
" (EXP)"
:
""
);
else
buildstr
[
0
]
=
'\0'
;
IWL_INFO
(
priv
,
"loaded firmware version %u.%u.%u.%u%s
\n
"
,
IWL_UCODE_MAJOR
(
priv
->
ucode_ver
),
IWL_UCODE_MINOR
(
priv
->
ucode_ver
),
IWL_UCODE_API
(
priv
->
ucode_ver
),
IWL_UCODE_SERIAL
(
priv
->
ucode_ver
),
buildstr
);
snprintf
(
priv
->
hw
->
wiphy
->
fw_version
,
sizeof
(
priv
->
hw
->
wiphy
->
fw_version
),
"%u.%u.%u.%u%s"
,
IWL_UCODE_MAJOR
(
priv
->
ucode_ver
),
IWL_UCODE_MINOR
(
priv
->
ucode_ver
),
IWL_UCODE_API
(
priv
->
ucode_ver
),
IWL_UCODE_SERIAL
(
priv
->
ucode_ver
),
buildstr
);
/*
* For any of the failures below (before allocating pci memory)
* we will try to load a version with a smaller API -- maybe the
* user just got a corrupted version of the latest API.
*/
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr ucode version raw = 0x%x
\n
"
,
priv
->
ucode_ver
);
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr runtime inst size = %Zd
\n
"
,
pieces
.
inst_size
);
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr runtime data size = %Zd
\n
"
,
pieces
.
data_size
);
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr init inst size = %Zd
\n
"
,
pieces
.
init_size
);
IWL_DEBUG_INFO
(
priv
,
"f/w package hdr init data size = %Zd
\n
"
,
pieces
.
init_data_size
);
/* Verify that uCode images will fit in card's SRAM */
if
(
pieces
.
inst_size
>
hw_params
(
priv
).
max_inst_size
)
{
IWL_ERR
(
priv
,
"uCode instr len %Zd too large to fit in
\n
"
,
pieces
.
inst_size
);
goto
try_again
;
}
if
(
pieces
.
data_size
>
hw_params
(
priv
).
max_data_size
)
{
IWL_ERR
(
priv
,
"uCode data len %Zd too large to fit in
\n
"
,
pieces
.
data_size
);
goto
try_again
;
}
if
(
pieces
.
init_size
>
hw_params
(
priv
).
max_inst_size
)
{
IWL_ERR
(
priv
,
"uCode init instr len %Zd too large to fit in
\n
"
,
pieces
.
init_size
);
goto
try_again
;
}
if
(
pieces
.
init_data_size
>
hw_params
(
priv
).
max_data_size
)
{
IWL_ERR
(
priv
,
"uCode init data len %Zd too large to fit in
\n
"
,
pieces
.
init_data_size
);
goto
try_again
;
}
/* Allocate ucode buffers for card's bus-master loading ... */
/* Runtime instructions and 2 copies of data:
* 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */
if
(
iwl_alloc_fw_desc
(
trans
(
priv
),
&
trans
(
priv
)
->
ucode_rt
.
code
,
pieces
.
inst
,
pieces
.
inst_size
))
goto
err_pci_alloc
;
if
(
iwl_alloc_fw_desc
(
trans
(
priv
),
&
trans
(
priv
)
->
ucode_rt
.
data
,
pieces
.
data
,
pieces
.
data_size
))
goto
err_pci_alloc
;
/* Initialization instructions and data */
if
(
pieces
.
init_size
&&
pieces
.
init_data_size
)
{
if
(
iwl_alloc_fw_desc
(
trans
(
priv
),
&
trans
(
priv
)
->
ucode_init
.
code
,
pieces
.
init
,
pieces
.
init_size
))
goto
err_pci_alloc
;
if
(
iwl_alloc_fw_desc
(
trans
(
priv
),
&
trans
(
priv
)
->
ucode_init
.
data
,
pieces
.
init_data
,
pieces
.
init_data_size
))
goto
err_pci_alloc
;
}
/* WoWLAN instructions and data */
if
(
pieces
.
wowlan_inst_size
&&
pieces
.
wowlan_data_size
)
{
if
(
iwl_alloc_fw_desc
(
trans
(
priv
),
&
trans
(
priv
)
->
ucode_wowlan
.
code
,
pieces
.
wowlan_inst
,
pieces
.
wowlan_inst_size
))
goto
err_pci_alloc
;
if
(
iwl_alloc_fw_desc
(
trans
(
priv
),
&
trans
(
priv
)
->
ucode_wowlan
.
data
,
pieces
.
wowlan_data
,
pieces
.
wowlan_data_size
))
goto
err_pci_alloc
;
}
/* Now that we can no longer fail, copy information */
/*
* The (size - 16) / 12 formula is based on the information recorded
* for each event, which is of mode 1 (including timestamp) for all
* new microcodes that include this information.
*/
priv
->
init_evtlog_ptr
=
pieces
.
init_evtlog_ptr
;
if
(
pieces
.
init_evtlog_size
)
priv
->
init_evtlog_size
=
(
pieces
.
init_evtlog_size
-
16
)
/
12
;
else
priv
->
init_evtlog_size
=
cfg
(
priv
)
->
base_params
->
max_event_log_size
;
priv
->
init_errlog_ptr
=
pieces
.
init_errlog_ptr
;
priv
->
inst_evtlog_ptr
=
pieces
.
inst_evtlog_ptr
;
if
(
pieces
.
inst_evtlog_size
)
priv
->
inst_evtlog_size
=
(
pieces
.
inst_evtlog_size
-
16
)
/
12
;
else
priv
->
inst_evtlog_size
=
cfg
(
priv
)
->
base_params
->
max_event_log_size
;
priv
->
inst_errlog_ptr
=
pieces
.
inst_errlog_ptr
;
#ifndef CONFIG_IWLWIFI_P2P
ucode_capa
.
flags
&=
~
IWL_UCODE_TLV_FLAGS_PAN
;
#endif
priv
->
new_scan_threshold_behaviour
=
!!
(
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_NEWSCAN
);
if
(
!
(
cfg
(
priv
)
->
sku
&
EEPROM_SKU_CAP_IPAN_ENABLE
))
ucode_capa
.
flags
&=
~
IWL_UCODE_TLV_FLAGS_PAN
;
/*
* if not PAN, then don't support P2P -- might be a uCode
* packaging bug or due to the eeprom check above
*/
if
(
!
(
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_PAN
))
ucode_capa
.
flags
&=
~
IWL_UCODE_TLV_FLAGS_P2P
;
if
(
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_PAN
)
{
priv
->
sta_key_max_num
=
STA_KEY_MAX_NUM_PAN
;
priv
->
shrd
->
cmd_queue
=
IWL_IPAN_CMD_QUEUE_NUM
;
}
else
{
priv
->
sta_key_max_num
=
STA_KEY_MAX_NUM
;
priv
->
shrd
->
cmd_queue
=
IWL_DEFAULT_CMD_QUEUE_NUM
;
}
/*
* figure out the offset of chain noise reset and gain commands
* base on the size of standard phy calibration commands table size
*/
if
(
ucode_capa
.
standard_phy_calibration_size
>
IWL_MAX_PHY_CALIBRATE_TBL_SIZE
)
ucode_capa
.
standard_phy_calibration_size
=
IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE
;
priv
->
phy_calib_chain_noise_reset_cmd
=
ucode_capa
.
standard_phy_calibration_size
;
priv
->
phy_calib_chain_noise_gain_cmd
=
ucode_capa
.
standard_phy_calibration_size
+
1
;
/* initialize all valid contexts */
iwl_init_context
(
priv
,
ucode_capa
.
flags
);
/**************************************************
* This is still part of probe() in a sense...
*
* 9. Setup and register with mac80211 and debugfs
**************************************************/
err
=
iwlagn_mac_setup_register
(
priv
,
&
ucode_capa
);
if
(
err
)
goto
out_unbind
;
err
=
iwl_dbgfs_register
(
priv
,
DRV_NAME
);
if
(
err
)
IWL_ERR
(
priv
,
"failed to create debugfs files. Ignoring error: %d
\n
"
,
err
);
/* We have our copies now, allow OS release its copies */
release_firmware
(
ucode_raw
);
complete
(
&
priv
->
firmware_loading_complete
);
return
;
try_again:
/* try next, if any */
if
(
iwl_request_firmware
(
priv
,
false
))
goto
out_unbind
;
release_firmware
(
ucode_raw
);
return
;
err_pci_alloc:
IWL_ERR
(
priv
,
"failed to allocate pci memory
\n
"
);
iwl_dealloc_ucode
(
trans
(
priv
));
out_unbind:
complete
(
&
priv
->
firmware_loading_complete
);
device_release_driver
(
trans
(
priv
)
->
dev
);
release_firmware
(
ucode_raw
);
}
drivers/net/wireless/iwlwifi/iwl-ucode.h
0 → 100644
View file @
8f0bb5ae
/******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef __iwl_ucode_h__
#define __iwl_ucode_h__
/* v1/v2 uCode file layout */
struct
iwl_ucode_header
{
__le32
ver
;
/* major/minor/API/serial */
union
{
struct
{
__le32
inst_size
;
/* bytes of runtime code */
__le32
data_size
;
/* bytes of runtime data */
__le32
init_size
;
/* bytes of init code */
__le32
init_data_size
;
/* bytes of init data */
__le32
boot_size
;
/* bytes of bootstrap code */
u8
data
[
0
];
/* in same order as sizes */
}
v1
;
struct
{
__le32
build
;
/* build number */
__le32
inst_size
;
/* bytes of runtime code */
__le32
data_size
;
/* bytes of runtime data */
__le32
init_size
;
/* bytes of init code */
__le32
init_data_size
;
/* bytes of init data */
__le32
boot_size
;
/* bytes of bootstrap code */
u8
data
[
0
];
/* in same order as sizes */
}
v2
;
}
u
;
};
/*
* new TLV uCode file layout
*
* The new TLV file format contains TLVs, that each specify
* some piece of data. To facilitate "groups", for example
* different instruction image with different capabilities,
* bundled with the same init image, an alternative mechanism
* is provided:
* When the alternative field is 0, that means that the item
* is always valid. When it is non-zero, then it is only
* valid in conjunction with items of the same alternative,
* in which case the driver (user) selects one alternative
* to use.
*/
enum
iwl_ucode_tlv_type
{
IWL_UCODE_TLV_INVALID
=
0
,
/* unused */
IWL_UCODE_TLV_INST
=
1
,
IWL_UCODE_TLV_DATA
=
2
,
IWL_UCODE_TLV_INIT
=
3
,
IWL_UCODE_TLV_INIT_DATA
=
4
,
IWL_UCODE_TLV_BOOT
=
5
,
IWL_UCODE_TLV_PROBE_MAX_LEN
=
6
,
/* a u32 value */
IWL_UCODE_TLV_PAN
=
7
,
IWL_UCODE_TLV_RUNT_EVTLOG_PTR
=
8
,
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE
=
9
,
IWL_UCODE_TLV_RUNT_ERRLOG_PTR
=
10
,
IWL_UCODE_TLV_INIT_EVTLOG_PTR
=
11
,
IWL_UCODE_TLV_INIT_EVTLOG_SIZE
=
12
,
IWL_UCODE_TLV_INIT_ERRLOG_PTR
=
13
,
IWL_UCODE_TLV_ENHANCE_SENS_TBL
=
14
,
IWL_UCODE_TLV_PHY_CALIBRATION_SIZE
=
15
,
IWL_UCODE_TLV_WOWLAN_INST
=
16
,
IWL_UCODE_TLV_WOWLAN_DATA
=
17
,
IWL_UCODE_TLV_FLAGS
=
18
,
};
/**
* enum iwl_ucode_tlv_flag - ucode API flags
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
* was a separate TLV but moved here to save space.
* @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
* treats good CRC threshold as a boolean
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
*/
enum
iwl_ucode_tlv_flag
{
IWL_UCODE_TLV_FLAGS_PAN
=
BIT
(
0
),
IWL_UCODE_TLV_FLAGS_NEWSCAN
=
BIT
(
1
),
IWL_UCODE_TLV_FLAGS_MFP
=
BIT
(
2
),
IWL_UCODE_TLV_FLAGS_P2P
=
BIT
(
3
),
};
struct
iwl_ucode_tlv
{
__le16
type
;
/* see above */
__le16
alternative
;
/* see comment */
__le32
length
;
/* not including type/length fields */
u8
data
[
0
];
};
#define IWL_TLV_UCODE_MAGIC 0x0a4c5749
struct
iwl_tlv_ucode_header
{
/*
* The TLV style ucode header is distinguished from
* the v1/v2 style header by first four bytes being
* zero, as such is an invalid combination of
* major/minor/API/serial versions.
*/
__le32
zero
;
__le32
magic
;
u8
human_readable
[
64
];
__le32
ver
;
/* major/minor/API/serial */
__le32
build
;
__le64
alternatives
;
/* bitmask of valid alternatives */
/*
* The data contained herein has a TLV layout,
* see above for the TLV header and types.
* Note that each TLV is padded to a length
* that is a multiple of 4 for alignment.
*/
u8
data
[
0
];
};
struct
iwl_priv
;
int
__must_check
iwl_request_firmware
(
struct
iwl_priv
*
priv
,
bool
first
);
#endif
/* __iwl_ucode_h__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment