Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
8f0bb5ae
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
8f0bb5ae
编写于
2月 06, 2012
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'wireless-next' of
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi
上级
b9d90578
6fe7dd0d
变更
30
隐藏空白更改
内联
并排
Showing
30 changed file
with
1837 addition
and
1776 deletion
+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
未找到文件。
drivers/net/wireless/iwlwifi/iwl-1000.c
浏览文件 @
8f0bb5ae
...
@@ -84,13 +84,13 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
...
@@ -84,13 +84,13 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
static
void
iwl1000_nic_config
(
struct
iwl_priv
*
priv
)
static
void
iwl1000_nic_config
(
struct
iwl_priv
*
priv
)
{
{
/* set CSR_HW_CONFIG_REG for uCode use */
/* 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_RADIO_SI
|
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI
);
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI
);
/* Setting digital SVR for 1000 card to 1.32V */
/* Setting digital SVR for 1000 card to 1.32V */
/* locking is acquired in iwl_set_bits_mask_prph() function */
/* 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_DIGITAL_VOLTAGE_1_32
,
~
APMG_SVR_VOLTAGE_CONFIG_BIT_MSK
);
~
APMG_SVR_VOLTAGE_CONFIG_BIT_MSK
);
}
}
...
@@ -128,8 +128,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
...
@@ -128,8 +128,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_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_data_size
=
IWLAGN_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWLAGN_RTC_INST_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWLAGN_RTC_INST_SIZE
;
...
...
drivers/net/wireless/iwlwifi/iwl-2000.c
浏览文件 @
8f0bb5ae
...
@@ -87,7 +87,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
...
@@ -87,7 +87,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
iwl_rf_config
(
priv
);
iwl_rf_config
(
priv
);
if
(
cfg
(
priv
)
->
iq_invert
)
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
);
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER
);
}
}
...
@@ -124,8 +124,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
...
@@ -124,8 +124,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_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_data_size
=
IWL60_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWL60_RTC_INST_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWL60_RTC_INST_SIZE
;
...
...
drivers/net/wireless/iwlwifi/iwl-5000.c
浏览文件 @
8f0bb5ae
...
@@ -73,7 +73,7 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
...
@@ -73,7 +73,7 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
* (PCIe power is lost before PERST# is asserted),
* (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back.
* 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
,
~
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)
...
@@ -170,8 +170,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_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_data_size
=
IWLAGN_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWLAGN_RTC_INST_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)
...
@@ -199,8 +197,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_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_data_size
=
IWLAGN_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWLAGN_RTC_INST_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWLAGN_RTC_INST_SIZE
;
...
...
drivers/net/wireless/iwlwifi/iwl-6000.c
浏览文件 @
8f0bb5ae
...
@@ -82,7 +82,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv)
...
@@ -82,7 +82,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv)
{
{
/* Indicate calibration version to uCode. */
/* Indicate calibration version to uCode. */
if
(
iwl_eeprom_calib_version
(
priv
->
shrd
)
>=
6
)
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
);
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6
);
}
}
...
@@ -90,9 +90,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
...
@@ -90,9 +90,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
{
{
/* Indicate calibration version to uCode. */
/* Indicate calibration version to uCode. */
if
(
iwl_eeprom_calib_version
(
priv
->
shrd
)
>=
6
)
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
);
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
);
CSR_GP_DRIVER_REG_BIT_6050_1x2
);
}
}
...
@@ -104,7 +104,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
...
@@ -104,7 +104,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
/* no locking required for register write */
/* no locking required for register write */
if
(
cfg
(
priv
)
->
pa_type
==
IWL_PA_INTERNAL
)
{
if
(
cfg
(
priv
)
->
pa_type
==
IWL_PA_INTERNAL
)
{
/* 2x2 IPA phy type */
/* 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
);
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA
);
}
}
/* do additional nic configuration if needed */
/* do additional nic configuration if needed */
...
@@ -145,8 +145,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
...
@@ -145,8 +145,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params
.
num_of_queues
;
iwlagn_mod_params
.
num_of_queues
;
hw_params
(
priv
).
max_txq_num
=
cfg
(
priv
)
->
base_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_data_size
=
IWL60_RTC_DATA_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWL60_RTC_INST_SIZE
;
hw_params
(
priv
).
max_inst_size
=
IWL60_RTC_INST_SIZE
;
...
...
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
浏览文件 @
8f0bb5ae
...
@@ -628,16 +628,16 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
...
@@ -628,16 +628,16 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
if
(
flags
&
(
SW_CARD_DISABLED
|
HW_CARD_DISABLED
|
if
(
flags
&
(
SW_CARD_DISABLED
|
HW_CARD_DISABLED
|
CT_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
);
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
);
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED
);
if
(
!
(
flags
&
RXON_CARD_DISABLED
))
{
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
);
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
);
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED
);
}
}
if
(
flags
&
CT_CARD_DISABLED
)
if
(
flags
&
CT_CARD_DISABLED
)
...
...
drivers/net/wireless/iwlwifi/iwl-agn-tt.c
浏览文件 @
8f0bb5ae
...
@@ -178,19 +178,19 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
...
@@ -178,19 +178,19 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
if
(
tt
->
state
==
IWL_TI_CT_KILL
)
{
if
(
tt
->
state
==
IWL_TI_CT_KILL
)
{
if
(
priv
->
thermal_throttle
.
ct_kill_toggle
)
{
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
);
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT
);
priv
->
thermal_throttle
.
ct_kill_toggle
=
false
;
priv
->
thermal_throttle
.
ct_kill_toggle
=
false
;
}
else
{
}
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
);
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT
);
priv
->
thermal_throttle
.
ct_kill_toggle
=
true
;
priv
->
thermal_throttle
.
ct_kill_toggle
=
true
;
}
}
iwl_read32
(
bu
s
(
priv
),
CSR_UCODE_DRV_GP1
);
iwl_read32
(
tran
s
(
priv
),
CSR_UCODE_DRV_GP1
);
spin_lock_irqsave
(
&
bu
s
(
priv
)
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
(
priv
)
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
bu
s
(
priv
)))
if
(
!
iwl_grab_nic_access
(
tran
s
(
priv
)))
iwl_release_nic_access
(
bu
s
(
priv
));
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
);
/* Reschedule the ct_kill timer to occur in
/* Reschedule the ct_kill timer to occur in
* CT_KILL_EXIT_DURATION seconds to ensure we get a
* CT_KILL_EXIT_DURATION seconds to ensure we get a
...
...
drivers/net/wireless/iwlwifi/iwl-agn.c
浏览文件 @
8f0bb5ae
...
@@ -34,7 +34,6 @@
...
@@ -34,7 +34,6 @@
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/if_arp.h>
...
@@ -42,6 +41,7 @@
...
@@ -42,6 +41,7 @@
#include <asm/div64.h>
#include <asm/div64.h>
#include "iwl-ucode.h"
#include "iwl-eeprom.h"
#include "iwl-eeprom.h"
#include "iwl-wifi.h"
#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-dev.h"
...
@@ -328,14 +328,14 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
...
@@ -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
));
ptr
=
base
+
(
4
*
sizeof
(
u32
))
+
(
start_idx
*
3
*
sizeof
(
u32
));
/* Make sure device is powered up for SRAM reads */
/* Make sure device is powered up for SRAM reads */
spin_lock_irqsave
(
&
bu
s
(
priv
)
->
reg_lock
,
reg_flags
);
spin_lock_irqsave
(
&
tran
s
(
priv
)
->
reg_lock
,
reg_flags
);
if
(
iwl_grab_nic_access
(
bu
s
(
priv
)))
{
if
(
iwl_grab_nic_access
(
tran
s
(
priv
)))
{
spin_unlock_irqrestore
(
&
bu
s
(
priv
)
->
reg_lock
,
reg_flags
);
spin_unlock_irqrestore
(
&
tran
s
(
priv
)
->
reg_lock
,
reg_flags
);
return
;
return
;
}
}
/* Set starting address; reads will auto-increment */
/* 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
();
rmb
();
/*
/*
...
@@ -352,19 +352,19 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
...
@@ -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.
* place event id # at far right for easier visual parsing.
*/
*/
for
(
i
=
0
;
i
<
num_events
;
i
++
)
{
for
(
i
=
0
;
i
<
num_events
;
i
++
)
{
ev
=
iwl_read32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
ev
=
iwl_read32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
time
=
iwl_read32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
time
=
iwl_read32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
if
(
mode
==
0
)
{
if
(
mode
==
0
)
{
trace_iwlwifi_dev_ucode_cont_event
(
priv
,
0
,
time
,
ev
);
trace_iwlwifi_dev_ucode_cont_event
(
priv
,
0
,
time
,
ev
);
}
else
{
}
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
,
trace_iwlwifi_dev_ucode_cont_event
(
priv
,
time
,
data
,
ev
);
data
,
ev
);
}
}
}
}
/* Allow device to power down */
/* Allow device to power down */
iwl_release_nic_access
(
bu
s
(
priv
));
iwl_release_nic_access
(
tran
s
(
priv
));
spin_unlock_irqrestore
(
&
bu
s
(
priv
)
->
reg_lock
,
reg_flags
);
spin_unlock_irqrestore
(
&
tran
s
(
priv
)
->
reg_lock
,
reg_flags
);
}
}
static
void
iwl_continuous_event_trace
(
struct
iwl_priv
*
priv
)
static
void
iwl_continuous_event_trace
(
struct
iwl_priv
*
priv
)
...
@@ -383,7 +383,7 @@ 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
;
base
=
priv
->
shrd
->
device_pointers
.
log_event_table
;
if
(
iwlagn_hw_valid_rtc_data_addr
(
base
))
{
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
;
capacity
=
read
.
capacity
;
mode
=
read
.
mode
;
mode
=
read
.
mode
;
...
@@ -490,7 +490,7 @@ static void iwl_bg_tx_flush(struct work_struct *work)
...
@@ -490,7 +490,7 @@ static void iwl_bg_tx_flush(struct work_struct *work)
iwlagn_dev_txfifo_flush
(
priv
,
IWL_DROP_ALL
);
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
;
int
i
;
...
@@ -513,6 +513,7 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
...
@@ -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
].
qos_cmd
=
REPLY_QOS_PARAM
;
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
ap_sta_id
=
IWL_AP_ID
;
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
].
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
=
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
exclusive_interface_modes
=
BIT
(
NL80211_IFTYPE_ADHOC
);
BIT
(
NL80211_IFTYPE_ADHOC
);
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
interface_modes
=
priv
->
contexts
[
IWL_RXON_CTX_BSS
].
interface_modes
=
...
@@ -547,609 +548,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
...
@@ -547,609 +548,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
BUILD_BUG_ON
(
NUM_IWL_RXON_CTX
!=
2
);
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
)
static
void
iwl_rf_kill_ct_config
(
struct
iwl_priv
*
priv
)
{
{
struct
iwl_ct_kill_config
cmd
;
struct
iwl_ct_kill_config
cmd
;
...
@@ -1158,7 +556,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
...
@@ -1158,7 +556,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
int
ret
=
0
;
int
ret
=
0
;
spin_lock_irqsave
(
&
priv
->
shrd
->
lock
,
flags
);
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
);
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT
);
spin_unlock_irqrestore
(
&
priv
->
shrd
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
priv
->
shrd
->
lock
,
flags
);
priv
->
thermal_throttle
.
ct_kill_toggle
=
false
;
priv
->
thermal_throttle
.
ct_kill_toggle
=
false
;
...
@@ -1243,9 +641,6 @@ int iwl_alive_start(struct iwl_priv *priv)
...
@@ -1243,9 +641,6 @@ int iwl_alive_start(struct iwl_priv *priv)
int
ret
=
0
;
int
ret
=
0
;
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
IWL_RXON_CTX_BSS
];
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
"
);
IWL_DEBUG_INFO
(
priv
,
"Runtime Alive received.
\n
"
);
/* After the ALIVE response, we can send host commands to the uCode */
/* 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)
...
@@ -1692,13 +1087,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
#endif
#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 */
/* Size of one Rx buffer in host DRAM */
#define IWL_RX_BUF_SIZE_4K (4 * 1024)
#define IWL_RX_BUF_SIZE_4K (4 * 1024)
#define IWL_RX_BUF_SIZE_8K (8 * 1024)
#define IWL_RX_BUF_SIZE_8K (8 * 1024)
...
@@ -1730,32 +1118,32 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
...
@@ -1730,32 +1118,32 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
static
void
iwl_debug_config
(
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
#ifdef CONFIG_IWLWIFI_DEBUG
"enabled
\n
"
);
"enabled
\n
"
);
#else
#else
"disabled
\n
"
);
"disabled
\n
"
);
#endif
#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
#ifdef CONFIG_IWLWIFI_DEBUGFS
"enabled
\n
"
);
"enabled
\n
"
);
#else
#else
"disabled
\n
"
);
"disabled
\n
"
);
#endif
#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
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
"enabled
\n
"
);
"enabled
\n
"
);
#else
#else
"disabled
\n
"
);
"disabled
\n
"
);
#endif
#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
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
"enabled
\n
"
);
"enabled
\n
"
);
#else
#else
"disabled
\n
"
);
"disabled
\n
"
);
#endif
#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
#ifdef CONFIG_IWLWIFI_P2P
"enabled
\n
"
);
"enabled
\n
"
);
#else
#else
...
@@ -1770,7 +1158,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
...
@@ -1770,7 +1158,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
struct
iwl_priv
*
priv
;
struct
iwl_priv
*
priv
;
struct
ieee80211_hw
*
hw
;
struct
ieee80211_hw
*
hw
;
u16
num_mac
;
u16
num_mac
;
u32
hw_rev
;
/************************
/************************
* 1. Allocating HW data
* 1. Allocating HW data
...
@@ -1783,22 +1170,14 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
...
@@ -1783,22 +1170,14 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
}
}
priv
=
hw
->
priv
;
priv
=
hw
->
priv
;
priv
->
shrd
=
&
priv
->
_shrd
;
priv
->
shrd
=
bus
->
shrd
;
bus
->
shrd
=
priv
->
shrd
;
priv
->
shrd
->
bus
=
bus
;
priv
->
shrd
->
priv
=
priv
;
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. */
/* 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_config
(
priv
);
IWL_DEBUG_INFO
(
priv
,
"*** LOAD DRIVER ***
\n
"
);
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,
...
@@ -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
/* these spin locks will be used in apm_ops.init and EEPROM access
* we should init now
* 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
);
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
* 3. Read REV register
***********************/
***********************/
hw_rev
=
iwl_hw_detect
(
priv
);
IWL_INFO
(
priv
,
"Detected %s, REV=0x%X
\n
"
,
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
)
if
(
err
)
goto
out_free_trans
;
goto
out_free_traffic_mem
;
if
(
iwl_trans_prepare_card_hw
(
trans
(
priv
)))
{
err
=
-
EIO
;
IWL_WARN
(
priv
,
"Failed, HW not ready
\n
"
);
goto
out_free_trans
;
}
/*****************
/*****************
* 4. Read EEPROM
* 4. Read EEPROM
*****************/
*****************/
/* Read the 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
)
{
if
(
err
)
{
IWL_ERR
(
priv
,
"Unable to init EEPROM
\n
"
);
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
);
err
=
iwl_eeprom_check_version
(
priv
);
if
(
err
)
if
(
err
)
...
@@ -1903,22 +1270,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
...
@@ -1903,22 +1270,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
iwl_setup_rx_handlers
(
priv
);
iwl_setup_rx_handlers
(
priv
);
iwl_testmode_init
(
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_power_initialize
(
priv
);
iwl_tt_initialize
(
priv
);
iwl_tt_initialize
(
priv
);
...
@@ -1936,8 +1287,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
...
@@ -1936,8 +1287,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
iwl_uninit_drv
(
priv
);
iwl_uninit_drv
(
priv
);
out_free_eeprom:
out_free_eeprom:
iwl_eeprom_free
(
priv
->
shrd
);
iwl_eeprom_free
(
priv
->
shrd
);
out_free_trans:
iwl_trans_free
(
trans
(
priv
));
out_free_traffic_mem:
out_free_traffic_mem:
iwl_free_traffic_mem
(
priv
);
iwl_free_traffic_mem
(
priv
);
ieee80211_free_hw
(
priv
->
hw
);
ieee80211_free_hw
(
priv
->
hw
);
...
@@ -1981,8 +1330,6 @@ void __devexit iwl_remove(struct iwl_priv * priv)
...
@@ -1981,8 +1330,6 @@ void __devexit iwl_remove(struct iwl_priv * priv)
priv
->
shrd
->
workqueue
=
NULL
;
priv
->
shrd
->
workqueue
=
NULL
;
iwl_free_traffic_mem
(
priv
);
iwl_free_traffic_mem
(
priv
);
iwl_trans_free
(
trans
(
priv
));
iwl_uninit_drv
(
priv
);
iwl_uninit_drv
(
priv
);
dev_kfree_skb
(
priv
->
beacon_skb
);
dev_kfree_skb
(
priv
->
beacon_skb
);
...
...
drivers/net/wireless/iwlwifi/iwl-agn.h
浏览文件 @
8f0bb5ae
...
@@ -73,8 +73,6 @@ struct iwlagn_ucode_capabilities {
...
@@ -73,8 +73,6 @@ struct iwlagn_ucode_capabilities {
extern
struct
ieee80211_ops
iwlagn_hw_ops
;
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
)
static
inline
void
iwl_set_calib_hdr
(
struct
iwl_calib_hdr
*
hdr
,
u8
cmd
)
{
{
hdr
->
op_code
=
cmd
;
hdr
->
op_code
=
cmd
;
...
@@ -109,6 +107,7 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
...
@@ -109,6 +107,7 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
int
iwlagn_rx_calib_result
(
struct
iwl_priv
*
priv
,
int
iwlagn_rx_calib_result
(
struct
iwl_priv
*
priv
,
struct
iwl_rx_mem_buffer
*
rxb
,
struct
iwl_rx_mem_buffer
*
rxb
,
struct
iwl_device_cmd
*
cmd
);
struct
iwl_device_cmd
*
cmd
);
void
iwl_init_context
(
struct
iwl_priv
*
priv
,
u32
ucode_flags
);
/* lib */
/* lib */
int
iwlagn_send_tx_power
(
struct
iwl_priv
*
priv
);
int
iwlagn_send_tx_power
(
struct
iwl_priv
*
priv
);
...
...
drivers/net/wireless/iwlwifi/iwl-bus.h
浏览文件 @
8f0bb5ae
...
@@ -118,88 +118,24 @@
...
@@ -118,88 +118,24 @@
struct
iwl_shared
;
struct
iwl_shared
;
struct
iwl_bus
;
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
* struct iwl_bus - bus common data
*
*
* This data is common to all bus layer implementations.
* This data is common to all bus layer implementations.
*
*
* @dev - pointer to struct device * that represents the device
* @ops - pointer to iwl_bus_ops
* @ops - pointer to iwl_bus_ops
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
* @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
* NB: for the time being this needs to be set by the upper layer since
* it allocates the shared data
* it allocates the shared data
* @irq - the irq number for the device
* @reg_lock - protect hw register access
*/
*/
struct
iwl_bus
{
struct
iwl_bus
{
struct
device
*
dev
;
const
struct
iwl_bus_ops
*
ops
;
struct
iwl_shared
*
shrd
;
struct
iwl_shared
*
shrd
;
unsigned
int
irq
;
spinlock_t
reg_lock
;
/* pointer to bus specific struct */
/* pointer to bus specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char
bus_specific
[
0
]
__attribute__
((
__aligned__
(
sizeof
(
void
*
))));
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
* Bus layer registration functions
******************************************************/
******************************************************/
...
...
drivers/net/wireless/iwlwifi/iwl-core.c
浏览文件 @
8f0bb5ae
...
@@ -203,10 +203,9 @@ int iwl_init_geos(struct iwl_priv *priv)
...
@@ -203,10 +203,9 @@ int iwl_init_geos(struct iwl_priv *priv)
if
((
priv
->
bands
[
IEEE80211_BAND_5GHZ
].
n_channels
==
0
)
&&
if
((
priv
->
bands
[
IEEE80211_BAND_5GHZ
].
n_channels
==
0
)
&&
cfg
(
priv
)
->
sku
&
EEPROM_SKU_CAP_BAND_52GHZ
)
{
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. "
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
;
cfg
(
priv
)
->
sku
&=
~
EEPROM_SKU_CAP_BAND_52GHZ
;
}
}
...
@@ -883,129 +882,6 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
...
@@ -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
iwl_set_tx_power
(
struct
iwl_priv
*
priv
,
s8
tx_power
,
bool
force
)
{
{
int
ret
;
int
ret
;
...
...
drivers/net/wireless/iwlwifi/iwl-core.h
浏览文件 @
8f0bb5ae
...
@@ -297,12 +297,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
...
@@ -297,12 +297,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
cfg
(
priv
)
->
bt_params
->
advanced_bt_coexist
;
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
;
extern
bool
bt_siso_mode
;
#endif
/* __iwl_core_h__ */
#endif
/* __iwl_core_h__ */
drivers/net/wireless/iwlwifi/iwl-debug.h
浏览文件 @
8f0bb5ae
...
@@ -35,10 +35,10 @@
...
@@ -35,10 +35,10 @@
struct
iwl_priv
;
struct
iwl_priv
;
/*No matter what is m (priv, bus, trans), this will work */
/*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_ERR(m, f, a...) dev_err(
tran
s(m)->dev, f, ## a)
#define IWL_WARN(m, f, a...) dev_warn(
bu
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(
bu
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(
bu
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) \
#define iwl_print_hex_error(m, p, len) \
do { \
do { \
...
@@ -50,7 +50,7 @@ do { \
...
@@ -50,7 +50,7 @@ do { \
#define IWL_DEBUG(m, level, fmt, ...) \
#define IWL_DEBUG(m, level, fmt, ...) \
do { \
do { \
if (iwl_get_debug_level((m)->shrd) & (level)) \
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__, \
in_interrupt() ? 'I' : 'U', __func__, \
##__VA_ARGS__); \
##__VA_ARGS__); \
} while (0)
} while (0)
...
@@ -59,7 +59,7 @@ do { \
...
@@ -59,7 +59,7 @@ do { \
do { \
do { \
if (iwl_get_debug_level((m)->shrd) & (level) && \
if (iwl_get_debug_level((m)->shrd) & (level) && \
net_ratelimit()) \
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__, \
in_interrupt() ? 'I' : 'U', __func__, \
##__VA_ARGS__); \
##__VA_ARGS__); \
} while (0)
} while (0)
...
@@ -74,12 +74,12 @@ do { \
...
@@ -74,12 +74,12 @@ do { \
#define IWL_DEBUG_QUIET_RFKILL(p, fmt, ...) \
#define IWL_DEBUG_QUIET_RFKILL(p, fmt, ...) \
do { \
do { \
if (!iwl_is_rfkill(p->shrd)) \
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__, \
in_interrupt() ? 'I' : 'U', __func__, \
##__VA_ARGS__); \
##__VA_ARGS__); \
else if (iwl_get_debug_level(p->shrd) & IWL_DL_RADIO) \
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) ", \
"(RFKILL) ", \
in_interrupt() ? 'I' : 'U', __func__, \
in_interrupt() ? 'I' : 'U', __func__, \
##__VA_ARGS__); \
##__VA_ARGS__); \
...
...
drivers/net/wireless/iwlwifi/iwl-debugfs.c
浏览文件 @
8f0bb5ae
...
@@ -263,7 +263,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
...
@@ -263,7 +263,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
sram
=
priv
->
dbgfs_sram_offset
&
~
0x3
;
sram
=
priv
->
dbgfs_sram_offset
&
~
0x3
;
/* read the first u32 from sram */
/* 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
--
)
{
for
(;
len
;
len
--
)
{
/* put the address at the start of every line */
/* put the address at the start of every line */
...
@@ -282,7 +282,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
...
@@ -282,7 +282,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
if
(
++
offset
==
4
)
{
if
(
++
offset
==
4
)
{
sram
+=
4
;
sram
+=
4
;
offset
=
0
;
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 */
/* 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,
...
@@ -2055,7 +2055,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
const
size_t
bufsz
=
sizeof
(
buf
);
const
size_t
bufsz
=
sizeof
(
buf
);
u32
pwrsave_status
;
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
;
CSR_GP_REG_POWER_SAVE_STATUS_MSK
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"Power Save Status: "
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"Power Save Status: "
);
...
...
drivers/net/wireless/iwlwifi/iwl-dev.h
浏览文件 @
8f0bb5ae
...
@@ -292,114 +292,6 @@ struct iwl_vif_priv {
...
@@ -292,114 +292,6 @@ struct iwl_vif_priv {
u8
ibss_bssid_sta_id
;
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
{
struct
iwl_sensitivity_ranges
{
u16
min_nrg_cck
;
u16
min_nrg_cck
;
u16
max_nrg_cck
;
u16
max_nrg_cck
;
...
@@ -821,7 +713,6 @@ struct iwl_wipan_noa_data {
...
@@ -821,7 +713,6 @@ struct iwl_wipan_noa_data {
struct
iwl_priv
{
struct
iwl_priv
{
/*data shared among all the driver's layers */
/*data shared among all the driver's layers */
struct
iwl_shared
_shrd
;
struct
iwl_shared
*
shrd
;
struct
iwl_shared
*
shrd
;
/* ieee device used by generic ieee processing code */
/* ieee device used by generic ieee processing code */
...
...
drivers/net/wireless/iwlwifi/iwl-eeprom.c
浏览文件 @
8f0bb5ae
...
@@ -156,16 +156,16 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus)
...
@@ -156,16 +156,16 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus)
for
(
count
=
0
;
count
<
EEPROM_SEM_RETRY_LIMIT
;
count
++
)
{
for
(
count
=
0
;
count
<
EEPROM_SEM_RETRY_LIMIT
;
count
++
)
{
/* Request semaphore */
/* 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
);
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM
);
/* See if we got it */
/* 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
,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM
,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM
,
EEPROM_SEM_TIMEOUT
);
EEPROM_SEM_TIMEOUT
);
if
(
ret
>=
0
)
{
if
(
ret
>=
0
)
{
IWL_DEBUG_EEPROM
(
bus
,
IWL_DEBUG_EEPROM
(
trans
(
bus
)
,
"Acquired semaphore after %d tries.
\n
"
,
"Acquired semaphore after %d tries.
\n
"
,
count
+
1
);
count
+
1
);
return
ret
;
return
ret
;
...
@@ -177,14 +177,15 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus)
...
@@ -177,14 +177,15 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus)
static
void
iwl_eeprom_release_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
);
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM
);
}
}
static
int
iwl_eeprom_verify_signature
(
struct
iwl_trans
*
trans
)
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
;
int
ret
=
0
;
IWL_DEBUG_EEPROM
(
trans
,
"EEPROM signature=0x%08x
\n
"
,
gp
);
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)
...
@@ -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
)
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
)
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
);
CSR_OTP_GP_REG_OTP_ACCESS_MODE
);
else
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
);
CSR_OTP_GP_REG_OTP_ACCESS_MODE
);
}
}
...
@@ -332,7 +333,7 @@ static int iwl_get_nvm_type(struct iwl_bus *bus, u32 hw_rev)
...
@@ -332,7 +333,7 @@ static int iwl_get_nvm_type(struct iwl_bus *bus, u32 hw_rev)
nvm_type
=
NVM_DEVICE_TYPE_EEPROM
;
nvm_type
=
NVM_DEVICE_TYPE_EEPROM
;
break
;
break
;
default:
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
)
if
(
otpgp
&
CSR_OTP_GP_REG_DEVICE_SELECT
)
nvm_type
=
NVM_DEVICE_TYPE_OTP
;
nvm_type
=
NVM_DEVICE_TYPE_OTP
;
else
else
...
@@ -347,22 +348,22 @@ static int iwl_init_otp_access(struct iwl_bus *bus)
...
@@ -347,22 +348,22 @@ static int iwl_init_otp_access(struct iwl_bus *bus)
int
ret
;
int
ret
;
/* Enable 40MHz radio clock */
/* Enable 40MHz radio clock */
iwl_write32
(
bus
,
CSR_GP_CNTRL
,
iwl_write32
(
trans
(
bus
)
,
CSR_GP_CNTRL
,
iwl_read32
(
bus
,
CSR_GP_CNTRL
)
|
iwl_read32
(
trans
(
bus
)
,
CSR_GP_CNTRL
)
|
CSR_GP_CNTRL_REG_FLAG_INIT_DONE
);
CSR_GP_CNTRL_REG_FLAG_INIT_DONE
);
/* wait for clock to be ready */
/* 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
,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
,
25000
);
25000
);
if
(
ret
<
0
)
if
(
ret
<
0
)
IWL_ERR
(
bus
,
"Time out access OTP
\n
"
);
IWL_ERR
(
bus
,
"Time out access OTP
\n
"
);
else
{
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
);
APMG_PS_CTRL_VAL_RESET_REQ
);
udelay
(
5
);
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
);
APMG_PS_CTRL_VAL_RESET_REQ
);
/*
/*
...
@@ -370,7 +371,7 @@ static int iwl_init_otp_access(struct iwl_bus *bus)
...
@@ -370,7 +371,7 @@ static int iwl_init_otp_access(struct iwl_bus *bus)
* this is only applicable for HW with OTP shadow RAM
* this is only applicable for HW with OTP shadow RAM
*/
*/
if
(
cfg
(
bus
)
->
base_params
->
shadow_ram_support
)
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
);
CSR_RESET_LINK_PWR_MGMT_DISABLED
);
}
}
return
ret
;
return
ret
;
...
@@ -382,9 +383,9 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data)
...
@@ -382,9 +383,9 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data)
u32
r
;
u32
r
;
u32
otpgp
;
u32
otpgp
;
iwl_write32
(
bus
,
CSR_EEPROM_REG
,
iwl_write32
(
trans
(
bus
)
,
CSR_EEPROM_REG
,
CSR_EEPROM_REG_MSK_ADDR
&
(
addr
<<
1
));
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
,
CSR_EEPROM_REG_READ_VALID_MSK
,
CSR_EEPROM_REG_READ_VALID_MSK
,
IWL_EEPROM_ACCESS_TIMEOUT
);
IWL_EEPROM_ACCESS_TIMEOUT
);
...
@@ -392,13 +393,13 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data)
...
@@ -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
);
IWL_ERR
(
bus
,
"Time out reading OTP[%d]
\n
"
,
addr
);
return
ret
;
return
ret
;
}
}
r
=
iwl_read32
(
bus
,
CSR_EEPROM_REG
);
r
=
iwl_read32
(
trans
(
bus
)
,
CSR_EEPROM_REG
);
/* check for ECC errors: */
/* 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
)
{
if
(
otpgp
&
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK
)
{
/* stop in this case */
/* stop in this case */
/* set the uncorrectable OTP ECC bit for acknowledgement */
/* 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
);
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK
);
IWL_ERR
(
bus
,
"Uncorrectable OTP ECC error, abort OTP read
\n
"
);
IWL_ERR
(
bus
,
"Uncorrectable OTP ECC error, abort OTP read
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -406,7 +407,7 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data)
...
@@ -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
)
{
if
(
otpgp
&
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK
)
{
/* continue in this case */
/* continue in this case */
/* set the correctable OTP ECC bit for acknowledgement */
/* 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
);
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK
);
IWL_ERR
(
bus
,
"Correctable OTP ECC error, continue read
\n
"
);
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)
...
@@ -656,7 +657,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
{
{
struct
iwl_shared
*
shrd
=
priv
->
shrd
;
struct
iwl_shared
*
shrd
=
priv
->
shrd
;
__le16
*
e
;
__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
sz
;
int
ret
;
int
ret
;
u16
addr
;
u16
addr
;
...
@@ -676,8 +677,6 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
...
@@ -676,8 +677,6 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
}
}
e
=
(
__le16
*
)
shrd
->
eeprom
;
e
=
(
__le16
*
)
shrd
->
eeprom
;
iwl_apm_init
(
priv
);
ret
=
iwl_eeprom_verify_signature
(
trans
(
priv
));
ret
=
iwl_eeprom_verify_signature
(
trans
(
priv
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
IWL_ERR
(
priv
,
"EEPROM not found, EEPROM_GP=0x%08x
\n
"
,
gp
);
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)
...
@@ -701,11 +700,11 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
ret
=
-
ENOENT
;
ret
=
-
ENOENT
;
goto
done
;
goto
done
;
}
}
iwl_write32
(
bu
s
(
priv
),
CSR_EEPROM_GP
,
iwl_write32
(
tran
s
(
priv
),
CSR_EEPROM_GP
,
iwl_read32
(
bu
s
(
priv
),
CSR_EEPROM_GP
)
&
iwl_read32
(
tran
s
(
priv
),
CSR_EEPROM_GP
)
&
~
CSR_EEPROM_GP_IF_OWNER_MSK
);
~
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_CORR_STATUS_MSK
|
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK
);
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK
);
/* traversing the linked list if no shadow ram supported */
/* traversing the linked list if no shadow ram supported */
...
@@ -730,10 +729,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
...
@@ -730,10 +729,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
for
(
addr
=
0
;
addr
<
sz
;
addr
+=
sizeof
(
u16
))
{
for
(
addr
=
0
;
addr
<
sz
;
addr
+=
sizeof
(
u16
))
{
u32
r
;
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
));
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
,
CSR_EEPROM_REG_READ_VALID_MSK
,
CSR_EEPROM_REG_READ_VALID_MSK
,
IWL_EEPROM_ACCESS_TIMEOUT
);
IWL_EEPROM_ACCESS_TIMEOUT
);
...
@@ -741,7 +740,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
...
@@ -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
);
IWL_ERR
(
priv
,
"Time out reading EEPROM[%d]
\n
"
,
addr
);
goto
done
;
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
);
e
[
addr
/
2
]
=
cpu_to_le16
(
r
>>
16
);
}
}
}
}
...
@@ -758,8 +757,6 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
...
@@ -758,8 +757,6 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
err:
err:
if
(
ret
)
if
(
ret
)
iwl_eeprom_free
(
priv
->
shrd
);
iwl_eeprom_free
(
priv
->
shrd
);
/* Reset chip to save power until we load uCode during "up". */
iwl_apm_stop
(
priv
);
alloc_err:
alloc_err:
return
ret
;
return
ret
;
}
}
...
@@ -1072,7 +1069,7 @@ void iwl_rf_config(struct iwl_priv *priv)
...
@@ -1072,7 +1069,7 @@ void iwl_rf_config(struct iwl_priv *priv)
/* write radio config values to register */
/* write radio config values to register */
if
(
EEPROM_RF_CFG_TYPE_MSK
(
radio_cfg
)
<=
EEPROM_RF_CONFIG_TYPE_MAX
)
{
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_TYPE_MSK
(
radio_cfg
)
|
EEPROM_RF_CFG_STEP_MSK
(
radio_cfg
)
|
EEPROM_RF_CFG_STEP_MSK
(
radio_cfg
)
|
EEPROM_RF_CFG_DASH_MSK
(
radio_cfg
));
EEPROM_RF_CFG_DASH_MSK
(
radio_cfg
));
...
@@ -1084,7 +1081,7 @@ void iwl_rf_config(struct iwl_priv *priv)
...
@@ -1084,7 +1081,7 @@ void iwl_rf_config(struct iwl_priv *priv)
WARN_ON
(
1
);
WARN_ON
(
1
);
/* set CSR_HW_CONFIG_REG for uCode use */
/* 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_RADIO_SI
|
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI
);
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI
);
}
}
drivers/net/wireless/iwlwifi/iwl-io.c
浏览文件 @
8f0bb5ae
...
@@ -34,41 +34,41 @@
...
@@ -34,41 +34,41 @@
#define IWL_POLL_INTERVAL 10
/* microseconds */
#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
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
__iwl_set_bit
(
bu
s
,
reg
,
mask
);
__iwl_set_bit
(
tran
s
,
reg
,
mask
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
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
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
__iwl_clear_bit
(
bu
s
,
reg
,
mask
);
__iwl_clear_bit
(
tran
s
,
reg
,
mask
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
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
)
u32
bits
,
u32
mask
,
int
timeout
)
{
{
int
t
=
0
;
int
t
=
0
;
do
{
do
{
if
((
iwl_read32
(
bu
s
,
addr
)
&
mask
)
==
(
bits
&
mask
))
if
((
iwl_read32
(
tran
s
,
addr
)
&
mask
)
==
(
bits
&
mask
))
return
t
;
return
t
;
udelay
(
IWL_POLL_INTERVAL
);
udelay
(
IWL_POLL_INTERVAL
);
t
+=
IWL_POLL_INTERVAL
;
t
+=
IWL_POLL_INTERVAL
;
...
@@ -77,14 +77,15 @@ int iwl_poll_bit(struct iwl_bus *bus, u32 addr,
...
@@ -77,14 +77,15 @@ int iwl_poll_bit(struct iwl_bus *bus, u32 addr,
return
-
ETIMEDOUT
;
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
;
int
ret
;
lockdep_assert_held
(
&
bu
s
->
reg_lock
);
lockdep_assert_held
(
&
tran
s
->
reg_lock
);
/* this bit wakes up the NIC */
/* 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
* 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)
...
@@ -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,
* 5000 series and later (including 1000 series) have non-volatile SRAM,
* and do not save/restore SRAM when power cycling.
* 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_VAL_MAC_ACCESS_EN
,
(
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
|
(
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
|
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP
),
15000
);
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP
),
15000
);
if
(
ret
<
0
)
{
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
-
EIO
;
}
}
return
0
;
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
)
{
if
(
ret
)
{
u32
val
=
iwl_read32
(
bu
s
,
CSR_GP_CNTRL
);
u32
val
=
iwl_read32
(
tran
s
,
CSR_GP_CNTRL
);
IWL_ERR
(
bu
s
,
IWL_ERR
(
tran
s
,
"MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X
\n
"
,
val
);
"MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X
\n
"
,
val
);
}
}
return
ret
;
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
);
lockdep_assert_held
(
&
tran
s
->
reg_lock
);
__iwl_clear_bit
(
bu
s
,
CSR_GP_CNTRL
,
__iwl_clear_bit
(
tran
s
,
CSR_GP_CNTRL
,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
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
;
u32
value
;
unsigned
long
flags
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
iwl_grab_nic_access
(
tran
s
);
value
=
iwl_read32
(
bu
s
,
reg
);
value
=
iwl_read32
(
tran
s
,
reg
);
iwl_release_nic_access
(
bu
s
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
return
value
;
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
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
bu
s
))
{
if
(
!
iwl_grab_nic_access
(
tran
s
))
{
iwl_write32
(
bu
s
,
reg
,
value
);
iwl_write32
(
tran
s
,
reg
,
value
);
iwl_release_nic_access
(
bu
s
);
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
timeout
)
{
{
int
t
=
0
;
int
t
=
0
;
do
{
do
{
if
((
iwl_read_direct32
(
bu
s
,
addr
)
&
mask
)
==
mask
)
if
((
iwl_read_direct32
(
tran
s
,
addr
)
&
mask
)
==
mask
)
return
t
;
return
t
;
udelay
(
IWL_POLL_INTERVAL
);
udelay
(
IWL_POLL_INTERVAL
);
t
+=
IWL_POLL_INTERVAL
;
t
+=
IWL_POLL_INTERVAL
;
...
@@ -177,135 +178,135 @@ int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask,
...
@@ -177,135 +178,135 @@ int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask,
return
-
ETIMEDOUT
;
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
();
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
)));
((
addr
&
0x0000FFFF
)
|
(
3
<<
24
)));
wmb
();
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
;
unsigned
long
flags
;
u32
val
;
u32
val
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
iwl_grab_nic_access
(
tran
s
);
val
=
__iwl_read_prph
(
bu
s
,
reg
);
val
=
__iwl_read_prph
(
tran
s
,
reg
);
iwl_release_nic_access
(
bu
s
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
return
val
;
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
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
bu
s
))
{
if
(
!
iwl_grab_nic_access
(
tran
s
))
{
__iwl_write_prph
(
bu
s
,
addr
,
val
);
__iwl_write_prph
(
tran
s
,
addr
,
val
);
iwl_release_nic_access
(
bu
s
);
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
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
iwl_grab_nic_access
(
tran
s
);
__iwl_write_prph
(
bus
,
reg
,
__iwl_read_prph
(
bu
s
,
reg
)
|
mask
);
__iwl_write_prph
(
trans
,
reg
,
__iwl_read_prph
(
tran
s
,
reg
)
|
mask
);
iwl_release_nic_access
(
bu
s
);
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_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
)
u32
bits
,
u32
mask
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
iwl_grab_nic_access
(
tran
s
);
__iwl_write_prph
(
bu
s
,
reg
,
__iwl_write_prph
(
tran
s
,
reg
,
(
__iwl_read_prph
(
bu
s
,
reg
)
&
mask
)
|
bits
);
(
__iwl_read_prph
(
tran
s
,
reg
)
&
mask
)
|
bits
);
iwl_release_nic_access
(
bu
s
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
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
;
unsigned
long
flags
;
u32
val
;
u32
val
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
iwl_grab_nic_access
(
tran
s
);
val
=
__iwl_read_prph
(
bu
s
,
reg
);
val
=
__iwl_read_prph
(
tran
s
,
reg
);
__iwl_write_prph
(
bu
s
,
reg
,
(
val
&
~
mask
));
__iwl_write_prph
(
tran
s
,
reg
,
(
val
&
~
mask
));
iwl_release_nic_access
(
bu
s
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
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
)
void
*
buf
,
int
words
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
int
offs
;
int
offs
;
u32
*
vals
=
buf
;
u32
*
vals
=
buf
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
iwl_grab_nic_access
(
bu
s
);
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
();
rmb
();
for
(
offs
=
0
;
offs
<
words
;
offs
++
)
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
);
iwl_release_nic_access
(
tran
s
);
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
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
;
u32
value
;
_iwl_read_targ_mem_words
(
bu
s
,
addr
,
&
value
,
1
);
_iwl_read_targ_mem_words
(
tran
s
,
addr
,
&
value
,
1
);
return
value
;
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
)
void
*
buf
,
int
words
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
int
offs
,
result
=
0
;
int
offs
,
result
=
0
;
u32
*
vals
=
buf
;
u32
*
vals
=
buf
;
spin_lock_irqsave
(
&
bu
s
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
->
reg_lock
,
flags
);
if
(
!
iwl_grab_nic_access
(
bu
s
))
{
if
(
!
iwl_grab_nic_access
(
tran
s
))
{
iwl_write32
(
bu
s
,
HBUS_TARG_MEM_WADDR
,
addr
);
iwl_write32
(
tran
s
,
HBUS_TARG_MEM_WADDR
,
addr
);
wmb
();
wmb
();
for
(
offs
=
0
;
offs
<
words
;
offs
++
)
for
(
offs
=
0
;
offs
<
words
;
offs
++
)
iwl_write32
(
bu
s
,
HBUS_TARG_MEM_WDAT
,
vals
[
offs
]);
iwl_write32
(
tran
s
,
HBUS_TARG_MEM_WDAT
,
vals
[
offs
]);
iwl_release_nic_access
(
bu
s
);
iwl_release_nic_access
(
tran
s
);
}
else
}
else
result
=
-
EBUSY
;
result
=
-
EBUSY
;
spin_unlock_irqrestore
(
&
bu
s
->
reg_lock
,
flags
);
spin_unlock_irqrestore
(
&
tran
s
->
reg_lock
,
flags
);
return
result
;
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
浏览文件 @
8f0bb5ae
...
@@ -31,63 +31,63 @@
...
@@ -31,63 +31,63 @@
#include "iwl-devtrace.h"
#include "iwl-devtrace.h"
#include "iwl-shared.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
);
trace_iwlwifi_dev_iowrite8
(
priv
(
tran
s
),
ofs
,
val
);
bus_write8
(
bu
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
);
trace_iwlwifi_dev_iowrite32
(
priv
(
tran
s
),
ofs
,
val
);
bus_write32
(
bu
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
);
u32
val
=
iwl_trans_read32
(
tran
s
,
ofs
);
trace_iwlwifi_dev_ioread32
(
priv
(
bu
s
),
ofs
,
val
);
trace_iwlwifi_dev_ioread32
(
priv
(
tran
s
),
ofs
,
val
);
return
val
;
return
val
;
}
}
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
);
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
);
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
);
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
timeout
);
int
iwl_grab_nic_access_silent
(
struct
iwl_
bus
*
bu
s
);
int
iwl_grab_nic_access_silent
(
struct
iwl_
trans
*
tran
s
);
int
iwl_grab_nic_access
(
struct
iwl_
bus
*
bu
s
);
int
iwl_grab_nic_access
(
struct
iwl_
trans
*
tran
s
);
void
iwl_release_nic_access
(
struct
iwl_
bus
*
bu
s
);
void
iwl_release_nic_access
(
struct
iwl_
trans
*
tran
s
);
u32
iwl_read_direct32
(
struct
iwl_
bus
*
bu
s
,
u32
reg
);
u32
iwl_read_direct32
(
struct
iwl_
trans
*
tran
s
,
u32
reg
);
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
);
u32
iwl_read_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_
bus
*
bu
s
,
u32
addr
,
u32
val
);
void
iwl_write_prph
(
struct
iwl_
trans
*
tran
s
,
u32
addr
,
u32
val
);
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
);
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
);
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
);
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 { \
do { \
BUILD_BUG_ON((bufsize) % sizeof(u32)); \
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));\
(bufsize) / sizeof(u32));\
} while (0)
} 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
);
void
*
buf
,
int
words
);
u32
iwl_read_targ_mem
(
struct
iwl_
bus
*
bu
s
,
u32
addr
);
u32
iwl_read_targ_mem
(
struct
iwl_
trans
*
tran
s
,
u32
addr
);
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
);
#endif
#endif
drivers/net/wireless/iwlwifi/iwl-led.c
浏览文件 @
8f0bb5ae
...
@@ -71,7 +71,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {
...
@@ -71,7 +71,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {
/* Set led register off */
/* Set led register off */
void
iwlagn_led_enable
(
struct
iwl_priv
*
priv
)
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)
...
@@ -107,9 +107,10 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
};
};
u32
reg
;
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
))
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
);
return
iwl_trans_send_cmd
(
trans
(
priv
),
&
cmd
);
}
}
...
@@ -206,7 +207,7 @@ void iwl_leds_init(struct iwl_priv *priv)
...
@@ -206,7 +207,7 @@ void iwl_leds_init(struct iwl_priv *priv)
break
;
break
;
}
}
ret
=
led_classdev_register
(
bu
s
(
priv
)
->
dev
,
&
priv
->
led
);
ret
=
led_classdev_register
(
tran
s
(
priv
)
->
dev
,
&
priv
->
led
);
if
(
ret
)
{
if
(
ret
)
{
kfree
(
priv
->
led
.
name
);
kfree
(
priv
->
led
.
name
);
return
;
return
;
...
...
drivers/net/wireless/iwlwifi/iwl-mac80211.c
浏览文件 @
8f0bb5ae
...
@@ -35,7 +35,6 @@
...
@@ -35,7 +35,6 @@
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/if_arp.h>
...
@@ -43,6 +42,7 @@
...
@@ -43,6 +42,7 @@
#include <asm/div64.h>
#include <asm/div64.h>
#include "iwl-ucode.h"
#include "iwl-eeprom.h"
#include "iwl-eeprom.h"
#include "iwl-wifi.h"
#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-dev.h"
...
@@ -196,7 +196,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
...
@@ -196,7 +196,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
WIPHY_FLAG_IBSS_RSN
;
WIPHY_FLAG_IBSS_RSN
;
if
(
trans
(
priv
)
->
ucode_wowlan
.
code
.
len
&&
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
|
hw
->
wiphy
->
wowlan
.
flags
=
WIPHY_WOWLAN_MAGIC_PKT
|
WIPHY_WOWLAN_DISCONNECT
|
WIPHY_WOWLAN_DISCONNECT
|
WIPHY_WOWLAN_EAP_IDENTITY_REQ
|
WIPHY_WOWLAN_EAP_IDENTITY_REQ
|
...
@@ -234,7 +234,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
...
@@ -234,7 +234,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
priv
->
hw
->
wiphy
->
bands
[
IEEE80211_BAND_5GHZ
]
=
priv
->
hw
->
wiphy
->
bands
[
IEEE80211_BAND_5GHZ
]
=
&
priv
->
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
);
iwl_leds_init
(
priv
);
...
@@ -346,9 +346,10 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
...
@@ -346,9 +346,10 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
flush_workqueue
(
priv
->
shrd
->
workqueue
);
flush_workqueue
(
priv
->
shrd
->
workqueue
);
/* User space software may expect getting rfkill changes
/* User space software may expect getting rfkill changes
* even if interface is down */
* even if interface is down, trans->down will leave the RF
iwl_write32
(
bus
(
priv
),
CSR_INT
,
0xFFFFFFFF
);
* kill interrupt enabled
iwl_enable_rfkill_int
(
priv
);
*/
iwl_trans_stop_hw
(
trans
(
priv
));
IWL_DEBUG_MAC80211
(
priv
,
"leave
\n
"
);
IWL_DEBUG_MAC80211
(
priv
,
"leave
\n
"
);
}
}
...
@@ -405,10 +406,10 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
...
@@ -405,10 +406,10 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
if
(
ret
)
if
(
ret
)
goto
error
;
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 */
/* 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
);
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE
);
goto
out
;
goto
out
;
...
@@ -436,19 +437,19 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
...
@@ -436,19 +437,19 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
IWL_DEBUG_MAC80211
(
priv
,
"enter
\n
"
);
IWL_DEBUG_MAC80211
(
priv
,
"enter
\n
"
);
mutex_lock
(
&
priv
->
shrd
->
mutex
);
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
);
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE
);
base
=
priv
->
shrd
->
device_pointers
.
error_event_table
;
base
=
priv
->
shrd
->
device_pointers
.
error_event_table
;
if
(
iwlagn_hw_valid_rtc_data_addr
(
base
))
{
if
(
iwlagn_hw_valid_rtc_data_addr
(
base
))
{
spin_lock_irqsave
(
&
bu
s
(
priv
)
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
tran
s
(
priv
)
->
reg_lock
,
flags
);
ret
=
iwl_grab_nic_access_silent
(
bu
s
(
priv
));
ret
=
iwl_grab_nic_access_silent
(
tran
s
(
priv
));
if
(
ret
==
0
)
{
if
(
ret
==
0
)
{
iwl_write32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RADDR
,
base
);
iwl_write32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RADDR
,
base
);
status
=
iwl_read32
(
bu
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
status
=
iwl_read32
(
tran
s
(
priv
),
HBUS_TARG_MEM_RDAT
);
iwl_release_nic_access
(
bu
s
(
priv
));
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
#ifdef CONFIG_IWLWIFI_DEBUGFS
if
(
ret
==
0
)
{
if
(
ret
==
0
)
{
...
@@ -460,7 +461,8 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
...
@@ -460,7 +461,8 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
if
(
priv
->
wowlan_sram
)
if
(
priv
->
wowlan_sram
)
_iwl_read_targ_mem_words
(
_iwl_read_targ_mem_words
(
bus
(
priv
),
0x800000
,
priv
->
wowlan_sram
,
trans
(
priv
),
0x800000
,
priv
->
wowlan_sram
,
trans
->
ucode_wowlan
.
data
.
len
/
4
);
trans
->
ucode_wowlan
.
data
.
len
/
4
);
}
}
#endif
#endif
...
@@ -471,7 +473,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
...
@@ -471,7 +473,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
priv
->
shrd
->
wowlan
=
false
;
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
);
iwlagn_prepare_restart
(
priv
);
...
...
drivers/net/wireless/iwlwifi/iwl-pci.c
浏览文件 @
8f0bb5ae
...
@@ -71,112 +71,6 @@
...
@@ -71,112 +71,6 @@
#include "iwl-csr.h"
#include "iwl-csr.h"
#include "iwl-cfg.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) \
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
...
@@ -362,112 +256,61 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
...
@@ -362,112 +256,61 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
};
};
MODULE_DEVICE_TABLE
(
pci
,
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
)
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_cfg
*
cfg
=
(
struct
iwl_cfg
*
)(
ent
->
driver_data
);
struct
iwl_bus
*
bus
;
struct
iwl_bus
*
bus
;
struct
iwl_pci_bus
*
pci_bus
;
u16
pci_cmd
;
int
err
;
int
err
;
bus
=
kzalloc
(
sizeof
(
*
bus
)
+
sizeof
(
*
pci_bus
)
,
GFP_KERNEL
);
bus
=
kzalloc
(
sizeof
(
*
bus
),
GFP_KERNEL
);
if
(
!
bus
)
{
if
(
!
bus
)
{
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
"Couldn't allocate iwl_pci_bus"
);
"Couldn't allocate iwl_pci_bus"
);
err
=
-
ENOMEM
;
return
-
ENOMEM
;
goto
out_no_pci
;
}
}
pci_bus
=
IWL_BUS_GET_PCI_BUS
(
bus
);
bus
->
shrd
=
kzalloc
(
sizeof
(
*
bus
->
shrd
),
GFP_KERNEL
);
pci_bus
->
pci_dev
=
pdev
;
if
(
!
bus
->
shrd
)
{
dev_printk
(
KERN_ERR
,
&
pdev
->
dev
,
pci_set_drvdata
(
pdev
,
bus
);
"Couldn't allocate iwl_shared"
);
err
=
-
ENOMEM
;
/* W/A - seems to solve weird behavior. We need to remove this if we
goto
out_free_bus
;
* 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
);
bus
->
shrd
->
bus
=
bus
;
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
;
}
}
err
=
pci_request_regions
(
pdev
,
DRV_NAME
);
pci_set_drvdata
(
pdev
,
bus
);
if
(
err
)
{
dev_printk
(
KERN_ERR
,
bus
->
dev
,
"pci_request_regions failed"
);
goto
out_pci_disable_device
;
}
pci_bus
->
hw_base
=
pci_iomap
(
pdev
,
0
,
0
);
#ifdef CONFIG_IWLWIFI_IDI
if
(
!
pci_bus
->
hw_base
)
{
trans
(
bus
)
=
iwl_trans_idi_alloc
(
bus
->
shrd
,
pdev
,
ent
);
dev_printk
(
KERN_ERR
,
bus
->
dev
,
"pci_iomap failed"
);
if
(
trans
(
bus
)
==
NULL
)
{
err
=
-
ENO
DEV
;
err
=
-
ENO
MEM
;
goto
out_
pci_release_region
s
;
goto
out_
free_bu
s
;
}
}
dev_printk
(
KERN_INFO
,
&
pdev
->
dev
,
err
=
iwl_probe
(
bus
,
&
trans_ops_idi
,
cfg
);
"pci_resource_len = 0x%08llx
\n
"
,
#else
(
unsigned
long
long
)
pci_resource_len
(
pdev
,
0
));
trans
(
bus
)
=
iwl_trans_pcie_alloc
(
bus
->
shrd
,
pdev
,
ent
);
dev_printk
(
KERN_INFO
,
&
pdev
->
dev
,
if
(
trans
(
bus
)
==
NULL
)
{
"pci_resource_base = %p
\n
"
,
pci_bus
->
hw_base
);
err
=
-
ENOMEM
;
goto
out_free_bus
;
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
);
}
}
bus
->
dev
=
&
pdev
->
dev
;
bus
->
irq
=
pdev
->
irq
;
bus
->
ops
=
&
bus_ops_pci
;
err
=
iwl_probe
(
bus
,
&
trans_ops_pcie
,
cfg
);
err
=
iwl_probe
(
bus
,
&
trans_ops_pcie
,
cfg
);
#endif
if
(
err
)
if
(
err
)
goto
out_disable_msi
;
goto
out_free_trans
;
return
0
;
return
0
;
out_disable_msi:
out_free_trans:
pci_disable_msi
(
pdev
);
iwl_trans_free
(
trans
(
bus
));
pci_iounmap
(
pdev
,
pci_bus
->
hw_base
);
out_pci_release_regions:
pci_set_drvdata
(
pdev
,
NULL
);
pci_set_drvdata
(
pdev
,
NULL
);
pci_release_regions
(
pdev
);
out_free_bus:
out_pci_disable_device:
kfree
(
bus
->
shrd
);
pci_disable_device
(
pdev
);
out_no_pci:
kfree
(
bus
);
kfree
(
bus
);
return
err
;
return
err
;
}
}
...
@@ -475,18 +318,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
...
@@ -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
)
static
void
__devexit
iwl_pci_remove
(
struct
pci_dev
*
pdev
)
{
{
struct
iwl_bus
*
bus
=
pci_get_drvdata
(
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
;
struct
iwl_shared
*
shrd
=
bus
->
shrd
;
iwl_remove
(
shrd
->
priv
);
iwl_remove
(
shrd
->
priv
);
iwl_trans_free
(
shrd
->
trans
);
pci_disable_msi
(
pci_dev
);
pci_set_drvdata
(
pdev
,
NULL
);
pci_iounmap
(
pci_dev
,
pci_bus
->
hw_base
);
pci_release_regions
(
pci_dev
);
pci_disable_device
(
pci_dev
);
pci_set_drvdata
(
pci_dev
,
NULL
);
kfree
(
bus
->
shrd
);
kfree
(
bus
);
kfree
(
bus
);
}
}
...
...
drivers/net/wireless/iwlwifi/iwl-power.c
浏览文件 @
8f0bb5ae
...
@@ -436,7 +436,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
...
@@ -436,7 +436,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
/* initialize to default */
/* initialize to default */
void
iwl_power_initialize
(
struct
iwl_priv
*
priv
)
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
;
priv
->
power_data
.
debug_sleep_level_override
=
-
1
;
...
...
drivers/net/wireless/iwlwifi/iwl-shared.h
浏览文件 @
8f0bb5ae
...
@@ -543,8 +543,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);
...
@@ -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_set_hw_rfkill_state
(
struct
iwl_priv
*
priv
,
bool
state
);
void
iwl_nic_config
(
struct
iwl_priv
*
priv
);
void
iwl_nic_config
(
struct
iwl_priv
*
priv
);
void
iwl_free_skb
(
struct
iwl_priv
*
priv
,
struct
sk_buff
*
skb
);
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
);
void
iwlagn_fw_error
(
struct
iwl_priv
*
priv
,
bool
ondemand
);
const
char
*
get_cmd_string
(
u8
cmd
);
const
char
*
get_cmd_string
(
u8
cmd
);
bool
iwl_check_for_ct_kill
(
struct
iwl_priv
*
priv
);
bool
iwl_check_for_ct_kill
(
struct
iwl_priv
*
priv
);
...
...
drivers/net/wireless/iwlwifi/iwl-testmode.c
浏览文件 @
8f0bb5ae
...
@@ -79,6 +79,7 @@
...
@@ -79,6 +79,7 @@
#include "iwl-testmode.h"
#include "iwl-testmode.h"
#include "iwl-trans.h"
#include "iwl-trans.h"
#include "iwl-bus.h"
#include "iwl-bus.h"
#include "iwl-fh.h"
/* The TLVs used in the gnl message policy between the kernel module and
/* 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
* 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)
...
@@ -208,7 +209,7 @@ static void iwl_trace_cleanup(struct iwl_priv *priv)
if
(
priv
->
testmode_trace
.
trace_enabled
)
{
if
(
priv
->
testmode_trace
.
trace_enabled
)
{
if
(
priv
->
testmode_trace
.
cpu_addr
&&
if
(
priv
->
testmode_trace
.
cpu_addr
&&
priv
->
testmode_trace
.
dma_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
.
total_size
,
priv
->
testmode_trace
.
cpu_addr
,
priv
->
testmode_trace
.
cpu_addr
,
priv
->
testmode_trace
.
dma_addr
);
priv
->
testmode_trace
.
dma_addr
);
...
@@ -288,7 +289,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
...
@@ -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
)
static
int
iwl_testmode_reg
(
struct
ieee80211_hw
*
hw
,
struct
nlattr
**
tb
)
{
{
struct
iwl_priv
*
priv
=
hw
->
priv
;
struct
iwl_priv
*
priv
=
hw
->
priv
;
u32
ofs
,
val32
;
u32
ofs
,
val32
,
cmd
;
u8
val8
;
u8
val8
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
int
status
=
0
;
int
status
=
0
;
...
@@ -300,9 +301,22 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
...
@@ -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
]);
ofs
=
nla_get_u32
(
tb
[
IWL_TM_ATTR_REG_OFFSET
]);
IWL_INFO
(
priv
,
"testmode register access command offset 0x%x
\n
"
,
ofs
);
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
:
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
);
IWL_INFO
(
priv
,
"32bit value to read 0x%x
\n
"
,
val32
);
skb
=
cfg80211_testmode_alloc_reply_skb
(
hw
->
wiphy
,
20
);
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)
...
@@ -324,7 +338,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
}
else
{
}
else
{
val32
=
nla_get_u32
(
tb
[
IWL_TM_ATTR_REG_VALUE32
]);
val32
=
nla_get_u32
(
tb
[
IWL_TM_ATTR_REG_VALUE32
]);
IWL_INFO
(
priv
,
"32bit value to write 0x%x
\n
"
,
val32
);
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
;
break
;
case
IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8
:
case
IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8
:
...
@@ -334,11 +348,11 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
...
@@ -334,11 +348,11 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
}
else
{
}
else
{
val8
=
nla_get_u8
(
tb
[
IWL_TM_ATTR_REG_VALUE8
]);
val8
=
nla_get_u8
(
tb
[
IWL_TM_ATTR_REG_VALUE8
]);
IWL_INFO
(
priv
,
"8bit value to write 0x%x
\n
"
,
val8
);
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
;
break
;
case
IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32
:
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
);
IWL_INFO
(
priv
,
"32bit value to read 0x%x
\n
"
,
val32
);
skb
=
cfg80211_testmode_alloc_reply_skb
(
hw
->
wiphy
,
20
);
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)
...
@@ -360,7 +374,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
}
else
{
}
else
{
val32
=
nla_get_u32
(
tb
[
IWL_TM_ATTR_REG_VALUE32
]);
val32
=
nla_get_u32
(
tb
[
IWL_TM_ATTR_REG_VALUE32
]);
IWL_INFO
(
priv
,
"32bit value to write 0x%x
\n
"
,
val32
);
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
;
break
;
default:
default:
...
@@ -536,7 +550,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
...
@@ -536,7 +550,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
break
;
break
;
case
IWL_TM_CMD_APP2DEV_GET_DEVICE_ID
:
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
);
IWL_INFO
(
priv
,
"hw version: 0x%x
\n
"
,
devid
);
skb
=
cfg80211_testmode_alloc_reply_skb
(
hw
->
wiphy
,
20
);
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)
...
@@ -615,7 +629,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
struct
iwl_priv
*
priv
=
hw
->
priv
;
struct
iwl_priv
*
priv
=
hw
->
priv
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
int
status
=
0
;
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
]))
{
switch
(
nla_get_u32
(
tb
[
IWL_TM_ATTR_COMMAND
]))
{
case
IWL_TM_CMD_APP2DEV_BEGIN_TRACE
:
case
IWL_TM_CMD_APP2DEV_BEGIN_TRACE
:
...
@@ -814,7 +828,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb)
...
@@ -814,7 +828,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb)
IWL_ERR
(
priv
,
"Error allocating memory
\n
"
);
IWL_ERR
(
priv
,
"Error allocating memory
\n
"
);
return
-
ENOMEM
;
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_addr
,
priv
->
testmode_sram
.
buff_size
/
4
);
priv
->
testmode_sram
.
buff_size
/
4
);
priv
->
testmode_sram
.
num_chunks
=
priv
->
testmode_sram
.
num_chunks
=
...
...
drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
浏览文件 @
8f0bb5ae
...
@@ -201,6 +201,7 @@ struct iwl_tx_queue {
...
@@ -201,6 +201,7 @@ struct iwl_tx_queue {
* @rxq: all the RX queue data
* @rxq: all the RX queue data
* @rx_replenish: work that will be called when buffers need to be allocated
* @rx_replenish: work that will be called when buffers need to be allocated
* @trans: pointer to the generic transport area
* @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_base_addr: scheduler sram base address in SRAM
* @scd_bc_tbls: pointer to the byte count table of the scheduler
* @scd_bc_tbls: pointer to the byte count table of the scheduler
* @kw: keep warm address
* @kw: keep warm address
...
@@ -211,6 +212,8 @@ struct iwl_tx_queue {
...
@@ -211,6 +212,8 @@ struct iwl_tx_queue {
* @txq_ctx_active_msk: what queue is active
* @txq_ctx_active_msk: what queue is active
* queue_stopped: tracks what queue is stopped
* queue_stopped: tracks what queue is stopped
* queue_stop_count: tracks what SW 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_trans_pcie
{
struct
iwl_rx_queue
rxq
;
struct
iwl_rx_queue
rxq
;
...
@@ -223,6 +226,7 @@ struct iwl_trans_pcie {
...
@@ -223,6 +226,7 @@ struct iwl_trans_pcie {
int
ict_index
;
int
ict_index
;
u32
inta
;
u32
inta
;
bool
use_ict
;
bool
use_ict
;
bool
irq_requested
;
struct
tasklet_struct
irq_tasklet
;
struct
tasklet_struct
irq_tasklet
;
struct
isr_statistics
isr_stats
;
struct
isr_statistics
isr_stats
;
...
@@ -241,6 +245,10 @@ struct iwl_trans_pcie {
...
@@ -241,6 +245,10 @@ struct iwl_trans_pcie {
#define IWL_MAX_HW_QUEUES 32
#define IWL_MAX_HW_QUEUES 32
unsigned
long
queue_stopped
[
BITS_TO_LONGS
(
IWL_MAX_HW_QUEUES
)];
unsigned
long
queue_stopped
[
BITS_TO_LONGS
(
IWL_MAX_HW_QUEUES
)];
atomic_t
queue_stop_count
[
4
];
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) \
#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
...
@@ -258,7 +266,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
...
@@ -258,7 +266,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
/*****************************************************
/*****************************************************
* ICT
* 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
);
void
iwl_disable_ict
(
struct
iwl_trans
*
trans
);
int
iwl_alloc_isr_ict
(
struct
iwl_trans
*
trans
);
int
iwl_alloc_isr_ict
(
struct
iwl_trans
*
trans
);
void
iwl_free_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)
...
@@ -311,12 +319,12 @@ static inline void iwl_disable_interrupts(struct iwl_trans *trans)
clear_bit
(
STATUS_INT_ENABLED
,
&
trans
->
shrd
->
status
);
clear_bit
(
STATUS_INT_ENABLED
,
&
trans
->
shrd
->
status
);
/* disable interrupts from uCode/NIC to host */
/* 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
/* acknowledge/clear/reset any interrupts still pending
* from uCode or flow handler (Rx/Tx DMA) */
* from uCode or flow handler (Rx/Tx DMA) */
iwl_write32
(
bus
(
trans
)
,
CSR_INT
,
0xffffffff
);
iwl_write32
(
trans
,
CSR_INT
,
0xffffffff
);
iwl_write32
(
bus
(
trans
)
,
CSR_FH_INT_STATUS
,
0xffffffff
);
iwl_write32
(
trans
,
CSR_FH_INT_STATUS
,
0xffffffff
);
IWL_DEBUG_ISR
(
trans
,
"Disabled interrupts
\n
"
);
IWL_DEBUG_ISR
(
trans
,
"Disabled interrupts
\n
"
);
}
}
...
@@ -327,7 +335,7 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
...
@@ -327,7 +335,7 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
IWL_DEBUG_ISR
(
trans
,
"Enabling interrupts
\n
"
);
IWL_DEBUG_ISR
(
trans
,
"Enabling interrupts
\n
"
);
set_bit
(
STATUS_INT_ENABLED
,
&
trans
->
shrd
->
status
);
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
浏览文件 @
8f0bb5ae
...
@@ -35,6 +35,10 @@
...
@@ -35,6 +35,10 @@
#include "iwl-io.h"
#include "iwl-io.h"
#include "iwl-trans-pcie-int.h"
#include "iwl-trans-pcie-int.h"
#ifdef CONFIG_IWLWIFI_IDI
#include "iwl-amfh.h"
#endif
/******************************************************************************
/******************************************************************************
*
*
* RX path functions
* RX path functions
...
@@ -140,30 +144,30 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
...
@@ -140,30 +144,30 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
/* shadow register enabled */
/* shadow register enabled */
/* Device expects a multiple of 8 */
/* Device expects a multiple of 8 */
q
->
write_actual
=
(
q
->
write
&
~
0x7
);
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
{
}
else
{
/* If power-saving is in use, make sure device is awake */
/* If power-saving is in use, make sure device is awake */
if
(
test_bit
(
STATUS_POWER_PMI
,
&
trans
->
shrd
->
status
))
{
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
)
{
if
(
reg
&
CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP
)
{
IWL_DEBUG_INFO
(
trans
,
IWL_DEBUG_INFO
(
trans
,
"Rx queue requesting wakeup,"
"Rx queue requesting wakeup,"
" GP1 = 0x%x
\n
"
,
reg
);
" 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
);
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
goto
exit_unlock
;
goto
exit_unlock
;
}
}
q
->
write_actual
=
(
q
->
write
&
~
0x7
);
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
);
q
->
write_actual
);
/* Else device is assumed to be awake */
/* Else device is assumed to be awake */
}
else
{
}
else
{
/* Device expects a multiple of 8 */
/* Device expects a multiple of 8 */
q
->
write_actual
=
(
q
->
write
&
~
0x7
);
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
);
q
->
write_actual
);
}
}
}
}
...
@@ -308,7 +312,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
...
@@ -308,7 +312,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
BUG_ON
(
rxb
->
page
);
BUG_ON
(
rxb
->
page
);
rxb
->
page
=
page
;
rxb
->
page
=
page
;
/* Get physical address of the RB */
/* 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
,
PAGE_SIZE
<<
hw_params
(
trans
).
rx_page_order
,
DMA_FROM_DEVICE
);
DMA_FROM_DEVICE
);
/* dma address must be no more than 36 bits */
/* dma address must be no more than 36 bits */
...
@@ -414,7 +418,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
...
@@ -414,7 +418,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
rxq
->
queue
[
i
]
=
NULL
;
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
,
PAGE_SIZE
<<
hw_params
(
trans
).
rx_page_order
,
DMA_FROM_DEVICE
);
DMA_FROM_DEVICE
);
pkt
=
rxb_addr
(
rxb
);
pkt
=
rxb_addr
(
rxb
);
...
@@ -485,7 +489,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
...
@@ -485,7 +489,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
* rx_free list for reuse later. */
* rx_free list for reuse later. */
spin_lock_irqsave
(
&
rxq
->
lock
,
flags
);
spin_lock_irqsave
(
&
rxq
->
lock
,
flags
);
if
(
rxb
->
page
!=
NULL
)
{
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
<<
0
,
PAGE_SIZE
<<
hw_params
(
trans
).
rx_page_order
,
hw_params
(
trans
).
rx_page_order
,
DMA_FROM_DEVICE
);
DMA_FROM_DEVICE
);
...
@@ -612,7 +616,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
...
@@ -612,7 +616,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
return
;
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
)
{
if
(
ERROR_START_OFFSET
<=
table
.
valid
*
ERROR_ELEM_SIZE
)
{
IWL_ERR
(
trans
,
"Start IWL Error Log Dump:
\n
"
);
IWL_ERR
(
trans
,
"Start IWL Error Log Dump:
\n
"
);
...
@@ -673,9 +677,9 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
...
@@ -673,9 +677,9 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
struct
iwl_priv
*
priv
=
priv
(
trans
);
struct
iwl_priv
*
priv
=
priv
(
trans
);
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
if
(
cfg
(
priv
)
->
internal_wimax_coex
&&
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
)
||
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
)))
{
APMG_PS_CTRL_VAL_RESET_REQ
)))
{
/*
/*
* Keep the restart process from trying to send host
* 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,
...
@@ -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
);
ptr
=
base
+
EVENT_START_OFFSET
+
(
start_idx
*
event_size
);
/* Make sure device is powered up for SRAM reads */
/* Make sure device is powered up for SRAM reads */
spin_lock_irqsave
(
&
bus
(
trans
)
->
reg_lock
,
reg_flags
);
spin_lock_irqsave
(
&
trans
->
reg_lock
,
reg_flags
);
iwl_grab_nic_access
(
bus
(
trans
)
);
iwl_grab_nic_access
(
trans
);
/* Set starting address; reads will auto-increment */
/* 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
();
rmb
();
/* "time" is actually "data" for mode 0 (no timestamp).
/* "time" is actually "data" for mode 0 (no timestamp).
* place event id # at far right for easier visual parsing. */
* place event id # at far right for easier visual parsing. */
for
(
i
=
0
;
i
<
num_events
;
i
++
)
{
for
(
i
=
0
;
i
<
num_events
;
i
++
)
{
ev
=
iwl_read32
(
bus
(
trans
)
,
HBUS_TARG_MEM_RDAT
);
ev
=
iwl_read32
(
trans
,
HBUS_TARG_MEM_RDAT
);
time
=
iwl_read32
(
bus
(
trans
)
,
HBUS_TARG_MEM_RDAT
);
time
=
iwl_read32
(
trans
,
HBUS_TARG_MEM_RDAT
);
if
(
mode
==
0
)
{
if
(
mode
==
0
)
{
/* data, ev */
/* data, ev */
if
(
bufsz
)
{
if
(
bufsz
)
{
...
@@ -766,7 +770,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
...
@@ -766,7 +770,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
time
,
ev
);
time
,
ev
);
}
}
}
else
{
}
else
{
data
=
iwl_read32
(
bus
(
trans
)
,
HBUS_TARG_MEM_RDAT
);
data
=
iwl_read32
(
trans
,
HBUS_TARG_MEM_RDAT
);
if
(
bufsz
)
{
if
(
bufsz
)
{
pos
+=
scnprintf
(
*
buf
+
pos
,
bufsz
-
pos
,
pos
+=
scnprintf
(
*
buf
+
pos
,
bufsz
-
pos
,
"EVT_LOGT:%010u:0x%08x:%04u
\n
"
,
"EVT_LOGT:%010u:0x%08x:%04u
\n
"
,
...
@@ -781,8 +785,8 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
...
@@ -781,8 +785,8 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
}
}
/* Allow device to power down */
/* Allow device to power down */
iwl_release_nic_access
(
bus
(
trans
)
);
iwl_release_nic_access
(
trans
);
spin_unlock_irqrestore
(
&
bus
(
trans
)
->
reg_lock
,
reg_flags
);
spin_unlock_irqrestore
(
&
trans
->
reg_lock
,
reg_flags
);
return
pos
;
return
pos
;
}
}
...
@@ -859,10 +863,10 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
...
@@ -859,10 +863,10 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
}
}
/* event log header */
/* event log header */
capacity
=
iwl_read_targ_mem
(
bus
(
trans
)
,
base
);
capacity
=
iwl_read_targ_mem
(
trans
,
base
);
mode
=
iwl_read_targ_mem
(
bus
(
trans
)
,
base
+
(
1
*
sizeof
(
u32
)));
mode
=
iwl_read_targ_mem
(
trans
,
base
+
(
1
*
sizeof
(
u32
)));
num_wraps
=
iwl_read_targ_mem
(
bus
(
trans
)
,
base
+
(
2
*
sizeof
(
u32
)));
num_wraps
=
iwl_read_targ_mem
(
trans
,
base
+
(
2
*
sizeof
(
u32
)));
next_entry
=
iwl_read_targ_mem
(
bus
(
trans
)
,
base
+
(
3
*
sizeof
(
u32
)));
next_entry
=
iwl_read_targ_mem
(
trans
,
base
+
(
3
*
sizeof
(
u32
)));
if
(
capacity
>
logsize
)
{
if
(
capacity
>
logsize
)
{
IWL_ERR
(
trans
,
"Log capacity %d is bogus, limit to %d "
IWL_ERR
(
trans
,
"Log capacity %d is bogus, limit to %d "
...
@@ -958,7 +962,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
...
@@ -958,7 +962,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
* hardware bugs here by ACKing all the possible interrupts so that
* hardware bugs here by ACKing all the possible interrupts so that
* interrupt coalescing can still be achieved.
* interrupt coalescing can still be achieved.
*/
*/
iwl_write32
(
bus
(
trans
)
,
CSR_INT
,
iwl_write32
(
trans
,
CSR_INT
,
trans_pcie
->
inta
|
~
trans_pcie
->
inta_mask
);
trans_pcie
->
inta
|
~
trans_pcie
->
inta_mask
);
inta
=
trans_pcie
->
inta
;
inta
=
trans_pcie
->
inta
;
...
@@ -966,7 +970,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
...
@@ -966,7 +970,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
#ifdef CONFIG_IWLWIFI_DEBUG
#ifdef CONFIG_IWLWIFI_DEBUG
if
(
iwl_get_debug_level
(
trans
->
shrd
)
&
IWL_DL_ISR
)
{
if
(
iwl_get_debug_level
(
trans
->
shrd
)
&
IWL_DL_ISR
)
{
/* just for debug */
/* 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
"
,
IWL_DEBUG_ISR
(
trans
,
"inta 0x%08x, enabled 0x%08x
\n
"
,
inta
,
inta_mask
);
inta
,
inta_mask
);
}
}
...
@@ -1014,7 +1018,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
...
@@ -1014,7 +1018,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
/* HW RF KILL switch toggled */
/* HW RF KILL switch toggled */
if
(
inta
&
CSR_INT_BIT_RF_KILL
)
{
if
(
inta
&
CSR_INT_BIT_RF_KILL
)
{
int
hw_rf_kill
=
0
;
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
))
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW
))
hw_rf_kill
=
1
;
hw_rf_kill
=
1
;
...
@@ -1078,12 +1082,12 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
...
@@ -1078,12 +1082,12 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
IWL_DEBUG_ISR
(
trans
,
"Rx interrupt
\n
"
);
IWL_DEBUG_ISR
(
trans
,
"Rx interrupt
\n
"
);
if
(
inta
&
(
CSR_INT_BIT_FH_RX
|
CSR_INT_BIT_SW_RX
))
{
if
(
inta
&
(
CSR_INT_BIT_FH_RX
|
CSR_INT_BIT_SW_RX
))
{
handled
|=
(
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
);
CSR_FH_INT_RX_MASK
);
}
}
if
(
inta
&
CSR_INT_BIT_RX_PERIODIC
)
{
if
(
inta
&
CSR_INT_BIT_RX_PERIODIC
)
{
handled
|=
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
);
CSR_INT
,
CSR_INT_BIT_RX_PERIODIC
);
}
}
/* Sending RX interrupt require many steps to be done in the
/* Sending RX interrupt require many steps to be done in the
...
@@ -1098,10 +1102,13 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
...
@@ -1098,10 +1102,13 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
*/
*/
/* Disable periodic interrupt; we use it as just a one-shot. */
/* 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
);
CSR_INT_PERIODIC_DIS
);
#ifdef CONFIG_IWLWIFI_IDI
iwl_amfh_rx_handler
();
#else
iwl_rx_handle
(
trans
);
iwl_rx_handle
(
trans
);
#endif
/*
/*
* Enable periodic interrupt in 8 msec only if we received
* Enable periodic interrupt in 8 msec only if we received
* real RX interrupt (instead of just periodic int), to catch
* real RX interrupt (instead of just periodic int), to catch
...
@@ -1110,7 +1117,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
...
@@ -1110,7 +1117,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
* to extend the periodic interrupt; one-shot is enough.
* to extend the periodic interrupt; one-shot is enough.
*/
*/
if
(
inta
&
(
CSR_INT_BIT_FH_RX
|
CSR_INT_BIT_SW_RX
))
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
);
CSR_INT_PERIODIC_ENA
);
isr_stats
->
rx
++
;
isr_stats
->
rx
++
;
...
@@ -1118,7 +1125,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
...
@@ -1118,7 +1125,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
/* This "Tx" DMA channel is used only for loading uCode */
/* This "Tx" DMA channel is used only for loading uCode */
if
(
inta
&
CSR_INT_BIT_FH_TX
)
{
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
"
);
IWL_DEBUG_ISR
(
trans
,
"uCode load interrupt
\n
"
);
isr_stats
->
tx
++
;
isr_stats
->
tx
++
;
handled
|=
CSR_INT_BIT_FH_TX
;
handled
|=
CSR_INT_BIT_FH_TX
;
...
@@ -1142,8 +1149,10 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
...
@@ -1142,8 +1149,10 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans
->
shrd
->
status
))
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans
->
shrd
->
status
))
iwl_enable_interrupts
(
trans
);
iwl_enable_interrupts
(
trans
);
/* Re-enable RF_KILL if it occurred */
/* Re-enable RF_KILL if it occurred */
else
if
(
handled
&
CSR_INT_BIT_RF_KILL
)
else
if
(
handled
&
CSR_INT_BIT_RF_KILL
)
{
iwl_enable_rfkill_int
(
priv
(
trans
));
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)
...
@@ -1164,7 +1173,7 @@ void iwl_free_isr_ict(struct iwl_trans *trans)
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
if
(
trans_pcie
->
ict_tbl
)
{
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
,
trans_pcie
->
ict_tbl_dma
);
trans_pcie
->
ict_tbl_dma
);
trans_pcie
->
ict_tbl
=
NULL
;
trans_pcie
->
ict_tbl
=
NULL
;
...
@@ -1184,7 +1193,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
...
@@ -1184,7 +1193,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
trans_pcie
->
ict_tbl
=
trans_pcie
->
ict_tbl
=
dma_alloc_coherent
(
bus
(
trans
)
->
dev
,
ICT_SIZE
,
dma_alloc_coherent
(
trans
->
dev
,
ICT_SIZE
,
&
trans_pcie
->
ict_tbl_dma
,
&
trans_pcie
->
ict_tbl_dma
,
GFP_KERNEL
);
GFP_KERNEL
);
if
(
!
trans_pcie
->
ict_tbl
)
if
(
!
trans_pcie
->
ict_tbl
)
...
@@ -1213,7 +1222,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
...
@@ -1213,7 +1222,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
/* Device is going up inform it about using ICT interrupt table,
/* Device is going up inform it about using ICT interrupt table,
* also we need to tell the driver to start using ICT interrupt.
* 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
;
u32
val
;
unsigned
long
flags
;
unsigned
long
flags
;
...
@@ -1221,7 +1230,7 @@ int iwl_reset_ict(struct iwl_trans *trans)
...
@@ -1221,7 +1230,7 @@ int iwl_reset_ict(struct iwl_trans *trans)
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
if
(
!
trans_pcie
->
ict_tbl
)
if
(
!
trans_pcie
->
ict_tbl
)
return
0
;
return
;
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
iwl_disable_interrupts
(
trans
);
iwl_disable_interrupts
(
trans
);
...
@@ -1235,14 +1244,12 @@ int iwl_reset_ict(struct iwl_trans *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_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
->
use_ict
=
true
;
trans_pcie
->
ict_index
=
0
;
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
);
iwl_enable_interrupts
(
trans
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
return
0
;
}
}
/* Device is going down disable ict interrupt usage */
/* Device is going down disable ict interrupt usage */
...
@@ -1280,11 +1287,11 @@ static irqreturn_t iwl_isr(int irq, void *data)
...
@@ -1280,11 +1287,11 @@ static irqreturn_t iwl_isr(int irq, void *data)
* back-to-back ISRs and sporadic interrupts from our NIC.
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* 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. */
* 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 */
inta_mask
=
iwl_read32
(
trans
,
CSR_INT_MASK
);
/* just for debug */
iwl_write32
(
bus
(
trans
)
,
CSR_INT_MASK
,
0x00000000
);
iwl_write32
(
trans
,
CSR_INT_MASK
,
0x00000000
);
/* Discover which interrupts are active/pending */
/* 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.
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
* This may be due to IRQ shared with another device,
...
@@ -1303,7 +1310,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
...
@@ -1303,7 +1310,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
#ifdef CONFIG_IWLWIFI_DEBUG
#ifdef CONFIG_IWLWIFI_DEBUG
if
(
iwl_get_debug_level
(
trans
->
shrd
)
&
(
IWL_DL_ISR
))
{
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, "
IWL_DEBUG_ISR
(
trans
,
"ISR inta 0x%08x, enabled 0x%08x, "
"fh 0x%08x
\n
"
,
inta
,
inta_mask
,
inta_fh
);
"fh 0x%08x
\n
"
,
inta
,
inta_mask
,
inta_fh
);
}
}
...
@@ -1369,8 +1376,8 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
...
@@ -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 have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here.
* 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 */
inta_mask
=
iwl_read32
(
trans
,
CSR_INT_MASK
);
/* just for debug */
iwl_write32
(
bus
(
trans
)
,
CSR_INT_MASK
,
0x00000000
);
iwl_write32
(
trans
,
CSR_INT_MASK
,
0x00000000
);
/* Ignore interrupt if there's nothing in NIC to service.
/* Ignore interrupt if there's nothing in NIC to service.
...
...
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
浏览文件 @
8f0bb5ae
...
@@ -100,7 +100,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
...
@@ -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
)
{
if
(
hw_params
(
trans
).
shadow_reg_enable
)
{
/* shadow register enabled */
/* shadow register enabled */
iwl_write32
(
bus
(
trans
)
,
HBUS_TARG_WRPTR
,
iwl_write32
(
trans
,
HBUS_TARG_WRPTR
,
txq
->
q
.
write_ptr
|
(
txq_id
<<
8
));
txq
->
q
.
write_ptr
|
(
txq_id
<<
8
));
}
else
{
}
else
{
/* if we're trying to save power */
/* 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)
...
@@ -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 ...
/* wake up nic if it's powered down ...
* uCode will wake up, and interrupt us again, so next
* uCode will wake up, and interrupt us again, so next
* time we'll skip this part. */
* 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
)
{
if
(
reg
&
CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP
)
{
IWL_DEBUG_INFO
(
trans
,
IWL_DEBUG_INFO
(
trans
,
"Tx queue %d requesting wakeup,"
"Tx queue %d requesting wakeup,"
" GP1 = 0x%x
\n
"
,
txq_id
,
reg
);
" 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
);
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
return
;
return
;
}
}
iwl_write_direct32
(
bus
(
trans
)
,
HBUS_TARG_WRPTR
,
iwl_write_direct32
(
trans
,
HBUS_TARG_WRPTR
,
txq
->
q
.
write_ptr
|
(
txq_id
<<
8
));
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)
...
@@ -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).
* trying to tx (during RFKILL, we're not trying to tx).
*/
*/
}
else
}
else
iwl_write32
(
bus
(
trans
)
,
HBUS_TARG_WRPTR
,
iwl_write32
(
trans
,
HBUS_TARG_WRPTR
,
txq
->
q
.
write_ptr
|
(
txq_id
<<
8
));
txq
->
q
.
write_ptr
|
(
txq_id
<<
8
));
}
}
txq
->
need_update
=
0
;
txq
->
need_update
=
0
;
...
@@ -190,14 +190,14 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
...
@@ -190,14 +190,14 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
/* Unmap tx_cmd */
/* Unmap tx_cmd */
if
(
num_tbs
)
if
(
num_tbs
)
dma_unmap_single
(
bus
(
trans
)
->
dev
,
dma_unmap_single
(
trans
->
dev
,
dma_unmap_addr
(
meta
,
mapping
),
dma_unmap_addr
(
meta
,
mapping
),
dma_unmap_len
(
meta
,
len
),
dma_unmap_len
(
meta
,
len
),
DMA_BIDIRECTIONAL
);
DMA_BIDIRECTIONAL
);
/* Unmap chunks, if any. */
/* Unmap chunks, if any. */
for
(
i
=
1
;
i
<
num_tbs
;
i
++
)
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
);
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,
...
@@ -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
+
tbl_dw_addr
=
trans_pcie
->
scd_base_addr
+
SCD_TRANS_TBL_OFFSET_QUEUE
(
txq_id
);
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
)
if
(
txq_id
&
0x1
)
tbl_dw
=
(
scd_q2ratid
<<
16
)
|
(
tbl_dw
&
0x0000FFFF
);
tbl_dw
=
(
scd_q2ratid
<<
16
)
|
(
tbl_dw
&
0x0000FFFF
);
else
else
tbl_dw
=
scd_q2ratid
|
(
tbl_dw
&
0xFFFF0000
);
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
;
return
0
;
}
}
...
@@ -399,7 +399,7 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id)
...
@@ -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;
/* Simply stop the queue, but don't change any configuration;
* the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
* 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
),
SCD_QUEUE_STATUS_BITS
(
txq_id
),
(
0
<<
SCD_QUEUE_STTS_REG_POS_ACTIVE
)
|
(
0
<<
SCD_QUEUE_STTS_REG_POS_ACTIVE
)
|
(
1
<<
SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN
));
(
1
<<
SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN
));
...
@@ -409,9 +409,9 @@ void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
...
@@ -409,9 +409,9 @@ void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
int
txq_id
,
u32
index
)
int
txq_id
,
u32
index
)
{
{
IWL_DEBUG_TX_QUEUES
(
trans
,
"Q %d WrPtr: %d"
,
txq_id
,
index
&
0xff
);
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
));
(
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
,
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,
...
@@ -423,7 +423,7 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
int
active
=
int
active
=
test_bit
(
txq_id
,
&
trans_pcie
->
txq_ctx_active_msk
)
?
1
:
0
;
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
)
|
(
active
<<
SCD_QUEUE_STTS_REG_POS_ACTIVE
)
|
(
tx_fifo_id
<<
SCD_QUEUE_STTS_REG_POS_TXF
)
|
(
tx_fifo_id
<<
SCD_QUEUE_STTS_REG_POS_TXF
)
|
(
1
<<
SCD_QUEUE_STTS_REG_POS_WSL
)
|
(
1
<<
SCD_QUEUE_STTS_REG_POS_WSL
)
|
...
@@ -431,9 +431,12 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
...
@@ -431,9 +431,12 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
txq
->
sched_retry
=
scd_retry
;
txq
->
sched_retry
=
scd_retry
;
IWL_DEBUG_TX_QUEUES
(
trans
,
"%s %s Queue %d on FIFO %d
\n
"
,
if
(
active
)
active
?
"Activate"
:
"Deactivate"
,
IWL_DEBUG_TX_QUEUES
(
trans
,
"Activate %s Queue %d on FIFO %d
\n
"
,
scd_retry
?
"BA"
:
"AC/CMD"
,
txq_id
,
tx_fifo_id
);
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
,
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,
...
@@ -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
);
iwlagn_tx_queue_set_q2ratid
(
trans
,
ra_tid
,
txq_id
);
/* Set this queue as a chain-building queue */
/* 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 */
/* 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.
/* Place first TFD at index corresponding to start sequence number.
* Assumes that ssn_idx is valid (!= 0xFFF) */
* Assumes that ssn_idx is valid (!= 0xFFF) */
...
@@ -510,7 +513,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
...
@@ -510,7 +513,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
iwl_trans_set_wr_ptrs
(
trans
,
txq_id
,
ssn
);
iwl_trans_set_wr_ptrs
(
trans
,
txq_id
,
ssn
);
/* Set up Tx window size and frame limit for this queue */
/* 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
)
+
SCD_CONTEXT_QUEUE_OFFSET
(
txq_id
)
+
sizeof
(
u32
),
sizeof
(
u32
),
((
frame_limit
<<
((
frame_limit
<<
...
@@ -520,7 +523,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
...
@@ -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_POS
)
&
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK
));
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 */
/* 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
],
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)
...
@@ -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
);
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
->
agg_txq
[
sta_id
][
tid
]
=
0
;
trans_pcie
->
txq
[
txq_id
].
q
.
read_ptr
=
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)
...
@@ -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) */
/* supposes that ssn_idx is valid (!= 0xFFF) */
iwl_trans_set_wr_ptrs
(
trans
,
txq_id
,
0
);
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_txq_ctx_deactivate
(
trans_pcie
,
txq_id
);
iwl_trans_tx_queue_set_status
(
trans
,
&
trans_pcie
->
txq
[
txq_id
],
0
,
0
);
iwl_trans_tx_queue_set_status
(
trans
,
&
trans_pcie
->
txq
[
txq_id
],
0
,
0
);
return
0
;
return
0
;
...
@@ -725,9 +728,9 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
...
@@ -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
,
le16_to_cpu
(
out_cmd
->
hdr
.
sequence
),
cmd_size
,
q
->
write_ptr
,
idx
,
trans
->
shrd
->
cmd_queue
);
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
);
DMA_BIDIRECTIONAL
);
if
(
unlikely
(
dma_mapping_error
(
bus
(
trans
)
->
dev
,
phys_addr
)))
{
if
(
unlikely
(
dma_mapping_error
(
trans
->
dev
,
phys_addr
)))
{
idx
=
-
ENOMEM
;
idx
=
-
ENOMEM
;
goto
out
;
goto
out
;
}
}
...
@@ -748,10 +751,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
...
@@ -748,10 +751,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
continue
;
continue
;
if
(
!
(
cmd
->
dataflags
[
i
]
&
IWL_HCMD_DFL_NOCOPY
))
if
(
!
(
cmd
->
dataflags
[
i
]
&
IWL_HCMD_DFL_NOCOPY
))
continue
;
continue
;
phys_addr
=
dma_map_single
(
bus
(
trans
)
->
dev
,
phys_addr
=
dma_map_single
(
trans
->
dev
,
(
void
*
)
cmd
->
data
[
i
],
(
void
*
)
cmd
->
data
[
i
],
cmd
->
len
[
i
],
DMA_BIDIRECTIONAL
);
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
,
iwlagn_unmap_tfd
(
trans
,
out_meta
,
&
txq
->
tfds
[
q
->
write_ptr
],
&
txq
->
tfds
[
q
->
write_ptr
],
DMA_BIDIRECTIONAL
);
DMA_BIDIRECTIONAL
);
...
...
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
浏览文件 @
8f0bb5ae
...
@@ -60,8 +60,11 @@
...
@@ -60,8 +60,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* 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/interrupt.h>
#include <linux/debugfs.h>
#include <linux/debugfs.h>
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/bitops.h>
#include <linux/gfp.h>
#include <linux/gfp.h>
...
@@ -72,13 +75,14 @@
...
@@ -72,13 +75,14 @@
#include "iwl-shared.h"
#include "iwl-shared.h"
#include "iwl-eeprom.h"
#include "iwl-eeprom.h"
#include "iwl-agn-hw.h"
#include "iwl-agn-hw.h"
#include "iwl-core.h"
static
int
iwl_trans_rx_alloc
(
struct
iwl_trans
*
trans
)
static
int
iwl_trans_rx_alloc
(
struct
iwl_trans
*
trans
)
{
{
struct
iwl_trans_pcie
*
trans_pcie
=
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
struct
iwl_rx_queue
*
rxq
=
&
trans_pcie
->
rxq
;
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
));
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)
...
@@ -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
/* In the reset function, these buffers may have been allocated
* to an SKB, so we need to unmap and free potential storage */
* to an SKB, so we need to unmap and free potential storage */
if
(
rxq
->
pool
[
i
].
page
!=
NULL
)
{
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
,
PAGE_SIZE
<<
hw_params
(
trans
).
rx_page_order
,
DMA_FROM_DEVICE
);
DMA_FROM_DEVICE
);
__free_pages
(
rxq
->
pool
[
i
].
page
,
__free_pages
(
rxq
->
pool
[
i
].
page
,
...
@@ -146,17 +150,17 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
...
@@ -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
;
rb_size
=
FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K
;
/* Stop Rx DMA */
/* 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 */
/* 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 */
/* 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
));
(
u32
)(
rxq
->
bd_dma
>>
8
));
/* Tell device where in DRAM to update its Rx status */
/* 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
);
rxq
->
rb_stts_dma
>>
4
);
/* Enable Rx DMA
/* Enable Rx DMA
...
@@ -167,7 +171,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
...
@@ -167,7 +171,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
* RB timeout 0x10
* RB timeout 0x10
* 256 RBDs
* 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_RX_CONFIG_CHNL_EN_ENABLE_VAL
|
FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY
|
FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY
|
FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL
|
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,
...
@@ -177,7 +181,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
(
rfdnlog
<<
FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS
));
(
rfdnlog
<<
FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS
));
/* Set interrupt coalescing timer to default (2048 usecs) */
/* 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
)
static
int
iwl_rx_init
(
struct
iwl_trans
*
trans
)
...
@@ -242,13 +246,13 @@ static void iwl_trans_pcie_rx_free(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
);
iwl_trans_rxq_free_rx_bufs
(
trans
);
spin_unlock_irqrestore
(
&
rxq
->
lock
,
flags
);
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
);
rxq
->
bd
,
rxq
->
bd_dma
);
memset
(
&
rxq
->
bd_dma
,
0
,
sizeof
(
rxq
->
bd_dma
));
memset
(
&
rxq
->
bd_dma
,
0
,
sizeof
(
rxq
->
bd_dma
));
rxq
->
bd
=
NULL
;
rxq
->
bd
=
NULL
;
if
(
rxq
->
rb_stts
)
if
(
rxq
->
rb_stts
)
dma_free_coherent
(
bus
(
trans
)
->
dev
,
dma_free_coherent
(
trans
->
dev
,
sizeof
(
struct
iwl_rb_status
),
sizeof
(
struct
iwl_rb_status
),
rxq
->
rb_stts
,
rxq
->
rb_stts_dma
);
rxq
->
rb_stts
,
rxq
->
rb_stts_dma
);
else
else
...
@@ -261,8 +265,8 @@ static int iwl_trans_rx_stop(struct iwl_trans *trans)
...
@@ -261,8 +265,8 @@ static int iwl_trans_rx_stop(struct iwl_trans *trans)
{
{
/* stop Rx DMA */
/* 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
);
return
iwl_poll_direct_bit
(
bus
(
trans
)
,
FH_MEM_RSSR_RX_STATUS_REG
,
return
iwl_poll_direct_bit
(
trans
,
FH_MEM_RSSR_RX_STATUS_REG
,
FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE
,
1000
);
FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE
,
1000
);
}
}
...
@@ -272,7 +276,7 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans,
...
@@ -272,7 +276,7 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans,
if
(
WARN_ON
(
ptr
->
addr
))
if
(
WARN_ON
(
ptr
->
addr
))
return
-
EINVAL
;
return
-
EINVAL
;
ptr
->
addr
=
dma_alloc_coherent
(
bus
(
trans
)
->
dev
,
size
,
ptr
->
addr
=
dma_alloc_coherent
(
trans
->
dev
,
size
,
&
ptr
->
dma
,
GFP_KERNEL
);
&
ptr
->
dma
,
GFP_KERNEL
);
if
(
!
ptr
->
addr
)
if
(
!
ptr
->
addr
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -286,7 +290,7 @@ static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans,
...
@@ -286,7 +290,7 @@ static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans,
if
(
unlikely
(
!
ptr
->
addr
))
if
(
unlikely
(
!
ptr
->
addr
))
return
;
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
));
memset
(
ptr
,
0
,
sizeof
(
*
ptr
));
}
}
...
@@ -333,7 +337,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
...
@@ -333,7 +337,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
/* Circular buffer of transmit frame descriptors (TFDs),
/* Circular buffer of transmit frame descriptors (TFDs),
* shared with device */
* 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
);
&
txq
->
q
.
dma_addr
,
GFP_KERNEL
);
if
(
!
txq
->
tfds
)
{
if
(
!
txq
->
tfds
)
{
IWL_ERR
(
trans
,
"dma_alloc_coherent(%zd) failed
\n
"
,
tfd_sz
);
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,
...
@@ -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
* Tell nic where to find circular buffer of Tx Frame Descriptors for
* given Tx queue, and enable the DMA channel used for that queue.
* given Tx queue, and enable the DMA channel used for that queue.
* Circular buffer (TFD queue in DRAM) physical base address */
* 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
);
txq
->
q
.
dma_addr
>>
8
);
return
0
;
return
0
;
...
@@ -443,7 +447,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
...
@@ -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_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
struct
iwl_tx_queue
*
txq
=
&
trans_pcie
->
txq
[
txq_id
];
struct
iwl_tx_queue
*
txq
=
&
trans_pcie
->
txq
[
txq_id
];
struct
device
*
dev
=
bus
(
trans
)
->
dev
;
struct
device
*
dev
=
trans
->
dev
;
int
i
;
int
i
;
if
(
WARN_ON
(
!
txq
))
if
(
WARN_ON
(
!
txq
))
return
;
return
;
...
@@ -584,10 +588,10 @@ static int iwl_tx_init(struct iwl_trans *trans)
...
@@ -584,10 +588,10 @@ static int iwl_tx_init(struct iwl_trans *trans)
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
/* Turn off all Tx DMA fifos */
/* 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 */
/* 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
);
trans_pcie
->
kw
.
dma
>>
4
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
...
@@ -619,26 +623,194 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans)
...
@@ -619,26 +623,194 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans)
* to set power to V_AUX, do:
* to set power to V_AUX, do:
if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
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_VAL_PWR_SRC_VAUX,
~APMG_PS_CTRL_MSK_PWR_SRC);
~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_VAL_PWR_SRC_VMAIN
,
~
APMG_PS_CTRL_MSK_PWR_SRC
);
~
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
)
static
int
iwl_nic_init
(
struct
iwl_trans
*
trans
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
/* nic_init */
/* nic_init */
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
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) */
/* 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
);
IWL_HOST_INT_CALIB_TIMEOUT_DEF
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
...
@@ -647,8 +819,10 @@ static int iwl_nic_init(struct iwl_trans *trans)
...
@@ -647,8 +819,10 @@ static int iwl_nic_init(struct iwl_trans *trans)
iwl_nic_config
(
priv
(
trans
));
iwl_nic_config
(
priv
(
trans
));
#ifndef CONFIG_IWLWIFI_IDI
/* Allocate the RX queue, or reset if it is already allocated */
/* Allocate the RX queue, or reset if it is already allocated */
iwl_rx_init
(
trans
);
iwl_rx_init
(
trans
);
#endif
/* Allocate or reset and init all Tx and Command queues */
/* Allocate or reset and init all Tx and Command queues */
if
(
iwl_tx_init
(
trans
))
if
(
iwl_tx_init
(
trans
))
...
@@ -656,7 +830,7 @@ static int iwl_nic_init(struct iwl_trans *trans)
...
@@ -656,7 +830,7 @@ static int iwl_nic_init(struct iwl_trans *trans)
if
(
hw_params
(
trans
).
shadow_reg_enable
)
{
if
(
hw_params
(
trans
).
shadow_reg_enable
)
{
/* enable shadow regs in HW */
/* 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
);
0x800FFFFF
);
}
}
...
@@ -672,11 +846,11 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
...
@@ -672,11 +846,11 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
{
{
int
ret
;
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
);
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY
);
/* See if we got it */
/* 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
,
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY
,
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY
,
HW_READY_TIMEOUT
);
HW_READY_TIMEOUT
);
...
@@ -686,21 +860,22 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
...
@@ -686,21 +860,22 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
}
}
/* Note: returns standard 0/-ERROR code */
/* 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
;
int
ret
;
IWL_DEBUG_INFO
(
trans
,
"iwl_trans_prepare_card_hw enter
\n
"
);
IWL_DEBUG_INFO
(
trans
,
"iwl_trans_prepare_card_hw enter
\n
"
);
ret
=
iwl_set_hw_ready
(
trans
);
ret
=
iwl_set_hw_ready
(
trans
);
/* If the card is ready, exit 0 */
if
(
ret
>=
0
)
if
(
ret
>=
0
)
return
0
;
return
0
;
/* If HW is not ready, prepare the conditions to check again */
/* 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
);
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
,
CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE
,
150000
);
CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE
,
150000
);
...
@@ -767,7 +942,79 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
...
@@ -767,7 +942,79 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
7
,
6
,
5
,
4
,
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
;
int
ret
;
struct
iwl_trans_pcie
*
trans_pcie
=
struct
iwl_trans_pcie
*
trans_pcie
=
...
@@ -784,13 +1031,13 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
...
@@ -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
;
trans_pcie
->
mcast_queue
[
IWL_RXON_CTX_PAN
]
=
IWL_IPAN_MCAST_QUEUE
;
if
((
hw_params
(
trans
).
sku
&
EEPROM_SKU_CAP_AMT_ENABLE
)
&&
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
"
);
IWL_WARN
(
trans
,
"Exit HW not ready
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
/* If platform's RF_KILL switch is NOT set to KILL */
/* 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
)
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW
)
clear_bit
(
STATUS_RF_KILL_HW
,
&
trans
->
shrd
->
status
);
clear_bit
(
STATUS_RF_KILL_HW
,
&
trans
->
shrd
->
status
);
else
else
...
@@ -802,7 +1049,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
...
@@ -802,7 +1049,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
return
-
ERFKILL
;
return
-
ERFKILL
;
}
}
iwl_write32
(
bus
(
trans
)
,
CSR_INT
,
0xFFFFFFFF
);
iwl_write32
(
trans
,
CSR_INT
,
0xFFFFFFFF
);
ret
=
iwl_nic_init
(
trans
);
ret
=
iwl_nic_init
(
trans
);
if
(
ret
)
{
if
(
ret
)
{
...
@@ -811,17 +1058,20 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
...
@@ -811,17 +1058,20 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
}
}
/* make sure rfkill handshake bits are cleared */
/* make sure rfkill handshake bits are cleared */
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
(
bus
(
trans
)
,
CSR_UCODE_DRV_GP1_CLR
,
iwl_write32
(
trans
,
CSR_UCODE_DRV_GP1_CLR
,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED
);
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED
);
/* clear (again), then enable host interrupts */
/* clear (again), then enable host interrupts */
iwl_write32
(
bus
(
trans
)
,
CSR_INT
,
0xFFFFFFFF
);
iwl_write32
(
trans
,
CSR_INT
,
0xFFFFFFFF
);
iwl_enable_interrupts
(
trans
);
iwl_enable_interrupts
(
trans
);
/* really make sure rfkill handshake bits are cleared */
/* really make sure rfkill handshake bits are cleared */
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
(
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
);
/* Load the given image to the HW */
iwl_load_given_ucode
(
trans
,
fw
);
return
0
;
return
0
;
}
}
...
@@ -832,10 +1082,10 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
...
@@ -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
)
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
;
const
struct
queue_to_fifo_ac
*
queue_to_fifo
;
struct
iwl_trans_pcie
*
trans_pcie
=
struct
iwl_trans_pcie
*
trans_pcie
=
...
@@ -848,46 +1098,46 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
...
@@ -848,46 +1098,46 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
spin_lock_irqsave
(
&
trans
->
shrd
->
lock
,
flags
);
trans_pcie
->
scd_base_addr
=
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
;
a
=
trans_pcie
->
scd_base_addr
+
SCD_CONTEXT_MEM_LOWER_BOUND
;
/* reset conext data memory */
/* reset conext data memory */
for
(;
a
<
trans_pcie
->
scd_base_addr
+
SCD_CONTEXT_MEM_UPPER_BOUND
;
for
(;
a
<
trans_pcie
->
scd_base_addr
+
SCD_CONTEXT_MEM_UPPER_BOUND
;
a
+=
4
)
a
+=
4
)
iwl_write_targ_mem
(
bus
(
trans
)
,
a
,
0
);
iwl_write_targ_mem
(
trans
,
a
,
0
);
/* reset tx status memory */
/* reset tx status memory */
for
(;
a
<
trans_pcie
->
scd_base_addr
+
SCD_TX_STTS_MEM_UPPER_BOUND
;
for
(;
a
<
trans_pcie
->
scd_base_addr
+
SCD_TX_STTS_MEM_UPPER_BOUND
;
a
+=
4
)
a
+=
4
)
iwl_write_targ_mem
(
bus
(
trans
)
,
a
,
0
);
iwl_write_targ_mem
(
trans
,
a
,
0
);
for
(;
a
<
trans_pcie
->
scd_base_addr
+
for
(;
a
<
trans_pcie
->
scd_base_addr
+
SCD_TRANS_TBL_OFFSET_QUEUE
(
hw_params
(
trans
).
max_txq_num
);
SCD_TRANS_TBL_OFFSET_QUEUE
(
hw_params
(
trans
).
max_txq_num
);
a
+=
4
)
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
);
trans_pcie
->
scd_bc_tbls
.
dma
>>
10
);
/* Enable DMA channel */
/* Enable DMA channel */
for
(
chan
=
0
;
chan
<
FH_TCSR_CHNL_NUM
;
chan
++
)
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_CHNL_ENABLE
|
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE
);
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE
);
/* Update FH chicken bits */
/* Update FH chicken bits */
reg_val
=
iwl_read_direct32
(
bus
(
trans
)
,
FH_TX_CHICKEN_BITS_REG
);
reg_val
=
iwl_read_direct32
(
trans
,
FH_TX_CHICKEN_BITS_REG
);
iwl_write_direct32
(
bus
(
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
);
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
));
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 */
/* initiate the queues */
for
(
i
=
0
;
i
<
hw_params
(
trans
).
max_txq_num
;
i
++
)
{
for
(
i
=
0
;
i
<
hw_params
(
trans
).
max_txq_num
;
i
++
)
{
iwl_write_prph
(
bus
(
trans
)
,
SCD_QUEUE_RDPTR
(
i
),
0
);
iwl_write_prph
(
trans
,
SCD_QUEUE_RDPTR
(
i
),
0
);
iwl_write_direct32
(
bus
(
trans
)
,
HBUS_TARG_WRPTR
,
0
|
(
i
<<
8
));
iwl_write_direct32
(
trans
,
HBUS_TARG_WRPTR
,
0
|
(
i
<<
8
));
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
),
0
);
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
)
+
SCD_CONTEXT_QUEUE_OFFSET
(
i
)
+
sizeof
(
u32
),
sizeof
(
u32
),
((
SCD_WIN_SIZE
<<
((
SCD_WIN_SIZE
<<
...
@@ -898,7 +1148,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
...
@@ -898,7 +1148,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK
));
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
));
IWL_MASK
(
0
,
hw_params
(
trans
).
max_txq_num
));
/* Activate all Tx DMA/FIFO channels */
/* Activate all Tx DMA/FIFO channels */
...
@@ -944,10 +1194,16 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
...
@@ -944,10 +1194,16 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
/* Enable L1-Active */
/* 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
);
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
* iwlagn_txq_ctx_stop - Stop all Tx DMA channels
*/
*/
...
@@ -964,14 +1220,14 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
...
@@ -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 */
/* Stop each Tx DMA channel, and wait for it to be idle */
for
(
ch
=
0
;
ch
<
FH_TCSR_CHNL_NUM
;
ch
++
)
{
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
);
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
),
FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
(
ch
),
1000
))
1000
))
IWL_ERR
(
trans
,
"Failing on timeout while stopping"
IWL_ERR
(
trans
,
"Failing on timeout while stopping"
" DMA channel %d [0x%08x]"
,
ch
,
" DMA channel %d [0x%08x]"
,
ch
,
iwl_read_direct32
(
bus
(
trans
)
,
iwl_read_direct32
(
trans
,
FH_TSSR_TX_STATUS_REG
));
FH_TSSR_TX_STATUS_REG
));
}
}
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
...
@@ -1010,20 +1266,21 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
...
@@ -1010,20 +1266,21 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
*/
*/
if
(
test_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
shrd
->
status
))
{
if
(
test_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
shrd
->
status
))
{
iwl_trans_tx_stop
(
trans
);
iwl_trans_tx_stop
(
trans
);
#ifndef CONFIG_IWLWIFI_IDI
iwl_trans_rx_stop
(
trans
);
iwl_trans_rx_stop
(
trans
);
#endif
/* Power-down device's busmaster DMA clocks */
/* 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
);
APMG_CLK_VAL_DMA_CLK_RQT
);
udelay
(
5
);
udelay
(
5
);
}
}
/* Make sure (redundant) we've released our request to stay awake */
/* 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
);
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
/* Stop the device, and put it in low power state */
/* 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.
/* Upon stop, the APM issues an interrupt if HW RF kill is set.
* Clean again the interrupt here
* Clean again the interrupt here
...
@@ -1033,11 +1290,11 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
...
@@ -1033,11 +1290,11 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
trans
->
shrd
->
lock
,
flags
);
/* wait to make sure we flush pending tasklet*/
/* wait to make sure we flush pending tasklet*/
synchronize_irq
(
bus
(
trans
)
->
irq
);
synchronize_irq
(
trans
->
irq
);
tasklet_kill
(
&
trans_pcie
->
irq_tasklet
);
tasklet_kill
(
&
trans_pcie
->
irq_tasklet
);
/* stop and reset the on-board processor */
/* 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
,
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,
...
@@ -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!),
/* Physical address of this Tx command's header (not MAC header!),
* within command buffer array. */
* within command buffer array. */
txcmd_phys
=
dma_map_single
(
bus
(
trans
)
->
dev
,
txcmd_phys
=
dma_map_single
(
trans
->
dev
,
&
dev_cmd
->
hdr
,
firstlen
,
&
dev_cmd
->
hdr
,
firstlen
,
DMA_BIDIRECTIONAL
);
DMA_BIDIRECTIONAL
);
if
(
unlikely
(
dma_mapping_error
(
bus
(
trans
)
->
dev
,
txcmd_phys
)))
if
(
unlikely
(
dma_mapping_error
(
trans
->
dev
,
txcmd_phys
)))
return
-
1
;
return
-
1
;
dma_unmap_addr_set
(
out_meta
,
mapping
,
txcmd_phys
);
dma_unmap_addr_set
(
out_meta
,
mapping
,
txcmd_phys
);
dma_unmap_len_set
(
out_meta
,
len
,
firstlen
);
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,
...
@@ -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). */
* if any (802.11 null frames have no payload). */
secondlen
=
skb
->
len
-
hdr_len
;
secondlen
=
skb
->
len
-
hdr_len
;
if
(
secondlen
>
0
)
{
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
);
secondlen
,
DMA_TO_DEVICE
);
if
(
unlikely
(
dma_mapping_error
(
bus
(
trans
)
->
dev
,
phys_addr
)))
{
if
(
unlikely
(
dma_mapping_error
(
trans
->
dev
,
phys_addr
)))
{
dma_unmap_single
(
bus
(
trans
)
->
dev
,
dma_unmap_single
(
trans
->
dev
,
dma_unmap_addr
(
out_meta
,
mapping
),
dma_unmap_addr
(
out_meta
,
mapping
),
dma_unmap_len
(
out_meta
,
len
),
dma_unmap_len
(
out_meta
,
len
),
DMA_BIDIRECTIONAL
);
DMA_BIDIRECTIONAL
);
...
@@ -1174,7 +1431,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
...
@@ -1174,7 +1431,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
offsetof
(
struct
iwl_tx_cmd
,
scratch
);
offsetof
(
struct
iwl_tx_cmd
,
scratch
);
/* take back ownership of DMA buffer to enable update */
/* 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
);
DMA_BIDIRECTIONAL
);
tx_cmd
->
dram_lsb_ptr
=
cpu_to_le32
(
scratch_phys
);
tx_cmd
->
dram_lsb_ptr
=
cpu_to_le32
(
scratch_phys
);
tx_cmd
->
dram_msb_ptr
=
iwl_get_dma_hi_addr
(
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,
...
@@ -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 */
/* 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
));
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
);
DMA_BIDIRECTIONAL
);
trace_iwlwifi_dev_tx
(
priv
(
trans
),
trace_iwlwifi_dev_tx
(
priv
(
trans
),
...
@@ -1218,13 +1475,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
...
@@ -1218,13 +1475,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
return
0
;
return
0
;
}
}
static
void
iwl_trans_pcie_kick_nic
(
struct
iwl_trans
*
trans
)
static
int
iwl_trans_pcie_start_hw
(
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
)
{
{
struct
iwl_trans_pcie
*
trans_pcie
=
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
...
@@ -1232,21 +1483,62 @@ static int iwl_trans_pcie_request_irq(struct iwl_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
;
trans_pcie
->
inta_mask
=
CSR_INI_SET_MASK
;
tasklet_init
(
&
trans_pcie
->
irq_tasklet
,
(
void
(
*
)(
unsigned
long
))
if
(
!
trans_pcie
->
irq_requested
)
{
iwl_irq_tasklet
,
(
unsigned
long
)
trans
);
tasklet_init
(
&
trans_pcie
->
irq_tasklet
,
(
void
(
*
)(
unsigned
long
))
iwl_irq_tasklet
,
(
unsigned
long
)
trans
);
iwl_alloc_isr_ict
(
trans
);
iwl_alloc_isr_ict
(
trans
);
err
=
request_irq
(
trans
->
irq
,
iwl_isr_ict
,
IRQF_SHARED
,
DRV_NAME
,
trans
);
if
(
err
)
{
IWL_ERR
(
trans
,
"Error allocating IRQ %d
\n
"
,
trans
->
irq
);
goto
error
;
}
err
=
request_irq
(
bus
(
trans
)
->
irq
,
iwl_isr_ict
,
IRQF_SHARED
,
INIT_WORK
(
&
trans_pcie
->
rx_replenish
,
iwl_bg_rx_replenish
);
DRV_NAME
,
trans
);
trans_pcie
->
irq_requested
=
true
;
}
err
=
iwl_prepare_card_hw
(
trans
);
if
(
err
)
{
if
(
err
)
{
IWL_ERR
(
trans
,
"Error allocating IRQ %d
\n
"
,
bus
(
trans
)
->
irq
);
IWL_ERR
(
trans
,
"Error while preparing HW: %d"
,
err
);
iwl_free_isr_ict
(
trans
);
goto
err_free_irq
;
return
err
;
}
}
INIT_WORK
(
&
trans_pcie
->
rx_replenish
,
iwl_bg_rx_replenish
);
iwl_apm_init
(
trans
);
return
0
;
/* 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
,
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,
...
@@ -1288,13 +1580,42 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
return
0
;
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
)
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_calib_free_results
(
trans
);
iwl_trans_pcie_tx_free
(
trans
);
iwl_trans_pcie_tx_free
(
trans
);
#ifndef CONFIG_IWLWIFI_IDI
iwl_trans_pcie_rx_free
(
trans
);
iwl_trans_pcie_rx_free
(
trans
);
free_irq
(
bus
(
trans
)
->
irq
,
trans
);
#endif
iwl_free_isr_ict
(
trans
);
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
;
trans
->
shrd
->
trans
=
NULL
;
kfree
(
trans
);
kfree
(
trans
);
}
}
...
@@ -1314,10 +1635,10 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
...
@@ -1314,10 +1635,10 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
* things already :-)
* things already :-)
*/
*/
if
(
!
trans
->
shrd
->
wowlan
)
{
if
(
!
trans
->
shrd
->
wowlan
)
{
iwl_apm_stop
(
priv
(
trans
)
);
iwl_apm_stop
(
trans
);
}
else
{
}
else
{
iwl_disable_interrupts
(
trans
);
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
);
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
);
}
}
...
@@ -1330,7 +1651,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
...
@@ -1330,7 +1651,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
iwl_enable_interrupts
(
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
))
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW
))
hw_rfkill
=
true
;
hw_rfkill
=
true
;
...
@@ -1363,25 +1684,6 @@ static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans,
...
@@ -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
,
static
void
iwl_trans_pcie_stop_queue
(
struct
iwl_trans
*
trans
,
int
txq_id
,
const
char
*
msg
)
const
char
*
msg
)
{
{
...
@@ -1445,9 +1747,9 @@ static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt)
...
@@ -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
"
,
IWL_ERR
(
trans
,
"Current SW read_ptr %d write_ptr %d
\n
"
,
q
->
read_ptr
,
q
->
write_ptr
);
q
->
read_ptr
,
q
->
write_ptr
);
IWL_ERR
(
trans
,
"Current HW read_ptr %d write_ptr %d
\n
"
,
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
),
&
(
TFD_QUEUE_SIZE_MAX
-
1
),
iwl_read_prph
(
bus
(
trans
)
,
SCD_QUEUE_WRPTR
(
cnt
)));
iwl_read_prph
(
trans
,
SCD_QUEUE_WRPTR
(
cnt
)));
return
1
;
return
1
;
}
}
...
@@ -1501,7 +1803,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
...
@@ -1501,7 +1803,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
pos
+=
scnprintf
(
*
buf
+
pos
,
bufsz
-
pos
,
pos
+=
scnprintf
(
*
buf
+
pos
,
bufsz
-
pos
,
" %34s: 0X%08x
\n
"
,
" %34s: 0X%08x
\n
"
,
get_fh_string
(
fh_tbl
[
i
]),
get_fh_string
(
fh_tbl
[
i
]),
iwl_read_direct32
(
bus
(
trans
)
,
fh_tbl
[
i
]));
iwl_read_direct32
(
trans
,
fh_tbl
[
i
]));
}
}
return
pos
;
return
pos
;
}
}
...
@@ -1510,7 +1812,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
...
@@ -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
++
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
fh_tbl
);
i
++
)
{
IWL_ERR
(
trans
,
" %34s: 0X%08x
\n
"
,
IWL_ERR
(
trans
,
" %34s: 0X%08x
\n
"
,
get_fh_string
(
fh_tbl
[
i
]),
get_fh_string
(
fh_tbl
[
i
]),
iwl_read_direct32
(
bus
(
trans
)
,
fh_tbl
[
i
]));
iwl_read_direct32
(
trans
,
fh_tbl
[
i
]));
}
}
return
0
;
return
0
;
}
}
...
@@ -1580,7 +1882,7 @@ void iwl_dump_csr(struct iwl_trans *trans)
...
@@ -1580,7 +1882,7 @@ void iwl_dump_csr(struct iwl_trans *trans)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
csr_tbl
);
i
++
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
csr_tbl
);
i
++
)
{
IWL_ERR
(
trans
,
" %25s: 0X%08x
\n
"
,
IWL_ERR
(
trans
,
" %25s: 0X%08x
\n
"
,
get_csr_string
(
csr_tbl
[
i
]),
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,
...
@@ -1901,13 +2203,12 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
#endif
/*CONFIG_IWLWIFI_DEBUGFS */
#endif
/*CONFIG_IWLWIFI_DEBUGFS */
const
struct
iwl_trans_ops
trans_ops_pcie
=
{
const
struct
iwl_trans_ops
trans_ops_pcie
=
{
.
alloc
=
iwl_trans_pcie_alloc
,
.
start_hw
=
iwl_trans_pcie_start_hw
,
.
request_irq
=
iwl_trans_pcie_request_irq
,
.
stop_hw
=
iwl_trans_pcie_stop_hw
,
.
start_device
=
iwl_trans_pcie_start_devic
e
,
.
fw_alive
=
iwl_trans_pcie_fw_aliv
e
,
.
prepare_card_hw
=
iwl_trans_pcie_prepare_card_h
w
,
.
start_fw
=
iwl_trans_pcie_start_f
w
,
.
stop_device
=
iwl_trans_pcie_stop_device
,
.
stop_device
=
iwl_trans_pcie_stop_device
,
.
tx_start
=
iwl_trans_pcie_tx_start
,
.
wake_any_queue
=
iwl_trans_pcie_wake_any_queue
,
.
wake_any_queue
=
iwl_trans_pcie_wake_any_queue
,
.
send_cmd
=
iwl_trans_pcie_send_cmd
,
.
send_cmd
=
iwl_trans_pcie_send_cmd
,
...
@@ -1919,8 +2220,6 @@ const struct iwl_trans_ops trans_ops_pcie = {
...
@@ -1919,8 +2220,6 @@ const struct iwl_trans_ops trans_ops_pcie = {
.
tx_agg_alloc
=
iwl_trans_pcie_tx_agg_alloc
,
.
tx_agg_alloc
=
iwl_trans_pcie_tx_agg_alloc
,
.
tx_agg_setup
=
iwl_trans_pcie_tx_agg_setup
,
.
tx_agg_setup
=
iwl_trans_pcie_tx_agg_setup
,
.
kick_nic
=
iwl_trans_pcie_kick_nic
,
.
free
=
iwl_trans_pcie_free
,
.
free
=
iwl_trans_pcie_free
,
.
stop_queue
=
iwl_trans_pcie_stop_queue
,
.
stop_queue
=
iwl_trans_pcie_stop_queue
,
...
@@ -1933,4 +2232,116 @@ const struct iwl_trans_ops trans_ops_pcie = {
...
@@ -1933,4 +2232,116 @@ const struct iwl_trans_ops trans_ops_pcie = {
.
suspend
=
iwl_trans_pcie_suspend
,
.
suspend
=
iwl_trans_pcie_suspend
,
.
resume
=
iwl_trans_pcie_resume
,
.
resume
=
iwl_trans_pcie_resume
,
#endif
#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
浏览文件 @
8f0bb5ae
...
@@ -131,16 +131,26 @@ struct iwl_host_cmd {
...
@@ -131,16 +131,26 @@ struct iwl_host_cmd {
u8
id
;
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
* struct iwl_trans_ops - transport specific operations
* @alloc: allocates the meta data (not the queues themselves)
* @start_hw: starts the HW- from that point on, the HW can send interrupts
* @request_irq: requests IRQ - will be called before the FW load in probe flow
* @stop_hw: stops the HW- from that point on, the HW will be in low power but
* @start_device: allocates and inits all the resources for the transport
* will still issue interrupt if the HW RF kill is triggered.
* layer.
* @start_fw: allocates and inits all the resources for the transport
* @prepare_card_hw: claim the ownership on the HW. Will be called during
* layer. Also kick a fw image. This handler may sleep.
* probe.
* @fw_alive: called when the fw sends alive notification
* @tx_start: starts and configures all the Tx fifo - usually done once the fw
* is alive.
* @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
* @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)
* @stop_device:stops the whole device (embedded CPU put to reset)
* @send_cmd:send a host command
* @send_cmd:send a host command
...
@@ -150,7 +160,6 @@ struct iwl_host_cmd {
...
@@ -150,7 +160,6 @@ struct iwl_host_cmd {
* @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
* @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.
* ready and a successful ADDBA response has been received.
* @tx_agg_disable: de-configure a Tx queue to send AMPDUs
* @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
* @free: release all the ressource for the transport layer itself such as
* irq, tasklet etc...
* irq, tasklet etc...
* @stop_queue: stop a specific queue
* @stop_queue: stop a specific queue
...
@@ -160,15 +169,17 @@ struct iwl_host_cmd {
...
@@ -160,15 +169,17 @@ struct iwl_host_cmd {
* automatically deleted.
* automatically deleted.
* @suspend: stop the device unless WoWLAN is configured
* @suspend: stop the device unless WoWLAN is configured
* @resume: resume activity of the device
* @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_ops
{
struct
iwl_trans
*
(
*
alloc
)(
struct
iwl_shared
*
shrd
);
int
(
*
start_hw
)(
struct
iwl_trans
*
iwl_trans
);
int
(
*
request_irq
)(
struct
iwl_trans
*
iwl_trans
);
void
(
*
stop_hw
)(
struct
iwl_trans
*
iwl_trans
);
int
(
*
start_
device
)(
struct
iwl_trans
*
trans
);
int
(
*
start_
fw
)(
struct
iwl_trans
*
trans
,
struct
fw_img
*
fw
);
int
(
*
prepare_card_hw
)(
struct
iwl_trans
*
trans
);
void
(
*
fw_alive
)(
struct
iwl_trans
*
trans
);
void
(
*
stop_device
)(
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
,
void
(
*
wake_any_queue
)(
struct
iwl_trans
*
trans
,
enum
iwl_rxon_context_id
ctx
,
enum
iwl_rxon_context_id
ctx
,
...
@@ -191,8 +202,6 @@ struct iwl_trans_ops {
...
@@ -191,8 +202,6 @@ struct iwl_trans_ops {
enum
iwl_rxon_context_id
ctx
,
int
sta_id
,
int
tid
,
enum
iwl_rxon_context_id
ctx
,
int
sta_id
,
int
tid
,
int
frame_limit
,
u16
ssn
);
int
frame_limit
,
u16
ssn
);
void
(
*
kick_nic
)(
struct
iwl_trans
*
trans
);
void
(
*
free
)(
struct
iwl_trans
*
trans
);
void
(
*
free
)(
struct
iwl_trans
*
trans
);
void
(
*
stop_queue
)(
struct
iwl_trans
*
trans
,
int
q
,
const
char
*
msg
);
void
(
*
stop_queue
)(
struct
iwl_trans
*
trans
,
int
q
,
const
char
*
msg
);
...
@@ -204,18 +213,9 @@ struct iwl_trans_ops {
...
@@ -204,18 +213,9 @@ struct iwl_trans_ops {
int
(
*
suspend
)(
struct
iwl_trans
*
trans
);
int
(
*
suspend
)(
struct
iwl_trans
*
trans
);
int
(
*
resume
)(
struct
iwl_trans
*
trans
);
int
(
*
resume
)(
struct
iwl_trans
*
trans
);
#endif
#endif
};
void
(
*
write8
)(
struct
iwl_trans
*
trans
,
u32
ofs
,
u8
val
);
void
(
*
write32
)(
struct
iwl_trans
*
trans
,
u32
ofs
,
u32
val
);
/* one for each uCode image (inst/data, boot/init/runtime) */
u32
(
*
read32
)(
struct
iwl_trans
*
trans
,
u32
ofs
);
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 */
};
};
/* Opaque calibration results */
/* Opaque calibration results */
...
@@ -231,17 +231,31 @@ struct iwl_calib_result {
...
@@ -231,17 +231,31 @@ struct iwl_calib_result {
* @ops - pointer to iwl_trans_ops
* @ops - pointer to iwl_trans_ops
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
* @hcmd_lock: protects HCMD
* @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_write_complete: indicates that the ucode has been copied.
* @ucode_rt: run time ucode image
* @ucode_rt: run time ucode image
* @ucode_init: init ucode image
* @ucode_init: init ucode image
* @ucode_wowlan: wake on wireless ucode image (optional)
* @ucode_wowlan: wake on wireless ucode image (optional)
* @nvm_device_type: indicates OTP or eeprom
* @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
* @calib_results: list head for init calibration results
*/
*/
struct
iwl_trans
{
struct
iwl_trans
{
const
struct
iwl_trans_ops
*
ops
;
const
struct
iwl_trans_ops
*
ops
;
struct
iwl_shared
*
shrd
;
struct
iwl_shared
*
shrd
;
spinlock_t
hcmd_lock
;
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 */
u8
ucode_write_complete
;
/* the image write is complete */
struct
fw_img
ucode_rt
;
struct
fw_img
ucode_rt
;
...
@@ -250,6 +264,7 @@ struct iwl_trans {
...
@@ -250,6 +264,7 @@ struct iwl_trans {
/* eeprom related variables */
/* eeprom related variables */
int
nvm_device_type
;
int
nvm_device_type
;
bool
pm_support
;
/* init calibration results */
/* init calibration results */
struct
list_head
calib_results
;
struct
list_head
calib_results
;
...
@@ -259,29 +274,31 @@ struct iwl_trans {
...
@@ -259,29 +274,31 @@ struct iwl_trans {
char
trans_specific
[
0
]
__attribute__
((
__aligned__
(
sizeof
(
void
*
))));
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
,
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,
...
@@ -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
);
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
)
static
inline
void
iwl_trans_free
(
struct
iwl_trans
*
trans
)
{
{
trans
->
ops
->
free
(
trans
);
trans
->
ops
->
free
(
trans
);
...
@@ -380,13 +392,24 @@ static inline int iwl_trans_resume(struct iwl_trans *trans)
...
@@ -380,13 +392,24 @@ static inline int iwl_trans_resume(struct iwl_trans *trans)
}
}
#endif
#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
);
void
iwl_dealloc_ucode
(
struct
iwl_trans
*
trans
);
int
iwl_send_calib_results
(
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,
...
@@ -394,4 +417,18 @@ int iwl_calib_set(struct iwl_trans *trans,
const
struct
iwl_calib_hdr
*
cmd
,
int
len
);
const
struct
iwl_calib_hdr
*
cmd
,
int
len
);
void
iwl_calib_free_results
(
struct
iwl_trans
*
trans
);
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__ */
#endif
/* __iwl_trans_h__ */
drivers/net/wireless/iwlwifi/iwl-ucode.c
浏览文件 @
8f0bb5ae
...
@@ -32,7 +32,9 @@
...
@@ -32,7 +32,9 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/dma-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include "iwl-ucode.h"
#include "iwl-wifi.h"
#include "iwl-wifi.h"
#include "iwl-dev.h"
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-core.h"
...
@@ -80,29 +82,29 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
...
@@ -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
)
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
,
desc
->
p_addr
);
desc
->
v_addr
=
NULL
;
desc
->
v_addr
=
NULL
;
desc
->
len
=
0
;
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
(
tran
s
,
&
img
->
code
);
iwl_free_fw_desc
(
bu
s
,
&
img
->
data
);
iwl_free_fw_desc
(
tran
s
,
&
img
->
data
);
}
}
void
iwl_dealloc_ucode
(
struct
iwl_trans
*
trans
)
void
iwl_dealloc_ucode
(
struct
iwl_trans
*
trans
)
{
{
iwl_free_fw_img
(
bus
(
trans
)
,
&
trans
->
ucode_rt
);
iwl_free_fw_img
(
trans
,
&
trans
->
ucode_rt
);
iwl_free_fw_img
(
bus
(
trans
)
,
&
trans
->
ucode_init
);
iwl_free_fw_img
(
trans
,
&
trans
->
ucode_init
);
iwl_free_fw_img
(
bus
(
trans
)
,
&
trans
->
ucode_wowlan
);
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
)
const
void
*
data
,
size_t
len
)
{
{
if
(
!
len
)
{
if
(
!
len
)
{
...
@@ -110,7 +112,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
...
@@ -110,7 +112,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
return
-
EINVAL
;
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
);
&
desc
->
p_addr
,
GFP_KERNEL
);
if
(
!
desc
->
v_addr
)
if
(
!
desc
->
v_addr
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -120,59 +122,6 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
...
@@ -120,59 +122,6 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
return
0
;
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
,
static
inline
struct
fw_img
*
iwl_get_ucode_image
(
struct
iwl_trans
*
trans
,
enum
iwl_ucode_type
ucode_type
)
enum
iwl_ucode_type
ucode_type
)
{
{
...
@@ -189,28 +138,6 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
...
@@ -189,28 +138,6 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
return
NULL
;
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
* Calibration
*/
*/
...
@@ -447,7 +374,7 @@ static int iwl_alive_notify(struct iwl_trans *trans)
...
@@ -447,7 +374,7 @@ static int iwl_alive_notify(struct iwl_trans *trans)
if
(
!
priv
->
tx_cmd_pool
)
if
(
!
priv
->
tx_cmd_pool
)
return
-
ENOMEM
;
return
-
ENOMEM
;
iwl_trans_
tx_start
(
trans
);
iwl_trans_
fw_alive
(
trans
);
for_each_context
(
priv
,
ctx
)
for_each_context
(
priv
,
ctx
)
ctx
->
last_tx_rejected
=
false
;
ctx
->
last_tx_rejected
=
false
;
...
@@ -470,7 +397,7 @@ static int iwl_alive_notify(struct iwl_trans *trans)
...
@@ -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,
* 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.
* 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
)
struct
fw_desc
*
fw_desc
)
{
{
__le32
*
image
=
(
__le32
*
)
fw_desc
->
v_addr
;
__le32
*
image
=
(
__le32
*
)
fw_desc
->
v_addr
;
...
@@ -478,15 +405,15 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus,
...
@@ -478,15 +405,15 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus,
u32
val
;
u32
val
;
u32
i
;
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
))
{
for
(
i
=
0
;
i
<
len
;
i
+=
100
,
image
+=
100
/
sizeof
(
u32
))
{
/* read data comes through single port, auto-incr addr */
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
/* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */
* 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
);
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
))
if
(
val
!=
le32_to_cpu
(
*
image
))
return
-
EIO
;
return
-
EIO
;
}
}
...
@@ -494,7 +421,7 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus,
...
@@ -494,7 +421,7 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus,
return
0
;
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
)
struct
fw_desc
*
fw_desc
)
{
{
__le32
*
image
=
(
__le32
*
)
fw_desc
->
v_addr
;
__le32
*
image
=
(
__le32
*
)
fw_desc
->
v_addr
;
...
@@ -503,18 +430,18 @@ static void iwl_print_mismatch_inst(struct iwl_bus *bus,
...
@@ -503,18 +430,18 @@ static void iwl_print_mismatch_inst(struct iwl_bus *bus,
u32
offs
;
u32
offs
;
int
errors
=
0
;
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
);
IWLAGN_RTC_INST_LOWER_BOUND
);
for
(
offs
=
0
;
for
(
offs
=
0
;
offs
<
len
&&
errors
<
20
;
offs
<
len
&&
errors
<
20
;
offs
+=
sizeof
(
u32
),
image
++
)
{
offs
+=
sizeof
(
u32
),
image
++
)
{
/* read data comes through single port, auto-incr addr */
/* 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
))
{
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
"
,
"offset 0x%x, is 0x%x, s/b 0x%x
\n
"
,
offs
,
val
,
le32_to_cpu
(
*
image
));
offs
,
val
,
le32_to_cpu
(
*
image
));
errors
++
;
errors
++
;
...
@@ -536,14 +463,14 @@ static int iwl_verify_ucode(struct iwl_trans *trans,
...
@@ -536,14 +463,14 @@ static int iwl_verify_ucode(struct iwl_trans *trans,
return
-
EINVAL
;
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
"
);
IWL_DEBUG_FW
(
trans
,
"uCode is good in inst SRAM
\n
"
);
return
0
;
return
0
;
}
}
IWL_ERR
(
trans
,
"UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!
\n
"
);
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
;
return
-
EIO
;
}
}
...
@@ -647,28 +574,27 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
...
@@ -647,28 +574,27 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
{
{
struct
iwl_notification_wait
alive_wait
;
struct
iwl_notification_wait
alive_wait
;
struct
iwl_alive_data
alive_data
;
struct
iwl_alive_data
alive_data
;
struct
fw_img
*
fw
;
int
ret
;
int
ret
;
enum
iwl_ucode_type
old_type
;
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_init_notification_wait
(
trans
->
shrd
,
&
alive_wait
,
REPLY_ALIVE
,
iwl_alive_fn
,
&
alive_data
);
iwl_alive_fn
,
&
alive_data
);
old_type
=
trans
->
shrd
->
ucode_type
;
old_type
=
trans
->
shrd
->
ucode_type
;
trans
->
shrd
->
ucode_type
=
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
)
{
if
(
ret
)
{
trans
->
shrd
->
ucode_type
=
old_type
;
trans
->
shrd
->
ucode_type
=
old_type
;
iwl_remove_notification
(
trans
->
shrd
,
&
alive_wait
);
iwl_remove_notification
(
trans
->
shrd
,
&
alive_wait
);
return
ret
;
return
ret
;
}
}
iwl_trans_kick_nic
(
trans
);
/*
/*
* Some things may run in the background now, but we
* Some things may run in the background now, but we
* just wait for the ALIVE notification here.
* just wait for the ALIVE notification here.
...
@@ -756,3 +682,609 @@ int iwl_run_init_ucode(struct iwl_trans *trans)
...
@@ -756,3 +682,609 @@ int iwl_run_init_ucode(struct iwl_trans *trans)
iwl_trans_stop_device
(
trans
);
iwl_trans_stop_device
(
trans
);
return
ret
;
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
浏览文件 @
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__ */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录