Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
d72c7282
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d72c7282
编写于
4月 10, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
上级
655d8e23
2d055afd
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
678 addition
and
219 deletion
+678
-219
drivers/net/wireless/iwlwifi/dvm/agn.h
drivers/net/wireless/iwlwifi/dvm/agn.h
+5
-1
drivers/net/wireless/iwlwifi/dvm/lib.c
drivers/net/wireless/iwlwifi/dvm/lib.c
+13
-3
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
+5
-2
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/dvm/tx.c
+45
-0
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-drv.c
+10
-4
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/iwl-trans.h
+1
-2
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+287
-46
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/d3.c
+8
-1
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/debugfs.c
+119
-0
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+22
-42
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
+26
-7
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
+25
-6
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/mvm.h
+23
-4
drivers/net/wireless/iwlwifi/mvm/power.c
drivers/net/wireless/iwlwifi/mvm/power.c
+48
-67
drivers/net/wireless/iwlwifi/mvm/rs.c
drivers/net/wireless/iwlwifi/mvm/rs.c
+18
-18
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.c
+4
-4
drivers/net/wireless/iwlwifi/mvm/sta.h
drivers/net/wireless/iwlwifi/mvm/sta.h
+2
-0
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
+6
-4
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/tx.c
+8
-6
drivers/net/wireless/iwlwifi/mvm/utils.c
drivers/net/wireless/iwlwifi/mvm/utils.c
+1
-1
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/drv.c
+1
-0
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/iwlwifi/pcie/tx.c
+1
-1
未找到文件。
drivers/net/wireless/iwlwifi/dvm/agn.h
浏览文件 @
d72c7282
...
...
@@ -73,6 +73,8 @@
/* AUX (TX during scan dwell) queue */
#define IWL_AUX_QUEUE 10
#define IWL_INVALID_STATION 255
/* device operations */
extern
struct
iwl_lib_ops
iwl1000_lib
;
extern
struct
iwl_lib_ops
iwl2000_lib
;
...
...
@@ -176,7 +178,7 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);
/* lib */
int
iwlagn_send_tx_power
(
struct
iwl_priv
*
priv
);
void
iwlagn_temperature
(
struct
iwl_priv
*
priv
);
int
iwlagn_txfifo_flush
(
struct
iwl_priv
*
priv
);
int
iwlagn_txfifo_flush
(
struct
iwl_priv
*
priv
,
u32
scd_q_msk
);
void
iwlagn_dev_txfifo_flush
(
struct
iwl_priv
*
priv
);
int
iwlagn_send_beacon_cmd
(
struct
iwl_priv
*
priv
);
int
iwl_send_statistics_request
(
struct
iwl_priv
*
priv
,
...
...
@@ -210,6 +212,8 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct
ieee80211_sta
*
sta
,
u16
tid
,
u8
buf_size
);
int
iwlagn_tx_agg_stop
(
struct
iwl_priv
*
priv
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
u16
tid
);
int
iwlagn_tx_agg_flush
(
struct
iwl_priv
*
priv
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
u16
tid
);
int
iwlagn_rx_reply_compressed_ba
(
struct
iwl_priv
*
priv
,
struct
iwl_rx_cmd_buffer
*
rxb
,
struct
iwl_device_cmd
*
cmd
);
...
...
drivers/net/wireless/iwlwifi/dvm/lib.c
浏览文件 @
d72c7282
...
...
@@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
* 1. acquire mutex before calling
* 2. make sure rf is on and not in exit state
*/
int
iwlagn_txfifo_flush
(
struct
iwl_priv
*
priv
)
int
iwlagn_txfifo_flush
(
struct
iwl_priv
*
priv
,
u32
scd_q_msk
)
{
struct
iwl_txfifo_flush_cmd
flush_cmd
;
struct
iwl_host_cmd
cmd
=
{
...
...
@@ -162,6 +162,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv)
if
(
priv
->
nvm_data
->
sku_cap_11n_enable
)
flush_cmd
.
queue_control
|=
IWL_AGG_TX_QUEUE_MSK
;
if
(
scd_q_msk
)
flush_cmd
.
queue_control
=
cpu_to_le32
(
scd_q_msk
);
IWL_DEBUG_INFO
(
priv
,
"queue control: 0x%x
\n
"
,
flush_cmd
.
queue_control
);
flush_cmd
.
flush_control
=
cpu_to_le16
(
IWL_DROP_ALL
);
...
...
@@ -173,7 +176,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
{
mutex_lock
(
&
priv
->
mutex
);
ieee80211_stop_queues
(
priv
->
hw
);
if
(
iwlagn_txfifo_flush
(
priv
))
{
if
(
iwlagn_txfifo_flush
(
priv
,
0
))
{
IWL_ERR
(
priv
,
"flush request fail
\n
"
);
goto
done
;
}
...
...
@@ -1084,7 +1087,14 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
IWL_RXON_CTX_BSS
];
struct
iwlagn_wowlan_kek_kck_material_cmd
kek_kck_cmd
;
struct
iwlagn_wowlan_tkip_params_cmd
tkip_cmd
=
{};
struct
iwlagn_d3_config_cmd
d3_cfg_cmd
=
{};
struct
iwlagn_d3_config_cmd
d3_cfg_cmd
=
{
/*
* Program the minimum sleep time to 10 seconds, as many
* platforms have issues processing a wakeup signal while
* still being in the process of suspending.
*/
.
min_sleep_time
=
cpu_to_le32
(
10
*
1000
*
1000
),
};
struct
wowlan_key_data
key_data
=
{
.
ctx
=
ctx
,
.
bssid
=
ctx
->
active
.
bssid_addr
,
...
...
drivers/net/wireless/iwlwifi/dvm/mac80211.c
浏览文件 @
d72c7282
...
...
@@ -777,9 +777,12 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT
(
priv
,
"start Tx
\n
"
);
ret
=
iwlagn_tx_agg_start
(
priv
,
vif
,
sta
,
tid
,
ssn
);
break
;
case
IEEE80211_AMPDU_TX_STOP_CONT
:
case
IEEE80211_AMPDU_TX_STOP_FLUSH
:
case
IEEE80211_AMPDU_TX_STOP_FLUSH_CONT
:
IWL_DEBUG_HT
(
priv
,
"Flush Tx
\n
"
);
ret
=
iwlagn_tx_agg_flush
(
priv
,
vif
,
sta
,
tid
);
break
;
case
IEEE80211_AMPDU_TX_STOP_CONT
:
IWL_DEBUG_HT
(
priv
,
"stop Tx
\n
"
);
ret
=
iwlagn_tx_agg_stop
(
priv
,
vif
,
sta
,
tid
);
if
((
ret
==
0
)
&&
(
priv
->
agg_tids_count
>
0
))
{
...
...
@@ -1122,7 +1125,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
*/
if
(
drop
)
{
IWL_DEBUG_MAC80211
(
priv
,
"send flush command
\n
"
);
if
(
iwlagn_txfifo_flush
(
priv
))
{
if
(
iwlagn_txfifo_flush
(
priv
,
0
))
{
IWL_ERR
(
priv
,
"flush request fail
\n
"
);
goto
done
;
}
...
...
drivers/net/wireless/iwlwifi/dvm/tx.c
浏览文件 @
d72c7282
...
...
@@ -674,6 +674,51 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
return
ret
;
}
int
iwlagn_tx_agg_flush
(
struct
iwl_priv
*
priv
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
u16
tid
)
{
struct
iwl_tid_data
*
tid_data
;
enum
iwl_agg_state
agg_state
;
int
sta_id
,
txq_id
;
sta_id
=
iwl_sta_id
(
sta
);
/*
* First set the agg state to OFF to avoid calling
* ieee80211_stop_tx_ba_cb in iwlagn_check_ratid_empty.
*/
spin_lock_bh
(
&
priv
->
sta_lock
);
tid_data
=
&
priv
->
tid_data
[
sta_id
][
tid
];
txq_id
=
tid_data
->
agg
.
txq_id
;
agg_state
=
tid_data
->
agg
.
state
;
IWL_DEBUG_TX_QUEUES
(
priv
,
"Flush AGG: sta %d tid %d q %d state %d
\n
"
,
sta_id
,
tid
,
txq_id
,
tid_data
->
agg
.
state
);
tid_data
->
agg
.
state
=
IWL_AGG_OFF
;
spin_unlock_bh
(
&
priv
->
sta_lock
);
if
(
iwlagn_txfifo_flush
(
priv
,
BIT
(
txq_id
)))
IWL_ERR
(
priv
,
"Couldn't flush the AGG queue
\n
"
);
if
(
test_bit
(
txq_id
,
priv
->
agg_q_alloc
))
{
/*
* If the transport didn't know that we wanted to start
* agreggation, don't tell it that we want to stop them.
* This can happen when we don't get the addBA response on
* time, or we hadn't time to drain the AC queues.
*/
if
(
agg_state
==
IWL_AGG_ON
)
iwl_trans_txq_disable
(
priv
->
trans
,
txq_id
);
else
IWL_DEBUG_TX_QUEUES
(
priv
,
"Don't disable tx agg: %d
\n
"
,
agg_state
);
iwlagn_dealloc_agg_txq
(
priv
,
txq_id
);
}
return
0
;
}
int
iwlagn_tx_agg_oper
(
struct
iwl_priv
*
priv
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
u16
tid
,
u8
buf_size
)
{
...
...
drivers/net/wireless/iwlwifi/iwl-drv.c
浏览文件 @
d72c7282
...
...
@@ -912,8 +912,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
}
}
IWL_INFO
(
drv
,
"loaded firmware version %s"
,
drv
->
fw
.
fw_version
);
/*
* In mvm uCode there is no difference between data and instructions
* sections.
...
...
@@ -970,6 +968,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
else
op
=
&
iwlwifi_opmode_table
[
DVM_OP_MODE
];
IWL_INFO
(
drv
,
"loaded firmware version %s op_mode %s
\n
"
,
drv
->
fw
.
fw_version
,
op
->
name
);
/* add this device to the list of devices using this op_mode */
list_add_tail
(
&
drv
->
list
,
&
op
->
drv
);
...
...
@@ -997,8 +998,13 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
* else from proceeding if the module fails to load
* or hangs loading.
*/
if
(
load_module
)
request_module
(
"%s"
,
op
->
name
);
if
(
load_module
)
{
err
=
request_module
(
"%s"
,
op
->
name
);
if
(
err
)
IWL_ERR
(
drv
,
"failed to load module %s (error %d), is dynamic loading enabled?
\n
"
,
op
->
name
,
err
);
}
return
;
try_again:
...
...
drivers/net/wireless/iwlwifi/iwl-trans.h
浏览文件 @
d72c7282
...
...
@@ -305,7 +305,6 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
* currently supports
*/
#define IWL_MAX_HW_QUEUES 32
#define IWL_INVALID_STATION 255
#define IWL_MAX_TID_COUNT 8
#define IWL_FRAME_LIMIT 64
...
...
@@ -682,7 +681,7 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
static
inline
void
iwl_trans_ac_txq_enable
(
struct
iwl_trans
*
trans
,
int
queue
,
int
fifo
)
{
iwl_trans_txq_enable
(
trans
,
queue
,
fifo
,
IWL_INVALID_STATION
,
iwl_trans_txq_enable
(
trans
,
queue
,
fifo
,
-
1
,
IWL_MAX_TID_COUNT
,
IWL_FRAME_LIMIT
,
0
);
}
...
...
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
浏览文件 @
d72c7282
...
...
@@ -61,6 +61,8 @@
*
*****************************************************************************/
#include <net/mac80211.h>
#include "fw-api-bt-coex.h"
#include "iwl-modparams.h"
#include "mvm.h"
...
...
@@ -96,6 +98,20 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
#undef EVENT_PRIO_ANT
/* BT Antenna Coupling Threshold (dB) */
#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
#define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3)
#define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62)
#define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65)
#define BT_REDUCED_TX_POWER_BIT BIT(7)
static
inline
bool
is_loose_coex
(
void
)
{
return
iwlwifi_mod_params
.
ant_coupling
>
IWL_BT_ANTENNA_COUPLING_THRESHOLD
;
}
int
iwl_send_bt_prio_tbl
(
struct
iwl_mvm
*
mvm
)
{
return
iwl_mvm_send_cmd_pdu
(
mvm
,
BT_COEX_PRIO_TABLE
,
CMD_SYNC
,
...
...
@@ -186,11 +202,6 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = {
cpu_to_le32
(
0x00000000
),
};
/* BT Antenna Coupling Threshold (dB) */
#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
#define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3)
int
iwl_send_bt_init_conf
(
struct
iwl_mvm
*
mvm
)
{
struct
iwl_bt_coex_cmd
cmd
=
{
...
...
@@ -203,8 +214,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
cmd
.
flags
=
iwlwifi_mod_params
.
bt_coex_active
?
BT_COEX_NW
:
BT_COEX_DISABLE
;
cmd
.
flags
|=
iwlwifi_mod_params
.
bt_ch_announce
?
BT_CH_PRIMARY_EN
:
0
;
cmd
.
flags
|=
BT_SYNC_2_BT_DISABLE
;
cmd
.
flags
|=
BT_CH_PRIMARY_EN
|
BT_SYNC_2_BT_DISABLE
;
cmd
.
valid_bit_msk
=
cpu_to_le16
(
BT_VALID_ENABLE
|
BT_VALID_BT_PRIO_BOOST
|
...
...
@@ -215,7 +225,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
BT_VALID_REDUCED_TX_POWER
|
BT_VALID_LUT
);
if
(
i
wlwifi_mod_params
.
ant_coupling
>
IWL_BT_ANTENNA_COUPLING_THRESHOLD
)
if
(
i
s_loose_coex
()
)
memcpy
(
&
cmd
.
decision_lut
,
iwl_loose_lookup
,
sizeof
(
iwl_tight_lookup
));
else
...
...
@@ -228,6 +238,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
cmd
.
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_cts_kill_msk
[
BT_KILL_MSK_DEFAULT
]);
memset
(
&
mvm
->
last_bt_notif
,
0
,
sizeof
(
mvm
->
last_bt_notif
));
/* go to CALIB state in internal BT-Coex state machine */
ret
=
iwl_send_bt_env
(
mvm
,
BT_COEX_ENV_OPEN
,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2
);
...
...
@@ -243,19 +255,101 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
sizeof
(
cmd
),
&
cmd
);
}
struct
iwl_bt_notif_iterator_data
{
struct
iwl_mvm
*
mvm
;
static
int
iwl_mvm_bt_udpate_ctrl_kill_msk
(
struct
iwl_mvm
*
mvm
,
bool
reduced_tx_power
)
{
enum
iwl_bt_kill_msk
bt_kill_msk
;
struct
iwl_bt_coex_cmd
cmd
=
{};
struct
iwl_bt_coex_profile_notif
*
notif
=
&
mvm
->
last_bt_notif
;
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"
);
/* Don't send HCMD if there is no update */
if
(
bt_kill_msk
==
mvm
->
bt_kill_msk
)
return
0
;
mvm
->
bt_kill_msk
=
bt_kill_msk
;
cmd
.
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_ack_kill_msk
[
bt_kill_msk
]);
cmd
.
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_cts_kill_msk
[
bt_kill_msk
]);
cmd
.
valid_bit_msk
=
cpu_to_le16
(
BT_VALID_KILL_ACK
|
BT_VALID_KILL_CTS
);
IWL_DEBUG_COEX
(
mvm
,
"bt_kill_msk = %d
\n
"
,
bt_kill_msk
);
return
iwl_mvm_send_cmd_pdu
(
mvm
,
BT_CONFIG
,
CMD_SYNC
,
sizeof
(
cmd
),
&
cmd
);
}
static
int
iwl_mvm_bt_coex_reduced_txp
(
struct
iwl_mvm
*
mvm
,
u8
sta_id
,
bool
enable
)
{
struct
iwl_bt_coex_cmd
cmd
=
{
.
valid_bit_msk
=
cpu_to_le16
(
BT_VALID_REDUCED_TX_POWER
),
.
bt_reduced_tx_power
=
sta_id
,
};
struct
ieee80211_sta
*
sta
;
struct
iwl_mvm_sta
*
mvmsta
;
/* This can happen if the station has been removed right now */
if
(
sta_id
==
IWL_MVM_STATION_COUNT
)
return
0
;
sta
=
rcu_dereference_protected
(
mvm
->
fw_id_to_mac_id
[
sta_id
],
lockdep_is_held
(
&
mvm
->
mutex
));
mvmsta
=
(
void
*
)
sta
->
drv_priv
;
/* nothing to do */
if
(
mvmsta
->
bt_reduced_txpower
==
enable
)
return
0
;
if
(
enable
)
cmd
.
bt_reduced_tx_power
|=
BT_REDUCED_TX_POWER_BIT
;
IWL_DEBUG_COEX
(
mvm
,
"%sable reduced Tx Power for sta %d
\n
"
,
enable
?
"en"
:
"dis"
,
sta_id
);
mvmsta
->
bt_reduced_txpower
=
enable
;
/* Send ASYNC since this can be sent from an atomic context */
return
iwl_mvm_send_cmd_pdu
(
mvm
,
BT_CONFIG
,
CMD_ASYNC
,
sizeof
(
cmd
),
&
cmd
);
}
struct
iwl_bt_iterator_data
{
struct
iwl_bt_coex_profile_notif
*
notif
;
struct
iwl_mvm
*
mvm
;
u32
num_bss_ifaces
;
bool
reduced_tx_power
;
};
static
void
iwl_mvm_bt_notif_iterator
(
void
*
_data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_bt_notif_iterator_data
*
data
=
_data
;
struct
iwl_bt_iterator_data
*
data
=
_data
;
struct
iwl_mvm
*
mvm
=
data
->
mvm
;
struct
ieee80211_chanctx_conf
*
chanctx_conf
;
enum
ieee80211_smps_mode
smps_mode
;
enum
ieee80211_band
band
;
int
ave_rssi
;
if
(
vif
->
type
!=
NL80211_IFTYPE_STATION
)
return
;
...
...
@@ -268,11 +362,13 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
band
=
-
1
;
rcu_read_unlock
();
if
(
band
!=
IEEE80211_BAND_2GHZ
)
return
;
smps_mode
=
IEEE80211_SMPS_AUTOMATIC
;
if
(
band
!=
IEEE80211_BAND_2GHZ
)
{
ieee80211_request_smps
(
vif
,
smps_mode
);
return
;
}
if
(
data
->
notif
->
bt_status
)
smps_mode
=
IEEE80211_SMPS_DYNAMIC
;
...
...
@@ -285,20 +381,88 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
data
->
notif
->
bt_traffic_load
,
smps_mode
);
ieee80211_request_smps
(
vif
,
smps_mode
);
/* don't reduce the Tx power if in loose scheme */
if
(
is_loose_coex
())
return
;
data
->
num_bss_ifaces
++
;
/* reduced Txpower only if there are open BT connections, so ...*/
if
(
!
BT_MBOX_MSG
(
data
->
notif
,
3
,
OPEN_CON_2
))
{
/* ... cancel reduced Tx power ... */
if
(
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
))
IWL_ERR
(
mvm
,
"Couldn't send BT_CONFIG cmd
\n
"
);
data
->
reduced_tx_power
=
false
;
/* ... and there is no need to get reports on RSSI any more. */
ieee80211_disable_rssi_reports
(
vif
);
return
;
}
ave_rssi
=
ieee80211_ave_rssi
(
vif
);
/* if the RSSI isn't valid, fake it is very low */
if
(
!
ave_rssi
)
ave_rssi
=
-
100
;
if
(
ave_rssi
>
BT_ENABLE_REDUCED_TXPOWER_THRESHOLD
)
{
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
<
BT_DISABLE_REDUCED_TXPOWER_THRESHOLD
)
{
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 */
ieee80211_enable_rssi_reports
(
vif
,
BT_DISABLE_REDUCED_TXPOWER_THRESHOLD
,
BT_ENABLE_REDUCED_TXPOWER_THRESHOLD
);
}
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
,
};
ieee80211_iterate_active_interfaces_atomic
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_bt_notif_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
))
IWL_ERR
(
mvm
,
"Failed to update the ctrl_kill_msk
\n
"
);
}
/* upon association, the fw will send in BT Coex notification */
int
iwl_mvm_rx_bt_coex_notif
(
struct
iwl_mvm
*
mvm
,
struct
iwl_rx_cmd_buffer
*
rxb
,
struct
iwl_device_cmd
*
dev_cmd
)
{
struct
iwl_rx_packet
*
pkt
=
rxb_addr
(
rxb
);
struct
iwl_bt_coex_profile_notif
*
notif
=
(
void
*
)
pkt
->
data
;
struct
iwl_bt_notif_iterator_data
data
=
{
.
mvm
=
mvm
,
.
notif
=
notif
,
};
struct
iwl_bt_coex_cmd
cmd
=
{};
enum
iwl_bt_kill_msk
bt_kill_msk
;
IWL_DEBUG_COEX
(
mvm
,
"BT Coex Notification received
\n
"
);
IWL_DEBUG_COEX
(
mvm
,
"
\t
BT %salive
\n
"
,
notif
->
bt_status
?
""
:
"not "
);
...
...
@@ -311,38 +475,115 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
/* remember this notification for future use: rssi fluctuations */
memcpy
(
&
mvm
->
last_bt_notif
,
notif
,
sizeof
(
mvm
->
last_bt_notif
));
ieee80211_iterate_active_interfaces_atomic
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_bt_notif_iterator
,
&
data
);
iwl_mvm_bt_coex_notif_handle
(
mvm
);
/*
* This is an async handler for a notification, returning anything other
* than 0 doesn't make sense even if HCMD failed.
*/
return
0
;
}
static
void
iwl_mvm_bt_rssi_iterator
(
void
*
_data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_vif
*
mvmvif
=
(
void
*
)
vif
->
drv_priv
;
struct
iwl_bt_iterator_data
*
data
=
_data
;
struct
iwl_mvm
*
mvm
=
data
->
mvm
;
struct
ieee80211_sta
*
sta
;
struct
iwl_mvm_sta
*
mvmsta
;
if
(
vif
->
type
!=
NL80211_IFTYPE_STATION
||
mvmvif
->
ap_sta_id
==
IWL_MVM_STATION_COUNT
)
return
;
sta
=
rcu_dereference_protected
(
mvm
->
fw_id_to_mac_id
[
mvmvif
->
ap_sta_id
],
lockdep_is_held
(
&
mvm
->
mutex
));
mvmsta
=
(
void
*
)
sta
->
drv_priv
;
/*
* 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
,
enum
ieee80211_rssi_event
rssi_event
)
{
struct
iwl_mvm_vif
*
mvmvif
=
(
void
*
)
vif
->
drv_priv
;
struct
iwl_bt_iterator_data
data
=
{
.
mvm
=
mvm
,
.
reduced_tx_power
=
true
,
};
int
ret
;
mutex_lock
(
&
mvm
->
mutex
);
/* Rssi update while not associated ?! */
if
(
WARN_ON_ONCE
(
mvmvif
->
ap_sta_id
==
IWL_MVM_STATION_COUNT
))
goto
out_unlock
;
/* 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
;
/* No open connection - reports should be disabled */
if
(
!
BT_MBOX_MSG
(
&
mvm
->
last_bt_notif
,
3
,
OPEN_CON_2
))
goto
out_unlock
;
IWL_DEBUG_COEX
(
mvm
,
"RSSI for %pM is now %s
\n
"
,
vif
->
bss_conf
.
bssid
,
rssi_event
==
RSSI_EVENT_HIGH
?
"HIGH"
:
"LOW"
);
/*
* Check if rssi is good enough for reduced Tx power, but not in loose
* scheme.
*/
if
(
rssi_event
==
RSSI_EVENT_LOW
||
is_loose_coex
())
ret
=
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
);
else
bt_kill_msk
=
BT_KILL_MSK_DEFAULT
;
ret
=
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
true
)
;
/* Don't send HCMD if there is no update */
if
(
bt_kill_msk
==
mvm
->
bt_kill_msk
)
return
0
;
if
(
ret
)
IWL_ERR
(
mvm
,
"couldn't send BT_CONFIG HCMD upon RSSI event
\n
"
);
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"
);
ieee80211_iterate_active_interfaces_atomic
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_bt_rssi_iterator
,
&
data
);
mvm
->
bt_kill_msk
=
bt_kill_msk
;
cmd
.
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_ack_kill_msk
[
bt_kill_msk
]);
cmd
.
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_cts_kill_msk
[
bt_kill_msk
]);
/*
* 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
;
cmd
.
valid_bit_msk
=
cpu_to_le16
(
BT_VALID_KILL_ACK
|
BT_VALID_KILL_CTS
);
if
(
iwl_mvm_bt_udpate_ctrl_kill_msk
(
mvm
,
data
.
reduced_tx_power
))
IWL_ERR
(
mvm
,
"Failed to update the ctrl_kill_msk
\n
"
);
if
(
iwl_mvm_send_cmd_pdu
(
mvm
,
BT_CONFIG
,
CMD_SYNC
,
sizeof
(
cmd
),
&
cmd
))
IWL_ERR
(
mvm
,
"Failed to sent BT Coex CMD
\n
"
);
out_unlock:
mutex_unlock
(
&
mvm
->
mutex
);
}
/* This handler is ASYNC */
return
0
;
void
iwl_mvm_bt_coex_vif_assoc
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
struct
ieee80211_chanctx_conf
*
chanctx_conf
;
enum
ieee80211_band
band
;
rcu_read_lock
();
chanctx_conf
=
rcu_dereference
(
vif
->
chanctx_conf
);
if
(
chanctx_conf
&&
chanctx_conf
->
def
.
chan
)
band
=
chanctx_conf
->
def
.
chan
->
band
;
else
band
=
-
1
;
rcu_read_unlock
();
/* if we are in 2GHz we will get a notification from the fw */
if
(
band
==
IEEE80211_BAND_2GHZ
)
return
;
/* else, we can remove all the constraints */
memset
(
&
mvm
->
last_bt_notif
,
0
,
sizeof
(
mvm
->
last_bt_notif
));
iwl_mvm_bt_coex_notif_handle
(
mvm
);
}
drivers/net/wireless/iwlwifi/mvm/d3.c
浏览文件 @
d72c7282
...
...
@@ -769,7 +769,14 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
struct
iwl_wowlan_config_cmd
wowlan_config_cmd
=
{};
struct
iwl_wowlan_kek_kck_material_cmd
kek_kck_cmd
=
{};
struct
iwl_wowlan_tkip_params_cmd
tkip_cmd
=
{};
struct
iwl_d3_manager_config
d3_cfg_cmd
=
{};
struct
iwl_d3_manager_config
d3_cfg_cmd
=
{
/*
* Program the minimum sleep time to 10 seconds, as many
* platforms have issues processing a wakeup signal while
* still being in the process of suspending.
*/
.
min_sleep_time
=
cpu_to_le32
(
10
*
1000
*
1000
),
};
struct
wowlan_key_data
key_data
=
{
.
use_rsc_tsc
=
false
,
.
tkip
=
&
tkip_cmd
,
...
...
drivers/net/wireless/iwlwifi/mvm/debugfs.c
浏览文件 @
d72c7282
...
...
@@ -300,6 +300,67 @@ static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file,
return
count
;
}
static
ssize_t
iwl_dbgfs_mac_params_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ieee80211_vif
*
vif
=
file
->
private_data
;
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_mvm
*
mvm
=
mvmvif
->
dbgfs_data
;
u8
ap_sta_id
;
struct
ieee80211_chanctx_conf
*
chanctx_conf
;
char
buf
[
512
];
int
bufsz
=
sizeof
(
buf
);
int
pos
=
0
;
int
i
;
mutex_lock
(
&
mvm
->
mutex
);
ap_sta_id
=
mvmvif
->
ap_sta_id
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"mac id/color: %d / %d
\n
"
,
mvmvif
->
id
,
mvmvif
->
color
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bssid: %pM
\n
"
,
vif
->
bss_conf
.
bssid
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"QoS:
\n
"
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
mvmvif
->
queue_params
);
i
++
)
{
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d
\n
"
,
i
,
mvmvif
->
queue_params
[
i
].
txop
,
mvmvif
->
queue_params
[
i
].
cw_min
,
mvmvif
->
queue_params
[
i
].
cw_max
,
mvmvif
->
queue_params
[
i
].
aifs
,
mvmvif
->
queue_params
[
i
].
uapsd
);
}
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
&&
ap_sta_id
!=
IWL_MVM_STATION_COUNT
)
{
struct
ieee80211_sta
*
sta
;
struct
iwl_mvm_sta
*
mvm_sta
;
sta
=
rcu_dereference_protected
(
mvm
->
fw_id_to_mac_id
[
ap_sta_id
],
lockdep_is_held
(
&
mvm
->
mutex
));
mvm_sta
=
(
void
*
)
sta
->
drv_priv
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"ap_sta_id %d - reduced Tx power %d
\n
"
,
ap_sta_id
,
mvm_sta
->
bt_reduced_txpower
);
}
rcu_read_lock
();
chanctx_conf
=
rcu_dereference
(
vif
->
chanctx_conf
);
if
(
chanctx_conf
)
{
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"idle rx chains %d, active rx chains: %d
\n
"
,
chanctx_conf
->
rx_chains_static
,
chanctx_conf
->
rx_chains_dynamic
);
}
rcu_read_unlock
();
mutex_unlock
(
&
mvm
->
mutex
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
pos
);
}
#define BT_MBOX_MSG(_notif, _num, _field) \
((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
>> BT_MBOX##_num##_##_field##_POS)
...
...
@@ -464,6 +525,9 @@ MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
MVM_DEBUGFS_WRITE_FILE_OPS
(
power_down_d3_allow
);
MVM_DEBUGFS_WRITE_FILE_OPS
(
fw_restart
);
/* Interface specific debugfs entries */
MVM_DEBUGFS_READ_FILE_OPS
(
mac_params
);
int
iwl_mvm_dbgfs_register
(
struct
iwl_mvm
*
mvm
,
struct
dentry
*
dbgfs_dir
)
{
char
buf
[
100
];
...
...
@@ -494,3 +558,58 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
IWL_ERR
(
mvm
,
"Can't create the mvm debugfs directory
\n
"
);
return
-
ENOMEM
;
}
void
iwl_mvm_vif_dbgfs_register
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
struct
dentry
*
dbgfs_dir
=
vif
->
debugfs_dir
;
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
char
buf
[
100
];
if
(
!
dbgfs_dir
)
return
;
mvmvif
->
dbgfs_dir
=
debugfs_create_dir
(
"iwlmvm"
,
dbgfs_dir
);
mvmvif
->
dbgfs_data
=
mvm
;
if
(
!
mvmvif
->
dbgfs_dir
)
{
IWL_ERR
(
mvm
,
"Failed to create debugfs directory under %s
\n
"
,
dbgfs_dir
->
d_name
.
name
);
return
;
}
MVM_DEBUGFS_ADD_FILE_VIF
(
mac_params
,
mvmvif
->
dbgfs_dir
,
S_IRUSR
);
/*
* Create symlink for convenience pointing to interface specific
* debugfs entries for the driver. For example, under
* /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
* find
* netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
*/
snprintf
(
buf
,
100
,
"../../../%s/%s/%s/%s"
,
dbgfs_dir
->
d_parent
->
d_parent
->
d_name
.
name
,
dbgfs_dir
->
d_parent
->
d_name
.
name
,
dbgfs_dir
->
d_name
.
name
,
mvmvif
->
dbgfs_dir
->
d_name
.
name
);
mvmvif
->
dbgfs_slink
=
debugfs_create_symlink
(
dbgfs_dir
->
d_name
.
name
,
mvm
->
debugfs_dir
,
buf
);
if
(
!
mvmvif
->
dbgfs_slink
)
IWL_ERR
(
mvm
,
"Can't create debugfs symbolic link under %s
\n
"
,
dbgfs_dir
->
d_name
.
name
);
return
;
err:
IWL_ERR
(
mvm
,
"Can't create debugfs entity
\n
"
);
}
void
iwl_mvm_vif_dbgfs_clean
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
debugfs_remove
(
mvmvif
->
dbgfs_slink
);
mvmvif
->
dbgfs_slink
=
NULL
;
debugfs_remove_recursive
(
mvmvif
->
dbgfs_dir
);
mvmvif
->
dbgfs_dir
=
NULL
;
}
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
浏览文件 @
d72c7282
...
...
@@ -68,73 +68,53 @@
/**
* enum iwl_scan_flags - masks for power table command flags
* @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
* receiver and transmitter. '0' - does not allow.
* @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
* '1' Driver enables PM (use rest of parameters)
* @POWER_FLAGS_S
LEE
P_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
* @POWER_FLAGS_S
KI
P_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
* '1' PM could sleep over DTIM till listen Interval.
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
* @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
* access categories are both delivery and trigger enabled.
* @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
* PBW Snoozing enabled
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
*/
enum
iwl_power_flags
{
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
=
BIT
(
0
),
POWER_FLAGS_SLEEP_OVER_DTIM_MSK
=
BIT
(
1
),
POWER_FLAGS_LPRX_ENA_MSK
=
BIT
(
2
),
POWER_FLAGS_SNOOZE_ENA_MSK
=
BIT
(
3
),
POWER_FLAGS_BT_SCO_ENA
=
BIT
(
4
),
POWER_FLAGS_ADVANCE_PM_ENA_MSK
=
BIT
(
5
)
POWER_FLAGS_POWER_SAVE_ENA_MSK
=
BIT
(
0
),
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
=
BIT
(
1
),
POWER_FLAGS_SKIP_OVER_DTIM_MSK
=
BIT
(
2
),
POWER_FLAGS_ADVANCE_PM_ENA_MSK
=
BIT
(
9
),
POWER_FLAGS_LPRX_ENA_MSK
=
BIT
(
11
),
};
#define IWL_POWER_VEC_SIZE 5
/**
* struct iwl_powertable_cmd - Power Table Command
* POWER_TABLE_CMD = 0x77 (command, has simple generic response)
*
* @id_and_color: MAC contex identifier
* @action: Action on context - no action, add new,
* modify existent, remove
* @flags: Power table command flags from POWER_FLAGS_*
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
* Minimum allowed:- 3 * DTIM
* Minimum allowed:- 3 * DTIM. Keep alive period must be
* set regardless of power scheme or current power state.
* FW use this value also when PM is disabled.
* @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
* PSM transition - legacy PM
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
* PSM transition - legacy PM
* @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
* PSM transition - uAPSD
* @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
* PSM transition - uAPSD
* @sleep_interval: not in use
* @keep_alive_beacons: not in use
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
* Default: 80dbm
* @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
* @snooze_interval: TBD
* @snooze_window: TBD
* @snooze_step: TBD
* @qndp_tid: TBD
* @uapsd_ac_flags: TBD
* @uapsd_max_sp: TBD
*/
struct
iwl_powertable_cmd
{
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32
id_and_color
;
__le32
action
;
/* PM_POWER_TABLE_CMD_API_S_VER_5 */
__le16
flags
;
u8
reserved
;
__le16
keep_alive_second
s
;
u8
keep_alive_seconds
;
u8
debug_flag
s
;
__le32
rx_data_timeout
;
__le32
tx_data_timeout
;
__le32
rx_data_timeout_uapsd
;
__le32
tx_data_timeout_uapsd
;
u8
lprx_rssi_threshold
;
u8
num_skip_dtim
;
__le16
snooze_interval
;
__le16
snooze_window
;
u8
snooze_step
;
u8
qndp_tid
;
u8
uapsd_ac_flags
;
u8
uapsd_max_sp
;
__le32
sleep_interval
[
IWL_POWER_VEC_SIZE
];
__le32
keep_alive_beacons
;
__le32
lprx_rssi_threshold
;
}
__packed
;
#endif
drivers/net/wireless/iwlwifi/mvm/fw-api.h
浏览文件 @
d72c7282
...
...
@@ -480,15 +480,34 @@ enum {
TE_DEP_TSF
=
2
,
TE_EVENT_SOCIOPATHIC
=
4
,
};
/* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */
/* When to send Time Event notifications and to whom (internal = FW) */
/*
* Supported Time event notifications configuration.
* A notification (both event and fragment) includes a status indicating weather
* the FW was able to schedule the event or not. For fragment start/end
* notification the status is always success. There is no start/end fragment
* notification for monolithic events.
*
* @TE_NOTIF_NONE: no notifications
* @TE_NOTIF_HOST_EVENT_START: request/receive notification on event start
* @TE_NOTIF_HOST_EVENT_END:request/receive notification on event end
* @TE_NOTIF_INTERNAL_EVENT_START: internal FW use
* @TE_NOTIF_INTERNAL_EVENT_END: internal FW use.
* @TE_NOTIF_HOST_FRAG_START: request/receive notification on frag start
* @TE_NOTIF_HOST_FRAG_END:request/receive notification on frag end
* @TE_NOTIF_INTERNAL_FRAG_START: internal FW use.
* @TE_NOTIF_INTERNAL_FRAG_END: internal FW use.
*/
enum
{
TE_NOTIF_NONE
=
0
,
TE_NOTIF_HOST_START
=
0x1
,
TE_NOTIF_HOST_END
=
0x2
,
TE_NOTIF_INTERNAL_START
=
0x4
,
TE_NOTIF_INTERNAL_END
=
0x8
};
/* MAC_EVENT_ACTION_API_E_VER_1 */
TE_NOTIF_HOST_EVENT_START
=
0x1
,
TE_NOTIF_HOST_EVENT_END
=
0x2
,
TE_NOTIF_INTERNAL_EVENT_START
=
0x4
,
TE_NOTIF_INTERNAL_EVENT_END
=
0x8
,
TE_NOTIF_HOST_FRAG_START
=
0x10
,
TE_NOTIF_HOST_FRAG_END
=
0x20
,
TE_NOTIF_INTERNAL_FRAG_START
=
0x40
,
TE_NOTIF_INTERNAL_FRAG_END
=
0x80
};
/* MAC_EVENT_ACTION_API_E_VER_2 */
/*
* @TE_FRAG_NONE: fragmentation of the time event is NOT allowed.
...
...
drivers/net/wireless/iwlwifi/mvm/mac80211.c
浏览文件 @
d72c7282
...
...
@@ -502,11 +502,15 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
/*
* TODO: remove this temporary code.
* Currently MVM FW supports power management only on single MAC.
* Iterate and disable PM on all active interfaces.
* If new interface added, disable PM on existing interface.
* P2P device is a special case, since it is handled by FW similary to
* scan. If P2P deviced is added, PM remains enabled on existing
* interface.
* Note: the method below does not count the new interface being added
* at this moment.
*/
mvm
->
vif_count
++
;
if
(
vif
->
type
!=
NL80211_IFTYPE_P2P_DEVICE
)
mvm
->
vif_count
++
;
if
(
mvm
->
vif_count
>
1
)
{
IWL_DEBUG_MAC80211
(
mvm
,
"Disable power on existing interfaces
\n
"
);
...
...
@@ -562,6 +566,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
mvm
->
p2p_device_vif
=
vif
;
}
iwl_mvm_vif_dbgfs_register
(
mvm
,
vif
);
goto
out_unlock
;
out_unbind:
...
...
@@ -575,10 +580,11 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
/*
* TODO: remove this temporary code.
* Currently MVM FW supports power management only on single MAC.
* Check if only one additional interface remains after re
r
easing
* Check if only one additional interface remains after re
l
easing
* current one. Update power mode on the remaining interface.
*/
mvm
->
vif_count
--
;
if
(
vif
->
type
!=
NL80211_IFTYPE_P2P_DEVICE
)
mvm
->
vif_count
--
;
IWL_DEBUG_MAC80211
(
mvm
,
"Currently %d interfaces active
\n
"
,
mvm
->
vif_count
);
if
(
mvm
->
vif_count
==
1
)
{
...
...
@@ -640,6 +646,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mutex_lock
(
&
mvm
->
mutex
);
iwl_mvm_vif_dbgfs_clean
(
mvm
,
vif
);
/*
* For AP/GO interface, the tear down of the resources allocated to the
* interface is be handled as part of the stop_ap flow.
...
...
@@ -663,7 +671,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
* Check if only one additional interface remains after removing
* current one. Update power mode on the remaining interface.
*/
if
(
mvm
->
vif_count
)
if
(
mvm
->
vif_count
&&
vif
->
type
!=
NL80211_IFTYPE_P2P_DEVICE
)
mvm
->
vif_count
--
;
IWL_DEBUG_MAC80211
(
mvm
,
"Currently %d interfaces active
\n
"
,
mvm
->
vif_count
);
...
...
@@ -713,6 +721,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_ERR
(
mvm
,
"failed to update quotas
\n
"
);
return
;
}
iwl_mvm_bt_coex_vif_assoc
(
mvm
,
vif
);
}
else
if
(
mvmvif
->
ap_sta_id
!=
IWL_MVM_STATION_COUNT
)
{
/* remove AP station now that the MAC is unassoc */
ret
=
iwl_mvm_rm_sta_id
(
mvm
,
vif
,
mvmvif
->
ap_sta_id
);
...
...
@@ -931,7 +940,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
*/
break
;
case
STA_NOTIFY_AWAKE
:
if
(
WARN_ON
(
mvmsta
->
sta_id
==
IWL_
INVALID_STATION
))
if
(
WARN_ON
(
mvmsta
->
sta_id
==
IWL_
MVM_STATION_COUNT
))
break
;
iwl_mvm_sta_modify_ps_wake
(
mvm
,
sta
);
break
;
...
...
@@ -1326,6 +1335,15 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
return
iwl_mvm_mac_ctxt_beacon_changed
(
mvm
,
mvm_sta
->
vif
);
}
static
void
iwl_mvm_mac_rssi_callback
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
enum
ieee80211_rssi_event
rssi_event
)
{
struct
iwl_mvm
*
mvm
=
IWL_MAC80211_GET_MVM
(
hw
);
iwl_mvm_bt_rssi_event
(
mvm
,
vif
,
rssi_event
);
}
struct
ieee80211_ops
iwl_mvm_hw_ops
=
{
.
tx
=
iwl_mvm_mac_tx
,
.
ampdu_action
=
iwl_mvm_mac_ampdu_action
,
...
...
@@ -1349,6 +1367,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
.
update_tkip_key
=
iwl_mvm_mac_update_tkip_key
,
.
remain_on_channel
=
iwl_mvm_roc
,
.
cancel_remain_on_channel
=
iwl_mvm_cancel_roc
,
.
rssi_callback
=
iwl_mvm_mac_rssi_callback
,
.
add_chanctx
=
iwl_mvm_add_chanctx
,
.
remove_chanctx
=
iwl_mvm_remove_chanctx
,
...
...
drivers/net/wireless/iwlwifi/mvm/mvm.h
浏览文件 @
d72c7282
...
...
@@ -212,6 +212,7 @@ struct iwl_mvm_vif {
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct
dentry
*
dbgfs_dir
;
struct
dentry
*
dbgfs_slink
;
void
*
dbgfs_data
;
#endif
};
...
...
@@ -321,6 +322,13 @@ struct iwl_mvm {
* can hold 16 keys at most. Reflect this fact.
*/
unsigned
long
fw_key_table
[
BITS_TO_LONGS
(
STA_KEY_MAX_NUM
)];
/*
* This counter of created interfaces is referenced only in conjunction
* with FW limitation related to power management. Currently PM is
* supported only on a single interface.
* IMPORTANT: this variable counts all interfaces except P2P device.
*/
u8
vif_count
;
struct
led_classdev
led
;
...
...
@@ -471,16 +479,22 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
/* MVM debugfs */
#ifdef CONFIG_IWLWIFI_DEBUGFS
int
iwl_mvm_dbgfs_register
(
struct
iwl_mvm
*
mvm
,
struct
dentry
*
dbgfs_dir
);
int
iwl_mvm_vif_dbgfs_register
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
dentry
*
dbgfs_dir
);
void
iwl_power_get_params
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_powertable_cmd
*
cmd
);
void
iwl_mvm_vif_dbgfs_register
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
);
void
iwl_mvm_vif_dbgfs_clean
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
);
#else
static
inline
int
iwl_mvm_dbgfs_register
(
struct
iwl_mvm
*
mvm
,
struct
dentry
*
dbgfs_dir
)
{
return
0
;
}
static
inline
void
iwl_mvm_vif_dbgfs_register
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
}
static
inline
void
iwl_mvm_vif_dbgfs_clean
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
}
#endif
/* CONFIG_IWLWIFI_DEBUGFS */
/* rate scaling */
...
...
@@ -490,6 +504,8 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
/* power managment */
int
iwl_mvm_power_update_mode
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
);
int
iwl_mvm_power_disable
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
);
void
iwl_mvm_power_build_cmd
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_powertable_cmd
*
cmd
);
int
iwl_mvm_leds_init
(
struct
iwl_mvm
*
mvm
);
void
iwl_mvm_leds_exit
(
struct
iwl_mvm
*
mvm
);
...
...
@@ -513,5 +529,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
int
iwl_mvm_rx_bt_coex_notif
(
struct
iwl_mvm
*
mvm
,
struct
iwl_rx_cmd_buffer
*
rxb
,
struct
iwl_device_cmd
*
cmd
);
void
iwl_mvm_bt_rssi_event
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
enum
ieee80211_rssi_event
rssi_event
);
void
iwl_mvm_bt_coex_vif_assoc
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
);
#endif
/* __IWL_MVM_H__ */
drivers/net/wireless/iwlwifi/mvm/power.c
浏览文件 @
d72c7282
...
...
@@ -75,23 +75,49 @@
#define POWER_KEEP_ALIVE_PERIOD_SEC 25
static
void
iwl_power_build_cmd
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_powertable_cmd
*
cmd
)
static
void
iwl_mvm_power_log
(
struct
iwl_mvm
*
mvm
,
struct
iwl_powertable_cmd
*
cmd
)
{
IWL_DEBUG_POWER
(
mvm
,
"Sending power table command for power level %d, flags = 0x%X
\n
"
,
iwlmvm_mod_params
.
power_scheme
,
le16_to_cpu
(
cmd
->
flags
));
IWL_DEBUG_POWER
(
mvm
,
"Keep alive = %u sec
\n
"
,
cmd
->
keep_alive_seconds
);
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
))
{
IWL_DEBUG_POWER
(
mvm
,
"Rx timeout = %u usec
\n
"
,
le32_to_cpu
(
cmd
->
rx_data_timeout
));
IWL_DEBUG_POWER
(
mvm
,
"Tx timeout = %u usec
\n
"
,
le32_to_cpu
(
cmd
->
tx_data_timeout
));
IWL_DEBUG_POWER
(
mvm
,
"LP RX RSSI threshold = %u
\n
"
,
cmd
->
lprx_rssi_threshold
);
}
}
void
iwl_mvm_power_build_cmd
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_powertable_cmd
*
cmd
)
{
struct
ieee80211_hw
*
hw
=
mvm
->
hw
;
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
ieee80211_chanctx_conf
*
chanctx_conf
;
struct
ieee80211_channel
*
chan
;
int
dtimper
,
dtimper_msec
;
int
keep_alive
;
bool
radar_detect
=
false
;
cmd
->
id_and_color
=
cpu_to_le32
(
FW_CMD_ID_AND_COLOR
(
mvmvif
->
id
,
mvmvif
->
color
));
cmd
->
action
=
cpu_to_le32
(
FW_CTXT_ACTION_MODIFY
);
/*
* Regardless of power management state the driver must set
* keep alive period. FW will use it for sending keep alive NDPs
* immediately after association.
*/
cmd
->
keep_alive_seconds
=
POWER_KEEP_ALIVE_PERIOD_SEC
;
if
((
iwlmvm_mod_params
.
power_scheme
==
IWL_POWER_SCHEME_CAM
)
||
!
iwlwifi_mod_params
.
power_save
)
return
;
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_POWER_SAVE_ENA_MSK
);
if
((
!
vif
->
bss_conf
.
ps
)
||
(
iwlmvm_mod_params
.
power_scheme
==
IWL_POWER_SCHEME_CAM
))
if
(
!
vif
->
bss_conf
.
ps
)
return
;
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
);
...
...
@@ -110,26 +136,23 @@ static void iwl_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* Check skip over DTIM conditions */
if
(
!
radar_detect
&&
(
dtimper
<=
10
)
&&
(
iwlmvm_mod_params
.
power_scheme
==
IWL_POWER_SCHEME_LP
))
{
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_SLEEP_OVER_DTIM_MSK
);
cmd
->
num_skip_dtim
=
2
;
}
(
iwlmvm_mod_params
.
power_scheme
==
IWL_POWER_SCHEME_LP
))
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_SKIP_OVER_DTIM_MSK
);
/* Check that keep alive period is at least 3 * DTIM */
dtimper_msec
=
dtimper
*
vif
->
bss_conf
.
beacon_int
;
keep_alive
=
max_t
(
int
,
3
*
dtimper_msec
,
MSEC_PER_SEC
*
POWER_KEEP_ALIVE_PERIOD_SEC
);
MSEC_PER_SEC
*
cmd
->
keep_alive_seconds
);
keep_alive
=
DIV_ROUND_UP
(
keep_alive
,
MSEC_PER_SEC
);
cmd
->
keep_alive_seconds
=
cpu_to_le16
(
keep_alive
);
cmd
->
keep_alive_seconds
=
keep_alive
;
if
(
iwlmvm_mod_params
.
power_scheme
==
IWL_POWER_SCHEME_LP
)
{
/* TODO: Also for D3 (device sleep / WoWLAN) */
cmd
->
rx_data_timeout
=
cpu_to_le32
(
10
);
cmd
->
tx_data_timeout
=
cpu_to_le32
(
10
);
cmd
->
rx_data_timeout
=
cpu_to_le32
(
10
*
USEC_PER_MSEC
);
cmd
->
tx_data_timeout
=
cpu_to_le32
(
10
*
USEC_PER_MSEC
);
}
else
{
cmd
->
rx_data_timeout
=
cpu_to_le32
(
50
);
cmd
->
tx_data_timeout
=
cpu_to_le32
(
50
);
cmd
->
rx_data_timeout
=
cpu_to_le32
(
100
*
USEC_PER_MSEC
);
cmd
->
tx_data_timeout
=
cpu_to_le32
(
100
*
USEC_PER_MSEC
);
}
}
...
...
@@ -137,36 +160,11 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct
iwl_powertable_cmd
cmd
=
{};
if
(
!
iwlwifi_mod_params
.
power_save
)
{
IWL_DEBUG_POWER
(
mvm
,
"Power management is not allowed
\n
"
);
return
0
;
}
if
(
vif
->
type
!=
NL80211_IFTYPE_STATION
||
vif
->
p2p
)
return
0
;
iwl_power_build_cmd
(
mvm
,
vif
,
&
cmd
);
IWL_DEBUG_POWER
(
mvm
,
"Sending power table command on mac id 0x%X for power level %d, flags = 0x%X
\n
"
,
cmd
.
id_and_color
,
iwlmvm_mod_params
.
power_scheme
,
le16_to_cpu
(
cmd
.
flags
));
if
(
cmd
.
flags
&
cpu_to_le16
(
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
))
{
IWL_DEBUG_POWER
(
mvm
,
"Keep alive = %u sec
\n
"
,
le16_to_cpu
(
cmd
.
keep_alive_seconds
));
IWL_DEBUG_POWER
(
mvm
,
"Rx timeout = %u usec
\n
"
,
le32_to_cpu
(
cmd
.
rx_data_timeout
));
IWL_DEBUG_POWER
(
mvm
,
"Tx timeout = %u usec
\n
"
,
le32_to_cpu
(
cmd
.
tx_data_timeout
));
IWL_DEBUG_POWER
(
mvm
,
"Rx timeout (uAPSD) = %u usec
\n
"
,
le32_to_cpu
(
cmd
.
rx_data_timeout_uapsd
));
IWL_DEBUG_POWER
(
mvm
,
"Tx timeout = %u usec
\n
"
,
le32_to_cpu
(
cmd
.
tx_data_timeout_uapsd
));
IWL_DEBUG_POWER
(
mvm
,
"LP RX RSSI threshold = %u
\n
"
,
cmd
.
lprx_rssi_threshold
);
IWL_DEBUG_POWER
(
mvm
,
"DTIMs to skip = %u
\n
"
,
cmd
.
num_skip_dtim
);
}
iwl_mvm_power_build_cmd
(
mvm
,
vif
,
&
cmd
);
iwl_mvm_power_log
(
mvm
,
&
cmd
);
return
iwl_mvm_send_cmd_pdu
(
mvm
,
POWER_TABLE_CMD
,
CMD_SYNC
,
sizeof
(
cmd
),
&
cmd
);
...
...
@@ -175,33 +173,16 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
int
iwl_mvm_power_disable
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_powertable_cmd
cmd
=
{};
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
if
(
!
iwlwifi_mod_params
.
power_save
)
{
IWL_DEBUG_POWER
(
mvm
,
"Power management is not allowed
\n
"
);
return
0
;
}
if
(
vif
->
type
!=
NL80211_IFTYPE_STATION
||
vif
->
p2p
)
return
0
;
cmd
.
id_and_color
=
cpu_to_le32
(
FW_CMD_ID_AND_COLOR
(
mvmvif
->
id
,
mvmvif
->
color
));
cmd
.
action
=
cpu_to_le32
(
FW_CTXT_ACTION_MODIFY
);
if
((
iwlmvm_mod_params
.
power_scheme
!=
IWL_POWER_SCHEME_CAM
)
&&
iwlwifi_mod_params
.
power_save
)
cmd
.
flags
|=
cpu_to_le16
(
POWER_FLAGS_POWER_SAVE_ENA_MSK
);
IWL_DEBUG_POWER
(
mvm
,
"Sending power table command on mac id 0x%X for power level %d, flags = 0x%X
\n
"
,
cmd
.
id_and_color
,
iwlmvm_mod_params
.
power_scheme
,
le16_to_cpu
(
cmd
.
flags
));
iwl_mvm_power_log
(
mvm
,
&
cmd
);
return
iwl_mvm_send_cmd_pdu
(
mvm
,
POWER_TABLE_CMD
,
CMD_ASYNC
,
sizeof
(
cmd
),
&
cmd
);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
void
iwl_power_get_params
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_powertable_cmd
*
cmd
)
{
iwl_power_build_cmd
(
mvm
,
vif
,
cmd
);
}
#endif
/* CONFIG_IWLWIFI_DEBUGFS */
drivers/net/wireless/iwlwifi/mvm/rs.c
浏览文件 @
d72c7282
...
...
@@ -793,7 +793,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
if
(
num_of_ant
(
tbl
->
ant_type
)
>
1
)
tbl
->
ant_type
=
first_antenna
(
mvm
->
nvm_data
->
valid_tx_ant
);
first_antenna
(
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
);
tbl
->
is_ht40
=
0
;
tbl
->
is_SGI
=
0
;
...
...
@@ -1235,7 +1235,7 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm,
return
-
1
;
/* Need both Tx chains/antennas to support MIMO */
if
(
num_of_ant
(
mvm
->
nvm_data
->
valid_tx_ant
)
<
2
)
if
(
num_of_ant
(
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
)
<
2
)
return
-
1
;
IWL_DEBUG_RATE
(
mvm
,
"LQ: try to switch to MIMO2
\n
"
);
...
...
@@ -1287,7 +1287,7 @@ static int rs_switch_to_mimo3(struct iwl_mvm *mvm,
return
-
1
;
/* Need both Tx chains/antennas to support MIMO */
if
(
num_of_ant
(
mvm
->
nvm_data
->
valid_tx_ant
)
<
3
)
if
(
num_of_ant
(
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
)
<
3
)
return
-
1
;
IWL_DEBUG_RATE
(
mvm
,
"LQ: try to switch to MIMO3
\n
"
);
...
...
@@ -1381,7 +1381,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm,
u32
sz
=
(
sizeof
(
struct
iwl_scale_tbl_info
)
-
(
sizeof
(
struct
iwl_rate_scale_data
)
*
IWL_RATE_COUNT
));
u8
start_action
;
u8
valid_tx_ant
=
mvm
->
nvm_data
->
valid_tx_ant
;
u8
valid_tx_ant
=
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
;
u8
tx_chains_num
=
num_of_ant
(
valid_tx_ant
);
int
ret
;
u8
update_search_tbl_counter
=
0
;
...
...
@@ -1514,7 +1514,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm,
u32
sz
=
(
sizeof
(
struct
iwl_scale_tbl_info
)
-
(
sizeof
(
struct
iwl_rate_scale_data
)
*
IWL_RATE_COUNT
));
u8
start_action
;
u8
valid_tx_ant
=
mvm
->
nvm_data
->
valid_tx_ant
;
u8
valid_tx_ant
=
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
;
u8
tx_chains_num
=
num_of_ant
(
valid_tx_ant
);
u8
update_search_tbl_counter
=
0
;
int
ret
;
...
...
@@ -1649,7 +1649,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
u32
sz
=
(
sizeof
(
struct
iwl_scale_tbl_info
)
-
(
sizeof
(
struct
iwl_rate_scale_data
)
*
IWL_RATE_COUNT
));
u8
start_action
;
u8
valid_tx_ant
=
mvm
->
nvm_data
->
valid_tx_ant
;
u8
valid_tx_ant
=
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
;
u8
tx_chains_num
=
num_of_ant
(
valid_tx_ant
);
u8
update_search_tbl_counter
=
0
;
int
ret
;
...
...
@@ -1786,7 +1786,7 @@ static int rs_move_mimo3_to_other(struct iwl_mvm *mvm,
u32
sz
=
(
sizeof
(
struct
iwl_scale_tbl_info
)
-
(
sizeof
(
struct
iwl_rate_scale_data
)
*
IWL_RATE_COUNT
));
u8
start_action
;
u8
valid_tx_ant
=
mvm
->
nvm_data
->
valid_tx_ant
;
u8
valid_tx_ant
=
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
;
u8
tx_chains_num
=
num_of_ant
(
valid_tx_ant
);
int
ret
;
u8
update_search_tbl_counter
=
0
;
...
...
@@ -2449,7 +2449,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
i
=
lq_sta
->
last_txrate_idx
;
valid_tx_ant
=
mvm
->
nvm_data
->
valid_tx_ant
;
valid_tx_ant
=
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
;
if
(
!
lq_sta
->
search_better_tbl
)
active_tbl
=
lq_sta
->
active_tbl
;
...
...
@@ -2639,15 +2639,15 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
/* These values will be overridden later */
lq_sta
->
lq
.
single_stream_ant_msk
=
first_antenna
(
mvm
->
nvm_data
->
valid_tx_ant
);
first_antenna
(
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
);
lq_sta
->
lq
.
dual_stream_ant_msk
=
mvm
->
nvm_data
->
valid_tx_ant
&
~
first_antenna
(
mvm
->
nvm_data
->
valid_tx_ant
);
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
&
~
first_antenna
(
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
);
if
(
!
lq_sta
->
lq
.
dual_stream_ant_msk
)
{
lq_sta
->
lq
.
dual_stream_ant_msk
=
ANT_AB
;
}
else
if
(
num_of_ant
(
mvm
->
nvm_data
->
valid_tx_ant
)
==
2
)
{
}
else
if
(
num_of_ant
(
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
)
==
2
)
{
lq_sta
->
lq
.
dual_stream_ant_msk
=
mvm
->
nvm_data
->
valid_tx_ant
;
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
;
}
/* as default allow aggregation for all tids */
...
...
@@ -2708,7 +2708,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
index
++
;
repeat_rate
--
;
if
(
mvm
)
valid_tx_ant
=
mvm
->
nvm_data
->
valid_tx_ant
;
valid_tx_ant
=
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
;
/* Fill rest of rate table */
while
(
index
<
LINK_QUAL_MAX_RETRY_NUM
)
{
...
...
@@ -2813,7 +2813,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
u8
ant_sel_tx
;
mvm
=
lq_sta
->
drv
;
valid_tx_ant
=
mvm
->
nvm_data
->
valid_tx_ant
;
valid_tx_ant
=
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
;
if
(
lq_sta
->
dbg_fixed_rate
)
{
ant_sel_tx
=
((
lq_sta
->
dbg_fixed_rate
&
RATE_MCS_ANT_ABC_MSK
)
...
...
@@ -2884,9 +2884,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
desc
+=
sprintf
(
buff
+
desc
,
"fixed rate 0x%X
\n
"
,
lq_sta
->
dbg_fixed_rate
);
desc
+=
sprintf
(
buff
+
desc
,
"valid_tx_ant %s%s%s
\n
"
,
(
mvm
->
nvm_data
->
valid_tx_ant
&
ANT_A
)
?
"ANT_A,"
:
""
,
(
mvm
->
nvm_data
->
valid_tx_ant
&
ANT_B
)
?
"ANT_B,"
:
""
,
(
mvm
->
nvm_data
->
valid_tx_ant
&
ANT_C
)
?
"ANT_C"
:
""
);
(
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
&
ANT_A
)
?
"ANT_A,"
:
""
,
(
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
&
ANT_B
)
?
"ANT_B,"
:
""
,
(
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
&
ANT_C
)
?
"ANT_C"
:
""
);
desc
+=
sprintf
(
buff
+
desc
,
"lq type %s
\n
"
,
(
is_legacy
(
tbl
->
lq_type
))
?
"legacy"
:
"HT"
);
if
(
is_Ht
(
tbl
->
lq_type
))
{
...
...
drivers/net/wireless/iwlwifi/mvm/sta.c
浏览文件 @
d72c7282
...
...
@@ -945,7 +945,7 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
mvmvif
->
ap_sta_id
!=
IWL_MVM_STATION_COUNT
)
return
mvmvif
->
ap_sta_id
;
return
IWL_
INVALID_STATION
;
return
IWL_
MVM_STATION_COUNT
;
}
static
int
iwl_mvm_send_sta_key
(
struct
iwl_mvm
*
mvm
,
...
...
@@ -1093,7 +1093,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
/* Get the station id from the mvm local station table */
sta_id
=
iwl_mvm_get_key_sta_id
(
vif
,
sta
);
if
(
sta_id
==
IWL_
INVALID_STATION
)
{
if
(
sta_id
==
IWL_
MVM_STATION_COUNT
)
{
IWL_ERR
(
mvm
,
"Failed to find station id
\n
"
);
return
-
EINVAL
;
}
...
...
@@ -1188,7 +1188,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
return
-
ENOENT
;
}
if
(
sta_id
==
IWL_
INVALID_STATION
)
{
if
(
sta_id
==
IWL_
MVM_STATION_COUNT
)
{
IWL_DEBUG_WEP
(
mvm
,
"station non-existent, early return.
\n
"
);
return
0
;
}
...
...
@@ -1254,7 +1254,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
struct
iwl_mvm_sta
*
mvm_sta
;
u8
sta_id
=
iwl_mvm_get_key_sta_id
(
vif
,
sta
);
if
(
WARN_ON_ONCE
(
sta_id
==
IWL_
INVALID_STATION
))
if
(
WARN_ON_ONCE
(
sta_id
==
IWL_
MVM_STATION_COUNT
))
return
;
rcu_read_lock
();
...
...
drivers/net/wireless/iwlwifi/mvm/sta.h
浏览文件 @
d72c7282
...
...
@@ -271,6 +271,7 @@ struct iwl_mvm_tid_data {
* @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
* tid.
* @max_agg_bufsize: the maximal size of the AGG buffer for this station
* @bt_reduced_txpower: is reduced tx power enabled for this station
* @lock: lock to protect the whole struct. Since %tid_data is access from Tx
* and from Tx response flow, it needs a spinlock.
* @pending_frames: number of frames for this STA on the shared Tx queues.
...
...
@@ -287,6 +288,7 @@ struct iwl_mvm_sta {
u32
mac_id_n_color
;
u16
tid_disable_agg
;
u8
max_agg_bufsize
;
bool
bt_reduced_txpower
;
spinlock_t
lock
;
atomic_t
pending_frames
;
struct
iwl_mvm_tid_data
tid_data
[
IWL_MAX_TID_COUNT
];
...
...
drivers/net/wireless/iwlwifi/mvm/time-event.c
浏览文件 @
d72c7282
...
...
@@ -166,7 +166,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
WARN_ONCE
(
!
le32_to_cpu
(
notif
->
status
),
"Failed to schedule time event
\n
"
);
if
(
le32_to_cpu
(
notif
->
action
)
==
TE_NOTIF_HOS
T_END
)
{
if
(
le32_to_cpu
(
notif
->
action
)
&
TE_NOTIF_HOST_EVEN
T_END
)
{
IWL_DEBUG_TE
(
mvm
,
"TE ended - current time %lu, estimated end %lu
\n
"
,
jiffies
,
te_data
->
end_jiffies
);
...
...
@@ -189,7 +189,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
}
iwl_mvm_te_clear_data
(
mvm
,
te_data
);
}
else
if
(
le32_to_cpu
(
notif
->
action
)
==
TE_NOTIF_HOS
T_START
)
{
}
else
if
(
le32_to_cpu
(
notif
->
action
)
&
TE_NOTIF_HOST_EVEN
T_START
)
{
te_data
->
running
=
true
;
te_data
->
end_jiffies
=
jiffies
+
TU_TO_JIFFIES
(
te_data
->
duration
);
...
...
@@ -368,7 +368,8 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
time_cmd
.
interval_reciprocal
=
cpu_to_le32
(
iwl_mvm_reciprocal
(
1
));
time_cmd
.
duration
=
cpu_to_le32
(
duration
);
time_cmd
.
repeat
=
cpu_to_le32
(
1
);
time_cmd
.
notify
=
cpu_to_le32
(
TE_NOTIF_HOST_START
|
TE_NOTIF_HOST_END
);
time_cmd
.
notify
=
cpu_to_le32
(
TE_NOTIF_HOST_EVENT_START
|
TE_NOTIF_HOST_EVENT_END
);
iwl_mvm_time_event_send_add
(
mvm
,
vif
,
te_data
,
&
time_cmd
);
}
...
...
@@ -485,7 +486,8 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
time_cmd
.
max_delay
=
cpu_to_le32
(
MSEC_TO_TU
(
duration
/
2
));
time_cmd
.
duration
=
cpu_to_le32
(
MSEC_TO_TU
(
duration
));
time_cmd
.
repeat
=
cpu_to_le32
(
1
);
time_cmd
.
notify
=
cpu_to_le32
(
TE_NOTIF_HOST_START
|
TE_NOTIF_HOST_END
);
time_cmd
.
notify
=
cpu_to_le32
(
TE_NOTIF_HOST_EVENT_START
|
TE_NOTIF_HOST_EVENT_END
);
return
iwl_mvm_time_event_send_add
(
mvm
,
vif
,
te_data
,
&
time_cmd
);
}
...
...
drivers/net/wireless/iwlwifi/mvm/tx.c
浏览文件 @
d72c7282
...
...
@@ -205,7 +205,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
rate_plcp
=
iwl_mvm_mac80211_idx_to_hwrate
(
rate_idx
);
mvm
->
mgmt_last_antenna_idx
=
iwl_mvm_next_antenna
(
mvm
,
mvm
->
nvm_data
->
valid_tx_ant
,
iwl_mvm_next_antenna
(
mvm
,
iwl_fw_valid_tx_ant
(
mvm
->
fw
)
,
mvm
->
mgmt_last_antenna_idx
);
rate_flags
=
BIT
(
mvm
->
mgmt_last_antenna_idx
)
<<
RATE_MCS_ANT_POS
;
...
...
@@ -365,7 +365,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
if
(
WARN_ON_ONCE
(
!
mvmsta
))
return
-
1
;
if
(
WARN_ON_ONCE
(
mvmsta
->
sta_id
==
IWL_
INVALID_STATION
))
if
(
WARN_ON_ONCE
(
mvmsta
->
sta_id
==
IWL_
MVM_STATION_COUNT
))
return
-
1
;
dev_cmd
=
iwl_mvm_set_tx_params
(
mvm
,
skb
,
sta
,
mvmsta
->
sta_id
);
...
...
@@ -641,10 +641,12 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
}
IWL_DEBUG_TX_REPLY
(
mvm
,
"TXQ %d status %s (0x%08x)
\n\t\t\t\t
initial_rate 0x%x "
"retries %d, idx=%d ssn=%d next_reclaimed=0x%x seq_ctl=0x%x
\n
"
,
txq_id
,
iwl_mvm_get_tx_fail_reason
(
status
),
status
,
le32_to_cpu
(
tx_resp
->
initial_rate
),
"TXQ %d status %s (0x%08x)
\n
"
,
txq_id
,
iwl_mvm_get_tx_fail_reason
(
status
),
status
);
IWL_DEBUG_TX_REPLY
(
mvm
,
"
\t\t\t\t
initial_rate 0x%x retries %d, idx=%d ssn=%d next_reclaimed=0x%x seq_ctl=0x%x
\n
"
,
le32_to_cpu
(
tx_resp
->
initial_rate
),
tx_resp
->
failure_frame
,
SEQ_TO_INDEX
(
sequence
),
ssn
,
next_reclaimed
,
seq_ctl
);
...
...
drivers/net/wireless/iwlwifi/mvm/utils.c
浏览文件 @
d72c7282
...
...
@@ -462,7 +462,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
.
data
=
{
lq
,
},
};
if
(
WARN_ON
(
lq
->
sta_id
==
IWL_
INVALID_STATION
))
if
(
WARN_ON
(
lq
->
sta_id
==
IWL_
MVM_STATION_COUNT
))
return
-
EINVAL
;
if
(
WARN_ON
(
init
&&
(
cmd
.
flags
&
CMD_ASYNC
)))
...
...
drivers/net/wireless/iwlwifi/pcie/drv.c
浏览文件 @
d72c7282
...
...
@@ -241,6 +241,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{
IWL_PCI_DEVICE
(
0x088F
,
0x4260
,
iwl6035_2agn_cfg
)},
{
IWL_PCI_DEVICE
(
0x088E
,
0x4460
,
iwl6035_2agn_cfg
)},
{
IWL_PCI_DEVICE
(
0x088E
,
0x4860
,
iwl6035_2agn_cfg
)},
{
IWL_PCI_DEVICE
(
0x088F
,
0x5260
,
iwl6035_2agn_cfg
)},
/* 105 Series */
{
IWL_PCI_DEVICE
(
0x0894
,
0x0022
,
iwl105_bgn_cfg
)},
...
...
drivers/net/wireless/iwlwifi/pcie/tx.c
浏览文件 @
d72c7282
...
...
@@ -1063,7 +1063,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
iwl_set_bits_prph
(
trans
,
SCD_QUEUECHAIN_SEL
,
BIT
(
txq_id
));
/* If this queue is mapped to a certain station: it is an AGG queue */
if
(
sta_id
!=
IWL_INVALID_STATION
)
{
if
(
sta_id
>=
0
)
{
u16
ra_tid
=
BUILD_RAxTID
(
sta_id
,
tid
);
/* Map receiver-address / traffic-ID to this queue */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录