Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
d878b3af
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
163
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d878b3af
编写于
7月 23, 2014
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
上级
16e75453
f697267f
变更
21
隐藏空白更改
内联
并排
Showing
21 changed file
with
966 addition
and
395 deletion
+966
-395
drivers/net/wireless/iwlwifi/Kconfig
drivers/net/wireless/iwlwifi/Kconfig
+13
-12
drivers/net/wireless/iwlwifi/iwl-8000.c
drivers/net/wireless/iwlwifi/iwl-8000.c
+4
-0
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-config.h
+2
-0
drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
+15
-2
drivers/net/wireless/iwlwifi/iwl-modparams.h
drivers/net/wireless/iwlwifi/iwl-modparams.h
+1
-1
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/iwl-trans.h
+12
-9
drivers/net/wireless/iwlwifi/mvm/coex.c
drivers/net/wireless/iwlwifi/mvm/coex.c
+84
-109
drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
+22
-97
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/debugfs.c
+84
-20
drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
+2
-0
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
+67
-0
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+13
-2
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
+288
-95
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/mvm.h
+44
-8
drivers/net/wireless/iwlwifi/mvm/nvm.c
drivers/net/wireless/iwlwifi/mvm/nvm.c
+2
-2
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/ops.c
+12
-2
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.c
+13
-11
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
+75
-14
drivers/net/wireless/iwlwifi/mvm/tt.c
drivers/net/wireless/iwlwifi/mvm/tt.c
+9
-3
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/tx.c
+10
-0
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/trans.c
+194
-8
未找到文件。
drivers/net/wireless/iwlwifi/Kconfig
浏览文件 @
d878b3af
...
...
@@ -20,16 +20,17 @@ config IWLWIFI
Intel 2000 Series Wi-Fi Adapters
Intel 7260 Wi-Fi Adapter
Intel 3160 Wi-Fi Adapter
Intel 7265 Wi-Fi Adapter
This driver uses the kernel's mac80211 subsystem.
In order to use this driver, you will need a
microcode (uCode)
In order to use this driver, you will need a
firmware
image for it. You can obtain the microcode from:
<http://
intellinuxwireless.org/
>.
<http://
wireless.kernel.org/en/users/Drivers/iwlwifi
>.
The
microcod
e is typically installed in /lib/firmware. You can
The
firmwar
e is typically installed in /lib/firmware. You can
look in the hotplug script /etc/hotplug/firmware.agent to
determine which directory FIRMWARE_DIR is set to when the script
runs.
...
...
@@ -39,9 +40,10 @@ config IWLWIFI
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwlwifi.
if IWLWIFI
config IWLWIFI_LEDS
bool
depends on IWLWIFI
depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
select LEDS_TRIGGERS
select MAC80211_LEDS
...
...
@@ -49,7 +51,7 @@ config IWLWIFI_LEDS
config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support"
depends on
IWLWIFI
depends on
m
default IWLWIFI
help
This is the driver that supports the DVM firmware which is
...
...
@@ -58,7 +60,7 @@ config IWLDVM
config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
depends on
IWLWIFI
depends on
m
help
This is the driver that supports the MVM firmware which is
currently only available for 7260 and 3160 devices.
...
...
@@ -70,7 +72,7 @@ config IWLWIFI_OPMODE_MODULAR
default y if IWLMVM=m
comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
depends on IWL
WIFI && IWL
DVM=n && IWLMVM=n
depends on IWLDVM=n && IWLMVM=n
config IWLWIFI_BCAST_FILTERING
bool "Enable broadcast filtering"
...
...
@@ -86,11 +88,9 @@ config IWLWIFI_BCAST_FILTERING
expect incoming broadcasts for their normal operations.
menu "Debugging Options"
depends on IWLWIFI
config IWLWIFI_DEBUG
bool "Enable full debugging output in the iwlwifi driver"
depends on IWLWIFI
---help---
This option will enable debug tracing output for the iwlwifi drivers
...
...
@@ -115,7 +115,7 @@ config IWLWIFI_DEBUG
config IWLWIFI_DEBUGFS
bool "iwlwifi debugfs support"
depends on
IWLWIFI &&
MAC80211_DEBUGFS
depends on MAC80211_DEBUGFS
---help---
Enable creation of debugfs files for the iwlwifi drivers. This
is a low-impact option that allows getting insight into the
...
...
@@ -123,13 +123,12 @@ config IWLWIFI_DEBUGFS
config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
bool "Experimental uCode support"
depends on IWLWIFI
&& IWLWIFI
_DEBUG
depends on IWLWIFI_DEBUG
---help---
Enable use of experimental ucode for testing and debugging.
config IWLWIFI_DEVICE_TRACING
bool "iwlwifi device access tracing"
depends on IWLWIFI
depends on EVENT_TRACING
help
Say Y here to trace all commands, including TX frames and IO
...
...
@@ -145,3 +144,5 @@ config IWLWIFI_DEVICE_TRACING
If unsure, say Y so we can help you better when problems
occur.
endmenu
endif
drivers/net/wireless/iwlwifi/iwl-8000.c
浏览文件 @
d878b3af
...
...
@@ -85,6 +85,9 @@
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
/* Max SDIO RX aggregation size of the ADDBA request/response */
#define MAX_RX_AGG_SIZE_8260_SDIO 28
static
const
struct
iwl_base_params
iwl8000_base_params
=
{
.
eeprom_size
=
OTP_LOW_IMAGE_SIZE_FAMILY_8000
,
.
num_of_queues
=
IWLAGN_NUM_QUEUES
,
...
...
@@ -129,6 +132,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.
nvm_ver
=
IWL8000_NVM_VERSION
,
.
nvm_calib_ver
=
IWL8000_TX_POWER_VERSION
,
.
default_nvm_file
=
DEFAULT_NVM_FILE_FAMILY_8000
,
.
max_rx_agg_size
=
MAX_RX_AGG_SIZE_8260_SDIO
,
};
MODULE_FIRMWARE
(
IWL8000_MODULE_FIRMWARE
(
IWL8000_UCODE_API_OK
));
drivers/net/wireless/iwlwifi/iwl-config.h
浏览文件 @
d878b3af
...
...
@@ -240,6 +240,7 @@ struct iwl_pwr_tx_backoff {
* @d0i3: device uses d0i3 instead of d3
* @nvm_hw_section_num: the ID of the HW NVM section
* @pwr_tx_backoffs: translation table between power limits and backoffs
* @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
...
...
@@ -276,6 +277,7 @@ struct iwl_cfg {
const
struct
iwl_pwr_tx_backoff
*
pwr_tx_backoffs
;
bool
no_power_up_nic_in_init
;
const
char
*
default_nvm_file
;
unsigned
int
max_rx_agg_size
;
};
/*
...
...
drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
浏览文件 @
d878b3af
...
...
@@ -70,21 +70,24 @@
/**
* enum iwl_fw_error_dump_type - types of data in the dump file
* @IWL_FW_ERROR_DUMP_SRAM:
* @IWL_FW_ERROR_DUMP_
REG:
* @IWL_FW_ERROR_DUMP_
CSR: Control Status Registers - from offset 0
* @IWL_FW_ERROR_DUMP_RXF:
* @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
* &struct iwl_fw_error_dump_txcmd packets
* @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info
* info on the device / firmware.
* @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
* @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
* sections like this in a single file.
*/
enum
iwl_fw_error_dump_type
{
IWL_FW_ERROR_DUMP_SRAM
=
0
,
IWL_FW_ERROR_DUMP_
REG
=
1
,
IWL_FW_ERROR_DUMP_
CSR
=
1
,
IWL_FW_ERROR_DUMP_RXF
=
2
,
IWL_FW_ERROR_DUMP_TXCMD
=
3
,
IWL_FW_ERROR_DUMP_DEV_FW_INFO
=
4
,
IWL_FW_ERROR_DUMP_FW_MONITOR
=
5
,
IWL_FW_ERROR_DUMP_PRPH
=
6
,
IWL_FW_ERROR_DUMP_MAX
,
};
...
...
@@ -162,6 +165,16 @@ struct iwl_fw_error_dump_fw_mon {
u8
data
[];
}
__packed
;
/**
* struct iwl_fw_error_dump_prph - periphery registers data
* @prph_start: address of the first register in this chunk
* @data: the content of the registers
*/
struct
iwl_fw_error_dump_prph
{
__le32
prph_start
;
__le32
data
[];
};
/**
* iwl_fw_error_next_data - advance fw error dump data pointer
* @data: previous data block
...
...
drivers/net/wireless/iwlwifi/iwl-modparams.h
浏览文件 @
d878b3af
...
...
@@ -99,7 +99,7 @@ enum iwl_disable_11n {
* @wd_disable: disable stuck queue check, default = 1
* @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0
* @power_save:
dis
able power save, default = false
* @power_save:
en
able power save, default = false
* @power_level: power level, default = 1
* @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0
...
...
drivers/net/wireless/iwlwifi/iwl-trans.h
浏览文件 @
d878b3af
...
...
@@ -394,6 +394,11 @@ struct iwl_trans_config {
const
char
*
const
*
command_names
;
};
struct
iwl_trans_dump_data
{
u32
len
;
u8
data
[];
};
struct
iwl_trans
;
/**
...
...
@@ -461,10 +466,8 @@ struct iwl_trans;
* @unref: release a reference previously taken with @ref. Note that
* initially the reference count is 1, making an initial @unref
* necessary to allow low power states.
* @dump_data: fill a data dump with debug data, maybe containing last
* TX'ed commands and similar. When called with a NULL buffer and
* zero buffer length, provide only the (estimated) required buffer
* length. Return the used buffer length.
* @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last
* TX'ed commands and similar. The buffer will be vfree'd by the caller.
* Note that the transport must fill in the proper file headers.
*/
struct
iwl_trans_ops
{
...
...
@@ -518,7 +521,7 @@ struct iwl_trans_ops {
void
(
*
unref
)(
struct
iwl_trans
*
trans
);
#ifdef CONFIG_IWLWIFI_DEBUGFS
u32
(
*
dump_data
)(
struct
iwl_trans
*
trans
,
void
*
buf
,
u32
buflen
);
struct
iwl_trans_dump_data
*
(
*
dump_data
)(
struct
iwl_trans
*
trans
);
#endif
};
...
...
@@ -685,12 +688,12 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
static
inline
u32
iwl_trans_dump_data
(
struct
iwl_trans
*
trans
,
void
*
buf
,
u32
buflen
)
static
inline
struct
iwl_trans_dump_data
*
iwl_trans_dump_data
(
struct
iwl_trans
*
trans
)
{
if
(
!
trans
->
ops
->
dump_data
)
return
0
;
return
trans
->
ops
->
dump_data
(
trans
,
buf
,
buflen
);
return
NULL
;
return
trans
->
ops
->
dump_data
(
trans
);
}
#endif
...
...
drivers/net/wireless/iwlwifi/mvm/coex.c
浏览文件 @
d878b3af
...
...
@@ -72,16 +72,56 @@
#define BT_ANTENNA_COUPLING_THRESHOLD (30)
const
u32
iwl_bt_
ack
_kill_msk
[
BT_KILL_MSK_MAX
]
=
{
[
BT_KILL_MSK_DEFAULT
]
=
0xffff
00
00
,
[
BT_KILL_MSK_
SCO_HID_A2DP
]
=
0xffffffff
,
[
BT_KILL_MSK_
REDUCED_TXPOW
]
=
0
,
const
u32
iwl_bt_
ctl
_kill_msk
[
BT_KILL_MSK_MAX
]
=
{
[
BT_KILL_MSK_DEFAULT
]
=
0xffff
fc
00
,
[
BT_KILL_MSK_
NEVER
]
=
0xffffffff
,
[
BT_KILL_MSK_
ALWAYS
]
=
0
,
};
const
u32
iwl_bt_cts_kill_msk
[
BT_KILL_MSK_MAX
]
=
{
[
BT_KILL_MSK_DEFAULT
]
=
0xffff0000
,
[
BT_KILL_MSK_SCO_HID_A2DP
]
=
0xffffffff
,
[
BT_KILL_MSK_REDUCED_TXPOW
]
=
0
,
const
u8
iwl_bt_cts_kill_msk
[
BT_MAX_AG
][
BT_COEX_MAX_LUT
]
=
{
{
BT_KILL_MSK_ALWAYS
,
BT_KILL_MSK_ALWAYS
,
BT_KILL_MSK_ALWAYS
,
},
{
BT_KILL_MSK_NEVER
,
BT_KILL_MSK_NEVER
,
BT_KILL_MSK_NEVER
,
},
{
BT_KILL_MSK_NEVER
,
BT_KILL_MSK_NEVER
,
BT_KILL_MSK_NEVER
,
},
{
BT_KILL_MSK_DEFAULT
,
BT_KILL_MSK_NEVER
,
BT_KILL_MSK_DEFAULT
,
},
};
const
u8
iwl_bt_ack_kill_msk
[
BT_MAX_AG
][
BT_COEX_MAX_LUT
]
=
{
{
BT_KILL_MSK_ALWAYS
,
BT_KILL_MSK_ALWAYS
,
BT_KILL_MSK_ALWAYS
,
},
{
BT_KILL_MSK_ALWAYS
,
BT_KILL_MSK_ALWAYS
,
BT_KILL_MSK_ALWAYS
,
},
{
BT_KILL_MSK_ALWAYS
,
BT_KILL_MSK_ALWAYS
,
BT_KILL_MSK_ALWAYS
,
},
{
BT_KILL_MSK_DEFAULT
,
BT_KILL_MSK_ALWAYS
,
BT_KILL_MSK_DEFAULT
,
},
};
static
const
__le32
iwl_bt_prio_boost
[
BT_COEX_BOOST_SIZE
]
=
{
...
...
@@ -611,54 +651,43 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
return
ret
;
}
static
int
iwl_mvm_bt_udpate_sw_boost
(
struct
iwl_mvm
*
mvm
,
bool
reduced_tx_power
)
static
int
iwl_mvm_bt_udpate_sw_boost
(
struct
iwl_mvm
*
mvm
)
{
enum
iwl_bt_kill_msk
bt_kill_msk
;
struct
iwl_bt_coex_sw_boost_update_cmd
cmd
=
{};
struct
iwl_bt_coex_profile_notif
*
notif
=
&
mvm
->
last_bt_notif
;
u32
primary_lut
=
le32_to_cpu
(
notif
->
primary_ch_lut
);
u32
secondary_lut
=
le32_to_cpu
(
notif
->
secondary_ch_lut
);
u32
ag
=
le32_to_cpu
(
notif
->
bt_activity_grading
);
struct
iwl_bt_coex_sw_boost_update_cmd
cmd
=
{};
u8
ack_kill_msk
[
NUM_PHY_CTX
]
=
{};
u8
cts_kill_msk
[
NUM_PHY_CTX
]
=
{};
int
i
;
lockdep_assert_held
(
&
mvm
->
mutex
);
if
(
reduced_tx_power
)
{
/* Reduced Tx power has precedence on the type of the profile */
bt_kill_msk
=
BT_KILL_MSK_REDUCED_TXPOW
;
}
else
{
/* Low latency BT profile is active: give higher prio to BT */
if
(
BT_MBOX_MSG
(
notif
,
3
,
SCO_STATE
)
||
BT_MBOX_MSG
(
notif
,
3
,
A2DP_STATE
)
||
BT_MBOX_MSG
(
notif
,
3
,
SNIFF_STATE
))
bt_kill_msk
=
BT_KILL_MSK_SCO_HID_A2DP
;
else
bt_kill_msk
=
BT_KILL_MSK_DEFAULT
;
}
ack_kill_msk
[
0
]
=
iwl_bt_ack_kill_msk
[
ag
][
primary_lut
];
cts_kill_msk
[
0
]
=
iwl_bt_cts_kill_msk
[
ag
][
primary_lut
];
IWL_DEBUG_COEX
(
mvm
,
"Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive
\n
"
,
bt_kill_msk
,
BT_MBOX_MSG
(
notif
,
3
,
SCO_STATE
)
?
""
:
"in"
,
BT_MBOX_MSG
(
notif
,
3
,
A2DP_STATE
)
?
""
:
"in"
,
BT_MBOX_MSG
(
notif
,
3
,
SNIFF_STATE
)
?
""
:
"in"
);
ack_kill_msk
[
1
]
=
iwl_bt_ack_kill_msk
[
ag
][
secondary_lut
];
cts_kill_msk
[
1
]
=
iwl_bt_cts_kill_msk
[
ag
][
secondary_lut
];
/* Don't send HCMD if there is no update */
if
(
bt_kill_msk
==
mvm
->
bt_kill_msk
)
if
(
!
memcmp
(
ack_kill_msk
,
mvm
->
bt_ack_kill_msk
,
sizeof
(
ack_kill_msk
))
||
!
memcmp
(
cts_kill_msk
,
mvm
->
bt_cts_kill_msk
,
sizeof
(
cts_kill_msk
)))
return
0
;
mvm
->
bt_kill_msk
=
bt_kill_msk
;
memcpy
(
mvm
->
bt_ack_kill_msk
,
ack_kill_msk
,
sizeof
(
mvm
->
bt_ack_kill_msk
));
memcpy
(
mvm
->
bt_cts_kill_msk
,
cts_kill_msk
,
sizeof
(
mvm
->
bt_cts_kill_msk
));
cmd
.
boost_values
[
0
].
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_ack_kill_msk
[
bt_kill_msk
]);
cmd
.
boost_values
[
0
].
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_cts_kill_msk
[
bt_kill_msk
]);
BUILD_BUG_ON
(
ARRAY_SIZE
(
ack_kill_msk
)
<
ARRAY_SIZE
(
cmd
.
boost_values
));
cmd
.
boost_values
[
1
].
kill_ack_msk
=
cmd
.
boost_values
[
0
].
kill_ack_msk
;
cmd
.
boost_values
[
2
].
kill_cts_msk
=
cmd
.
boost_values
[
0
].
kill_cts_msk
;
cmd
.
boost_values
[
1
].
kill_ack_msk
=
cmd
.
boost_values
[
0
].
kill_ack_msk
;
cmd
.
boost_values
[
2
].
kill_cts_msk
=
cmd
.
boost_values
[
0
].
kill_cts_msk
;
IWL_DEBUG_COEX
(
mvm
,
"ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x
\n
"
,
iwl_bt_ack_kill_msk
[
bt_kill_msk
],
iwl_bt_cts_kill_msk
[
bt_kill_msk
]);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
cmd
.
boost_values
);
i
++
)
{
cmd
.
boost_values
[
i
].
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_ctl_kill_msk
[
ack_kill_msk
[
i
]]);
cmd
.
boost_values
[
i
].
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_ctl_kill_msk
[
cts_kill_msk
[
i
]]);
}
return
iwl_mvm_send_cmd_pdu
(
mvm
,
BT_COEX_UPDATE_SW_BOOST
,
0
,
sizeof
(
cmd
),
&
cmd
);
...
...
@@ -700,8 +729,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
struct
iwl_bt_iterator_data
{
struct
iwl_bt_coex_profile_notif
*
notif
;
struct
iwl_mvm
*
mvm
;
u32
num_bss_ifaces
;
bool
reduced_tx_power
;
struct
ieee80211_chanctx_conf
*
primary
;
struct
ieee80211_chanctx_conf
*
secondary
;
bool
primary_ll
;
...
...
@@ -737,22 +764,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
switch
(
vif
->
type
)
{
case
NL80211_IFTYPE_STATION
:
/* Count BSSes vifs */
data
->
num_bss_ifaces
++
;
/* default smps_mode for BSS / P2P client is AUTOMATIC */
smps_mode
=
IEEE80211_SMPS_AUTOMATIC
;
break
;
case
NL80211_IFTYPE_AP
:
/* default smps_mode for AP / GO is OFF */
smps_mode
=
IEEE80211_SMPS_OFF
;
if
(
!
mvmvif
->
ap_ibss_active
)
{
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
if
(
!
mvmvif
->
ap_ibss_active
)
return
;
}
/* the Ack / Cts kill mask must be default if AP / GO */
data
->
reduced_tx_power
=
false
;
break
;
default:
return
;
...
...
@@ -763,11 +780,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* If channel context is invalid or not on 2.4GHz .. */
if
((
!
chanctx_conf
||
chanctx_conf
->
def
.
chan
->
band
!=
IEEE80211_BAND_2GHZ
))
{
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
data
->
reduced_tx_power
=
false
;
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
)
{
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
);
iwl_mvm_bt_coex_enable_rssi_event
(
mvm
,
vif
,
false
,
0
);
...
...
@@ -779,9 +795,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if
(
bt_activity_grading
>=
BT_HIGH_TRAFFIC
)
smps_mode
=
IEEE80211_SMPS_STATIC
;
else
if
(
bt_activity_grading
>=
BT_LOW_TRAFFIC
)
smps_mode
=
vif
->
type
==
NL80211_IFTYPE_AP
?
IEEE80211_SMPS_OFF
:
IEEE80211_SMPS_DYNAMIC
;
smps_mode
=
IEEE80211_SMPS_DYNAMIC
;
/* relax SMPS contraints for next association */
if
(
!
vif
->
bss_conf
.
assoc
)
...
...
@@ -795,7 +809,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
"mac %d: bt_activity_grading %d smps_req %d
\n
"
,
mvmvif
->
id
,
bt_activity_grading
,
smps_mode
);
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
)
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
/* low latency is always primary */
if
(
iwl_mvm_vif_low_latency
(
mvmvif
))
{
...
...
@@ -846,7 +862,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if
(
iwl_get_coex_type
(
mvm
,
vif
)
==
BT_COEX_LOOSE_LUT
||
mvm
->
cfg
->
bt_shared_single_ant
||
!
vif
->
bss_conf
.
assoc
||
le32_to_cpu
(
mvm
->
last_bt_notif
.
bt_activity_grading
)
==
BT_OFF
)
{
data
->
reduced_tx_power
=
false
;
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
);
iwl_mvm_bt_coex_enable_rssi_event
(
mvm
,
vif
,
false
,
0
);
return
;
...
...
@@ -861,23 +876,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if
(
ave_rssi
>
-
IWL_MVM_BT_COEX_EN_RED_TXP_THRESH
)
{
if
(
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
true
))
IWL_ERR
(
mvm
,
"Couldn't send BT_CONFIG cmd
\n
"
);
/*
* bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
* BSS / P2P clients have rssi above threshold.
* We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
* the iteration, if one interface's rssi isn't good enough,
* bt_kill_msk will be set to default values.
*/
}
else
if
(
ave_rssi
<
-
IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH
)
{
if
(
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
))
IWL_ERR
(
mvm
,
"Couldn't send BT_CONFIG cmd
\n
"
);
/*
* One interface hasn't rssi above threshold, bt_kill_msk must
* be set to default values.
*/
data
->
reduced_tx_power
=
false
;
}
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
...
...
@@ -889,7 +890,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
struct
iwl_bt_iterator_data
data
=
{
.
mvm
=
mvm
,
.
notif
=
&
mvm
->
last_bt_notif
,
.
reduced_tx_power
=
true
,
};
struct
iwl_bt_coex_ci_cmd
cmd
=
{};
u8
ci_bw_idx
;
...
...
@@ -959,14 +959,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
memcpy
(
&
mvm
->
last_bt_ci_cmd
,
&
cmd
,
sizeof
(
cmd
));
}
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data
.
reduced_tx_power
=
data
.
reduced_tx_power
&&
data
.
num_bss_ifaces
;
if
(
iwl_mvm_bt_udpate_sw_boost
(
mvm
,
data
.
reduced_tx_power
))
if
(
iwl_mvm_bt_udpate_sw_boost
(
mvm
))
IWL_ERR
(
mvm
,
"Failed to update the ctrl_kill_msk
\n
"
);
}
...
...
@@ -1035,16 +1028,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
return
;
mvmsta
=
iwl_mvm_sta_from_mac80211
(
sta
);
data
->
num_bss_ifaces
++
;
/*
* This interface doesn't support reduced Tx power (because of low
* RSSI probably), then set bt_kill_msk to default values.
*/
if
(
!
mvmsta
->
bt_reduced_txpower
)
data
->
reduced_tx_power
=
false
;
/* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
}
void
iwl_mvm_bt_rssi_event
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
...
...
@@ -1053,7 +1036,6 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct
iwl_mvm_vif
*
mvmvif
=
(
void
*
)
vif
->
drv_priv
;
struct
iwl_bt_iterator_data
data
=
{
.
mvm
=
mvm
,
.
reduced_tx_power
=
true
,
};
int
ret
;
...
...
@@ -1100,14 +1082,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_bt_rssi_iterator
,
&
data
);
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data
.
reduced_tx_power
=
data
.
reduced_tx_power
&&
data
.
num_bss_ifaces
;
if
(
iwl_mvm_bt_udpate_sw_boost
(
mvm
,
data
.
reduced_tx_power
))
if
(
iwl_mvm_bt_udpate_sw_boost
(
mvm
))
IWL_ERR
(
mvm
,
"Failed to update the ctrl_kill_msk
\n
"
);
}
...
...
@@ -1150,7 +1125,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
enum
iwl_bt_coex_lut_type
lut_type
;
if
(
!
(
mvm
->
fw
->
ucode_capa
.
api
[
0
]
&
IWL_UCODE_TLV_API_BT_COEX_SPLIT
))
return
iwl_mvm_
coex_agg_time_limit
_old
(
mvm
,
sta
);
return
iwl_mvm_
bt_coex_is_mimo_allowed
_old
(
mvm
,
sta
);
if
(
IWL_COEX_IS_TTC_ON
(
mvm
->
last_bt_notif
.
ttc_rrc_status
,
phy_ctxt
->
id
))
return
true
;
...
...
drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
浏览文件 @
d878b3af
...
...
@@ -649,10 +649,6 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
sizeof
(
iwl_bt_prio_boost
));
memcpy
(
&
bt_cmd
->
bt4_multiprio_lut
,
iwl_bt_mprio_lut
,
sizeof
(
iwl_bt_mprio_lut
));
bt_cmd
->
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_ack_kill_msk
[
BT_KILL_MSK_DEFAULT
]);
bt_cmd
->
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_cts_kill_msk
[
BT_KILL_MSK_DEFAULT
]);
send_cmd:
memset
(
&
mvm
->
last_bt_notif_old
,
0
,
sizeof
(
mvm
->
last_bt_notif_old
));
...
...
@@ -664,12 +660,13 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
return
ret
;
}
static
int
iwl_mvm_bt_udpate_ctrl_kill_msk
(
struct
iwl_mvm
*
mvm
,
bool
reduced_tx_power
)
static
int
iwl_mvm_bt_udpate_ctrl_kill_msk
(
struct
iwl_mvm
*
mvm
)
{
enum
iwl_bt_kill_msk
bt_kill_msk
;
struct
iwl_bt_coex_cmd_old
*
bt_cmd
;
struct
iwl_bt_coex_profile_notif_old
*
notif
=
&
mvm
->
last_bt_notif_old
;
u32
primary_lut
=
le32_to_cpu
(
notif
->
primary_ch_lut
);
u32
ag
=
le32_to_cpu
(
notif
->
bt_activity_grading
);
struct
iwl_bt_coex_cmd_old
*
bt_cmd
;
u8
ack_kill_msk
,
cts_kill_msk
;
struct
iwl_host_cmd
cmd
=
{
.
id
=
BT_CONFIG
,
.
data
[
0
]
=
&
bt_cmd
,
...
...
@@ -680,31 +677,15 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
lockdep_assert_held
(
&
mvm
->
mutex
);
if
(
reduced_tx_power
)
{
/* Reduced Tx power has precedence on the type of the profile */
bt_kill_msk
=
BT_KILL_MSK_REDUCED_TXPOW
;
}
else
{
/* Low latency BT profile is active: give higher prio to BT */
if
(
BT_MBOX_MSG
(
notif
,
3
,
SCO_STATE
)
||
BT_MBOX_MSG
(
notif
,
3
,
A2DP_STATE
)
||
BT_MBOX_MSG
(
notif
,
3
,
SNIFF_STATE
))
bt_kill_msk
=
BT_KILL_MSK_SCO_HID_A2DP
;
else
bt_kill_msk
=
BT_KILL_MSK_DEFAULT
;
}
IWL_DEBUG_COEX
(
mvm
,
"Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive
\n
"
,
bt_kill_msk
,
BT_MBOX_MSG
(
notif
,
3
,
SCO_STATE
)
?
""
:
"in"
,
BT_MBOX_MSG
(
notif
,
3
,
A2DP_STATE
)
?
""
:
"in"
,
BT_MBOX_MSG
(
notif
,
3
,
SNIFF_STATE
)
?
""
:
"in"
);
ack_kill_msk
=
iwl_bt_ack_kill_msk
[
ag
][
primary_lut
];
cts_kill_msk
=
iwl_bt_cts_kill_msk
[
ag
][
primary_lut
];
/* Don't send HCMD if there is no update */
if
(
bt_kill_msk
==
mvm
->
bt
_kill_msk
)
if
(
mvm
->
bt_ack_kill_msk
[
0
]
==
ack_kill_msk
&&
mvm
->
bt_cts_kill_msk
[
0
]
==
cts
_kill_msk
)
return
0
;
mvm
->
bt_kill_msk
=
bt_kill_msk
;
mvm
->
bt_ack_kill_msk
[
0
]
=
ack_kill_msk
;
mvm
->
bt_cts_kill_msk
[
0
]
=
cts_kill_msk
;
bt_cmd
=
kzalloc
(
sizeof
(
*
bt_cmd
),
GFP_KERNEL
);
if
(
!
bt_cmd
)
...
...
@@ -712,16 +693,12 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
cmd
.
data
[
0
]
=
bt_cmd
;
bt_cmd
->
flags
=
cpu_to_le32
(
BT_COEX_NW_OLD
);
bt_cmd
->
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_
ack_kill_msk
[
bt
_kill_msk
]);
bt_cmd
->
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_ct
s_kill_msk
[
bt
_kill_msk
]);
bt_cmd
->
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_
ctl_kill_msk
[
ack
_kill_msk
]);
bt_cmd
->
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_ct
l_kill_msk
[
cts
_kill_msk
]);
bt_cmd
->
valid_bit_msk
|=
cpu_to_le32
(
BT_VALID_ENABLE
|
BT_VALID_KILL_ACK
|
BT_VALID_KILL_CTS
);
IWL_DEBUG_COEX
(
mvm
,
"ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x
\n
"
,
iwl_bt_ack_kill_msk
[
bt_kill_msk
],
iwl_bt_cts_kill_msk
[
bt_kill_msk
]);
ret
=
iwl_mvm_send_cmd
(
mvm
,
&
cmd
);
kfree
(
bt_cmd
);
...
...
@@ -777,8 +754,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
struct
iwl_bt_iterator_data
{
struct
iwl_bt_coex_profile_notif_old
*
notif
;
struct
iwl_mvm
*
mvm
;
u32
num_bss_ifaces
;
bool
reduced_tx_power
;
struct
ieee80211_chanctx_conf
*
primary
;
struct
ieee80211_chanctx_conf
*
secondary
;
bool
primary_ll
;
...
...
@@ -814,22 +789,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
switch
(
vif
->
type
)
{
case
NL80211_IFTYPE_STATION
:
/* Count BSSes vifs */
data
->
num_bss_ifaces
++
;
/* default smps_mode for BSS / P2P client is AUTOMATIC */
smps_mode
=
IEEE80211_SMPS_AUTOMATIC
;
break
;
case
NL80211_IFTYPE_AP
:
/* default smps_mode for AP / GO is OFF */
smps_mode
=
IEEE80211_SMPS_OFF
;
if
(
!
mvmvif
->
ap_ibss_active
)
{
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
if
(
!
mvmvif
->
ap_ibss_active
)
return
;
}
/* the Ack / Cts kill mask must be default if AP / GO */
data
->
reduced_tx_power
=
false
;
break
;
default:
return
;
...
...
@@ -840,11 +805,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* If channel context is invalid or not on 2.4GHz .. */
if
((
!
chanctx_conf
||
chanctx_conf
->
def
.
chan
->
band
!=
IEEE80211_BAND_2GHZ
))
{
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
data
->
reduced_tx_power
=
false
;
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
)
{
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
);
iwl_mvm_bt_coex_enable_rssi_event
(
mvm
,
vif
,
false
,
0
);
...
...
@@ -869,7 +833,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
mvmvif
->
id
,
data
->
notif
->
bt_status
,
bt_activity_grading
,
smps_mode
);
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
)
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
/* low latency is always primary */
if
(
iwl_mvm_vif_low_latency
(
mvmvif
))
{
...
...
@@ -920,7 +886,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if
(
iwl_get_coex_type
(
mvm
,
vif
)
==
BT_COEX_LOOSE_LUT
||
mvm
->
cfg
->
bt_shared_single_ant
||
!
vif
->
bss_conf
.
assoc
||
!
data
->
notif
->
bt_status
)
{
data
->
reduced_tx_power
=
false
;
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
);
iwl_mvm_bt_coex_enable_rssi_event
(
mvm
,
vif
,
false
,
0
);
return
;
...
...
@@ -935,23 +900,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if
(
ave_rssi
>
-
IWL_MVM_BT_COEX_EN_RED_TXP_THRESH
)
{
if
(
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
true
))
IWL_ERR
(
mvm
,
"Couldn't send BT_CONFIG cmd
\n
"
);
/*
* bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
* BSS / P2P clients have rssi above threshold.
* We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
* the iteration, if one interface's rssi isn't good enough,
* bt_kill_msk will be set to default values.
*/
}
else
if
(
ave_rssi
<
-
IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH
)
{
if
(
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
))
IWL_ERR
(
mvm
,
"Couldn't send BT_CONFIG cmd
\n
"
);
/*
* One interface hasn't rssi above threshold, bt_kill_msk must
* be set to default values.
*/
data
->
reduced_tx_power
=
false
;
}
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
...
...
@@ -963,7 +914,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
struct
iwl_bt_iterator_data
data
=
{
.
mvm
=
mvm
,
.
notif
=
&
mvm
->
last_bt_notif_old
,
.
reduced_tx_power
=
true
,
};
struct
iwl_bt_coex_ci_cmd_old
cmd
=
{};
u8
ci_bw_idx
;
...
...
@@ -1037,14 +987,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
memcpy
(
&
mvm
->
last_bt_ci_cmd_old
,
&
cmd
,
sizeof
(
cmd
));
}
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data
.
reduced_tx_power
=
data
.
reduced_tx_power
&&
data
.
num_bss_ifaces
;
if
(
iwl_mvm_bt_udpate_ctrl_kill_msk
(
mvm
,
data
.
reduced_tx_power
))
if
(
iwl_mvm_bt_udpate_ctrl_kill_msk
(
mvm
))
IWL_ERR
(
mvm
,
"Failed to update the ctrl_kill_msk
\n
"
);
}
...
...
@@ -1115,16 +1058,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
return
;
mvmsta
=
iwl_mvm_sta_from_mac80211
(
sta
);
data
->
num_bss_ifaces
++
;
/*
* This interface doesn't support reduced Tx power (because of low
* RSSI probably), then set bt_kill_msk to default values.
*/
if
(
!
mvmsta
->
bt_reduced_txpower
)
data
->
reduced_tx_power
=
false
;
/* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
}
void
iwl_mvm_bt_rssi_event_old
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
...
...
@@ -1133,7 +1066,6 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct
iwl_mvm_vif
*
mvmvif
=
(
void
*
)
vif
->
drv_priv
;
struct
iwl_bt_iterator_data
data
=
{
.
mvm
=
mvm
,
.
reduced_tx_power
=
true
,
};
int
ret
;
...
...
@@ -1175,14 +1107,7 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_bt_rssi_iterator
,
&
data
);
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data
.
reduced_tx_power
=
data
.
reduced_tx_power
&&
data
.
num_bss_ifaces
;
if
(
iwl_mvm_bt_udpate_ctrl_kill_msk
(
mvm
,
data
.
reduced_tx_power
))
if
(
iwl_mvm_bt_udpate_ctrl_kill_msk
(
mvm
))
IWL_ERR
(
mvm
,
"Failed to update the ctrl_kill_msk
\n
"
);
}
...
...
drivers/net/wireless/iwlwifi/mvm/debugfs.c
浏览文件 @
d878b3af
...
...
@@ -146,17 +146,47 @@ static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
iwl_fw_error_dump_file
*
dump_file
=
file
->
private_data
;
struct
iwl_mvm_dump_ptrs
*
dump_ptrs
=
(
void
*
)
file
->
private_data
;
ssize_t
bytes_read
=
0
;
ssize_t
bytes_read_trans
=
0
;
if
(
*
ppos
<
dump_ptrs
->
op_mode_len
)
bytes_read
+=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
dump_ptrs
->
op_mode_ptr
,
dump_ptrs
->
op_mode_len
);
if
(
bytes_read
<
0
||
*
ppos
<
dump_ptrs
->
op_mode_len
)
return
bytes_read
;
if
(
dump_ptrs
->
trans_ptr
)
{
*
ppos
-=
dump_ptrs
->
op_mode_len
;
bytes_read_trans
=
simple_read_from_buffer
(
user_buf
+
bytes_read
,
count
-
bytes_read
,
ppos
,
dump_ptrs
->
trans_ptr
->
data
,
dump_ptrs
->
trans_ptr
->
len
);
*
ppos
+=
dump_ptrs
->
op_mode_len
;
if
(
bytes_read_trans
>=
0
)
bytes_read
+=
bytes_read_trans
;
else
if
(
!
bytes_read
)
/* propagate the failure */
return
bytes_read_trans
;
}
return
bytes_read
;
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
dump_file
,
le32_to_cpu
(
dump_file
->
file_len
));
}
static
int
iwl_dbgfs_fw_error_dump_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
vfree
(
file
->
private_data
);
struct
iwl_mvm_dump_ptrs
*
dump_ptrs
=
(
void
*
)
file
->
private_data
;
vfree
(
dump_ptrs
->
op_mode_ptr
);
vfree
(
dump_ptrs
->
trans_ptr
);
kfree
(
dump_ptrs
);
return
0
;
}
...
...
@@ -514,9 +544,9 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"BT Configuration CMD
\n
"
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
ACK Kill Mask 0x%08x
\n
"
,
iwl_bt_
ack_kill_msk
[
mvm
->
bt_kill_msk
]);
iwl_bt_
ctl_kill_msk
[
mvm
->
bt_ack_kill_msk
[
0
]
]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
CTS Kill Mask 0x%08x
\n
"
,
iwl_bt_ct
s_kill_msk
[
mvm
->
bt_kill_msk
]);
iwl_bt_ct
l_kill_msk
[
mvm
->
bt_cts_kill_msk
[
0
]
]);
}
else
{
struct
iwl_bt_coex_ci_cmd
*
cmd
=
&
mvm
->
last_bt_ci_cmd
;
...
...
@@ -531,10 +561,19 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
le64_to_cpu
(
cmd
->
bt_secondary_ci
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"BT Configuration CMD
\n
"
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
ACK Kill Mask 0x%08x
\n
"
,
iwl_bt_ack_kill_msk
[
mvm
->
bt_kill_msk
]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
CTS Kill Mask 0x%08x
\n
"
,
iwl_bt_cts_kill_msk
[
mvm
->
bt_kill_msk
]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
Primary: ACK Kill Mask 0x%08x
\n
"
,
iwl_bt_ctl_kill_msk
[
mvm
->
bt_ack_kill_msk
[
0
]]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
Primary: CTS Kill Mask 0x%08x
\n
"
,
iwl_bt_ctl_kill_msk
[
mvm
->
bt_cts_kill_msk
[
0
]]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
Secondary: ACK Kill Mask 0x%08x
\n
"
,
iwl_bt_ctl_kill_msk
[
mvm
->
bt_ack_kill_msk
[
1
]]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
Secondary: CTS Kill Mask 0x%08x
\n
"
,
iwl_bt_ctl_kill_msk
[
mvm
->
bt_cts_kill_msk
[
1
]]);
}
mutex_unlock
(
&
mvm
->
mutex
);
...
...
@@ -830,8 +869,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static
ssize_t
iwl_dbgfs_fw_nmi_write
(
struct
iwl_mvm
*
mvm
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
int
ret
=
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_NMI
);
if
(
ret
)
return
ret
;
iwl_force_nmi
(
mvm
->
trans
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_NMI
);
return
count
;
}
...
...
@@ -1115,11 +1160,11 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
}
#endif
#define PRINT_MVM_REF(ref) do { \
if (
test_bit(ref, mvm->ref_bitmap))
\
pos += scnprintf(buf + pos, bufsz - pos, \
"\t(0x%lx)
%s\n",
\
BIT(ref),
#ref);
\
#define PRINT_MVM_REF(ref) do {
\
if (
mvm->refs[ref])
\
pos += scnprintf(buf + pos, bufsz - pos,
\
"\t(0x%lx)
: %d %s\n",
\
BIT(ref),
mvm->refs[ref], #ref);
\
} while (0)
static
ssize_t
iwl_dbgfs_d0i3_refs_read
(
struct
file
*
file
,
...
...
@@ -1127,12 +1172,17 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
size_t
count
,
loff_t
*
ppos
)
{
struct
iwl_mvm
*
mvm
=
file
->
private_data
;
int
pos
=
0
;
int
i
,
pos
=
0
;
char
buf
[
256
];
const
size_t
bufsz
=
sizeof
(
buf
);
u32
refs
=
0
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"taken mvm refs: 0x%lx
\n
"
,
mvm
->
ref_bitmap
[
0
]);
for
(
i
=
0
;
i
<
IWL_MVM_REF_COUNT
;
i
++
)
if
(
mvm
->
refs
[
i
])
refs
|=
BIT
(
i
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"taken mvm refs: 0x%x
\n
"
,
refs
);
PRINT_MVM_REF
(
IWL_MVM_REF_UCODE_DOWN
);
PRINT_MVM_REF
(
IWL_MVM_REF_SCAN
);
...
...
@@ -1158,7 +1208,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
mutex_lock
(
&
mvm
->
mutex
);
taken
=
test_bit
(
IWL_MVM_REF_USER
,
mvm
->
ref_bitmap
)
;
taken
=
mvm
->
refs
[
IWL_MVM_REF_USER
]
;
if
(
value
==
1
&&
!
taken
)
iwl_mvm_ref
(
mvm
,
IWL_MVM_REF_USER
);
else
if
(
value
==
0
&&
taken
)
...
...
@@ -1194,14 +1244,21 @@ iwl_dbgfs_prph_reg_read(struct file *file,
int
pos
=
0
;
char
buf
[
32
];
const
size_t
bufsz
=
sizeof
(
buf
);
int
ret
;
if
(
!
mvm
->
dbgfs_prph_reg_addr
)
return
-
EINVAL
;
ret
=
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_PRPH_READ
);
if
(
ret
)
return
ret
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"Reg 0x%x: (0x%x)
\n
"
,
mvm
->
dbgfs_prph_reg_addr
,
iwl_read_prph
(
mvm
->
trans
,
mvm
->
dbgfs_prph_reg_addr
));
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_PRPH_READ
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
pos
);
}
...
...
@@ -1211,6 +1268,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
{
u8
args
;
u32
value
;
int
ret
;
args
=
sscanf
(
buf
,
"%i %i"
,
&
mvm
->
dbgfs_prph_reg_addr
,
&
value
);
/* if we only want to set the reg address - nothing more to do */
...
...
@@ -1221,7 +1279,13 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
if
(
args
!=
2
)
return
-
EINVAL
;
ret
=
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_PRPH_WRITE
);
if
(
ret
)
return
ret
;
iwl_write_prph
(
mvm
->
trans
,
mvm
->
dbgfs_prph_reg_addr
,
value
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_PRPH_WRITE
);
out:
return
count
;
}
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
浏览文件 @
d878b3af
...
...
@@ -385,6 +385,8 @@ enum iwl_bt_activity_grading {
BT_ON_NO_CONNECTION
=
1
,
BT_LOW_TRAFFIC
=
2
,
BT_HIGH_TRAFFIC
=
3
,
BT_MAX_AG
,
};
/* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */
enum
iwl_bt_ci_compliance
{
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api.h
浏览文件 @
d878b3af
...
...
@@ -133,6 +133,7 @@ enum {
/* Scan offload */
SCAN_OFFLOAD_REQUEST_CMD
=
0x51
,
SCAN_OFFLOAD_ABORT_CMD
=
0x52
,
HOT_SPOT_CMD
=
0x53
,
SCAN_OFFLOAD_COMPLETE
=
0x6D
,
SCAN_OFFLOAD_UPDATE_PROFILES_CMD
=
0x6E
,
SCAN_OFFLOAD_CONFIG_CMD
=
0x6f
,
...
...
@@ -910,6 +911,72 @@ struct iwl_phy_context_cmd {
__le32
dsp_cfg_flags
;
}
__packed
;
/* PHY_CONTEXT_CMD_API_VER_1 */
/*
* Aux ROC command
*
* Command requests the firmware to create a time event for a certain duration
* and remain on the given channel. This is done by using the Aux framework in
* the FW.
* The command was first used for Hot Spot issues - but can be used regardless
* to Hot Spot.
*
* ( HOT_SPOT_CMD 0x53 )
*
* @id_and_color: ID and color of the MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
* @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
* event_unique_id should be the id of the time event assigned by ucode.
* Otherwise ignore the event_unique_id.
* @sta_id_and_color: station id and color, resumed during "Remain On Channel"
* activity.
* @channel_info: channel info
* @node_addr: Our MAC Address
* @reserved: reserved for alignment
* @apply_time: GP2 value to start (should always be the current GP2 value)
* @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
* time by which start of the event is allowed to be postponed.
* @duration: event duration in TU To calculate event duration:
* timeEventDuration = min(duration, remainingQuota)
*/
struct
iwl_hs20_roc_req
{
/* COMMON_INDEX_HDR_API_S_VER_1 hdr */
__le32
id_and_color
;
__le32
action
;
__le32
event_unique_id
;
__le32
sta_id_and_color
;
struct
iwl_fw_channel_info
channel_info
;
u8
node_addr
[
ETH_ALEN
];
__le16
reserved
;
__le32
apply_time
;
__le32
apply_time_max_delay
;
__le32
duration
;
}
__packed
;
/* HOT_SPOT_CMD_API_S_VER_1 */
/*
* values for AUX ROC result values
*/
enum
iwl_mvm_hot_spot
{
HOT_SPOT_RSP_STATUS_OK
,
HOT_SPOT_RSP_STATUS_TOO_MANY_EVENTS
,
HOT_SPOT_MAX_NUM_OF_SESSIONS
,
};
/*
* Aux ROC command response
*
* In response to iwl_hs20_roc_req the FW sends this command to notify the
* driver the uid of the timevent.
*
* ( HOT_SPOT_CMD 0x53 )
*
* @event_unique_id: Unique ID of time event assigned by ucode
* @status: Return status 0 is success, all the rest used for specific errors
*/
struct
iwl_hs20_roc_res
{
__le32
event_unique_id
;
__le32
status
;
}
__packed
;
/* HOT_SPOT_RSP_API_S_VER_1 */
#define IWL_RX_INFO_PHY_CNT 8
#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
...
...
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
浏览文件 @
d878b3af
...
...
@@ -1074,8 +1074,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common
(
mvm
,
vif
,
&
cmd
,
action
);
/* Also enable probe requests to pass */
cmd
.
filter_flags
|=
cpu_to_le32
(
MAC_FILTER_IN_PROBE_REQUEST
);
/*
* pass probe requests and beacons from other APs (needed
* for ht protection)
*/
cmd
.
filter_flags
|=
cpu_to_le32
(
MAC_FILTER_IN_PROBE_REQUEST
|
MAC_FILTER_IN_BEACON
);
/* Fill the data specific for ap mode */
iwl_mvm_mac_ctxt_cmd_fill_ap
(
mvm
,
vif
,
&
cmd
.
ap
,
...
...
@@ -1096,6 +1100,13 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common
(
mvm
,
vif
,
&
cmd
,
action
);
/*
* pass probe requests and beacons from other APs (needed
* for ht protection)
*/
cmd
.
filter_flags
|=
cpu_to_le32
(
MAC_FILTER_IN_PROBE_REQUEST
|
MAC_FILTER_IN_BEACON
);
/* Fill the data specific for GO mode */
iwl_mvm_mac_ctxt_cmd_fill_ap
(
mvm
,
vif
,
&
cmd
.
go
.
ap
,
action
==
FW_CTXT_ACTION_ADD
);
...
...
drivers/net/wireless/iwlwifi/mvm/mac80211.c
浏览文件 @
d878b3af
...
...
@@ -211,7 +211,9 @@ void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
return
;
IWL_DEBUG_RPM
(
mvm
,
"Take mvm reference - type %d
\n
"
,
ref_type
);
WARN_ON
(
test_and_set_bit
(
ref_type
,
mvm
->
ref_bitmap
));
spin_lock_bh
(
&
mvm
->
refs_lock
);
mvm
->
refs
[
ref_type
]
++
;
spin_unlock_bh
(
&
mvm
->
refs_lock
);
iwl_trans_ref
(
mvm
->
trans
);
}
...
...
@@ -221,29 +223,35 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
return
;
IWL_DEBUG_RPM
(
mvm
,
"Leave mvm reference - type %d
\n
"
,
ref_type
);
WARN_ON
(
!
test_and_clear_bit
(
ref_type
,
mvm
->
ref_bitmap
));
spin_lock_bh
(
&
mvm
->
refs_lock
);
WARN_ON
(
!
mvm
->
refs
[
ref_type
]
--
);
spin_unlock_bh
(
&
mvm
->
refs_lock
);
iwl_trans_unref
(
mvm
->
trans
);
}
static
void
iwl_mvm_unref_all_except
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
ref
)
static
void
iwl_mvm_unref_all_except
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
except_
ref
)
{
int
i
;
int
i
,
j
;
if
(
!
iwl_mvm_is_d0i3_supported
(
mvm
))
return
;
for_each_set_bit
(
i
,
mvm
->
ref_bitmap
,
IWL_MVM_REF_COUNT
)
{
if
(
ref
==
i
)
spin_lock_bh
(
&
mvm
->
refs_lock
);
for
(
i
=
0
;
i
<
IWL_MVM_REF_COUNT
;
i
++
)
{
if
(
except_ref
==
i
||
!
mvm
->
refs
[
i
])
continue
;
IWL_DEBUG_RPM
(
mvm
,
"Cleanup: remove mvm ref type %d
\n
"
,
i
);
clear_bit
(
i
,
mvm
->
ref_bitmap
);
iwl_trans_unref
(
mvm
->
trans
);
IWL_DEBUG_RPM
(
mvm
,
"Cleanup: remove mvm ref type %d (%d)
\n
"
,
i
,
mvm
->
refs
[
i
]);
for
(
j
=
0
;
j
<
mvm
->
refs
[
i
];
j
++
)
iwl_trans_unref
(
mvm
->
trans
);
mvm
->
refs
[
i
]
=
0
;
}
spin_unlock_bh
(
&
mvm
->
refs_lock
);
}
static
int
iwl_mvm_ref_sync
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
ref_type
)
int
iwl_mvm_ref_sync
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
ref_type
)
{
iwl_mvm_ref
(
mvm
,
ref_type
);
...
...
@@ -321,13 +329,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw
->
uapsd_max_sp_len
=
IWL_UAPSD_MAX_SP
;
}
if
(
mvm
->
fw
->
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT
&&
!
iwlwifi_mod_params
.
uapsd_disable
)
{
hw
->
flags
|=
IEEE80211_HW_SUPPORTS_UAPSD
;
hw
->
uapsd_queues
=
IWL_UAPSD_AC_INFO
;
hw
->
uapsd_max_sp_len
=
IWL_UAPSD_MAX_SP
;
}
if
(
mvm
->
fw
->
ucode_capa
.
api
[
0
]
&
IWL_UCODE_TLV_API_LMAC_SCAN
)
hw
->
flags
|=
IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS
;
...
...
@@ -660,6 +661,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
spin_unlock_bh
(
&
mvm
->
time_event_lock
);
mvmvif
->
phy_ctxt
=
NULL
;
memset
(
&
mvmvif
->
bf_data
,
0
,
sizeof
(
mvmvif
->
bf_data
));
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
...
...
@@ -668,11 +670,11 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct
iwl_fw_error_dump_file
*
dump_file
;
struct
iwl_fw_error_dump_data
*
dump_data
;
struct
iwl_fw_error_dump_info
*
dump_info
;
struct
iwl_mvm_dump_ptrs
*
fw_error_dump
;
const
struct
fw_img
*
img
;
u32
sram_len
,
sram_ofs
;
u32
file_len
,
rxf_len
;
unsigned
long
flags
;
u32
trans_len
;
int
reg_val
;
lockdep_assert_held
(
&
mvm
->
mutex
);
...
...
@@ -680,6 +682,10 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
if
(
mvm
->
fw_error_dump
)
return
;
fw_error_dump
=
kzalloc
(
sizeof
(
*
mvm
->
fw_error_dump
),
GFP_KERNEL
);
if
(
!
fw_error_dump
)
return
;
img
=
&
mvm
->
fw
->
img
[
mvm
->
cur_ucode
];
sram_ofs
=
img
->
sec
[
IWL_UCODE_SECTION_DATA
].
offset
;
sram_len
=
img
->
sec
[
IWL_UCODE_SECTION_DATA
].
len
;
...
...
@@ -697,18 +703,15 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
rxf_len
+
sizeof
(
*
dump_info
);
trans_len
=
iwl_trans_dump_data
(
mvm
->
trans
,
NULL
,
0
);
if
(
trans_len
)
file_len
+=
trans_len
;
dump_file
=
vzalloc
(
file_len
);
if
(
!
dump_file
)
if
(
!
dump_file
)
{
kfree
(
fw_error_dump
);
return
;
}
mvm
->
fw_error_dump
=
dump_file
;
fw_error_dump
->
op_mode_ptr
=
dump_file
;
dump_file
->
barker
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_BARKER
);
dump_file
->
file_len
=
cpu_to_le32
(
file_len
);
dump_data
=
(
void
*
)
dump_file
->
data
;
dump_data
->
type
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_DEV_FW_INFO
);
...
...
@@ -749,14 +752,12 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
iwl_trans_read_mem_bytes
(
mvm
->
trans
,
sram_ofs
,
dump_data
->
data
,
sram_len
);
if
(
trans_len
)
{
void
*
buf
=
iwl_fw_error_next_data
(
dump_data
);
u32
real_trans_len
=
iwl_trans_dump_data
(
mvm
->
trans
,
buf
,
trans_len
);
dump_data
=
(
void
*
)((
u8
*
)
buf
+
real_trans_len
);
dump_file
->
file_len
=
cpu_to_le32
(
file_len
-
trans_len
+
real_trans_len
);
}
fw_error_dump
->
trans_ptr
=
iwl_trans_dump_data
(
mvm
->
trans
);
fw_error_dump
->
op_mode_len
=
file_len
;
if
(
fw_error_dump
->
trans_ptr
)
file_len
+=
fw_error_dump
->
trans_ptr
->
len
;
dump_file
->
file_len
=
cpu_to_le32
(
file_len
);
mvm
->
fw_error_dump
=
fw_error_dump
;
}
#endif
...
...
@@ -788,6 +789,12 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_mvm_reset_phy_ctxts
(
mvm
);
memset
(
mvm
->
fw_key_table
,
0
,
sizeof
(
mvm
->
fw_key_table
));
memset
(
mvm
->
sta_drained
,
0
,
sizeof
(
mvm
->
sta_drained
));
memset
(
&
mvm
->
last_bt_notif
,
0
,
sizeof
(
mvm
->
last_bt_notif
));
memset
(
&
mvm
->
last_bt_notif_old
,
0
,
sizeof
(
mvm
->
last_bt_notif_old
));
memset
(
&
mvm
->
last_bt_ci_cmd
,
0
,
sizeof
(
mvm
->
last_bt_ci_cmd
));
memset
(
&
mvm
->
last_bt_ci_cmd_old
,
0
,
sizeof
(
mvm
->
last_bt_ci_cmd_old
));
memset
(
&
mvm
->
bt_ack_kill_msk
,
0
,
sizeof
(
mvm
->
bt_ack_kill_msk
));
memset
(
&
mvm
->
bt_cts_kill_msk
,
0
,
sizeof
(
mvm
->
bt_cts_kill_msk
));
ieee80211_wake_queues
(
mvm
->
hw
);
...
...
@@ -1399,6 +1406,28 @@ static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
}
#endif
static
void
iwl_mvm_teardown_tdls_peers
(
struct
iwl_mvm
*
mvm
)
{
struct
ieee80211_sta
*
sta
;
struct
iwl_mvm_sta
*
mvmsta
;
int
i
;
lockdep_assert_held
(
&
mvm
->
mutex
);
for
(
i
=
0
;
i
<
IWL_MVM_STATION_COUNT
;
i
++
)
{
sta
=
rcu_dereference_protected
(
mvm
->
fw_id_to_mac_id
[
i
],
lockdep_is_held
(
&
mvm
->
mutex
));
if
(
!
sta
||
IS_ERR
(
sta
)
||
!
sta
->
tdls
)
continue
;
mvmsta
=
iwl_mvm_sta_from_mac80211
(
sta
);
ieee80211_tdls_oper_request
(
mvmsta
->
vif
,
sta
->
addr
,
NL80211_TDLS_TEARDOWN
,
WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED
,
GFP_KERNEL
);
}
}
static
void
iwl_mvm_bss_info_changed_station
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_bss_conf
*
bss_conf
,
...
...
@@ -1494,14 +1523,18 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
*/
iwl_mvm_remove_time_event
(
mvm
,
mvmvif
,
&
mvmvif
->
time_event_data
);
iwl_mvm_sf_update
(
mvm
,
vif
,
false
);
WARN_ON
(
iwl_mvm_enable_beacon_filter
(
mvm
,
vif
,
0
));
}
else
if
(
changes
&
(
BSS_CHANGED_PS
|
BSS_CHANGED_P2P_PS
|
BSS_CHANGED_QOS
))
{
ret
=
iwl_mvm_power_update_mac
(
mvm
);
if
(
ret
)
IWL_ERR
(
mvm
,
"failed to update power mode
\n
"
);
}
if
(
changes
&
BSS_CHANGED_BEACON_INFO
)
{
iwl_mvm_sf_update
(
mvm
,
vif
,
false
);
WARN_ON
(
iwl_mvm_enable_beacon_filter
(
mvm
,
vif
,
0
));
}
if
(
changes
&
BSS_CHANGED_TXPOWER
)
{
IWL_DEBUG_CALIB
(
mvm
,
"Changing TX Power to %d
\n
"
,
bss_conf
->
txpower
);
...
...
@@ -1533,6 +1566,14 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
int
ret
;
/*
* iwl_mvm_mac_ctxt_add() might read directly from the device
* (the system time), so make sure it is available.
*/
ret
=
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_START_AP
);
if
(
ret
)
return
ret
;
mutex_lock
(
&
mvm
->
mutex
);
/* Send the beacon template */
...
...
@@ -1581,6 +1622,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_bt_coex_vif_change
(
mvm
);
/* we don't support TDLS during DCM */
if
(
iwl_mvm_phy_ctx_count
(
mvm
)
>
1
)
iwl_mvm_teardown_tdls_peers
(
mvm
);
mutex_unlock
(
&
mvm
->
mutex
);
return
0
;
...
...
@@ -1594,6 +1639,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_mac_ctxt_remove
(
mvm
,
vif
);
out_unlock:
mutex_unlock
(
&
mvm
->
mutex
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_START_AP
);
return
ret
;
}
...
...
@@ -1671,6 +1717,14 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
{
struct
iwl_mvm
*
mvm
=
IWL_MAC80211_GET_MVM
(
hw
);
/*
* iwl_mvm_bss_info_changed_station() might call
* iwl_mvm_protect_session(), which reads directly from
* the device (the system time), so make sure it is available.
*/
if
(
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_BSS_CHANGED
))
return
;
mutex_lock
(
&
mvm
->
mutex
);
if
(
changes
&
BSS_CHANGED_IDLE
&&
!
bss_conf
->
idle
)
...
...
@@ -1690,8 +1744,50 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
}
mutex_unlock
(
&
mvm
->
mutex
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_BSS_CHANGED
);
}
static
int
iwl_mvm_cancel_scan_wait_notif
(
struct
iwl_mvm
*
mvm
,
enum
iwl_scan_status
scan_type
)
{
int
ret
;
bool
wait_for_handlers
=
false
;
mutex_lock
(
&
mvm
->
mutex
);
if
(
mvm
->
scan_status
!=
scan_type
)
{
ret
=
0
;
/* make sure there are no pending notifications */
wait_for_handlers
=
true
;
goto
out
;
}
switch
(
scan_type
)
{
case
IWL_MVM_SCAN_SCHED
:
ret
=
iwl_mvm_scan_offload_stop
(
mvm
,
true
);
break
;
case
IWL_MVM_SCAN_OS
:
ret
=
iwl_mvm_cancel_scan
(
mvm
);
break
;
case
IWL_MVM_SCAN_NONE
:
default:
WARN_ON_ONCE
(
1
);
ret
=
-
EINVAL
;
break
;
}
if
(
ret
)
goto
out
;
wait_for_handlers
=
true
;
out:
mutex_unlock
(
&
mvm
->
mutex
);
/* make sure we consume the completion notification */
if
(
wait_for_handlers
)
iwl_mvm_wait_for_async_handlers
(
mvm
);
return
ret
;
}
static
int
iwl_mvm_mac_hw_scan
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_scan_request
*
hw_req
)
...
...
@@ -1704,19 +1800,13 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
req
->
n_channels
>
mvm
->
fw
->
ucode_capa
.
n_scan_channels
)
return
-
EINVAL
;
ret
=
iwl_mvm_cancel_scan_wait_notif
(
mvm
,
IWL_MVM_SCAN_SCHED
);
if
(
ret
)
return
ret
;
mutex_lock
(
&
mvm
->
mutex
);
switch
(
mvm
->
scan_status
)
{
case
IWL_MVM_SCAN_SCHED
:
ret
=
iwl_mvm_scan_offload_stop
(
mvm
,
true
);
if
(
ret
)
{
ret
=
-
EBUSY
;
goto
out
;
}
break
;
case
IWL_MVM_SCAN_NONE
:
break
;
default:
if
(
mvm
->
scan_status
!=
IWL_MVM_SCAN_NONE
)
{
ret
=
-
EBUSY
;
goto
out
;
}
...
...
@@ -1732,8 +1822,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_SCAN
);
out:
mutex_unlock
(
&
mvm
->
mutex
);
/* make sure to flush the Rx handler before the next scan arrives */
iwl_mvm_wait_for_async_handlers
(
mvm
);
return
ret
;
}
...
...
@@ -1885,28 +1973,6 @@ static void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm,
iwl_mvm_power_update_mac
(
mvm
);
}
static
void
iwl_mvm_teardown_tdls_peers
(
struct
iwl_mvm
*
mvm
)
{
struct
ieee80211_sta
*
sta
;
struct
iwl_mvm_sta
*
mvmsta
;
int
i
;
lockdep_assert_held
(
&
mvm
->
mutex
);
for
(
i
=
0
;
i
<
IWL_MVM_STATION_COUNT
;
i
++
)
{
sta
=
rcu_dereference_protected
(
mvm
->
fw_id_to_mac_id
[
i
],
lockdep_is_held
(
&
mvm
->
mutex
));
if
(
!
sta
||
IS_ERR
(
sta
)
||
!
sta
->
tdls
)
continue
;
mvmsta
=
iwl_mvm_sta_from_mac80211
(
sta
);
ieee80211_tdls_oper_request
(
mvmsta
->
vif
,
sta
->
addr
,
NL80211_TDLS_TEARDOWN
,
WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED
,
GFP_KERNEL
);
}
}
static
int
iwl_mvm_mac_sta_state
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
...
...
@@ -2065,10 +2131,19 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
if
(
WARN_ON_ONCE
(
vif
->
bss_conf
.
assoc
))
return
;
/*
* iwl_mvm_protect_session() reads directly from the device
* (the system time), so make sure it is available.
*/
if
(
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_PREPARE_TX
))
return
;
mutex_lock
(
&
mvm
->
mutex
);
/* Try really hard to protect the session and hear a beacon */
iwl_mvm_protect_session
(
mvm
,
vif
,
duration
,
min_duration
,
500
);
mutex_unlock
(
&
mvm
->
mutex
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_PREPARE_TX
);
}
static
void
iwl_mvm_mac_mgd_protect_tdls_discover
(
struct
ieee80211_hw
*
hw
,
...
...
@@ -2077,10 +2152,19 @@ static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
struct
iwl_mvm
*
mvm
=
IWL_MAC80211_GET_MVM
(
hw
);
u32
duration
=
2
*
vif
->
bss_conf
.
dtim_period
*
vif
->
bss_conf
.
beacon_int
;
/*
* iwl_mvm_protect_session() reads directly from the device
* (the system time), so make sure it is available.
*/
if
(
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_PROTECT_TDLS
))
return
;
mutex_lock
(
&
mvm
->
mutex
);
/* Protect the session to hear the TDLS setup response on the channel */
iwl_mvm_protect_session
(
mvm
,
vif
,
duration
,
duration
,
100
);
mutex_unlock
(
&
mvm
->
mutex
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_PROTECT_TDLS
);
}
static
int
iwl_mvm_mac_sched_scan_start
(
struct
ieee80211_hw
*
hw
,
...
...
@@ -2091,6 +2175,10 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
struct
iwl_mvm
*
mvm
=
IWL_MAC80211_GET_MVM
(
hw
);
int
ret
;
ret
=
iwl_mvm_cancel_scan_wait_notif
(
mvm
,
IWL_MVM_SCAN_OS
);
if
(
ret
)
return
ret
;
mutex_lock
(
&
mvm
->
mutex
);
if
(
!
iwl_mvm_is_idle
(
mvm
))
{
...
...
@@ -2098,26 +2186,7 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
goto
out
;
}
switch
(
mvm
->
scan_status
)
{
case
IWL_MVM_SCAN_OS
:
IWL_DEBUG_SCAN
(
mvm
,
"Stopping previous scan for sched_scan
\n
"
);
ret
=
iwl_mvm_cancel_scan
(
mvm
);
if
(
ret
)
{
ret
=
-
EBUSY
;
goto
out
;
}
/*
* iwl_mvm_rx_scan_complete() will be called soon but will
* not reset the scan status as it won't be IWL_MVM_SCAN_OS
* any more since we queue the next scan immediately (below).
* We make sure it is called before the next scan starts by
* flushing the async-handlers work.
*/
break
;
case
IWL_MVM_SCAN_NONE
:
break
;
default:
if
(
mvm
->
scan_status
!=
IWL_MVM_SCAN_NONE
)
{
ret
=
-
EBUSY
;
goto
out
;
}
...
...
@@ -2145,8 +2214,6 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
mvm
->
scan_status
=
IWL_MVM_SCAN_NONE
;
out:
mutex_unlock
(
&
mvm
->
mutex
);
/* make sure to flush the Rx handler before the next scan arrives */
iwl_mvm_wait_for_async_handlers
(
mvm
);
return
ret
;
}
...
...
@@ -2266,6 +2333,119 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
}
static
bool
iwl_mvm_rx_aux_roc
(
struct
iwl_notif_wait_data
*
notif_wait
,
struct
iwl_rx_packet
*
pkt
,
void
*
data
)
{
struct
iwl_mvm
*
mvm
=
container_of
(
notif_wait
,
struct
iwl_mvm
,
notif_wait
);
struct
iwl_hs20_roc_res
*
resp
;
int
resp_len
=
iwl_rx_packet_payload_len
(
pkt
);
struct
iwl_mvm_time_event_data
*
te_data
=
data
;
if
(
WARN_ON
(
pkt
->
hdr
.
cmd
!=
HOT_SPOT_CMD
))
return
true
;
if
(
WARN_ON_ONCE
(
resp_len
!=
sizeof
(
*
resp
)))
{
IWL_ERR
(
mvm
,
"Invalid HOT_SPOT_CMD response
\n
"
);
return
true
;
}
resp
=
(
void
*
)
pkt
->
data
;
IWL_DEBUG_TE
(
mvm
,
"Aux ROC: Recieved response from ucode: status=%d uid=%d
\n
"
,
resp
->
status
,
resp
->
event_unique_id
);
te_data
->
uid
=
le32_to_cpu
(
resp
->
event_unique_id
);
IWL_DEBUG_TE
(
mvm
,
"TIME_EVENT_CMD response - UID = 0x%x
\n
"
,
te_data
->
uid
);
spin_lock_bh
(
&
mvm
->
time_event_lock
);
list_add_tail
(
&
te_data
->
list
,
&
mvm
->
aux_roc_te_list
);
spin_unlock_bh
(
&
mvm
->
time_event_lock
);
return
true
;
}
#define AUX_ROC_MAX_DELAY_ON_CHANNEL 5000
static
int
iwl_mvm_send_aux_roc_cmd
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_channel
*
channel
,
struct
ieee80211_vif
*
vif
,
int
duration
)
{
int
res
,
time_reg
=
DEVICE_SYSTEM_TIME_REG
;
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_mvm_time_event_data
*
te_data
=
&
mvmvif
->
hs_time_event_data
;
static
const
u8
time_event_response
[]
=
{
HOT_SPOT_CMD
};
struct
iwl_notification_wait
wait_time_event
;
struct
iwl_hs20_roc_req
aux_roc_req
=
{
.
action
=
cpu_to_le32
(
FW_CTXT_ACTION_ADD
),
.
id_and_color
=
cpu_to_le32
(
FW_CMD_ID_AND_COLOR
(
MAC_INDEX_AUX
,
0
)),
.
sta_id_and_color
=
cpu_to_le32
(
mvm
->
aux_sta
.
sta_id
),
/* Set the channel info data */
.
channel_info
.
band
=
(
channel
->
band
==
IEEE80211_BAND_2GHZ
)
?
PHY_BAND_24
:
PHY_BAND_5
,
.
channel_info
.
channel
=
channel
->
hw_value
,
.
channel_info
.
width
=
PHY_VHT_CHANNEL_MODE20
,
/* Set the time and duration */
.
apply_time
=
cpu_to_le32
(
iwl_read_prph
(
mvm
->
trans
,
time_reg
)),
.
apply_time_max_delay
=
cpu_to_le32
(
MSEC_TO_TU
(
AUX_ROC_MAX_DELAY_ON_CHANNEL
)),
.
duration
=
cpu_to_le32
(
MSEC_TO_TU
(
duration
)),
};
/* Set the node address */
memcpy
(
aux_roc_req
.
node_addr
,
vif
->
addr
,
ETH_ALEN
);
te_data
->
vif
=
vif
;
te_data
->
duration
=
duration
;
te_data
->
id
=
HOT_SPOT_CMD
;
lockdep_assert_held
(
&
mvm
->
mutex
);
spin_lock_bh
(
&
mvm
->
time_event_lock
);
list_add_tail
(
&
te_data
->
list
,
&
mvm
->
time_event_list
);
spin_unlock_bh
(
&
mvm
->
time_event_lock
);
/*
* Use a notification wait, which really just processes the
* command response and doesn't wait for anything, in order
* to be able to process the response and get the UID inside
* the RX path. Using CMD_WANT_SKB doesn't work because it
* stores the buffer and then wakes up this thread, by which
* time another notification (that the time event started)
* might already be processed unsuccessfully.
*/
iwl_init_notification_wait
(
&
mvm
->
notif_wait
,
&
wait_time_event
,
time_event_response
,
ARRAY_SIZE
(
time_event_response
),
iwl_mvm_rx_aux_roc
,
te_data
);
res
=
iwl_mvm_send_cmd_pdu
(
mvm
,
HOT_SPOT_CMD
,
0
,
sizeof
(
aux_roc_req
),
&
aux_roc_req
);
if
(
res
)
{
IWL_ERR
(
mvm
,
"Couldn't send HOT_SPOT_CMD: %d
\n
"
,
res
);
iwl_remove_notification
(
&
mvm
->
notif_wait
,
&
wait_time_event
);
goto
out_clear_te
;
}
/* No need to wait for anything, so just pass 1 (0 isn't valid) */
res
=
iwl_wait_notification
(
&
mvm
->
notif_wait
,
&
wait_time_event
,
1
);
/* should never fail */
WARN_ON_ONCE
(
res
);
if
(
res
)
{
out_clear_te:
spin_lock_bh
(
&
mvm
->
time_event_lock
);
iwl_mvm_te_clear_data
(
mvm
,
te_data
);
spin_unlock_bh
(
&
mvm
->
time_event_lock
);
}
return
res
;
}
static
int
iwl_mvm_roc
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_channel
*
channel
,
...
...
@@ -2281,8 +2461,17 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211
(
mvm
,
"enter (%d, %d, %d)
\n
"
,
channel
->
hw_value
,
duration
,
type
);
if
(
vif
->
type
!=
NL80211_IFTYPE_P2P_DEVICE
)
{
IWL_ERR
(
mvm
,
"vif isn't a P2P_DEVICE: %d
\n
"
,
vif
->
type
);
switch
(
vif
->
type
)
{
case
NL80211_IFTYPE_STATION
:
/* Use aux roc framework (HS20) */
ret
=
iwl_mvm_send_aux_roc_cmd
(
mvm
,
channel
,
vif
,
duration
);
return
ret
;
case
NL80211_IFTYPE_P2P_DEVICE
:
/* handle below */
break
;
default:
IWL_ERR
(
mvm
,
"vif isn't P2P_DEVICE: %d
\n
"
,
vif
->
type
);
return
-
EINVAL
;
}
...
...
@@ -2661,6 +2850,10 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
goto
out_remove
;
}
/* we don't support TDLS during DCM - can be caused by channel switch */
if
(
iwl_mvm_phy_ctx_count
(
mvm
)
>
1
)
iwl_mvm_teardown_tdls_peers
(
mvm
);
goto
out
;
out_remove:
...
...
drivers/net/wireless/iwlwifi/mvm/mvm.h
浏览文件 @
d878b3af
...
...
@@ -82,6 +82,8 @@
/* RSSI offset for WkP */
#define IWL_RSSI_OFFSET 50
#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
/* A TimeUnit is 1024 microsecond */
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
/*
* The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0"
...
...
@@ -126,6 +128,21 @@ struct iwl_mvm_mod_params {
};
extern
struct
iwl_mvm_mod_params
iwlmvm_mod_params
;
/**
* struct iwl_mvm_dump_ptrs - set of pointers needed for the fw-error-dump
*
* @op_mode_ptr: pointer to the buffer coming from the mvm op_mode
* @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
* transport's data.
* @trans_len: length of the valid data in trans_ptr
* @op_mode_len: length of the valid data in op_mode_ptr
*/
struct
iwl_mvm_dump_ptrs
{
struct
iwl_trans_dump_data
*
trans_ptr
;
void
*
op_mode_ptr
;
u32
op_mode_len
;
};
struct
iwl_mvm_phy_ctxt
{
u16
id
;
u16
color
;
...
...
@@ -249,6 +266,15 @@ enum iwl_mvm_ref_type {
IWL_MVM_REF_TX
,
IWL_MVM_REF_TX_AGG
,
IWL_MVM_REF_ADD_IF
,
IWL_MVM_REF_START_AP
,
IWL_MVM_REF_BSS_CHANGED
,
IWL_MVM_REF_PREPARE_TX
,
IWL_MVM_REF_PROTECT_TDLS
,
IWL_MVM_REF_CHECK_CTKILL
,
IWL_MVM_REF_PRPH_READ
,
IWL_MVM_REF_PRPH_WRITE
,
IWL_MVM_REF_NMI
,
IWL_MVM_REF_TM_CMD
,
IWL_MVM_REF_EXIT_WORK
,
IWL_MVM_REF_COUNT
,
...
...
@@ -327,6 +353,7 @@ struct iwl_mvm_vif {
*/
struct
ieee80211_tx_queue_params
queue_params
[
IEEE80211_NUM_ACS
];
struct
iwl_mvm_time_event_data
time_event_data
;
struct
iwl_mvm_time_event_data
hs_time_event_data
;
struct
iwl_mvm_int_sta
bcast_sta
;
...
...
@@ -606,14 +633,15 @@ struct iwl_mvm {
*/
unsigned
long
fw_key_table
[
BITS_TO_LONGS
(
STA_KEY_MAX_NUM
)];
/* A bitmap of reference types taken by the driver. */
unsigned
long
ref_bitmap
[
BITS_TO_LONGS
(
IWL_MVM_REF_COUNT
)];
/* references taken by the driver and spinlock protecting them */
spinlock_t
refs_lock
;
u8
refs
[
IWL_MVM_REF_COUNT
];
u8
vif_count
;
/* -1 for always, 0 for never, >0 for that many times */
s8
restart_fw
;
void
*
fw_error_dump
;
struct
iwl_mvm_dump_ptrs
*
fw_error_dump
;
#ifdef CONFIG_IWLWIFI_LEDS
struct
led_classdev
led
;
...
...
@@ -647,7 +675,8 @@ struct iwl_mvm {
wait_queue_head_t
d0i3_exit_waitq
;
/* BT-Coex */
u8
bt_kill_msk
;
u8
bt_ack_kill_msk
[
NUM_PHY_CTX
];
u8
bt_cts_kill_msk
[
NUM_PHY_CTX
];
struct
iwl_bt_coex_profile_notif_old
last_bt_notif_old
;
struct
iwl_bt_coex_ci_cmd_old
last_bt_ci_cmd_old
;
...
...
@@ -659,6 +688,9 @@ struct iwl_mvm {
u8
bt_tx_prio
;
enum
iwl_bt_force_ant_mode
bt_force_ant_mode
;
/* Aux ROC */
struct
list_head
aux_roc_te_list
;
/* Thermal Throttling and CTkill */
struct
iwl_mvm_tt_mgmt
thermal_throttle
;
s32
temperature
;
/* Celsius */
...
...
@@ -697,6 +729,7 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_ROC_RUNNING
,
IWL_MVM_STATUS_IN_HW_RESTART
,
IWL_MVM_STATUS_IN_D0I3
,
IWL_MVM_STATUS_ROC_AUX_RUNNING
,
};
static
inline
bool
iwl_mvm_is_radio_killed
(
struct
iwl_mvm
*
mvm
)
...
...
@@ -988,6 +1021,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
/* D0i3 */
void
iwl_mvm_ref
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
ref_type
);
void
iwl_mvm_unref
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
ref_type
);
int
iwl_mvm_ref_sync
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
ref_type
);
void
iwl_mvm_d0i3_enable_tx
(
struct
iwl_mvm
*
mvm
,
__le16
*
qos_seq
);
int
_iwl_mvm_exit_d0i3
(
struct
iwl_mvm
*
mvm
);
...
...
@@ -1029,12 +1063,14 @@ int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
enum
iwl_bt_kill_msk
{
BT_KILL_MSK_DEFAULT
,
BT_KILL_MSK_
SCO_HID_A2DP
,
BT_KILL_MSK_
REDUCED_TXPOW
,
BT_KILL_MSK_
NEVER
,
BT_KILL_MSK_
ALWAYS
,
BT_KILL_MSK_MAX
,
};
extern
const
u32
iwl_bt_ack_kill_msk
[
BT_KILL_MSK_MAX
];
extern
const
u32
iwl_bt_cts_kill_msk
[
BT_KILL_MSK_MAX
];
extern
const
u8
iwl_bt_ack_kill_msk
[
BT_MAX_AG
][
BT_COEX_MAX_LUT
];
extern
const
u8
iwl_bt_cts_kill_msk
[
BT_MAX_AG
][
BT_COEX_MAX_LUT
];
extern
const
u32
iwl_bt_ctl_kill_msk
[
BT_KILL_MSK_MAX
];
/* beacon filtering */
#ifdef CONFIG_IWLWIFI_DEBUGFS
...
...
drivers/net/wireless/iwlwifi/mvm/nvm.c
浏览文件 @
d878b3af
...
...
@@ -265,7 +265,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
if
(
mvm
->
trans
->
cfg
->
device_family
!=
IWL_DEVICE_FAMILY_8000
)
{
if
(
!
mvm
->
nvm_sections
[
NVM_SECTION_TYPE_SW
].
data
||
!
mvm
->
nvm_sections
[
mvm
->
cfg
->
nvm_hw_section_num
].
data
)
{
IWL_ERR
(
mvm
,
"Can't parse empty NVM sections
\n
"
);
IWL_ERR
(
mvm
,
"Can't parse empty
OTP/
NVM sections
\n
"
);
return
NULL
;
}
}
else
{
...
...
@@ -273,7 +273,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
if
(
!
mvm
->
nvm_sections
[
NVM_SECTION_TYPE_SW
].
data
||
!
mvm
->
nvm_sections
[
NVM_SECTION_TYPE_REGULATORY
].
data
)
{
IWL_ERR
(
mvm
,
"Can't parse empty family 8000 NVM sections
\n
"
);
"Can't parse empty family 8000
OTP/
NVM sections
\n
"
);
return
NULL
;
}
/* MAC_OVERRIDE or at least HW section must exist */
...
...
drivers/net/wireless/iwlwifi/mvm/ops.c
浏览文件 @
d878b3af
...
...
@@ -289,6 +289,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD
(
MATCH_FOUND_NOTIFICATION
),
CMD
(
SCAN_OFFLOAD_REQUEST_CMD
),
CMD
(
SCAN_OFFLOAD_ABORT_CMD
),
CMD
(
HOT_SPOT_CMD
),
CMD
(
SCAN_OFFLOAD_COMPLETE
),
CMD
(
SCAN_OFFLOAD_UPDATE_PROFILES_CMD
),
CMD
(
SCAN_ITERATION_COMPLETE
),
...
...
@@ -391,6 +392,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if
(
!
hw
)
return
NULL
;
if
(
cfg
->
max_rx_agg_size
)
hw
->
max_rx_aggregation_subframes
=
cfg
->
max_rx_agg_size
;
op_mode
=
hw
->
priv
;
op_mode
->
ops
=
&
iwl_mvm_ops
;
...
...
@@ -416,6 +420,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mutex_init
(
&
mvm
->
d0i3_suspend_mutex
);
spin_lock_init
(
&
mvm
->
async_handlers_lock
);
INIT_LIST_HEAD
(
&
mvm
->
time_event_list
);
INIT_LIST_HEAD
(
&
mvm
->
aux_roc_te_list
);
INIT_LIST_HEAD
(
&
mvm
->
async_handlers_list
);
spin_lock_init
(
&
mvm
->
time_event_lock
);
...
...
@@ -425,6 +430,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
INIT_WORK
(
&
mvm
->
d0i3_exit_work
,
iwl_mvm_d0i3_exit_work
);
spin_lock_init
(
&
mvm
->
d0i3_tx_lock
);
spin_lock_init
(
&
mvm
->
refs_lock
);
skb_queue_head_init
(
&
mvm
->
d0i3_tx
);
init_waitqueue_head
(
&
mvm
->
d0i3_exit_waitq
);
...
...
@@ -539,7 +545,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
memset
(
&
mvm
->
rx_stats
,
0
,
sizeof
(
struct
mvm_statistics_rx
));
/* rpm starts with a taken ref. only set the appropriate bit here. */
set_bit
(
IWL_MVM_REF_UCODE_DOWN
,
mvm
->
ref_bitmap
)
;
mvm
->
refs
[
IWL_MVM_REF_UCODE_DOWN
]
=
1
;
return
op_mode
;
...
...
@@ -567,7 +573,11 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
ieee80211_unregister_hw
(
mvm
->
hw
);
kfree
(
mvm
->
scan_cmd
);
vfree
(
mvm
->
fw_error_dump
);
if
(
mvm
->
fw_error_dump
)
{
vfree
(
mvm
->
fw_error_dump
->
op_mode_ptr
);
vfree
(
mvm
->
fw_error_dump
->
trans_ptr
);
kfree
(
mvm
->
fw_error_dump
);
}
kfree
(
mvm
->
mcast_filter_cmd
);
mvm
->
mcast_filter_cmd
=
NULL
;
...
...
drivers/net/wireless/iwlwifi/mvm/sta.c
浏览文件 @
d878b3af
...
...
@@ -98,23 +98,21 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
bool
update
)
{
struct
iwl_mvm_sta
*
mvm_sta
=
(
void
*
)
sta
->
drv_priv
;
struct
iwl_mvm_add_sta_cmd
add_sta_cmd
;
struct
iwl_mvm_add_sta_cmd
add_sta_cmd
=
{
.
sta_id
=
mvm_sta
->
sta_id
,
.
mac_id_n_color
=
cpu_to_le32
(
mvm_sta
->
mac_id_n_color
),
.
add_modify
=
update
?
1
:
0
,
.
station_flags_msk
=
cpu_to_le32
(
STA_FLG_FAT_EN_MSK
|
STA_FLG_MIMO_EN_MSK
),
};
int
ret
;
u32
status
;
u32
agg_size
=
0
,
mpdu_dens
=
0
;
memset
(
&
add_sta_cmd
,
0
,
sizeof
(
add_sta_cmd
));
add_sta_cmd
.
sta_id
=
mvm_sta
->
sta_id
;
add_sta_cmd
.
mac_id_n_color
=
cpu_to_le32
(
mvm_sta
->
mac_id_n_color
);
if
(
!
update
)
{
add_sta_cmd
.
tfd_queue_msk
=
cpu_to_le32
(
mvm_sta
->
tfd_queue_msk
);
memcpy
(
&
add_sta_cmd
.
addr
,
sta
->
addr
,
ETH_ALEN
);
}
add_sta_cmd
.
add_modify
=
update
?
1
:
0
;
add_sta_cmd
.
station_flags_msk
|=
cpu_to_le32
(
STA_FLG_FAT_EN_MSK
|
STA_FLG_MIMO_EN_MSK
);
switch
(
sta
->
bandwidth
)
{
case
IEEE80211_STA_RX_BW_160
:
...
...
@@ -528,8 +526,12 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
lockdep_assert_held
(
&
mvm
->
mutex
);
/* Add the aux station, but without any queues */
ret
=
iwl_mvm_allocate_int_sta
(
mvm
,
&
mvm
->
aux_sta
,
0
,
/* Map Aux queue to fifo - needs to happen before adding Aux station */
iwl_trans_ac_txq_enable
(
mvm
->
trans
,
mvm
->
aux_queue
,
IWL_MVM_TX_FIFO_MCAST
);
/* Allocate aux station and assign to it the aux queue */
ret
=
iwl_mvm_allocate_int_sta
(
mvm
,
&
mvm
->
aux_sta
,
BIT
(
mvm
->
aux_queue
),
NL80211_IFTYPE_UNSPECIFIED
);
if
(
ret
)
return
ret
;
...
...
drivers/net/wireless/iwlwifi/mvm/time-event.c
浏览文件 @
d878b3af
...
...
@@ -72,9 +72,6 @@
#include "iwl-io.h"
#include "iwl-prph.h"
/* A TimeUnit is 1024 microsecond */
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
/*
* For the high priority TE use a time event type that has similar priority to
* the FW's action scan priority.
...
...
@@ -100,6 +97,21 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
void
iwl_mvm_roc_done_wk
(
struct
work_struct
*
wk
)
{
struct
iwl_mvm
*
mvm
=
container_of
(
wk
,
struct
iwl_mvm
,
roc_done_wk
);
u32
queues
=
0
;
/*
* Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit.
* This will cause the TX path to drop offchannel transmissions.
* That would also be done by mac80211, but it is racy, in particular
* in the case that the time event actually completed in the firmware
* (which is handled in iwl_mvm_te_handle_notif).
*/
if
(
test_and_clear_bit
(
IWL_MVM_STATUS_ROC_RUNNING
,
&
mvm
->
status
))
queues
|=
BIT
(
IWL_MVM_OFFCHANNEL_QUEUE
);
if
(
test_and_clear_bit
(
IWL_MVM_STATUS_ROC_AUX_RUNNING
,
&
mvm
->
status
))
queues
|=
BIT
(
mvm
->
aux_queue
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_ROC
);
synchronize_net
();
...
...
@@ -113,21 +125,11 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* issue as it will have to complete before the next command is
* executed, and a new time event means a new command.
*/
iwl_mvm_flush_tx_path
(
mvm
,
BIT
(
IWL_MVM_OFFCHANNEL_QUEUE
)
,
false
);
iwl_mvm_flush_tx_path
(
mvm
,
queues
,
false
);
}
static
void
iwl_mvm_roc_finished
(
struct
iwl_mvm
*
mvm
)
{
/*
* First, clear the ROC_RUNNING status bit. This will cause the TX
* path to drop offchannel transmissions. That would also be done
* by mac80211, but it is racy, in particular in the case that the
* time event actually completed in the firmware (which is handled
* in iwl_mvm_te_handle_notif).
*/
clear_bit
(
IWL_MVM_STATUS_ROC_RUNNING
,
&
mvm
->
status
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_ROC
);
/*
* Of course, our status bit is just as racy as mac80211, so in
* addition, fire off the work struct which will drop all frames
...
...
@@ -262,6 +264,60 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
}
}
/*
* Handle A Aux ROC time event
*/
static
int
iwl_mvm_aux_roc_te_handle_notif
(
struct
iwl_mvm
*
mvm
,
struct
iwl_time_event_notif
*
notif
)
{
struct
iwl_mvm_time_event_data
*
te_data
,
*
tmp
;
bool
aux_roc_te
=
false
;
list_for_each_entry_safe
(
te_data
,
tmp
,
&
mvm
->
aux_roc_te_list
,
list
)
{
if
(
le32_to_cpu
(
notif
->
unique_id
)
==
te_data
->
uid
)
{
aux_roc_te
=
true
;
break
;
}
}
if
(
!
aux_roc_te
)
/* Not a Aux ROC time event */
return
-
EINVAL
;
if
(
!
le32_to_cpu
(
notif
->
status
))
{
IWL_DEBUG_TE
(
mvm
,
"ERROR: Aux ROC Time Event %s notification failure
\n
"
,
(
le32_to_cpu
(
notif
->
action
)
&
TE_V2_NOTIF_HOST_EVENT_START
)
?
"start"
:
"end"
);
return
-
EINVAL
;
}
IWL_DEBUG_TE
(
mvm
,
"Aux ROC time event notification - UID = 0x%x action %d
\n
"
,
le32_to_cpu
(
notif
->
unique_id
),
le32_to_cpu
(
notif
->
action
));
if
(
le32_to_cpu
(
notif
->
action
)
==
TE_V2_NOTIF_HOST_EVENT_END
)
{
/* End TE, notify mac80211 */
ieee80211_remain_on_channel_expired
(
mvm
->
hw
);
iwl_mvm_roc_finished
(
mvm
);
/* flush aux queue */
list_del
(
&
te_data
->
list
);
/* remove from list */
te_data
->
running
=
false
;
te_data
->
vif
=
NULL
;
te_data
->
uid
=
0
;
}
else
if
(
le32_to_cpu
(
notif
->
action
)
==
TE_V2_NOTIF_HOST_EVENT_START
)
{
set_bit
(
IWL_MVM_STATUS_ROC_RUNNING
,
&
mvm
->
status
);
set_bit
(
IWL_MVM_STATUS_ROC_AUX_RUNNING
,
&
mvm
->
status
);
te_data
->
running
=
true
;
ieee80211_ready_on_channel
(
mvm
->
hw
);
/* Start TE */
}
else
{
IWL_DEBUG_TE
(
mvm
,
"ERROR: Unknown Aux ROC Time Event (action = %d)
\n
"
,
le32_to_cpu
(
notif
->
action
));
return
-
EINVAL
;
}
return
0
;
}
/*
* The Rx handler for time event notifications
*/
...
...
@@ -278,10 +334,15 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
le32_to_cpu
(
notif
->
action
));
spin_lock_bh
(
&
mvm
->
time_event_lock
);
/* This time event is triggered for Aux ROC request */
if
(
!
iwl_mvm_aux_roc_te_handle_notif
(
mvm
,
notif
))
goto
unlock
;
list_for_each_entry_safe
(
te_data
,
tmp
,
&
mvm
->
time_event_list
,
list
)
{
if
(
le32_to_cpu
(
notif
->
unique_id
)
==
te_data
->
uid
)
iwl_mvm_te_handle_notif
(
mvm
,
te_data
,
notif
);
}
unlock:
spin_unlock_bh
(
&
mvm
->
time_event_lock
);
return
0
;
...
...
drivers/net/wireless/iwlwifi/mvm/tt.c
浏览文件 @
d878b3af
...
...
@@ -140,9 +140,9 @@ static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm)
/* TODO: move parsing to NVM code */
calib
=
mvm
->
nvm_sections
[
NVM_SECTION_TYPE_CALIBRATION
].
data
;
ptat
=
calib
[
OTP_DTS_DIODE_DEVIATION
];
pa1
=
calib
[
OTP_DTS_DIODE_DEVIATION
+
1
];
pa2
=
calib
[
OTP_DTS_DIODE_DEVIATION
+
2
];
ptat
=
calib
[
OTP_DTS_DIODE_DEVIATION
*
2
];
pa1
=
calib
[
OTP_DTS_DIODE_DEVIATION
*
2
+
1
];
pa2
=
calib
[
OTP_DTS_DIODE_DEVIATION
*
2
+
2
];
/* get the median: */
if
(
ptat
>
pa1
)
{
...
...
@@ -338,10 +338,16 @@ static void check_exit_ctkill(struct work_struct *work)
duration
=
tt
->
params
->
ct_kill_duration
;
/* make sure the device is available for direct read/writes */
if
(
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_CHECK_CTKILL
))
goto
reschedule
;
iwl_trans_start_hw
(
mvm
->
trans
);
temp
=
check_nic_temperature
(
mvm
);
iwl_trans_stop_device
(
mvm
->
trans
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_CHECK_CTKILL
);
if
(
temp
<
MIN_TEMPERATURE
||
temp
>
MAX_TEMPERATURE
)
{
IWL_DEBUG_TEMP
(
mvm
,
"Failed to measure NIC temperature
\n
"
);
goto
reschedule
;
...
...
drivers/net/wireless/iwlwifi/mvm/tx.c
浏览文件 @
d878b3af
...
...
@@ -310,6 +310,16 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
info
->
hw_queue
!=
info
->
control
.
vif
->
cab_queue
)))
return
-
1
;
/*
* IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
* in 2 different types of vifs, P2P & STATION. P2P uses the offchannel
* queue. STATION (HS2.0) uses the auxiliary context of the FW,
* and hence needs to be sent on the aux queue
*/
if
(
IEEE80211_SKB_CB
(
skb
)
->
hw_queue
==
IWL_MVM_OFFCHANNEL_QUEUE
&&
info
->
control
.
vif
->
type
==
NL80211_IFTYPE_STATION
)
IEEE80211_SKB_CB
(
skb
)
->
hw_queue
=
mvm
->
aux_queue
;
/*
* If the interface on which frame is sent is the P2P_DEVICE
* or an AP/GO interface use the broadcast station associated
...
...
drivers/net/wireless/iwlwifi/pcie/trans.c
浏览文件 @
d878b3af
...
...
@@ -67,6 +67,7 @@
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/gfp.h>
#include <linux/vmalloc.h>
#include "iwl-drv.h"
#include "iwl-trans.h"
...
...
@@ -1773,28 +1774,207 @@ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
return
cmdlen
;
}
static
u32
iwl_trans_pcie_dump_data
(
struct
iwl_trans
*
trans
,
void
*
buf
,
u32
buflen
)
static
const
struct
{
u32
start
,
end
;
}
iwl_prph_dump_addr
[]
=
{
{
.
start
=
0x00a00000
,
.
end
=
0x00a00000
},
{
.
start
=
0x00a0000c
,
.
end
=
0x00a00024
},
{
.
start
=
0x00a0002c
,
.
end
=
0x00a0003c
},
{
.
start
=
0x00a00410
,
.
end
=
0x00a00418
},
{
.
start
=
0x00a00420
,
.
end
=
0x00a00420
},
{
.
start
=
0x00a00428
,
.
end
=
0x00a00428
},
{
.
start
=
0x00a00430
,
.
end
=
0x00a0043c
},
{
.
start
=
0x00a00444
,
.
end
=
0x00a00444
},
{
.
start
=
0x00a004c0
,
.
end
=
0x00a004cc
},
{
.
start
=
0x00a004d8
,
.
end
=
0x00a004d8
},
{
.
start
=
0x00a004e0
,
.
end
=
0x00a004f0
},
{
.
start
=
0x00a00840
,
.
end
=
0x00a00840
},
{
.
start
=
0x00a00850
,
.
end
=
0x00a00858
},
{
.
start
=
0x00a01004
,
.
end
=
0x00a01008
},
{
.
start
=
0x00a01010
,
.
end
=
0x00a01010
},
{
.
start
=
0x00a01018
,
.
end
=
0x00a01018
},
{
.
start
=
0x00a01024
,
.
end
=
0x00a01024
},
{
.
start
=
0x00a0102c
,
.
end
=
0x00a01034
},
{
.
start
=
0x00a0103c
,
.
end
=
0x00a01040
},
{
.
start
=
0x00a01048
,
.
end
=
0x00a01094
},
{
.
start
=
0x00a01c00
,
.
end
=
0x00a01c20
},
{
.
start
=
0x00a01c58
,
.
end
=
0x00a01c58
},
{
.
start
=
0x00a01c7c
,
.
end
=
0x00a01c7c
},
{
.
start
=
0x00a01c28
,
.
end
=
0x00a01c54
},
{
.
start
=
0x00a01c5c
,
.
end
=
0x00a01c5c
},
{
.
start
=
0x00a01c84
,
.
end
=
0x00a01c84
},
{
.
start
=
0x00a01ce0
,
.
end
=
0x00a01d0c
},
{
.
start
=
0x00a01d18
,
.
end
=
0x00a01d20
},
{
.
start
=
0x00a01d2c
,
.
end
=
0x00a01d30
},
{
.
start
=
0x00a01d40
,
.
end
=
0x00a01d5c
},
{
.
start
=
0x00a01d80
,
.
end
=
0x00a01d80
},
{
.
start
=
0x00a01d98
,
.
end
=
0x00a01d98
},
{
.
start
=
0x00a01dc0
,
.
end
=
0x00a01dfc
},
{
.
start
=
0x00a01e00
,
.
end
=
0x00a01e2c
},
{
.
start
=
0x00a01e40
,
.
end
=
0x00a01e60
},
{
.
start
=
0x00a01e84
,
.
end
=
0x00a01e90
},
{
.
start
=
0x00a01e9c
,
.
end
=
0x00a01ec4
},
{
.
start
=
0x00a01ed0
,
.
end
=
0x00a01ed0
},
{
.
start
=
0x00a01f00
,
.
end
=
0x00a01f14
},
{
.
start
=
0x00a01f44
,
.
end
=
0x00a01f58
},
{
.
start
=
0x00a01f80
,
.
end
=
0x00a01fa8
},
{
.
start
=
0x00a01fb0
,
.
end
=
0x00a01fbc
},
{
.
start
=
0x00a01ff8
,
.
end
=
0x00a01ffc
},
{
.
start
=
0x00a02000
,
.
end
=
0x00a02048
},
{
.
start
=
0x00a02068
,
.
end
=
0x00a020f0
},
{
.
start
=
0x00a02100
,
.
end
=
0x00a02118
},
{
.
start
=
0x00a02140
,
.
end
=
0x00a0214c
},
{
.
start
=
0x00a02168
,
.
end
=
0x00a0218c
},
{
.
start
=
0x00a021c0
,
.
end
=
0x00a021c0
},
{
.
start
=
0x00a02400
,
.
end
=
0x00a02410
},
{
.
start
=
0x00a02418
,
.
end
=
0x00a02420
},
{
.
start
=
0x00a02428
,
.
end
=
0x00a0242c
},
{
.
start
=
0x00a02434
,
.
end
=
0x00a02434
},
{
.
start
=
0x00a02440
,
.
end
=
0x00a02460
},
{
.
start
=
0x00a02468
,
.
end
=
0x00a024b0
},
{
.
start
=
0x00a024c8
,
.
end
=
0x00a024cc
},
{
.
start
=
0x00a02500
,
.
end
=
0x00a02504
},
{
.
start
=
0x00a0250c
,
.
end
=
0x00a02510
},
{
.
start
=
0x00a02540
,
.
end
=
0x00a02554
},
{
.
start
=
0x00a02580
,
.
end
=
0x00a025f4
},
{
.
start
=
0x00a02600
,
.
end
=
0x00a0260c
},
{
.
start
=
0x00a02648
,
.
end
=
0x00a02650
},
{
.
start
=
0x00a02680
,
.
end
=
0x00a02680
},
{
.
start
=
0x00a026c0
,
.
end
=
0x00a026d0
},
{
.
start
=
0x00a02700
,
.
end
=
0x00a0270c
},
{
.
start
=
0x00a02804
,
.
end
=
0x00a02804
},
{
.
start
=
0x00a02818
,
.
end
=
0x00a0281c
},
{
.
start
=
0x00a02c00
,
.
end
=
0x00a02db4
},
{
.
start
=
0x00a02df4
,
.
end
=
0x00a02fb0
},
{
.
start
=
0x00a03000
,
.
end
=
0x00a03014
},
{
.
start
=
0x00a0301c
,
.
end
=
0x00a0302c
},
{
.
start
=
0x00a03034
,
.
end
=
0x00a03038
},
{
.
start
=
0x00a03040
,
.
end
=
0x00a03048
},
{
.
start
=
0x00a03060
,
.
end
=
0x00a03068
},
{
.
start
=
0x00a03070
,
.
end
=
0x00a03074
},
{
.
start
=
0x00a0307c
,
.
end
=
0x00a0307c
},
{
.
start
=
0x00a03080
,
.
end
=
0x00a03084
},
{
.
start
=
0x00a0308c
,
.
end
=
0x00a03090
},
{
.
start
=
0x00a03098
,
.
end
=
0x00a03098
},
{
.
start
=
0x00a030a0
,
.
end
=
0x00a030a0
},
{
.
start
=
0x00a030a8
,
.
end
=
0x00a030b4
},
{
.
start
=
0x00a030bc
,
.
end
=
0x00a030bc
},
{
.
start
=
0x00a030c0
,
.
end
=
0x00a0312c
},
{
.
start
=
0x00a03c00
,
.
end
=
0x00a03c5c
},
{
.
start
=
0x00a04400
,
.
end
=
0x00a04454
},
{
.
start
=
0x00a04460
,
.
end
=
0x00a04474
},
{
.
start
=
0x00a044c0
,
.
end
=
0x00a044ec
},
{
.
start
=
0x00a04500
,
.
end
=
0x00a04504
},
{
.
start
=
0x00a04510
,
.
end
=
0x00a04538
},
{
.
start
=
0x00a04540
,
.
end
=
0x00a04548
},
{
.
start
=
0x00a04560
,
.
end
=
0x00a0457c
},
{
.
start
=
0x00a04590
,
.
end
=
0x00a04598
},
{
.
start
=
0x00a045c0
,
.
end
=
0x00a045f4
},
};
static
u32
iwl_trans_pcie_dump_prph
(
struct
iwl_trans
*
trans
,
struct
iwl_fw_error_dump_data
**
data
)
{
struct
iwl_fw_error_dump_prph
*
prph
;
unsigned
long
flags
;
u32
prph_len
=
0
,
i
;
if
(
!
iwl_trans_grab_nic_access
(
trans
,
false
,
&
flags
))
return
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
iwl_prph_dump_addr
);
i
++
)
{
/* The range includes both boundaries */
int
num_bytes_in_chunk
=
iwl_prph_dump_addr
[
i
].
end
-
iwl_prph_dump_addr
[
i
].
start
+
4
;
int
reg
;
__le32
*
val
;
prph_len
+=
sizeof
(
*
data
)
+
sizeof
(
*
prph
)
+
num_bytes_in_chunk
;
(
*
data
)
->
type
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_PRPH
);
(
*
data
)
->
len
=
cpu_to_le32
(
sizeof
(
*
prph
)
+
num_bytes_in_chunk
);
prph
=
(
void
*
)(
*
data
)
->
data
;
prph
->
prph_start
=
cpu_to_le32
(
iwl_prph_dump_addr
[
i
].
start
);
val
=
(
void
*
)
prph
->
data
;
for
(
reg
=
iwl_prph_dump_addr
[
i
].
start
;
reg
<=
iwl_prph_dump_addr
[
i
].
end
;
reg
+=
4
)
*
val
++
=
cpu_to_le32
(
iwl_trans_pcie_read_prph
(
trans
,
reg
));
*
data
=
iwl_fw_error_next_data
(
*
data
);
}
iwl_trans_release_nic_access
(
trans
,
&
flags
);
return
prph_len
;
}
#define IWL_CSR_TO_DUMP (0x250)
static
u32
iwl_trans_pcie_dump_csr
(
struct
iwl_trans
*
trans
,
struct
iwl_fw_error_dump_data
**
data
)
{
u32
csr_len
=
sizeof
(
**
data
)
+
IWL_CSR_TO_DUMP
;
__le32
*
val
;
int
i
;
(
*
data
)
->
type
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_CSR
);
(
*
data
)
->
len
=
cpu_to_le32
(
IWL_CSR_TO_DUMP
);
val
=
(
void
*
)(
*
data
)
->
data
;
for
(
i
=
0
;
i
<
IWL_CSR_TO_DUMP
;
i
+=
4
)
*
val
++
=
cpu_to_le32
(
iwl_trans_pcie_read32
(
trans
,
i
));
*
data
=
iwl_fw_error_next_data
(
*
data
);
return
csr_len
;
}
static
struct
iwl_trans_dump_data
*
iwl_trans_pcie_dump_data
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
struct
iwl_fw_error_dump_data
*
data
;
struct
iwl_txq
*
cmdq
=
&
trans_pcie
->
txq
[
trans_pcie
->
cmd_queue
];
struct
iwl_fw_error_dump_txcmd
*
txcmd
;
struct
iwl_trans_dump_data
*
dump_data
;
u32
len
;
int
i
,
ptr
;
len
=
sizeof
(
*
data
)
+
/* transport dump header */
len
=
sizeof
(
*
dump_data
);
/* host commands */
len
+=
sizeof
(
*
data
)
+
cmdq
->
q
.
n_window
*
(
sizeof
(
*
txcmd
)
+
TFD_MAX_PAYLOAD_SIZE
);
/* CSR registers */
len
+=
sizeof
(
*
data
)
+
IWL_CSR_TO_DUMP
;
/* PRPH registers */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
iwl_prph_dump_addr
);
i
++
)
{
/* The range includes both boundaries */
int
num_bytes_in_chunk
=
iwl_prph_dump_addr
[
i
].
end
-
iwl_prph_dump_addr
[
i
].
start
+
4
;
len
+=
sizeof
(
*
data
)
+
sizeof
(
struct
iwl_fw_error_dump_prph
)
+
num_bytes_in_chunk
;
}
/* FW monitor */
if
(
trans_pcie
->
fw_mon_page
)
len
+=
sizeof
(
*
data
)
+
sizeof
(
struct
iwl_fw_error_dump_fw_mon
)
+
trans_pcie
->
fw_mon_size
;
if
(
!
buf
)
return
len
;
dump_data
=
vzalloc
(
len
);
if
(
!
dump_data
)
return
NULL
;
len
=
0
;
data
=
buf
;
data
=
(
void
*
)
dump_data
->
data
;
data
->
type
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_TXCMD
);
txcmd
=
(
void
*
)
data
->
data
;
spin_lock_bh
(
&
cmdq
->
lock
);
...
...
@@ -1820,11 +2000,15 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
data
->
len
=
cpu_to_le32
(
len
);
len
+=
sizeof
(
*
data
);
data
=
iwl_fw_error_next_data
(
data
);
len
+=
iwl_trans_pcie_dump_prph
(
trans
,
&
data
);
len
+=
iwl_trans_pcie_dump_csr
(
trans
,
&
data
);
/* data is already pointing to the next section */
if
(
trans_pcie
->
fw_mon_page
)
{
struct
iwl_fw_error_dump_fw_mon
*
fw_mon_data
;
data
=
iwl_fw_error_next_data
(
data
);
data
->
type
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_FW_MONITOR
);
data
->
len
=
cpu_to_le32
(
trans_pcie
->
fw_mon_size
+
sizeof
(
*
fw_mon_data
));
...
...
@@ -1852,7 +2036,9 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
trans_pcie
->
fw_mon_size
;
}
return
len
;
dump_data
->
len
=
len
;
return
dump_data
;
}
#else
static
int
iwl_trans_pcie_dbgfs_register
(
struct
iwl_trans
*
trans
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录