Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
3d5c2032
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看板
提交
3d5c2032
编写于
3月 08, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
上级
7da060c1
87f59c70
变更
59
展开全部
隐藏空白更改
内联
并排
Showing
59 changed file
with
2537 addition
and
1911 deletion
+2537
-1911
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/cfg80211.c
+5
-3
drivers/net/wireless/iwlegacy/3945.h
drivers/net/wireless/iwlegacy/3945.h
+0
-4
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/4965-mac.c
+7
-6
drivers/net/wireless/iwlegacy/common.h
drivers/net/wireless/iwlegacy/common.h
+0
-4
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
+2
-1
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/dvm/tx.c
+6
-5
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/iwl-trans.h
+0
-3
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
+4
-3
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.c
+2
-2
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/tx.c
+1
-1
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/iwlwifi/pcie/tx.c
+1
-1
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mac80211_hwsim.c
+2
-1
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/rtlwifi/wifi.h
+0
-3
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/main.c
+2
-1
include/linux/ieee80211.h
include/linux/ieee80211.h
+38
-14
include/net/cfg80211.h
include/net/cfg80211.h
+106
-20
include/net/mac80211.h
include/net/mac80211.h
+22
-7
include/uapi/linux/nl80211.h
include/uapi/linux/nl80211.h
+106
-11
net/mac80211/cfg.c
net/mac80211/cfg.c
+114
-48
net/mac80211/debugfs_sta.c
net/mac80211/debugfs_sta.c
+31
-0
net/mac80211/driver-ops.h
net/mac80211/driver-ops.h
+4
-3
net/mac80211/ht.c
net/mac80211/ht.c
+25
-27
net/mac80211/ibss.c
net/mac80211/ibss.c
+1
-28
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+8
-18
net/mac80211/iface.c
net/mac80211/iface.c
+14
-8
net/mac80211/key.c
net/mac80211/key.c
+56
-47
net/mac80211/key.h
net/mac80211/key.h
+3
-2
net/mac80211/main.c
net/mac80211/main.c
+24
-31
net/mac80211/mesh.c
net/mac80211/mesh.c
+3
-56
net/mac80211/mesh.h
net/mac80211/mesh.h
+0
-12
net/mac80211/mesh_plink.c
net/mac80211/mesh_plink.c
+8
-29
net/mac80211/mlme.c
net/mac80211/mlme.c
+27
-83
net/mac80211/offchannel.c
net/mac80211/offchannel.c
+1
-1
net/mac80211/pm.c
net/mac80211/pm.c
+7
-110
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel.c
+114
-90
net/mac80211/rc80211_minstrel.h
net/mac80211/rc80211_minstrel.h
+26
-5
net/mac80211/rc80211_minstrel_debugfs.c
net/mac80211/rc80211_minstrel_debugfs.c
+7
-5
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rc80211_minstrel_ht.c
+43
-36
net/mac80211/rc80211_minstrel_ht.h
net/mac80211/rc80211_minstrel_ht.h
+1
-5
net/mac80211/rx.c
net/mac80211/rx.c
+26
-35
net/mac80211/sta_info.c
net/mac80211/sta_info.c
+9
-2
net/mac80211/sta_info.h
net/mac80211/sta_info.h
+0
-2
net/mac80211/trace.h
net/mac80211/trace.h
+7
-4
net/mac80211/tx.c
net/mac80211/tx.c
+51
-29
net/mac80211/util.c
net/mac80211/util.c
+22
-51
net/mac80211/vht.c
net/mac80211/vht.c
+211
-1
net/rfkill/rfkill-regulator.c
net/rfkill/rfkill-regulator.c
+1
-1
net/wireless/ap.c
net/wireless/ap.c
+0
-62
net/wireless/core.c
net/wireless/core.c
+42
-34
net/wireless/core.h
net/wireless/core.h
+11
-11
net/wireless/mesh.c
net/wireless/mesh.c
+1
-14
net/wireless/mlme.c
net/wireless/mlme.c
+34
-196
net/wireless/nl80211.c
net/wireless/nl80211.c
+1200
-645
net/wireless/nl80211.h
net/wireless/nl80211.h
+0
-68
net/wireless/rdev-ops.h
net/wireless/rdev-ops.h
+17
-3
net/wireless/reg.c
net/wireless/reg.c
+3
-3
net/wireless/sme.c
net/wireless/sme.c
+15
-11
net/wireless/sysfs.c
net/wireless/sysfs.c
+20
-5
net/wireless/trace.h
net/wireless/trace.h
+46
-0
未找到文件。
drivers/net/wireless/ath/ath6kl/cfg80211.c
浏览文件 @
3d5c2032
...
...
@@ -2990,13 +2990,15 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
{
struct
ath6kl
*
ar
=
ath6kl_priv
(
dev
);
struct
ath6kl_vif
*
vif
=
netdev_priv
(
dev
);
int
err
;
if
(
vif
->
nw_type
!=
AP_NETWORK
)
return
-
EOPNOTSUPP
;
/* Use this only for authorizing/unauthorizing a station */
if
(
!
(
params
->
sta_flags_mask
&
BIT
(
NL80211_STA_FLAG_AUTHORIZED
)))
return
-
EOPNOTSUPP
;
err
=
cfg80211_check_station_change
(
wiphy
,
params
,
CFG80211_STA_AP_MLME_CLIENT
);
if
(
err
)
return
err
;
if
(
params
->
sta_flags_set
&
BIT
(
NL80211_STA_FLAG_AUTHORIZED
))
return
ath6kl_wmi_ap_set_mlme
(
ar
->
wmi
,
vif
->
fw_vif_idx
,
...
...
drivers/net/wireless/iwlegacy/3945.h
浏览文件 @
3d5c2032
...
...
@@ -150,10 +150,6 @@ struct il3945_frame {
struct
list_head
list
;
};
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
...
...
drivers/net/wireless/iwlegacy/4965-mac.c
浏览文件 @
3d5c2032
...
...
@@ -2258,7 +2258,7 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif,
spin_lock_irqsave
(
&
il
->
sta_lock
,
flags
);
tid_data
=
&
il
->
stations
[
sta_id
].
tid
[
tid
];
*
ssn
=
SEQ_TO_SN
(
tid_data
->
seq_number
);
*
ssn
=
IEEE80211_
SEQ_TO_SN
(
tid_data
->
seq_number
);
tid_data
->
agg
.
txq_id
=
txq_id
;
il_set_swq_id
(
&
il
->
txq
[
txq_id
],
il4965_get_ac_from_tid
(
tid
),
txq_id
);
spin_unlock_irqrestore
(
&
il
->
sta_lock
,
flags
);
...
...
@@ -2408,7 +2408,7 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id)
/* aggregated HW queue */
if
(
txq_id
==
tid_data
->
agg
.
txq_id
&&
q
->
read_ptr
==
q
->
write_ptr
)
{
u16
ssn
=
SEQ_TO_SN
(
tid_data
->
seq_number
);
u16
ssn
=
IEEE80211_
SEQ_TO_SN
(
tid_data
->
seq_number
);
int
tx_fifo
=
il4965_get_fifo_from_tid
(
tid
);
D_HT
(
"HW queue empty: continue DELBA flow
\n
"
);
il4965_txq_agg_disable
(
il
,
txq_id
,
ssn
,
tx_fifo
);
...
...
@@ -2627,7 +2627,8 @@ il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr)
static
inline
u32
il4965_get_scd_ssn
(
struct
il4965_tx_resp
*
tx_resp
)
{
return
le32_to_cpup
(
&
tx_resp
->
u
.
status
+
tx_resp
->
frame_count
)
&
MAX_SN
;
return
le32_to_cpup
(
&
tx_resp
->
u
.
status
+
tx_resp
->
frame_count
)
&
IEEE80211_MAX_SN
;
}
static
inline
u32
...
...
@@ -2717,15 +2718,15 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg,
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
sc
=
le16_to_cpu
(
hdr
->
seq_ctrl
);
if
(
idx
!=
(
SEQ_TO_SN
(
sc
)
&
0xff
))
{
if
(
idx
!=
(
IEEE80211_
SEQ_TO_SN
(
sc
)
&
0xff
))
{
IL_ERR
(
"BUG_ON idx doesn't match seq control"
" idx=%d, seq_idx=%d, seq=%d
\n
"
,
idx
,
SEQ_TO_SN
(
sc
),
hdr
->
seq_ctrl
);
IEEE80211_
SEQ_TO_SN
(
sc
),
hdr
->
seq_ctrl
);
return
-
1
;
}
D_TX_REPLY
(
"AGG Frame i=%d idx %d seq=%d
\n
"
,
i
,
idx
,
SEQ_TO_SN
(
sc
));
IEEE80211_
SEQ_TO_SN
(
sc
));
sh
=
idx
-
start
;
if
(
sh
>
64
)
{
...
...
drivers/net/wireless/iwlegacy/common.h
浏览文件 @
3d5c2032
...
...
@@ -541,10 +541,6 @@ struct il_frame {
struct
list_head
list
;
};
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
enum
{
CMD_SYNC
=
0
,
CMD_SIZE_NORMAL
=
0
,
...
...
drivers/net/wireless/iwlwifi/dvm/mac80211.c
浏览文件 @
3d5c2032
...
...
@@ -1137,7 +1137,8 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
static
int
iwlagn_mac_remain_on_channel
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_channel
*
channel
,
int
duration
)
int
duration
,
enum
ieee80211_roc_type
type
)
{
struct
iwl_priv
*
priv
=
IWL_MAC80211_GET_DVM
(
hw
);
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
IWL_RXON_CTX_PAN
];
...
...
drivers/net/wireless/iwlwifi/dvm/tx.c
浏览文件 @
3d5c2032
...
...
@@ -418,7 +418,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
" Tx flags = 0x%08x, agg.state = %d"
,
info
->
flags
,
tid_data
->
agg
.
state
);
IWL_ERR
(
priv
,
"sta_id = %d, tid = %d seq_num = %d"
,
sta_id
,
tid
,
SEQ_TO_SN
(
tid_data
->
seq_number
));
sta_id
,
tid
,
IEEE80211_SEQ_TO_SN
(
tid_data
->
seq_number
));
goto
drop_unlock_sta
;
}
...
...
@@ -569,7 +570,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
return
0
;
}
tid_data
->
agg
.
ssn
=
SEQ_TO_SN
(
tid_data
->
seq_number
);
tid_data
->
agg
.
ssn
=
IEEE80211_
SEQ_TO_SN
(
tid_data
->
seq_number
);
/* There are still packets for this RA / TID in the HW */
if
(
!
test_bit
(
txq_id
,
priv
->
agg_q_alloc
))
{
...
...
@@ -651,7 +652,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
spin_lock_bh
(
&
priv
->
sta_lock
);
tid_data
=
&
priv
->
tid_data
[
sta_id
][
tid
];
tid_data
->
agg
.
ssn
=
SEQ_TO_SN
(
tid_data
->
seq_number
);
tid_data
->
agg
.
ssn
=
IEEE80211_
SEQ_TO_SN
(
tid_data
->
seq_number
);
tid_data
->
agg
.
txq_id
=
txq_id
;
*
ssn
=
tid_data
->
agg
.
ssn
;
...
...
@@ -911,7 +912,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
static
inline
u32
iwlagn_get_scd_ssn
(
struct
iwlagn_tx_resp
*
tx_resp
)
{
return
le32_to_cpup
((
__le32
*
)
&
tx_resp
->
status
+
tx_resp
->
frame_count
)
&
MAX_SN
;
tx_resp
->
frame_count
)
&
IEEE80211_
MAX_SN
;
}
static
void
iwl_rx_reply_tx_agg
(
struct
iwl_priv
*
priv
,
...
...
@@ -1148,7 +1149,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
if
(
tx_resp
->
frame_count
==
1
)
{
u16
next_reclaimed
=
le16_to_cpu
(
tx_resp
->
seq_ctl
);
next_reclaimed
=
SEQ_TO_SN
(
next_reclaimed
+
0x10
);
next_reclaimed
=
IEEE80211_
SEQ_TO_SN
(
next_reclaimed
+
0x10
);
if
(
is_agg
)
{
/* If this is an aggregation queue, we can rely on the
...
...
drivers/net/wireless/iwlwifi/iwl-trans.h
浏览文件 @
3d5c2032
...
...
@@ -114,9 +114,6 @@
* completely agnostic to these differences.
* The transport does provide helper functionnality (i.e. SYNC / ASYNC mode),
*/
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
#define SEQ_TO_INDEX(s) ((s) & 0xff)
...
...
drivers/net/wireless/iwlwifi/mvm/mac80211.c
浏览文件 @
3d5c2032
...
...
@@ -1081,7 +1081,8 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
static
int
iwl_mvm_roc
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_channel
*
channel
,
int
duration
)
int
duration
,
enum
ieee80211_roc_type
type
)
{
struct
iwl_mvm
*
mvm
=
IWL_MAC80211_GET_MVM
(
hw
);
struct
cfg80211_chan_def
chandef
;
...
...
@@ -1092,8 +1093,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
return
-
EINVAL
;
}
IWL_DEBUG_MAC80211
(
mvm
,
"enter (%d, %d)
\n
"
,
channel
->
hw_value
,
duration
);
IWL_DEBUG_MAC80211
(
mvm
,
"enter (%d, %d
, %d
)
\n
"
,
channel
->
hw_value
,
duration
,
type
);
mutex_lock
(
&
mvm
->
mutex
);
...
...
drivers/net/wireless/iwlwifi/mvm/sta.c
浏览文件 @
3d5c2032
...
...
@@ -686,7 +686,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
spin_lock_bh
(
&
mvmsta
->
lock
);
tid_data
=
&
mvmsta
->
tid_data
[
tid
];
tid_data
->
ssn
=
SEQ_TO_SN
(
tid_data
->
seq_number
);
tid_data
->
ssn
=
IEEE80211_
SEQ_TO_SN
(
tid_data
->
seq_number
);
tid_data
->
txq_id
=
txq_id
;
*
ssn
=
tid_data
->
ssn
;
...
...
@@ -779,7 +779,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
switch
(
tid_data
->
state
)
{
case
IWL_AGG_ON
:
tid_data
->
ssn
=
SEQ_TO_SN
(
tid_data
->
seq_number
);
tid_data
->
ssn
=
IEEE80211_
SEQ_TO_SN
(
tid_data
->
seq_number
);
IWL_DEBUG_TX_QUEUES
(
mvm
,
"ssn = %d, next_recl = %d
\n
"
,
...
...
drivers/net/wireless/iwlwifi/mvm/tx.c
浏览文件 @
3d5c2032
...
...
@@ -641,7 +641,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
next_reclaimed
=
ssn
;
}
else
{
/* The next packet to be reclaimed is the one after this one */
next_reclaimed
=
SEQ_TO_SN
(
seq_ctl
+
0x10
);
next_reclaimed
=
IEEE80211_
SEQ_TO_SN
(
seq_ctl
+
0x10
);
}
IWL_DEBUG_TX_REPLY
(
mvm
,
...
...
drivers/net/wireless/iwlwifi/pcie/tx.c
浏览文件 @
3d5c2032
...
...
@@ -1581,7 +1581,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
* Check here that the packets are in the right place on the ring.
*/
#ifdef CONFIG_IWLWIFI_DEBUG
wifi_seq
=
SEQ_TO_SN
(
le16_to_cpu
(
hdr
->
seq_ctrl
));
wifi_seq
=
IEEE80211_
SEQ_TO_SN
(
le16_to_cpu
(
hdr
->
seq_ctrl
));
WARN_ONCE
((
iwl_read_prph
(
trans
,
SCD_AGGR_SEL
)
&
BIT
(
txq_id
))
&&
((
wifi_seq
&
0xff
)
!=
q
->
write_ptr
),
"Q: %d WiFi Seq %d tfdNum %d"
,
...
...
drivers/net/wireless/mac80211_hwsim.c
浏览文件 @
3d5c2032
...
...
@@ -1535,7 +1535,8 @@ static void hw_roc_done(struct work_struct *work)
static
int
mac80211_hwsim_roc
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_channel
*
chan
,
int
duration
)
int
duration
,
enum
ieee80211_roc_type
type
)
{
struct
mac80211_hwsim_data
*
hwsim
=
hw
->
priv
;
...
...
drivers/net/wireless/rtlwifi/wifi.h
浏览文件 @
3d5c2032
...
...
@@ -2127,9 +2127,6 @@ value to host byte ordering.*/
#define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE)
#define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE)
#define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA)
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
#define RT_RF_OFF_LEVL_ASPM BIT(0)
/*PCI ASPM */
#define RT_RF_OFF_LEVL_CLK_REQ BIT(1)
/*PCI clock request */
...
...
drivers/net/wireless/ti/wlcore/main.c
浏览文件 @
3d5c2032
...
...
@@ -4956,7 +4956,8 @@ static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop)
static
int
wlcore_op_remain_on_channel
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_channel
*
chan
,
int
duration
)
int
duration
,
enum
ieee80211_roc_type
type
)
{
struct
wl12xx_vif
*
wlvif
=
wl12xx_vif_to_data
(
vif
);
struct
wl1271
*
wl
=
hw
->
priv
;
...
...
include/linux/ieee80211.h
浏览文件 @
3d5c2032
...
...
@@ -113,6 +113,34 @@
#define IEEE80211_CTL_EXT_SSW_FBACK 0x9000
#define IEEE80211_CTL_EXT_SSW_ACK 0xa000
#define IEEE80211_SN_MASK ((IEEE80211_SCTL_SEQ) >> 4)
#define IEEE80211_MAX_SN IEEE80211_SN_MASK
#define IEEE80211_SN_MODULO (IEEE80211_MAX_SN + 1)
static
inline
int
ieee80211_sn_less
(
u16
sn1
,
u16
sn2
)
{
return
((
sn1
-
sn2
)
&
IEEE80211_SN_MASK
)
>
(
IEEE80211_SN_MODULO
>>
1
);
}
static
inline
u16
ieee80211_sn_add
(
u16
sn1
,
u16
sn2
)
{
return
(
sn1
+
sn2
)
&
IEEE80211_SN_MASK
;
}
static
inline
u16
ieee80211_sn_inc
(
u16
sn
)
{
return
ieee80211_sn_add
(
sn
,
1
);
}
static
inline
u16
ieee80211_sn_sub
(
u16
sn1
,
u16
sn2
)
{
return
(
sn1
-
sn2
)
&
IEEE80211_SN_MASK
;
}
#define IEEE80211_SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define IEEE80211_SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
/* miscellaneous IEEE 802.11 constants */
#define IEEE80211_MAX_FRAG_THRESHOLD 2352
#define IEEE80211_MAX_RTS_THRESHOLD 2353
...
...
@@ -185,7 +213,7 @@ struct ieee80211_hdr {
u8
addr3
[
6
];
__le16
seq_ctrl
;
u8
addr4
[
6
];
}
__packed
;
}
__packed
__aligned
(
2
)
;
struct
ieee80211_hdr_3addr
{
__le16
frame_control
;
...
...
@@ -194,7 +222,7 @@ struct ieee80211_hdr_3addr {
u8
addr2
[
6
];
u8
addr3
[
6
];
__le16
seq_ctrl
;
}
__packed
;
}
__packed
__aligned
(
2
)
;
struct
ieee80211_qos_hdr
{
__le16
frame_control
;
...
...
@@ -204,7 +232,7 @@ struct ieee80211_qos_hdr {
u8
addr3
[
6
];
__le16
seq_ctrl
;
__le16
qos_ctrl
;
}
__packed
;
}
__packed
__aligned
(
2
)
;
/**
* ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set
...
...
@@ -581,7 +609,7 @@ struct ieee80211s_hdr {
__le32
seqnum
;
u8
eaddr1
[
6
];
u8
eaddr2
[
6
];
}
__packed
;
}
__packed
__aligned
(
2
)
;
/* Mesh flags */
#define MESH_FLAGS_AE_A4 0x1
...
...
@@ -875,7 +903,7 @@ struct ieee80211_mgmt {
}
u
;
}
__packed
action
;
}
u
;
}
__packed
;
}
__packed
__aligned
(
2
)
;
/* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
...
...
@@ -906,20 +934,20 @@ struct ieee80211_rts {
__le16
duration
;
u8
ra
[
6
];
u8
ta
[
6
];
}
__packed
;
}
__packed
__aligned
(
2
)
;
struct
ieee80211_cts
{
__le16
frame_control
;
__le16
duration
;
u8
ra
[
6
];
}
__packed
;
}
__packed
__aligned
(
2
)
;
struct
ieee80211_pspoll
{
__le16
frame_control
;
__le16
aid
;
u8
bssid
[
6
];
u8
ta
[
6
];
}
__packed
;
}
__packed
__aligned
(
2
)
;
/* TDLS */
...
...
@@ -1290,11 +1318,6 @@ struct ieee80211_vht_operation {
}
__packed
;
#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0
#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1
#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2
#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3
/* 802.11ac VHT Capabilities */
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
...
...
@@ -1310,10 +1333,11 @@ struct ieee80211_vht_operation {
#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200
#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700
#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000
#define IEEE80211_VHT_CAP_SOUNDING_DIMEN
TION
_MAX 0x00030000
#define IEEE80211_VHT_CAP_SOUNDING_DIMEN
SIONS
_MAX 0x00030000
#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
...
...
include/net/cfg80211.h
浏览文件 @
3d5c2032
...
...
@@ -610,23 +610,11 @@ struct cfg80211_ap_settings {
bool
radar_required
;
};
/**
* enum plink_action - actions to perform in mesh peers
*
* @PLINK_ACTION_INVALID: action 0 is reserved
* @PLINK_ACTION_OPEN: start mesh peer link establishment
* @PLINK_ACTION_BLOCK: block traffic from this mesh peer
*/
enum
plink_actions
{
PLINK_ACTION_INVALID
,
PLINK_ACTION_OPEN
,
PLINK_ACTION_BLOCK
,
};
/**
* enum station_parameters_apply_mask - station parameter values to apply
* @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
* @STATION_PARAM_APPLY_CAPABILITY: apply new capability
* @STATION_PARAM_APPLY_PLINK_STATE: apply new plink state
*
* Not all station parameters have in-band "no change" signalling,
* for those that don't these flags will are used.
...
...
@@ -634,6 +622,7 @@ enum plink_actions {
enum
station_parameters_apply_mask
{
STATION_PARAM_APPLY_UAPSD
=
BIT
(
0
),
STATION_PARAM_APPLY_CAPABILITY
=
BIT
(
1
),
STATION_PARAM_APPLY_PLINK_STATE
=
BIT
(
2
),
};
/**
...
...
@@ -669,7 +658,7 @@ enum station_parameters_apply_mask {
* @ext_capab_len: number of extended capabilities
*/
struct
station_parameters
{
u8
*
supported_rates
;
const
u8
*
supported_rates
;
struct
net_device
*
vlan
;
u32
sta_flags_mask
,
sta_flags_set
;
u32
sta_modify_mask
;
...
...
@@ -678,16 +667,59 @@ struct station_parameters {
u8
supported_rates_len
;
u8
plink_action
;
u8
plink_state
;
struct
ieee80211_ht_cap
*
ht_capa
;
struct
ieee80211_vht_cap
*
vht_capa
;
const
struct
ieee80211_ht_cap
*
ht_capa
;
const
struct
ieee80211_vht_cap
*
vht_capa
;
u8
uapsd_queues
;
u8
max_sp
;
enum
nl80211_mesh_power_mode
local_pm
;
u16
capability
;
u8
*
ext_capab
;
const
u8
*
ext_capab
;
u8
ext_capab_len
;
};
/**
* enum cfg80211_station_type - the type of station being modified
* @CFG80211_STA_AP_CLIENT: client of an AP interface
* @CFG80211_STA_AP_MLME_CLIENT: client of an AP interface that has
* the AP MLME in the device
* @CFG80211_STA_AP_STA: AP station on managed interface
* @CFG80211_STA_IBSS: IBSS station
* @CFG80211_STA_TDLS_PEER_SETUP: TDLS peer on managed interface (dummy entry
* while TDLS setup is in progress, it moves out of this state when
* being marked authorized; use this only if TDLS with external setup is
* supported/used)
* @CFG80211_STA_TDLS_PEER_ACTIVE: TDLS peer on managed interface (active
* entry that is operating, has been marked authorized by userspace)
* @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed)
* @CFG80211_STA_MESH_PEER_USER: peer on mesh interface (user managed)
*/
enum
cfg80211_station_type
{
CFG80211_STA_AP_CLIENT
,
CFG80211_STA_AP_MLME_CLIENT
,
CFG80211_STA_AP_STA
,
CFG80211_STA_IBSS
,
CFG80211_STA_TDLS_PEER_SETUP
,
CFG80211_STA_TDLS_PEER_ACTIVE
,
CFG80211_STA_MESH_PEER_KERNEL
,
CFG80211_STA_MESH_PEER_USER
,
};
/**
* cfg80211_check_station_change - validate parameter changes
* @wiphy: the wiphy this operates on
* @params: the new parameters for a station
* @statype: the type of station being modified
*
* Utility function for the @change_station driver method. Call this function
* with the appropriate station type looking up the station (and checking that
* it exists). It will verify whether the station change is acceptable, and if
* not will return an error code. Note that it may modify the parameters for
* backward compatibility reasons, so don't use them before calling this.
*/
int
cfg80211_check_station_change
(
struct
wiphy
*
wiphy
,
struct
station_parameters
*
params
,
enum
cfg80211_station_type
statype
);
/**
* enum station_info_flags - station information flags
*
...
...
@@ -1119,6 +1151,7 @@ struct mesh_config {
* @ie_len: length of vendor information elements
* @is_authenticated: this mesh requires authentication
* @is_secure: this mesh uses security
* @user_mpm: userspace handles all MPM functions
* @dtim_period: DTIM period to use
* @beacon_interval: beacon interval to use
* @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
...
...
@@ -1136,6 +1169,7 @@ struct mesh_setup {
u8
ie_len
;
bool
is_authenticated
;
bool
is_secure
;
bool
user_mpm
;
u8
dtim_period
;
u16
beacon_interval
;
int
mcast_rate
[
IEEE80211_NUM_BANDS
];
...
...
@@ -1398,9 +1432,11 @@ struct cfg80211_auth_request {
* enum cfg80211_assoc_req_flags - Over-ride default behaviour in association.
*
* @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n)
* @ASSOC_REQ_DISABLE_VHT: Disable VHT
*/
enum
cfg80211_assoc_req_flags
{
ASSOC_REQ_DISABLE_HT
=
BIT
(
0
),
ASSOC_REQ_DISABLE_VHT
=
BIT
(
1
),
};
/**
...
...
@@ -1422,6 +1458,8 @@ enum cfg80211_assoc_req_flags {
* @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
* will be used in ht_capa. Un-supported values will be ignored.
* @ht_capa_mask: The bits of ht_capa which are to be used.
* @vht_capa: VHT capability override
* @vht_capa_mask: VHT capability mask indicating which fields to use
*/
struct
cfg80211_assoc_request
{
struct
cfg80211_bss
*
bss
;
...
...
@@ -1432,6 +1470,7 @@ struct cfg80211_assoc_request {
u32
flags
;
struct
ieee80211_ht_cap
ht_capa
;
struct
ieee80211_ht_cap
ht_capa_mask
;
struct
ieee80211_vht_cap
vht_capa
,
vht_capa_mask
;
};
/**
...
...
@@ -1542,6 +1581,8 @@ struct cfg80211_ibss_params {
* @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
* will be used in ht_capa. Un-supported values will be ignored.
* @ht_capa_mask: The bits of ht_capa which are to be used.
* @vht_capa: VHT Capability overrides
* @vht_capa_mask: The bits of vht_capa which are to be used.
*/
struct
cfg80211_connect_params
{
struct
ieee80211_channel
*
channel
;
...
...
@@ -1560,6 +1601,8 @@ struct cfg80211_connect_params {
int
bg_scan_period
;
struct
ieee80211_ht_cap
ht_capa
;
struct
ieee80211_ht_cap
ht_capa_mask
;
struct
ieee80211_vht_cap
vht_capa
;
struct
ieee80211_vht_cap
vht_capa_mask
;
};
/**
...
...
@@ -1721,6 +1764,21 @@ struct cfg80211_gtk_rekey_data {
u8
replay_ctr
[
NL80211_REPLAY_CTR_LEN
];
};
/**
* struct cfg80211_update_ft_ies_params - FT IE Information
*
* This structure provides information needed to update the fast transition IE
*
* @md: The Mobility Domain ID, 2 Octet value
* @ie: Fast Transition IEs
* @ie_len: Length of ft_ie in octets
*/
struct
cfg80211_update_ft_ies_params
{
u16
md
;
const
u8
*
ie
;
size_t
ie_len
;
};
/**
* struct cfg80211_ops - backend description for wireless configuration
*
...
...
@@ -1781,9 +1839,8 @@ struct cfg80211_gtk_rekey_data {
* @change_station: Modify a given station. Note that flags changes are not much
* validated in cfg80211, in particular the auth/assoc/authorized flags
* might come to the driver in invalid combinations -- make sure to check
* them, also against the existing state! Also, supported_rates changes are
* not checked in station mode -- drivers need to reject (or ignore) them
* for anything but TDLS peers.
* them, also against the existing state! Drivers must call
* cfg80211_check_station_change() to validate the information.
* @get_station: get station information for the station identified by @mac
* @dump_station: dump station callback -- resume dump at index @idx
*
...
...
@@ -2168,6 +2225,8 @@ struct cfg80211_ops {
int
(
*
start_radar_detection
)(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
cfg80211_chan_def
*
chandef
);
int
(
*
update_ft_ies
)(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
cfg80211_update_ft_ies_params
*
ftie
);
};
/*
...
...
@@ -2485,6 +2544,8 @@ struct wiphy_wowlan_support {
* @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
* @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden.
* If null, then none can be over-ridden.
* @vht_capa_mod_mask: Specify what VHT capabilities can be over-ridden.
* If null, then none can be over-ridden.
*
* @max_acl_mac_addrs: Maximum number of MAC addresses that the device
* supports for ACL.
...
...
@@ -2593,6 +2654,7 @@ struct wiphy {
struct
dentry
*
debugfsdir
;
const
struct
ieee80211_ht_cap
*
ht_capa_mod_mask
;
const
struct
ieee80211_vht_cap
*
vht_capa_mod_mask
;
#ifdef CONFIG_NET_NS
/* the network namespace this phy lives in currently */
...
...
@@ -4001,6 +4063,30 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate);
*/
void
cfg80211_unregister_wdev
(
struct
wireless_dev
*
wdev
);
/**
* struct cfg80211_ft_event - FT Information Elements
* @ies: FT IEs
* @ies_len: length of the FT IE in bytes
* @target_ap: target AP's MAC address
* @ric_ies: RIC IE
* @ric_ies_len: length of the RIC IE in bytes
*/
struct
cfg80211_ft_event_params
{
const
u8
*
ies
;
size_t
ies_len
;
const
u8
*
target_ap
;
const
u8
*
ric_ies
;
size_t
ric_ies_len
;
};
/**
* cfg80211_ft_event - notify userspace about FT IE and RIC IE
* @netdev: network device
* @ft_event: IE information
*/
void
cfg80211_ft_event
(
struct
net_device
*
netdev
,
struct
cfg80211_ft_event_params
*
ft_event
);
/**
* cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer
* @ies: the input IE buffer
...
...
include/net/mac80211.h
浏览文件 @
3d5c2032
...
...
@@ -1101,8 +1101,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
* These flags are used for communication about keys between the driver
* and mac80211, with the @flags parameter of &struct ieee80211_key_conf.
*
* @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates
* that the STA this key will be used with could be using QoS.
* @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the
* driver to indicate that it requires IV generation for this
* particular key.
...
...
@@ -1127,7 +1125,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
* %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW.
*/
enum
ieee80211_key_flags
{
IEEE80211_KEY_FLAG_WMM_STA
=
1
<<
0
,
IEEE80211_KEY_FLAG_GENERATE_IV
=
1
<<
1
,
IEEE80211_KEY_FLAG_GENERATE_MMIC
=
1
<<
2
,
IEEE80211_KEY_FLAG_PAIRWISE
=
1
<<
3
,
...
...
@@ -1231,9 +1228,8 @@ enum ieee80211_sta_rx_bandwidth {
* @addr: MAC address
* @aid: AID we assigned to the station if we're an AP
* @supp_rates: Bitmap of supported rates (per band)
* @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
* @vht_cap: VHT capabilities of this STA; Not restricting any capabilities
* of remote STA. Taking as is.
* @ht_cap: HT capabilities of this STA; restricted to our own capabilities
* @vht_cap: VHT capabilities of this STA; restricted to our own capabilities
* @wme: indicates whether the STA supports WME. Only valid during AP-mode.
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *), size is determined in hw information.
...
...
@@ -2134,6 +2130,24 @@ enum ieee80211_rate_control_changed {
IEEE80211_RC_NSS_CHANGED
=
BIT
(
3
),
};
/**
* enum ieee80211_roc_type - remain on channel type
*
* With the support for multi channel contexts and multi channel operations,
* remain on channel operations might be limited/deferred/aborted by other
* flows/operations which have higher priority (and vise versa).
* Specifying the ROC type can be used by devices to prioritize the ROC
* operations compared to other operations/flows.
*
* @IEEE80211_ROC_TYPE_NORMAL: There are no special requirements for this ROC.
* @IEEE80211_ROC_TYPE_MGMT_TX: The remain on channel request is required
* for sending managment frames offchannel.
*/
enum
ieee80211_roc_type
{
IEEE80211_ROC_TYPE_NORMAL
=
0
,
IEEE80211_ROC_TYPE_MGMT_TX
,
};
/**
* struct ieee80211_ops - callbacks from mac80211 to the driver
*
...
...
@@ -2687,7 +2701,8 @@ struct ieee80211_ops {
int
(
*
remain_on_channel
)(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_channel
*
chan
,
int
duration
);
int
duration
,
enum
ieee80211_roc_type
type
);
int
(
*
cancel_remain_on_channel
)(
struct
ieee80211_hw
*
hw
);
int
(
*
set_ringparam
)(
struct
ieee80211_hw
*
hw
,
u32
tx
,
u32
rx
);
void
(
*
get_ringparam
)(
struct
ieee80211_hw
*
hw
,
...
...
include/uapi/linux/nl80211.h
浏览文件 @
3d5c2032
...
...
@@ -36,7 +36,21 @@
* The station is still assumed to belong to the AP interface it was added
* to.
*
* TODO: need more info?
* Station handling varies per interface type and depending on the driver's
* capabilities.
*
* For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS
* and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows:
* - a setup station entry is added, not yet authorized, without any rate
* or capability information, this just exists to avoid race conditions
* - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid
* to add rate and capability information to the station and at the same
* time mark it authorized.
* - %NL80211_TDLS_ENABLE_LINK is then used
* - after this, the only valid operation is to remove it by tearing down
* the TDLS link (%NL80211_TDLS_DISABLE_LINK)
*
* TODO: need more info for other interface types
*/
/**
...
...
@@ -499,9 +513,11 @@
* @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a
* beacon or probe response from a compatible mesh peer. This is only
* sent while no station information (sta_info) exists for the new peer
* candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set. On
* reception of this notification, userspace may decide to create a new
* station (@NL80211_CMD_NEW_STATION). To stop this notification from
* candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH,
* @NL80211_MESH_SETUP_USERSPACE_AMPE, or
* @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this
* notification, userspace may decide to create a new station
* (@NL80211_CMD_NEW_STATION). To stop this notification from
* reoccurring, the userspace authentication daemon may want to create the
* new station with the AUTHENTICATED flag unset and maybe change it later
* depending on the authentication result.
...
...
@@ -611,6 +627,18 @@
* %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the
* event.
*
* @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features,
* i.e. features for the nl80211 protocol rather than device features.
* Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap.
*
* @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition
* Information Element to the WLAN driver
*
* @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver
* to the supplicant. This will carry the target AP's MAC address along
* with the relevant Information Elements. This event is used to report
* received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
...
...
@@ -765,6 +793,11 @@ enum nl80211_commands {
NL80211_CMD_RADAR_DETECT
,
NL80211_CMD_GET_PROTOCOL_FEATURES
,
NL80211_CMD_UPDATE_FT_IES
,
NL80211_CMD_FT_EVENT
,
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
...
...
@@ -884,7 +917,8 @@ enum nl80211_commands {
* consisting of a nested array.
*
* @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
* @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link.
* @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link
* (see &enum nl80211_plink_action).
* @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
* @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
* info given for %NL80211_CMD_GET_MPATH, nested attribute described at
...
...
@@ -1167,10 +1201,10 @@ enum nl80211_commands {
* @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver
* allows auth frames in a mesh to be passed to userspace for processing via
* the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.
* @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as
*
defined in &enum nl80211_plink_state. Used when userspace is
*
driving the peer link management state machine.
* @NL80211_MESH_SETUP_USERSPACE_
AMPE
must be enabled.
* @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as
defined in
*
&enum nl80211_plink_state. Used when userspace is driving the peer link
*
management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or
* @NL80211_MESH_SETUP_USERSPACE_
MPM
must be enabled.
*
* @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy
* capabilities, the supported WoWLAN triggers
...
...
@@ -1368,6 +1402,18 @@ enum nl80211_commands {
* advertised to the driver, e.g., to enable TDLS off channel operations
* and PU-APSD.
*
* @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see
* &enum nl80211_protocol_features, the attribute is a u32.
*
* @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports
* receiving the data for a single wiphy split across multiple
* messages, given with wiphy dump message
*
* @NL80211_ATTR_MDID: Mobility Domain Identifier
*
* @NL80211_ATTR_IE_RIC: Resource Information Container Information
* Element
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
...
...
@@ -1654,6 +1700,15 @@ enum nl80211_attrs {
NL80211_ATTR_STA_CAPABILITY
,
NL80211_ATTR_STA_EXT_CAPABILITY
,
NL80211_ATTR_PROTOCOL_FEATURES
,
NL80211_ATTR_SPLIT_WIPHY_DUMP
,
NL80211_ATTR_DISABLE_VHT
,
NL80211_ATTR_VHT_CAPABILITY_MASK
,
NL80211_ATTR_MDID
,
NL80211_ATTR_IE_RIC
,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST
,
...
...
@@ -2412,8 +2467,10 @@ enum nl80211_mesh_power_mode {
* @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh
* point.
*
* @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically
* open peer links when we detect compatible mesh peers.
* @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open
* peer links when we detect compatible mesh peers. Disabled if
* @NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are
* set.
*
* @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames
* containing a PREQ that an MP can send to a particular destination (path
...
...
@@ -2559,6 +2616,9 @@ enum nl80211_meshconf_params {
* vendor specific synchronization method or disable it to use the default
* neighbor offset synchronization
*
* @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will
* implement an MPM which handles peer allocation and state.
*
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
*
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
...
...
@@ -2571,6 +2631,7 @@ enum nl80211_mesh_setup_params {
NL80211_MESH_SETUP_USERSPACE_AUTH
,
NL80211_MESH_SETUP_USERSPACE_AMPE
,
NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC
,
NL80211_MESH_SETUP_USERSPACE_MPM
,
/* keep last */
__NL80211_MESH_SETUP_ATTR_AFTER_LAST
,
...
...
@@ -3307,6 +3368,23 @@ enum nl80211_plink_state {
MAX_NL80211_PLINK_STATES
=
NUM_NL80211_PLINK_STATES
-
1
};
/**
* enum nl80211_plink_action - actions to perform in mesh peers
*
* @NL80211_PLINK_ACTION_NO_ACTION: perform no action
* @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment
* @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer
* @NUM_NL80211_PLINK_ACTIONS: number of possible actions
*/
enum
plink_actions
{
NL80211_PLINK_ACTION_NO_ACTION
,
NL80211_PLINK_ACTION_OPEN
,
NL80211_PLINK_ACTION_BLOCK
,
NUM_NL80211_PLINK_ACTIONS
,
};
#define NL80211_KCK_LEN 16
#define NL80211_KEK_LEN 16
#define NL80211_REPLAY_CTR_LEN 8
...
...
@@ -3456,6 +3534,10 @@ enum nl80211_ap_sme_features {
* stations the authenticated/associated bits have to be set in the mask.
* @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits
* (HT40, VHT 80/160 MHz) if this flag is set
* @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh
* Peering Management entity which may be implemented by registering for
* beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is
* still generated by the driver.
*/
enum
nl80211_feature_flags
{
NL80211_FEATURE_SK_TX_STATUS
=
1
<<
0
,
...
...
@@ -3474,6 +3556,7 @@ enum nl80211_feature_flags {
/* bit 13 is reserved */
NL80211_FEATURE_ADVERTISE_CHAN_LIMITS
=
1
<<
14
,
NL80211_FEATURE_FULL_AP_CLIENT_STATE
=
1
<<
15
,
NL80211_FEATURE_USERSPACE_MPM
=
1
<<
16
,
};
/**
...
...
@@ -3587,4 +3670,16 @@ enum nl80211_dfs_state {
NL80211_DFS_AVAILABLE
,
};
/**
* enum enum nl80211_protocol_features - nl80211 protocol features
* @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting
* wiphy dumps (if requested by the application with the attribute
* %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the
* wiphy dump by %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFINDEX or
* %NL80211_ATTR_WDEV.
*/
enum
nl80211_protocol_features
{
NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP
=
1
<<
0
,
};
#endif
/* __LINUX_NL80211_H */
net/mac80211/cfg.c
浏览文件 @
3d5c2032
...
...
@@ -254,7 +254,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
goto
out_unlock
;
}
__ieee80211_key_free
(
key
);
__ieee80211_key_free
(
key
,
true
);
ret
=
0
;
out_unlock:
...
...
@@ -1035,9 +1035,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
sta_info_flush_defer
(
vlan
);
sta_info_flush_defer
(
sdata
);
rcu_barrier
();
list_for_each_entry
(
vlan
,
&
sdata
->
u
.
ap
.
vlans
,
u
.
vlan
.
list
)
list_for_each_entry
(
vlan
,
&
sdata
->
u
.
ap
.
vlans
,
u
.
vlan
.
list
)
{
sta_info_flush_cleanup
(
vlan
);
ieee80211_free_keys
(
vlan
);
}
sta_info_flush_cleanup
(
sdata
);
ieee80211_free_keys
(
sdata
);
sdata
->
vif
.
bss_conf
.
enable_beacon
=
false
;
clear_bit
(
SDATA_STATE_OFFCHANNEL_BEACON_STOPPED
,
&
sdata
->
state
);
...
...
@@ -1177,6 +1180,18 @@ static int sta_apply_parameters(struct ieee80211_local *local,
mask
|=
BIT
(
NL80211_STA_FLAG_ASSOCIATED
);
if
(
set
&
BIT
(
NL80211_STA_FLAG_AUTHENTICATED
))
set
|=
BIT
(
NL80211_STA_FLAG_ASSOCIATED
);
}
else
if
(
test_sta_flag
(
sta
,
WLAN_STA_TDLS_PEER
))
{
/*
* TDLS -- everything follows authorized, but
* only becoming authorized is possible, not
* going back
*/
if
(
set
&
BIT
(
NL80211_STA_FLAG_AUTHORIZED
))
{
set
|=
BIT
(
NL80211_STA_FLAG_AUTHENTICATED
)
|
BIT
(
NL80211_STA_FLAG_ASSOCIATED
);
mask
|=
BIT
(
NL80211_STA_FLAG_AUTHENTICATED
)
|
BIT
(
NL80211_STA_FLAG_ASSOCIATED
);
}
}
ret
=
sta_apply_auth_flags
(
local
,
sta
,
mask
,
set
);
...
...
@@ -1261,7 +1276,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
if
(
ieee80211_vif_is_mesh
(
&
sdata
->
vif
))
{
#ifdef CONFIG_MAC80211_MESH
u32
changed
=
0
;
if
(
sdata
->
u
.
mesh
.
security
&
IEEE80211_MESH_SEC_SECURED
)
{
if
(
params
->
sta_modify_mask
&
STATION_PARAM_APPLY_PLINK_STATE
)
{
switch
(
params
->
plink_state
)
{
case
NL80211_PLINK_ESTAB
:
if
(
sta
->
plink_state
!=
NL80211_PLINK_ESTAB
)
...
...
@@ -1292,15 +1308,18 @@ static int sta_apply_parameters(struct ieee80211_local *local,
/* nothing */
break
;
}
}
else
{
switch
(
params
->
plink_action
)
{
case
PLINK_ACTION_OPEN
:
changed
|=
mesh_plink_open
(
sta
);
break
;
case
PLINK_ACTION_BLOCK
:
changed
|=
mesh_plink_block
(
sta
);
break
;
}
}
switch
(
params
->
plink_action
)
{
case
NL80211_PLINK_ACTION_NO_ACTION
:
/* nothing */
break
;
case
NL80211_PLINK_ACTION_OPEN
:
changed
|=
mesh_plink_open
(
sta
);
break
;
case
NL80211_PLINK_ACTION_BLOCK
:
changed
|=
mesh_plink_block
(
sta
);
break
;
}
if
(
params
->
local_pm
)
...
...
@@ -1346,8 +1365,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
* defaults -- if userspace wants something else we'll
* change it accordingly in sta_apply_parameters()
*/
sta_info_pre_move_state
(
sta
,
IEEE80211_STA_AUTH
);
sta_info_pre_move_state
(
sta
,
IEEE80211_STA_ASSOC
);
if
(
!
(
params
->
sta_flags_set
&
BIT
(
NL80211_STA_FLAG_TDLS_PEER
)))
{
sta_info_pre_move_state
(
sta
,
IEEE80211_STA_AUTH
);
sta_info_pre_move_state
(
sta
,
IEEE80211_STA_ASSOC
);
}
err
=
sta_apply_parameters
(
local
,
sta
,
params
);
if
(
err
)
{
...
...
@@ -1356,8 +1377,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
}
/*
* for TDLS, rate control should be initialized only when
supported
* rates are known
.
* for TDLS, rate control should be initialized only when
* rates are known
and station is marked authorized
*/
if
(
!
test_sta_flag
(
sta
,
WLAN_STA_TDLS_PEER
))
rate_control_rate_init
(
sta
);
...
...
@@ -1394,50 +1415,67 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
}
static
int
ieee80211_change_station
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
u8
*
mac
,
struct
net_device
*
dev
,
u8
*
mac
,
struct
station_parameters
*
params
)
{
struct
ieee80211_sub_if_data
*
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
dev
);
struct
ieee80211_local
*
local
=
wiphy_priv
(
wiphy
);
struct
sta_info
*
sta
;
struct
ieee80211_sub_if_data
*
vlansdata
;
enum
cfg80211_station_type
statype
;
int
err
;
mutex_lock
(
&
local
->
sta_mtx
);
sta
=
sta_info_get_bss
(
sdata
,
mac
);
if
(
!
sta
)
{
mutex_unlock
(
&
local
->
sta_mtx
)
;
return
-
ENOENT
;
err
=
-
ENOENT
;
goto
out_err
;
}
/* in station mode, some updates are only valid with TDLS */
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_STATION
&&
(
params
->
supported_rates
||
params
->
ht_capa
||
params
->
vht_capa
||
params
->
sta_modify_mask
||
(
params
->
sta_flags_mask
&
BIT
(
NL80211_STA_FLAG_WME
)))
&&
!
test_sta_flag
(
sta
,
WLAN_STA_TDLS_PEER
))
{
mutex_unlock
(
&
local
->
sta_mtx
);
return
-
EINVAL
;
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_MESH_POINT
:
if
(
sdata
->
u
.
mesh
.
user_mpm
)
statype
=
CFG80211_STA_MESH_PEER_USER
;
else
statype
=
CFG80211_STA_MESH_PEER_KERNEL
;
break
;
case
NL80211_IFTYPE_ADHOC
:
statype
=
CFG80211_STA_IBSS
;
break
;
case
NL80211_IFTYPE_STATION
:
if
(
!
test_sta_flag
(
sta
,
WLAN_STA_TDLS_PEER
))
{
statype
=
CFG80211_STA_AP_STA
;
break
;
}
if
(
test_sta_flag
(
sta
,
WLAN_STA_AUTHORIZED
))
statype
=
CFG80211_STA_TDLS_PEER_ACTIVE
;
else
statype
=
CFG80211_STA_TDLS_PEER_SETUP
;
break
;
case
NL80211_IFTYPE_AP
:
case
NL80211_IFTYPE_AP_VLAN
:
statype
=
CFG80211_STA_AP_CLIENT
;
break
;
default:
err
=
-
EOPNOTSUPP
;
goto
out_err
;
}
err
=
cfg80211_check_station_change
(
wiphy
,
params
,
statype
);
if
(
err
)
goto
out_err
;
if
(
params
->
vlan
&&
params
->
vlan
!=
sta
->
sdata
->
dev
)
{
bool
prev_4addr
=
false
;
bool
new_4addr
=
false
;
vlansdata
=
IEEE80211_DEV_TO_SUB_IF
(
params
->
vlan
);
if
(
vlansdata
->
vif
.
type
!=
NL80211_IFTYPE_AP_VLAN
&&
vlansdata
->
vif
.
type
!=
NL80211_IFTYPE_AP
)
{
mutex_unlock
(
&
local
->
sta_mtx
);
return
-
EINVAL
;
}
if
(
params
->
vlan
->
ieee80211_ptr
->
use_4addr
)
{
if
(
vlansdata
->
u
.
vlan
.
sta
)
{
mutex_unlock
(
&
local
->
sta_mtx
)
;
return
-
EBUSY
;
err
=
-
EBUSY
;
goto
out_err
;
}
rcu_assign_pointer
(
vlansdata
->
u
.
vlan
.
sta
,
sta
);
...
...
@@ -1464,12 +1502,12 @@ static int ieee80211_change_station(struct wiphy *wiphy,
}
err
=
sta_apply_parameters
(
local
,
sta
,
params
);
if
(
err
)
{
mutex_unlock
(
&
local
->
sta_mtx
);
return
err
;
}
if
(
err
)
goto
out_err
;
if
(
test_sta_flag
(
sta
,
WLAN_STA_TDLS_PEER
)
&&
params
->
supported_rates
)
/* When peer becomes authorized, init rate control as well */
if
(
test_sta_flag
(
sta
,
WLAN_STA_TDLS_PEER
)
&&
test_sta_flag
(
sta
,
WLAN_STA_AUTHORIZED
))
rate_control_rate_init
(
sta
);
mutex_unlock
(
&
local
->
sta_mtx
);
...
...
@@ -1479,7 +1517,11 @@ static int ieee80211_change_station(struct wiphy *wiphy,
ieee80211_recalc_ps
(
local
,
-
1
);
ieee80211_recalc_ps_vif
(
sdata
);
}
return
0
;
out_err:
mutex_unlock
(
&
local
->
sta_mtx
);
return
err
;
}
#ifdef CONFIG_MAC80211_MESH
...
...
@@ -1687,6 +1729,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
ifmsh
->
mesh_sp_id
=
setup
->
sync_method
;
ifmsh
->
mesh_pp_id
=
setup
->
path_sel_proto
;
ifmsh
->
mesh_pm_id
=
setup
->
path_metric
;
ifmsh
->
user_mpm
=
setup
->
user_mpm
;
ifmsh
->
security
=
IEEE80211_MESH_SEC_NONE
;
if
(
setup
->
is_authenticated
)
ifmsh
->
security
|=
IEEE80211_MESH_SEC_AUTHED
;
...
...
@@ -1730,8 +1773,11 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
conf
->
dot11MeshTTL
=
nconf
->
dot11MeshTTL
;
if
(
_chg_mesh_attr
(
NL80211_MESHCONF_ELEMENT_TTL
,
mask
))
conf
->
element_ttl
=
nconf
->
element_ttl
;
if
(
_chg_mesh_attr
(
NL80211_MESHCONF_AUTO_OPEN_PLINKS
,
mask
))
if
(
_chg_mesh_attr
(
NL80211_MESHCONF_AUTO_OPEN_PLINKS
,
mask
))
{
if
(
ifmsh
->
user_mpm
)
return
-
EBUSY
;
conf
->
auto_open_plinks
=
nconf
->
auto_open_plinks
;
}
if
(
_chg_mesh_attr
(
NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR
,
mask
))
conf
->
dot11MeshNbrOffsetMaxNeighbor
=
nconf
->
dot11MeshNbrOffsetMaxNeighbor
;
...
...
@@ -2371,7 +2417,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_channel
*
channel
,
unsigned
int
duration
,
u64
*
cookie
,
struct
sk_buff
*
txskb
)
struct
sk_buff
*
txskb
,
enum
ieee80211_roc_type
type
)
{
struct
ieee80211_roc_work
*
roc
,
*
tmp
;
bool
queued
=
false
;
...
...
@@ -2390,6 +2437,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
roc
->
duration
=
duration
;
roc
->
req_duration
=
duration
;
roc
->
frame
=
txskb
;
roc
->
type
=
type
;
roc
->
mgmt_tx_cookie
=
(
unsigned
long
)
txskb
;
roc
->
sdata
=
sdata
;
INIT_DELAYED_WORK
(
&
roc
->
work
,
ieee80211_sw_roc_work
);
...
...
@@ -2420,7 +2468,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
if
(
!
duration
)
duration
=
10
;
ret
=
drv_remain_on_channel
(
local
,
sdata
,
channel
,
duration
);
ret
=
drv_remain_on_channel
(
local
,
sdata
,
channel
,
duration
,
type
);
if
(
ret
)
{
kfree
(
roc
);
return
ret
;
...
...
@@ -2439,10 +2487,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
*
* If it hasn't started yet, just increase the duration
* and add the new one to the list of dependents.
* If the type of the new ROC has higher priority, modify the
* type of the previous one to match that of the new one.
*/
if
(
!
tmp
->
started
)
{
list_add_tail
(
&
roc
->
list
,
&
tmp
->
dependents
);
tmp
->
duration
=
max
(
tmp
->
duration
,
roc
->
duration
);
tmp
->
type
=
max
(
tmp
->
type
,
roc
->
type
);
queued
=
true
;
break
;
}
...
...
@@ -2454,16 +2505,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
/*
* In the offloaded ROC case, if it hasn't begun, add
* this new one to the dependent list to be handled
* when the
the
master one begins. If it has begun,
* when the master one begins. If it has begun,
* check that there's still a minimum time left and
* if so, start this one, transmitting the frame, but
* add it to the list directly after this one with
a
* add it to the list directly after this one with
* a reduced time so we'll ask the driver to execute
* it right after finishing the previous one, in the
* hope that it'll also be executed right afterwards,
* effectively extending the old one.
* If there's no minimum time left, just add it to the
* normal list.
* TODO: the ROC type is ignored here, assuming that it
* is better to immediately use the current ROC.
*/
if
(
!
tmp
->
hw_begun
)
{
list_add_tail
(
&
roc
->
list
,
&
tmp
->
dependents
);
...
...
@@ -2557,7 +2610,8 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy,
mutex_lock
(
&
local
->
mtx
);
ret
=
ieee80211_start_roc_work
(
local
,
sdata
,
chan
,
duration
,
cookie
,
NULL
);
duration
,
cookie
,
NULL
,
IEEE80211_ROC_TYPE_NORMAL
);
mutex_unlock
(
&
local
->
mtx
);
return
ret
;
...
...
@@ -2790,7 +2844,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
/* This will handle all kinds of coalescing and immediate TX */
ret
=
ieee80211_start_roc_work
(
local
,
sdata
,
chan
,
wait
,
cookie
,
skb
);
wait
,
cookie
,
skb
,
IEEE80211_ROC_TYPE_MGMT_TX
);
if
(
ret
)
kfree_skb
(
skb
);
out_unlock:
...
...
@@ -3285,6 +3340,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
struct
cfg80211_chan_def
*
chandef
)
{
struct
ieee80211_sub_if_data
*
sdata
=
IEEE80211_WDEV_TO_SUB_IF
(
wdev
);
struct
ieee80211_local
*
local
=
wiphy_priv
(
wiphy
);
struct
ieee80211_chanctx_conf
*
chanctx_conf
;
int
ret
=
-
ENODATA
;
...
...
@@ -3293,6 +3349,16 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
if
(
chanctx_conf
)
{
*
chandef
=
chanctx_conf
->
def
;
ret
=
0
;
}
else
if
(
local
->
open_count
>
0
&&
local
->
open_count
==
local
->
monitors
&&
sdata
->
vif
.
type
==
NL80211_IFTYPE_MONITOR
)
{
if
(
local
->
use_chanctx
)
*
chandef
=
local
->
monitor_chandef
;
else
cfg80211_chandef_create
(
chandef
,
local
->
_oper_channel
,
local
->
_oper_channel_type
);
ret
=
0
;
}
rcu_read_unlock
();
...
...
net/mac80211/debugfs_sta.c
浏览文件 @
3d5c2032
...
...
@@ -325,6 +325,36 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
}
STA_OPS
(
ht_capa
);
static
ssize_t
sta_vht_capa_read
(
struct
file
*
file
,
char
__user
*
userbuf
,
size_t
count
,
loff_t
*
ppos
)
{
char
buf
[
128
],
*
p
=
buf
;
struct
sta_info
*
sta
=
file
->
private_data
;
struct
ieee80211_sta_vht_cap
*
vhtc
=
&
sta
->
sta
.
vht_cap
;
p
+=
scnprintf
(
p
,
sizeof
(
buf
)
+
buf
-
p
,
"VHT %ssupported
\n
"
,
vhtc
->
vht_supported
?
""
:
"not "
);
if
(
vhtc
->
vht_supported
)
{
p
+=
scnprintf
(
p
,
sizeof
(
buf
)
+
buf
-
p
,
"cap: %#.8x
\n
"
,
vhtc
->
cap
);
p
+=
scnprintf
(
p
,
sizeof
(
buf
)
+
buf
-
p
,
"RX MCS: %.4x
\n
"
,
le16_to_cpu
(
vhtc
->
vht_mcs
.
rx_mcs_map
));
if
(
vhtc
->
vht_mcs
.
rx_highest
)
p
+=
scnprintf
(
p
,
sizeof
(
buf
)
+
buf
-
p
,
"MCS RX highest: %d Mbps
\n
"
,
le16_to_cpu
(
vhtc
->
vht_mcs
.
rx_highest
));
p
+=
scnprintf
(
p
,
sizeof
(
buf
)
+
buf
-
p
,
"TX MCS: %.4x
\n
"
,
le16_to_cpu
(
vhtc
->
vht_mcs
.
tx_mcs_map
));
if
(
vhtc
->
vht_mcs
.
tx_highest
)
p
+=
scnprintf
(
p
,
sizeof
(
buf
)
+
buf
-
p
,
"MCS TX highest: %d Mbps
\n
"
,
le16_to_cpu
(
vhtc
->
vht_mcs
.
tx_highest
));
}
return
simple_read_from_buffer
(
userbuf
,
count
,
ppos
,
buf
,
p
-
buf
);
}
STA_OPS
(
vht_capa
);
static
ssize_t
sta_current_tx_rate_read
(
struct
file
*
file
,
char
__user
*
userbuf
,
size_t
count
,
loff_t
*
ppos
)
{
...
...
@@ -405,6 +435,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD
(
dev
);
DEBUGFS_ADD
(
last_signal
);
DEBUGFS_ADD
(
ht_capa
);
DEBUGFS_ADD
(
vht_capa
);
DEBUGFS_ADD
(
last_ack_signal
);
DEBUGFS_ADD
(
current_tx_rate
);
DEBUGFS_ADD
(
last_rx_rate
);
...
...
net/mac80211/driver-ops.h
浏览文件 @
3d5c2032
...
...
@@ -787,15 +787,16 @@ static inline int drv_get_antenna(struct ieee80211_local *local,
static
inline
int
drv_remain_on_channel
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_channel
*
chan
,
unsigned
int
duration
)
unsigned
int
duration
,
enum
ieee80211_roc_type
type
)
{
int
ret
;
might_sleep
();
trace_drv_remain_on_channel
(
local
,
sdata
,
chan
,
duration
);
trace_drv_remain_on_channel
(
local
,
sdata
,
chan
,
duration
,
type
);
ret
=
local
->
ops
->
remain_on_channel
(
&
local
->
hw
,
&
sdata
->
vif
,
chan
,
duration
);
chan
,
duration
,
type
);
trace_drv_return_int
(
local
,
ret
);
return
ret
;
...
...
net/mac80211/ht.c
浏览文件 @
3d5c2032
...
...
@@ -40,13 +40,6 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
if
(
!
ht_cap
->
ht_supported
)
return
;
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
)
{
/* AP interfaces call this code when adding new stations,
* so just silently ignore non station interfaces.
*/
return
;
}
/* NOTE: If you add more over-rides here, update register_hw
* ht_capa_mod_msk logic in main.c as well.
* And, if this method can ever change ht_cap.ht_supported, fix
...
...
@@ -97,7 +90,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
const
struct
ieee80211_ht_cap
*
ht_cap_ie
,
struct
sta_info
*
sta
)
{
struct
ieee80211_sta_ht_cap
ht_cap
;
struct
ieee80211_sta_ht_cap
ht_cap
,
own_cap
;
u8
ampdu_info
,
tx_mcs_set_cap
;
int
i
,
max_tx_streams
;
bool
changed
;
...
...
@@ -111,6 +104,18 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
ht_cap
.
ht_supported
=
true
;
own_cap
=
sband
->
ht_cap
;
/*
* If user has specified capability over-rides, take care
* of that if the station we're setting up is the AP that
* we advertised a restricted capability set to. Override
* our own capabilities and then use those below.
*/
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_STATION
&&
!
test_sta_flag
(
sta
,
WLAN_STA_TDLS_PEER
))
ieee80211_apply_htcap_overrides
(
sdata
,
&
own_cap
);
/*
* The bits listed in this expression should be
* the same for the peer and us, if the station
...
...
@@ -118,21 +123,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
* we mask them out.
*/
ht_cap
.
cap
=
le16_to_cpu
(
ht_cap_ie
->
cap_info
)
&
(
sband
->
ht_cap
.
cap
|
~
(
IEEE80211_HT_CAP_LDPC_CODING
|
IEEE80211_HT_CAP_SUP_WIDTH_20_40
|
IEEE80211_HT_CAP_GRN_FLD
|
IEEE80211_HT_CAP_SGI_20
|
IEEE80211_HT_CAP_SGI_40
|
IEEE80211_HT_CAP_DSSSCCK40
));
(
own_cap
.
cap
|
~
(
IEEE80211_HT_CAP_LDPC_CODING
|
IEEE80211_HT_CAP_SUP_WIDTH_20_40
|
IEEE80211_HT_CAP_GRN_FLD
|
IEEE80211_HT_CAP_SGI_20
|
IEEE80211_HT_CAP_SGI_40
|
IEEE80211_HT_CAP_DSSSCCK40
));
/*
* The STBC bits are asymmetric -- if we don't have
* TX then mask out the peer's RX and vice versa.
*/
if
(
!
(
sband
->
ht
_cap
.
cap
&
IEEE80211_HT_CAP_TX_STBC
))
if
(
!
(
own
_cap
.
cap
&
IEEE80211_HT_CAP_TX_STBC
))
ht_cap
.
cap
&=
~
IEEE80211_HT_CAP_RX_STBC
;
if
(
!
(
sband
->
ht
_cap
.
cap
&
IEEE80211_HT_CAP_RX_STBC
))
if
(
!
(
own
_cap
.
cap
&
IEEE80211_HT_CAP_RX_STBC
))
ht_cap
.
cap
&=
~
IEEE80211_HT_CAP_TX_STBC
;
ampdu_info
=
ht_cap_ie
->
ampdu_params_info
;
...
...
@@ -142,7 +146,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
(
ampdu_info
&
IEEE80211_HT_AMPDU_PARM_DENSITY
)
>>
2
;
/* own MCS TX capabilities */
tx_mcs_set_cap
=
sband
->
ht
_cap
.
mcs
.
tx_params
;
tx_mcs_set_cap
=
own
_cap
.
mcs
.
tx_params
;
/* Copy peer MCS TX capabilities, the driver might need them. */
ht_cap
.
mcs
.
tx_params
=
ht_cap_ie
->
mcs
.
tx_params
;
...
...
@@ -168,26 +172,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
*/
for
(
i
=
0
;
i
<
max_tx_streams
;
i
++
)
ht_cap
.
mcs
.
rx_mask
[
i
]
=
sband
->
ht
_cap
.
mcs
.
rx_mask
[
i
]
&
ht_cap_ie
->
mcs
.
rx_mask
[
i
];
own
_cap
.
mcs
.
rx_mask
[
i
]
&
ht_cap_ie
->
mcs
.
rx_mask
[
i
];
if
(
tx_mcs_set_cap
&
IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION
)
for
(
i
=
IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE
;
i
<
IEEE80211_HT_MCS_MASK_LEN
;
i
++
)
ht_cap
.
mcs
.
rx_mask
[
i
]
=
sband
->
ht
_cap
.
mcs
.
rx_mask
[
i
]
&
own
_cap
.
mcs
.
rx_mask
[
i
]
&
ht_cap_ie
->
mcs
.
rx_mask
[
i
];
/* handle MCS rate 32 too */
if
(
sband
->
ht
_cap
.
mcs
.
rx_mask
[
32
/
8
]
&
ht_cap_ie
->
mcs
.
rx_mask
[
32
/
8
]
&
1
)
if
(
own
_cap
.
mcs
.
rx_mask
[
32
/
8
]
&
ht_cap_ie
->
mcs
.
rx_mask
[
32
/
8
]
&
1
)
ht_cap
.
mcs
.
rx_mask
[
32
/
8
]
|=
1
;
apply:
/*
* If user has specified capability over-rides, take care
* of that here.
*/
ieee80211_apply_htcap_overrides
(
sdata
,
&
ht_cap
);
changed
=
memcmp
(
&
sta
->
sta
.
ht_cap
,
&
ht_cap
,
sizeof
(
ht_cap
));
memcpy
(
&
sta
->
sta
.
ht_cap
,
&
ht_cap
,
sizeof
(
ht_cap
));
...
...
net/mac80211/ibss.c
浏览文件 @
3d5c2032
...
...
@@ -985,36 +985,9 @@ static void ieee80211_ibss_timer(unsigned long data)
{
struct
ieee80211_sub_if_data
*
sdata
=
(
struct
ieee80211_sub_if_data
*
)
data
;
struct
ieee80211_if_ibss
*
ifibss
=
&
sdata
->
u
.
ibss
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
if
(
local
->
quiescing
)
{
ifibss
->
timer_running
=
true
;
return
;
}
ieee80211_queue_work
(
&
local
->
hw
,
&
sdata
->
work
);
}
#ifdef CONFIG_PM
void
ieee80211_ibss_quiesce
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_if_ibss
*
ifibss
=
&
sdata
->
u
.
ibss
;
if
(
del_timer_sync
(
&
ifibss
->
timer
))
ifibss
->
timer_running
=
true
;
}
void
ieee80211_ibss_restart
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_if_ibss
*
ifibss
=
&
sdata
->
u
.
ibss
;
if
(
ifibss
->
timer_running
)
{
add_timer
(
&
ifibss
->
timer
);
ifibss
->
timer_running
=
false
;
}
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
work
);
}
#endif
void
ieee80211_ibss_setup_sdata
(
struct
ieee80211_sub_if_data
*
sdata
)
{
...
...
net/mac80211/ieee80211_i.h
浏览文件 @
3d5c2032
...
...
@@ -315,6 +315,7 @@ struct ieee80211_roc_work {
u32
duration
,
req_duration
;
struct
sk_buff
*
frame
;
u64
cookie
,
mgmt_tx_cookie
;
enum
ieee80211_roc_type
type
;
};
/* flags used in struct ieee80211_if_managed.flags */
...
...
@@ -400,7 +401,6 @@ struct ieee80211_if_managed {
u16
aid
;
unsigned
long
timers_running
;
/* used for quiesce/restart */
bool
powersave
;
/* powersave requested for this iface */
bool
broken_ap
;
/* AP is broken -- turn off powersave */
u8
dtim_period
;
...
...
@@ -479,6 +479,8 @@ struct ieee80211_if_managed {
struct
ieee80211_ht_cap
ht_capa
;
/* configured ht-cap over-rides */
struct
ieee80211_ht_cap
ht_capa_mask
;
/* Valid parts of ht_capa */
struct
ieee80211_vht_cap
vht_capa
;
/* configured VHT overrides */
struct
ieee80211_vht_cap
vht_capa_mask
;
/* Valid parts of vht_capa */
};
struct
ieee80211_if_ibss
{
...
...
@@ -490,8 +492,6 @@ struct ieee80211_if_ibss {
u32
basic_rates
;
bool
timer_running
;
bool
fixed_bssid
;
bool
fixed_channel
;
bool
privacy
;
...
...
@@ -543,8 +543,6 @@ struct ieee80211_if_mesh {
struct
timer_list
mesh_path_timer
;
struct
timer_list
mesh_path_root_timer
;
unsigned
long
timers_running
;
unsigned
long
wrkq_flags
;
u8
mesh_id
[
IEEE80211_MAX_MESH_ID_LEN
];
...
...
@@ -590,6 +588,7 @@ struct ieee80211_if_mesh {
IEEE80211_MESH_SEC_AUTHED
=
0x1
,
IEEE80211_MESH_SEC_SECURED
=
0x2
,
}
security
;
bool
user_mpm
;
/* Extensible Synchronization Framework */
const
struct
ieee80211_mesh_sync_ops
*
sync_ops
;
s64
sync_offset_clockdrift_max
;
...
...
@@ -682,6 +681,8 @@ struct ieee80211_sub_if_data {
/* count for keys needing tailroom space allocation */
int
crypto_tx_tailroom_needed_cnt
;
int
crypto_tx_tailroom_pending_dec
;
struct
delayed_work
dec_tailroom_needed_wk
;
struct
net_device
*
dev
;
struct
ieee80211_local
*
local
;
...
...
@@ -765,10 +766,6 @@ struct ieee80211_sub_if_data {
}
debugfs
;
#endif
#ifdef CONFIG_PM
struct
ieee80211_bss_conf
suspend_bss_conf
;
#endif
/* must be last, dynamically sized area in this! */
struct
ieee80211_vif
vif
;
};
...
...
@@ -1136,11 +1133,6 @@ struct ieee80211_local {
struct
ieee80211_sub_if_data
__rcu
*
p2p_sdata
;
/* dummy netdev for use w/ NAPI */
struct
net_device
napi_dev
;
struct
napi_struct
napi
;
/* virtual monitor interface */
struct
ieee80211_sub_if_data
__rcu
*
monitor_sdata
;
struct
cfg80211_chan_def
monitor_chandef
;
...
...
@@ -1283,8 +1275,6 @@ void
ieee80211_sta_process_chanswitch
(
struct
ieee80211_sub_if_data
*
sdata
,
const
struct
ieee80211_channel_sw_ie
*
sw_elem
,
struct
ieee80211_bss
*
bss
,
u64
timestamp
);
void
ieee80211_sta_quiesce
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_sta_restart
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_sta_work
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_sta_rx_queued_mgmt
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
sk_buff
*
skb
);
...
...
@@ -1302,8 +1292,6 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
int
ieee80211_ibss_join
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
cfg80211_ibss_params
*
params
);
int
ieee80211_ibss_leave
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_ibss_quiesce
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_ibss_restart
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_ibss_work
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_ibss_rx_queued_mgmt
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
sk_buff
*
skb
);
...
...
@@ -1441,6 +1429,8 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta);
void
ieee80211_vht_handle_opmode
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
sta_info
*
sta
,
u8
opmode
,
enum
ieee80211_band
band
,
bool
nss_only
);
void
ieee80211_apply_vhtcap_overrides
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_sta_vht_cap
*
vht_cap
);
/* Spectrum management */
void
ieee80211_process_measurement_req
(
struct
ieee80211_sub_if_data
*
sdata
,
...
...
net/mac80211/iface.c
浏览文件 @
3d5c2032
...
...
@@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
lockdep_assert_held
(
&
local
->
mtx
);
active
=
!
list_empty
(
&
local
->
chanctx_list
);
active
=
!
list_empty
(
&
local
->
chanctx_list
)
||
local
->
monitors
;
if
(
!
local
->
ops
->
remain_on_channel
)
{
list_for_each_entry
(
roc
,
&
local
->
roc_list
,
list
)
{
...
...
@@ -485,8 +485,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
res
=
drv_start
(
local
);
if
(
res
)
goto
err_del_bss
;
if
(
local
->
ops
->
napi_poll
)
napi_enable
(
&
local
->
napi
);
/* we're brought up, everything changes */
hw_reconf_flags
=
~
0
;
ieee80211_led_radio
(
local
,
true
);
...
...
@@ -541,6 +539,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
ieee80211_adjust_monitor_flags
(
sdata
,
1
);
ieee80211_configure_filter
(
local
);
mutex_lock
(
&
local
->
mtx
);
ieee80211_recalc_idle
(
local
);
mutex_unlock
(
&
local
->
mtx
);
netif_carrier_on
(
dev
);
break
;
...
...
@@ -812,6 +813,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
ieee80211_adjust_monitor_flags
(
sdata
,
-
1
);
ieee80211_configure_filter
(
local
);
mutex_lock
(
&
local
->
mtx
);
ieee80211_recalc_idle
(
local
);
mutex_unlock
(
&
local
->
mtx
);
break
;
case
NL80211_IFTYPE_P2P_DEVICE
:
/* relies on synchronize_rcu() below */
...
...
@@ -832,14 +836,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
rcu_barrier
();
sta_info_flush_cleanup
(
sdata
);
skb_queue_purge
(
&
sdata
->
skb_queue
);
/*
* Free all remaining keys, there shouldn't be any,
* except maybe
group keys in AP more or WDS
?
* except maybe
in WDS mode
?
*/
ieee80211_free_keys
(
sdata
);
/* fall through */
case
NL80211_IFTYPE_AP
:
skb_queue_purge
(
&
sdata
->
skb_queue
);
drv_remove_interface_debugfs
(
local
,
sdata
);
if
(
going_down
)
...
...
@@ -851,8 +857,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_ps
(
local
,
-
1
);
if
(
local
->
open_count
==
0
)
{
if
(
local
->
ops
->
napi_poll
)
napi_disable
(
&
local
->
napi
);
ieee80211_clear_tx_pending
(
local
);
ieee80211_stop_device
(
local
);
...
...
@@ -1541,6 +1545,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
INIT_WORK
(
&
sdata
->
cleanup_stations_wk
,
ieee80211_cleanup_sdata_stas_wk
);
INIT_DELAYED_WORK
(
&
sdata
->
dfs_cac_timer_work
,
ieee80211_dfs_cac_timer_work
);
INIT_DELAYED_WORK
(
&
sdata
->
dec_tailroom_needed_wk
,
ieee80211_delayed_tailroom_dec
);
for
(
i
=
0
;
i
<
IEEE80211_NUM_BANDS
;
i
++
)
{
struct
ieee80211_supported_band
*
sband
;
...
...
net/mac80211/key.c
浏览文件 @
3d5c2032
...
...
@@ -397,7 +397,8 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
return
key
;
}
static
void
__ieee80211_key_destroy
(
struct
ieee80211_key
*
key
)
static
void
__ieee80211_key_destroy
(
struct
ieee80211_key
*
key
,
bool
delay_tailroom
)
{
if
(
!
key
)
return
;
...
...
@@ -416,8 +417,18 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
if
(
key
->
conf
.
cipher
==
WLAN_CIPHER_SUITE_AES_CMAC
)
ieee80211_aes_cmac_key_free
(
key
->
u
.
aes_cmac
.
tfm
);
if
(
key
->
local
)
{
struct
ieee80211_sub_if_data
*
sdata
=
key
->
sdata
;
ieee80211_debugfs_key_remove
(
key
);
key
->
sdata
->
crypto_tx_tailroom_needed_cnt
--
;
if
(
delay_tailroom
)
{
/* see ieee80211_delayed_tailroom_dec */
sdata
->
crypto_tx_tailroom_pending_dec
++
;
schedule_delayed_work
(
&
sdata
->
dec_tailroom_needed_wk
,
HZ
/
2
);
}
else
{
sdata
->
crypto_tx_tailroom_needed_cnt
--
;
}
}
kfree
(
key
);
...
...
@@ -440,32 +451,6 @@ int ieee80211_key_link(struct ieee80211_key *key,
key
->
sdata
=
sdata
;
key
->
sta
=
sta
;
if
(
sta
)
{
/*
* some hardware cannot handle TKIP with QoS, so
* we indicate whether QoS could be in use.
*/
if
(
test_sta_flag
(
sta
,
WLAN_STA_WME
))
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_WMM_STA
;
}
else
{
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_STATION
)
{
struct
sta_info
*
ap
;
/*
* We're getting a sta pointer in, so must be under
* appropriate locking for sta_info_get().
*/
/* same here, the AP could be using QoS */
ap
=
sta_info_get
(
key
->
sdata
,
key
->
sdata
->
u
.
mgd
.
bssid
);
if
(
ap
)
{
if
(
test_sta_flag
(
ap
,
WLAN_STA_WME
))
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_WMM_STA
;
}
}
}
mutex_lock
(
&
sdata
->
local
->
key_mtx
);
if
(
sta
&&
pairwise
)
...
...
@@ -478,7 +463,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
increment_tailroom_need_count
(
sdata
);
__ieee80211_key_replace
(
sdata
,
sta
,
pairwise
,
old_key
,
key
);
__ieee80211_key_destroy
(
old_key
);
__ieee80211_key_destroy
(
old_key
,
true
);
ieee80211_debugfs_key_add
(
key
);
...
...
@@ -489,7 +474,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
return
ret
;
}
void
__ieee80211_key_free
(
struct
ieee80211_key
*
key
)
void
__ieee80211_key_free
(
struct
ieee80211_key
*
key
,
bool
delay_tailroom
)
{
if
(
!
key
)
return
;
...
...
@@ -501,14 +486,14 @@ void __ieee80211_key_free(struct ieee80211_key *key)
__ieee80211_key_replace
(
key
->
sdata
,
key
->
sta
,
key
->
conf
.
flags
&
IEEE80211_KEY_FLAG_PAIRWISE
,
key
,
NULL
);
__ieee80211_key_destroy
(
key
);
__ieee80211_key_destroy
(
key
,
delay_tailroom
);
}
void
ieee80211_key_free
(
struct
ieee80211_local
*
local
,
struct
ieee80211_key
*
key
)
{
mutex_lock
(
&
local
->
key_mtx
);
__ieee80211_key_free
(
key
);
__ieee80211_key_free
(
key
,
true
);
mutex_unlock
(
&
local
->
key_mtx
);
}
...
...
@@ -566,36 +551,60 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL
(
ieee80211_iter_keys
);
void
ieee80211_disable_keys
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_key
*
key
;
ASSERT_RTNL
();
mutex_lock
(
&
sdata
->
local
->
key_mtx
);
list_for_each_entry
(
key
,
&
sdata
->
key_list
,
list
)
ieee80211_key_disable_hw_accel
(
key
);
mutex_unlock
(
&
sdata
->
local
->
key_mtx
);
}
void
ieee80211_free_keys
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_key
*
key
,
*
tmp
;
cancel_delayed_work_sync
(
&
sdata
->
dec_tailroom_needed_wk
);
mutex_lock
(
&
sdata
->
local
->
key_mtx
);
sdata
->
crypto_tx_tailroom_needed_cnt
-=
sdata
->
crypto_tx_tailroom_pending_dec
;
sdata
->
crypto_tx_tailroom_pending_dec
=
0
;
ieee80211_debugfs_key_remove_mgmt_default
(
sdata
);
list_for_each_entry_safe
(
key
,
tmp
,
&
sdata
->
key_list
,
list
)
__ieee80211_key_free
(
key
);
__ieee80211_key_free
(
key
,
false
);
ieee80211_debugfs_key_update_default
(
sdata
);
WARN_ON_ONCE
(
sdata
->
crypto_tx_tailroom_needed_cnt
||
sdata
->
crypto_tx_tailroom_pending_dec
);
mutex_unlock
(
&
sdata
->
local
->
key_mtx
);
}
void
ieee80211_delayed_tailroom_dec
(
struct
work_struct
*
wk
)
{
struct
ieee80211_sub_if_data
*
sdata
;
sdata
=
container_of
(
wk
,
struct
ieee80211_sub_if_data
,
dec_tailroom_needed_wk
.
work
);
/*
* The reason for the delayed tailroom needed decrementing is to
* make roaming faster: during roaming, all keys are first deleted
* and then new keys are installed. The first new key causes the
* crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes
* the cost of synchronize_net() (which can be slow). Avoid this
* by deferring the crypto_tx_tailroom_needed_cnt decrementing on
* key removal for a while, so if we roam the value is larger than
* zero and no 0->1 transition happens.
*
* The cost is that if the AP switching was from an AP with keys
* to one without, we still allocate tailroom while it would no
* longer be needed. However, in the typical (fast) roaming case
* within an ESS this usually won't happen.
*/
mutex_lock
(
&
sdata
->
local
->
key_mtx
);
sdata
->
crypto_tx_tailroom_needed_cnt
-=
sdata
->
crypto_tx_tailroom_pending_dec
;
sdata
->
crypto_tx_tailroom_pending_dec
=
0
;
mutex_unlock
(
&
sdata
->
local
->
key_mtx
);
}
void
ieee80211_gtk_rekey_notify
(
struct
ieee80211_vif
*
vif
,
const
u8
*
bssid
,
const
u8
*
replay_ctr
,
gfp_t
gfp
)
...
...
net/mac80211/key.h
浏览文件 @
3d5c2032
...
...
@@ -134,7 +134,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
int
__must_check
ieee80211_key_link
(
struct
ieee80211_key
*
key
,
struct
ieee80211_sub_if_data
*
sdata
,
struct
sta_info
*
sta
);
void
__ieee80211_key_free
(
struct
ieee80211_key
*
key
);
void
__ieee80211_key_free
(
struct
ieee80211_key
*
key
,
bool
delay_tailroom
);
void
ieee80211_key_free
(
struct
ieee80211_local
*
local
,
struct
ieee80211_key
*
key
);
void
ieee80211_set_default_key
(
struct
ieee80211_sub_if_data
*
sdata
,
int
idx
,
...
...
@@ -143,9 +143,10 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
int
idx
);
void
ieee80211_free_keys
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_enable_keys
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_disable_keys
(
struct
ieee80211_sub_if_data
*
sdata
);
#define key_mtx_dereference(local, ref) \
rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
void
ieee80211_delayed_tailroom_dec
(
struct
work_struct
*
wk
);
#endif
/* IEEE80211_KEY_H */
net/mac80211/main.c
浏览文件 @
3d5c2032
...
...
@@ -399,30 +399,6 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb,
}
#endif
static
int
ieee80211_napi_poll
(
struct
napi_struct
*
napi
,
int
budget
)
{
struct
ieee80211_local
*
local
=
container_of
(
napi
,
struct
ieee80211_local
,
napi
);
return
local
->
ops
->
napi_poll
(
&
local
->
hw
,
budget
);
}
void
ieee80211_napi_schedule
(
struct
ieee80211_hw
*
hw
)
{
struct
ieee80211_local
*
local
=
hw_to_local
(
hw
);
napi_schedule
(
&
local
->
napi
);
}
EXPORT_SYMBOL
(
ieee80211_napi_schedule
);
void
ieee80211_napi_complete
(
struct
ieee80211_hw
*
hw
)
{
struct
ieee80211_local
*
local
=
hw_to_local
(
hw
);
napi_complete
(
&
local
->
napi
);
}
EXPORT_SYMBOL
(
ieee80211_napi_complete
);
/* There isn't a lot of sense in it, but you can transmit anything you like */
static
const
struct
ieee80211_txrx_stypes
ieee80211_default_mgmt_stypes
[
NUM_NL80211_IFTYPES
]
=
{
...
...
@@ -501,6 +477,27 @@ static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
},
};
static
const
struct
ieee80211_vht_cap
mac80211_vht_capa_mod_mask
=
{
.
vht_cap_info
=
cpu_to_le32
(
IEEE80211_VHT_CAP_RXLDPC
|
IEEE80211_VHT_CAP_SHORT_GI_80
|
IEEE80211_VHT_CAP_SHORT_GI_160
|
IEEE80211_VHT_CAP_RXSTBC_1
|
IEEE80211_VHT_CAP_RXSTBC_2
|
IEEE80211_VHT_CAP_RXSTBC_3
|
IEEE80211_VHT_CAP_RXSTBC_4
|
IEEE80211_VHT_CAP_TXSTBC
|
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
|
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
|
IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN
|
IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN
|
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK
),
.
supp_mcs
=
{
.
rx_mcs_map
=
cpu_to_le16
(
~
0
),
.
tx_mcs_map
=
cpu_to_le16
(
~
0
),
},
};
static
const
u8
extended_capabilities
[]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
WLAN_EXT_CAPA8_OPMODE_NOTIF
,
...
...
@@ -572,7 +569,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
wiphy
->
features
|=
NL80211_FEATURE_SK_TX_STATUS
|
NL80211_FEATURE_SAE
|
NL80211_FEATURE_HT_IBSS
|
NL80211_FEATURE_VIF_TXPOWER
;
NL80211_FEATURE_VIF_TXPOWER
|
NL80211_FEATURE_USERSPACE_MPM
;
if
(
!
ops
->
hw_scan
)
wiphy
->
features
|=
NL80211_FEATURE_LOW_PRIORITY_SCAN
|
...
...
@@ -609,6 +607,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH
;
local
->
user_power_level
=
IEEE80211_UNSET_POWER_LEVEL
;
wiphy
->
ht_capa_mod_mask
=
&
mac80211_ht_capa_mod_mask
;
wiphy
->
vht_capa_mod_mask
=
&
mac80211_vht_capa_mod_mask
;
INIT_LIST_HEAD
(
&
local
->
interfaces
);
...
...
@@ -664,9 +663,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
skb_queue_head_init
(
&
local
->
skb_queue
);
skb_queue_head_init
(
&
local
->
skb_queue_unreliable
);
/* init dummy netdev for use w/ NAPI */
init_dummy_netdev
(
&
local
->
napi_dev
);
ieee80211_led_names
(
local
);
ieee80211_roc_setup
(
local
);
...
...
@@ -1021,9 +1017,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
goto
fail_ifa6
;
#endif
netif_napi_add
(
&
local
->
napi_dev
,
&
local
->
napi
,
ieee80211_napi_poll
,
local
->
hw
.
napi_weight
);
return
0
;
#if IS_ENABLED(CONFIG_IPV6)
...
...
net/mac80211/mesh.c
浏览文件 @
3d5c2032
...
...
@@ -13,10 +13,6 @@
#include "ieee80211_i.h"
#include "mesh.h"
#define TMR_RUNNING_HK 0
#define TMR_RUNNING_MP 1
#define TMR_RUNNING_MPR 2
static
int
mesh_allocated
;
static
struct
kmem_cache
*
rm_cache
;
...
...
@@ -50,11 +46,6 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
set_bit
(
MESH_WORK_HOUSEKEEPING
,
&
ifmsh
->
wrkq_flags
);
if
(
local
->
quiescing
)
{
set_bit
(
TMR_RUNNING_HK
,
&
ifmsh
->
timers_running
);
return
;
}
ieee80211_queue_work
(
&
local
->
hw
,
&
sdata
->
work
);
}
...
...
@@ -165,7 +156,7 @@ void mesh_sta_cleanup(struct sta_info *sta)
* an update.
*/
changed
=
mesh_accept_plinks_update
(
sdata
);
if
(
sdata
->
u
.
mesh
.
security
==
IEEE80211_MESH_SEC_NONE
)
{
if
(
!
sdata
->
u
.
mesh
.
user_mpm
)
{
changed
|=
mesh_plink_deactivate
(
sta
);
del_timer_sync
(
&
sta
->
plink_timer
);
}
...
...
@@ -479,15 +470,8 @@ static void ieee80211_mesh_path_timer(unsigned long data)
{
struct
ieee80211_sub_if_data
*
sdata
=
(
struct
ieee80211_sub_if_data
*
)
data
;
struct
ieee80211_if_mesh
*
ifmsh
=
&
sdata
->
u
.
mesh
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
if
(
local
->
quiescing
)
{
set_bit
(
TMR_RUNNING_MP
,
&
ifmsh
->
timers_running
);
return
;
}
ieee80211_queue_work
(
&
local
->
hw
,
&
sdata
->
work
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
work
);
}
static
void
ieee80211_mesh_path_root_timer
(
unsigned
long
data
)
...
...
@@ -495,16 +479,10 @@ static void ieee80211_mesh_path_root_timer(unsigned long data)
struct
ieee80211_sub_if_data
*
sdata
=
(
struct
ieee80211_sub_if_data
*
)
data
;
struct
ieee80211_if_mesh
*
ifmsh
=
&
sdata
->
u
.
mesh
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
set_bit
(
MESH_WORK_ROOT
,
&
ifmsh
->
wrkq_flags
);
if
(
local
->
quiescing
)
{
set_bit
(
TMR_RUNNING_MPR
,
&
ifmsh
->
timers_running
);
return
;
}
ieee80211_queue_work
(
&
local
->
hw
,
&
sdata
->
work
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
work
);
}
void
ieee80211_mesh_root_setup
(
struct
ieee80211_if_mesh
*
ifmsh
)
...
...
@@ -622,35 +600,6 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
round_jiffies
(
TU_TO_EXP_TIME
(
interval
)));
}
#ifdef CONFIG_PM
void
ieee80211_mesh_quiesce
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_if_mesh
*
ifmsh
=
&
sdata
->
u
.
mesh
;
/* use atomic bitops in case all timers fire at the same time */
if
(
del_timer_sync
(
&
ifmsh
->
housekeeping_timer
))
set_bit
(
TMR_RUNNING_HK
,
&
ifmsh
->
timers_running
);
if
(
del_timer_sync
(
&
ifmsh
->
mesh_path_timer
))
set_bit
(
TMR_RUNNING_MP
,
&
ifmsh
->
timers_running
);
if
(
del_timer_sync
(
&
ifmsh
->
mesh_path_root_timer
))
set_bit
(
TMR_RUNNING_MPR
,
&
ifmsh
->
timers_running
);
}
void
ieee80211_mesh_restart
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_if_mesh
*
ifmsh
=
&
sdata
->
u
.
mesh
;
if
(
test_and_clear_bit
(
TMR_RUNNING_HK
,
&
ifmsh
->
timers_running
))
add_timer
(
&
ifmsh
->
housekeeping_timer
);
if
(
test_and_clear_bit
(
TMR_RUNNING_MP
,
&
ifmsh
->
timers_running
))
add_timer
(
&
ifmsh
->
mesh_path_timer
);
if
(
test_and_clear_bit
(
TMR_RUNNING_MPR
,
&
ifmsh
->
timers_running
))
add_timer
(
&
ifmsh
->
mesh_path_root_timer
);
ieee80211_mesh_root_setup
(
ifmsh
);
}
#endif
static
int
ieee80211_mesh_build_beacon
(
struct
ieee80211_if_mesh
*
ifmsh
)
{
...
...
@@ -871,8 +820,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
local
->
fif_other_bss
--
;
atomic_dec
(
&
local
->
iff_allmultis
);
ieee80211_configure_filter
(
local
);
sdata
->
u
.
mesh
.
timers_running
=
0
;
}
static
void
...
...
net/mac80211/mesh.h
浏览文件 @
3d5c2032
...
...
@@ -313,8 +313,6 @@ void mesh_path_timer(unsigned long data);
void
mesh_path_flush_by_nexthop
(
struct
sta_info
*
sta
);
void
mesh_path_discard_frame
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
sk_buff
*
skb
);
void
mesh_path_quiesce
(
struct
ieee80211_sub_if_data
*
sdata
);
void
mesh_path_restart
(
struct
ieee80211_sub_if_data
*
sdata
);
void
mesh_path_tx_root_frame
(
struct
ieee80211_sub_if_data
*
sdata
);
bool
mesh_action_is_path_sel
(
struct
ieee80211_mgmt
*
mgmt
);
...
...
@@ -359,22 +357,12 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
void
ieee80211_mesh_notify_scan_completed
(
struct
ieee80211_local
*
local
);
void
ieee80211_mesh_quiesce
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_mesh_restart
(
struct
ieee80211_sub_if_data
*
sdata
);
void
mesh_plink_quiesce
(
struct
sta_info
*
sta
);
void
mesh_plink_restart
(
struct
sta_info
*
sta
);
void
mesh_path_flush_by_iface
(
struct
ieee80211_sub_if_data
*
sdata
);
void
mesh_sync_adjust_tbtt
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211s_stop
(
void
);
#else
static
inline
void
ieee80211_mesh_notify_scan_completed
(
struct
ieee80211_local
*
local
)
{}
static
inline
void
ieee80211_mesh_quiesce
(
struct
ieee80211_sub_if_data
*
sdata
)
{}
static
inline
void
ieee80211_mesh_restart
(
struct
ieee80211_sub_if_data
*
sdata
)
{}
static
inline
void
mesh_plink_quiesce
(
struct
sta_info
*
sta
)
{}
static
inline
void
mesh_plink_restart
(
struct
sta_info
*
sta
)
{}
static
inline
bool
mesh_path_sel_is_hwmp
(
struct
ieee80211_sub_if_data
*
sdata
)
{
return
false
;
}
static
inline
void
mesh_path_flush_by_iface
(
struct
ieee80211_sub_if_data
*
sdata
)
...
...
net/mac80211/mesh_plink.c
浏览文件 @
3d5c2032
...
...
@@ -420,7 +420,6 @@ __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr)
return
NULL
;
sta
->
plink_state
=
NL80211_PLINK_LISTEN
;
init_timer
(
&
sta
->
plink_timer
);
sta_info_pre_move_state
(
sta
,
IEEE80211_STA_AUTH
);
sta_info_pre_move_state
(
sta
,
IEEE80211_STA_ASSOC
);
...
...
@@ -437,8 +436,9 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr,
{
struct
sta_info
*
sta
=
NULL
;
/* Userspace handles peer allocation when security is enabled */
if
(
sdata
->
u
.
mesh
.
security
&
IEEE80211_MESH_SEC_AUTHED
)
/* Userspace handles station allocation */
if
(
sdata
->
u
.
mesh
.
user_mpm
||
sdata
->
u
.
mesh
.
security
&
IEEE80211_MESH_SEC_AUTHED
)
cfg80211_notify_new_peer_candidate
(
sdata
->
dev
,
addr
,
elems
->
ie_start
,
elems
->
total_len
,
...
...
@@ -534,10 +534,8 @@ static void mesh_plink_timer(unsigned long data)
*/
sta
=
(
struct
sta_info
*
)
data
;
if
(
sta
->
sdata
->
local
->
quiescing
)
{
sta
->
plink_timer_was_running
=
true
;
if
(
sta
->
sdata
->
local
->
quiescing
)
return
;
}
spin_lock_bh
(
&
sta
->
lock
);
if
(
sta
->
ignore_plink_timer
)
{
...
...
@@ -598,29 +596,6 @@ static void mesh_plink_timer(unsigned long data)
}
}
#ifdef CONFIG_PM
void
mesh_plink_quiesce
(
struct
sta_info
*
sta
)
{
if
(
!
ieee80211_vif_is_mesh
(
&
sta
->
sdata
->
vif
))
return
;
/* no kernel mesh sta timers have been initialized */
if
(
sta
->
sdata
->
u
.
mesh
.
security
!=
IEEE80211_MESH_SEC_NONE
)
return
;
if
(
del_timer_sync
(
&
sta
->
plink_timer
))
sta
->
plink_timer_was_running
=
true
;
}
void
mesh_plink_restart
(
struct
sta_info
*
sta
)
{
if
(
sta
->
plink_timer_was_running
)
{
add_timer
(
&
sta
->
plink_timer
);
sta
->
plink_timer_was_running
=
false
;
}
}
#endif
static
inline
void
mesh_plink_timer_set
(
struct
sta_info
*
sta
,
int
timeout
)
{
sta
->
plink_timer
.
expires
=
jiffies
+
(
HZ
*
timeout
/
1000
);
...
...
@@ -695,6 +670,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
if
(
len
<
IEEE80211_MIN_ACTION_SIZE
+
3
)
return
;
if
(
sdata
->
u
.
mesh
.
user_mpm
)
/* userspace must register for these */
return
;
if
(
is_multicast_ether_addr
(
mgmt
->
da
))
{
mpl_dbg
(
sdata
,
"Mesh plink: ignore frame from multicast address
\n
"
);
...
...
net/mac80211/mlme.c
浏览文件 @
3d5c2032
...
...
@@ -87,9 +87,6 @@ MODULE_PARM_DESC(probe_wait_ms,
*/
#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
#define TMR_RUNNING_TIMER 0
#define TMR_RUNNING_CHANSW 1
/*
* All cfg80211 functions have to be called outside a locked
* section so that they can acquire a lock themselves... This
...
...
@@ -609,6 +606,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
BUILD_BUG_ON
(
sizeof
(
vht_cap
)
!=
sizeof
(
sband
->
vht_cap
));
memcpy
(
&
vht_cap
,
&
sband
->
vht_cap
,
sizeof
(
vht_cap
));
ieee80211_apply_vhtcap_overrides
(
sdata
,
&
vht_cap
);
/* determine capability flags */
cap
=
vht_cap
.
cap
;
...
...
@@ -647,6 +645,9 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
our_mcs
=
(
le16_to_cpu
(
vht_cap
.
vht_mcs
.
rx_mcs_map
)
&
mask
)
>>
shift
;
if
(
our_mcs
==
IEEE80211_VHT_MCS_NOT_SUPPORTED
)
continue
;
switch
(
ap_mcs
)
{
default:
if
(
our_mcs
<=
ap_mcs
)
...
...
@@ -1035,14 +1036,8 @@ static void ieee80211_chswitch_timer(unsigned long data)
{
struct
ieee80211_sub_if_data
*
sdata
=
(
struct
ieee80211_sub_if_data
*
)
data
;
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
if
(
sdata
->
local
->
quiescing
)
{
set_bit
(
TMR_RUNNING_CHANSW
,
&
ifmgd
->
timers_running
);
return
;
}
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
ifmgd
->
chswitch_work
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
u
.
mgd
.
chswitch_work
);
}
void
...
...
@@ -1799,9 +1794,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
sdata
->
vif
.
bss_conf
.
p2p_ctwindow
=
0
;
sdata
->
vif
.
bss_conf
.
p2p_oppps
=
false
;
/* on the next assoc, re-program HT parameters */
/* on the next assoc, re-program HT
/VHT
parameters */
memset
(
&
ifmgd
->
ht_capa
,
0
,
sizeof
(
ifmgd
->
ht_capa
));
memset
(
&
ifmgd
->
ht_capa_mask
,
0
,
sizeof
(
ifmgd
->
ht_capa_mask
));
memset
(
&
ifmgd
->
vht_capa
,
0
,
sizeof
(
ifmgd
->
vht_capa
));
memset
(
&
ifmgd
->
vht_capa_mask
,
0
,
sizeof
(
ifmgd
->
vht_capa_mask
));
sdata
->
ap_power_level
=
IEEE80211_UNSET_POWER_LEVEL
;
...
...
@@ -1827,8 +1824,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
del_timer_sync
(
&
sdata
->
u
.
mgd
.
timer
);
del_timer_sync
(
&
sdata
->
u
.
mgd
.
chswitch_timer
);
sdata
->
u
.
mgd
.
timers_running
=
0
;
sdata
->
vif
.
bss_conf
.
dtim_period
=
0
;
ifmgd
->
flags
=
0
;
...
...
@@ -3137,15 +3132,8 @@ static void ieee80211_sta_timer(unsigned long data)
{
struct
ieee80211_sub_if_data
*
sdata
=
(
struct
ieee80211_sub_if_data
*
)
data
;
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
if
(
local
->
quiescing
)
{
set_bit
(
TMR_RUNNING_TIMER
,
&
ifmgd
->
timers_running
);
return
;
}
ieee80211_queue_work
(
&
local
->
hw
,
&
sdata
->
work
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
work
);
}
static
void
ieee80211_sta_connection_lost
(
struct
ieee80211_sub_if_data
*
sdata
,
...
...
@@ -3497,68 +3485,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
}
}
#ifdef CONFIG_PM
void
ieee80211_sta_quiesce
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
/*
* we need to use atomic bitops for the running bits
* only because both timers might fire at the same
* time -- the code here is properly synchronised.
*/
cancel_work_sync
(
&
ifmgd
->
request_smps_work
);
cancel_work_sync
(
&
ifmgd
->
monitor_work
);
cancel_work_sync
(
&
ifmgd
->
beacon_connection_loss_work
);
cancel_work_sync
(
&
ifmgd
->
csa_connection_drop_work
);
if
(
del_timer_sync
(
&
ifmgd
->
timer
))
set_bit
(
TMR_RUNNING_TIMER
,
&
ifmgd
->
timers_running
);
cancel_work_sync
(
&
ifmgd
->
chswitch_work
);
if
(
del_timer_sync
(
&
ifmgd
->
chswitch_timer
))
set_bit
(
TMR_RUNNING_CHANSW
,
&
ifmgd
->
timers_running
);
/* these will just be re-established on connection */
del_timer_sync
(
&
ifmgd
->
conn_mon_timer
);
del_timer_sync
(
&
ifmgd
->
bcn_mon_timer
);
}
void
ieee80211_sta_restart
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
mutex_lock
(
&
ifmgd
->
mtx
);
if
(
!
ifmgd
->
associated
)
{
mutex_unlock
(
&
ifmgd
->
mtx
);
return
;
}
if
(
sdata
->
flags
&
IEEE80211_SDATA_DISCONNECT_RESUME
)
{
sdata
->
flags
&=
~
IEEE80211_SDATA_DISCONNECT_RESUME
;
mlme_dbg
(
sdata
,
"driver requested disconnect after resume
\n
"
);
ieee80211_sta_connection_lost
(
sdata
,
ifmgd
->
associated
->
bssid
,
WLAN_REASON_UNSPECIFIED
,
true
);
mutex_unlock
(
&
ifmgd
->
mtx
);
return
;
}
mutex_unlock
(
&
ifmgd
->
mtx
);
if
(
test_and_clear_bit
(
TMR_RUNNING_TIMER
,
&
ifmgd
->
timers_running
))
add_timer
(
&
ifmgd
->
timer
);
if
(
test_and_clear_bit
(
TMR_RUNNING_CHANSW
,
&
ifmgd
->
timers_running
))
add_timer
(
&
ifmgd
->
chswitch_timer
);
ieee80211_sta_reset_beacon_monitor
(
sdata
);
mutex_lock
(
&
sdata
->
local
->
mtx
);
ieee80211_restart_sta_timer
(
sdata
);
mutex_unlock
(
&
sdata
->
local
->
mtx
);
}
#endif
/* interface setup */
void
ieee80211_sta_setup_sdata
(
struct
ieee80211_sub_if_data
*
sdata
)
{
...
...
@@ -4064,6 +3990,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
ifmgd
->
flags
|=
IEEE80211_STA_DISABLE_VHT
;
}
if
(
req
->
flags
&
ASSOC_REQ_DISABLE_VHT
)
ifmgd
->
flags
|=
IEEE80211_STA_DISABLE_VHT
;
/* Also disable HT if we don't support it or the AP doesn't use WMM */
sband
=
local
->
hw
.
wiphy
->
bands
[
req
->
bss
->
channel
->
band
];
if
(
!
sband
->
ht_cap
.
ht_supported
||
...
...
@@ -4087,6 +4016,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
memcpy
(
&
ifmgd
->
ht_capa_mask
,
&
req
->
ht_capa_mask
,
sizeof
(
ifmgd
->
ht_capa_mask
));
memcpy
(
&
ifmgd
->
vht_capa
,
&
req
->
vht_capa
,
sizeof
(
ifmgd
->
vht_capa
));
memcpy
(
&
ifmgd
->
vht_capa_mask
,
&
req
->
vht_capa_mask
,
sizeof
(
ifmgd
->
vht_capa_mask
));
if
(
req
->
ie
&&
req
->
ie_len
)
{
memcpy
(
assoc_data
->
ie
,
req
->
ie
,
req
->
ie_len
);
assoc_data
->
ie_len
=
req
->
ie_len
;
...
...
@@ -4315,6 +4248,17 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
{
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
/*
* Make sure some work items will not run after this,
* they will not do anything but might not have been
* cancelled when disconnecting.
*/
cancel_work_sync
(
&
ifmgd
->
monitor_work
);
cancel_work_sync
(
&
ifmgd
->
beacon_connection_loss_work
);
cancel_work_sync
(
&
ifmgd
->
request_smps_work
);
cancel_work_sync
(
&
ifmgd
->
csa_connection_drop_work
);
cancel_work_sync
(
&
ifmgd
->
chswitch_work
);
mutex_lock
(
&
ifmgd
->
mtx
);
if
(
ifmgd
->
assoc_data
)
ieee80211_destroy_assoc_data
(
sdata
,
false
);
...
...
net/mac80211/offchannel.c
浏览文件 @
3d5c2032
...
...
@@ -277,7 +277,7 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
duration
=
10
;
ret
=
drv_remain_on_channel
(
local
,
roc
->
sdata
,
roc
->
chan
,
duration
);
duration
,
roc
->
type
);
roc
->
started
=
true
;
...
...
net/mac80211/pm.c
浏览文件 @
3d5c2032
...
...
@@ -6,32 +6,11 @@
#include "driver-ops.h"
#include "led.h"
/* return value indicates whether the driver should be further notified */
static
void
ieee80211_quiesce
(
struct
ieee80211_sub_if_data
*
sdata
)
{
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_STATION
:
ieee80211_sta_quiesce
(
sdata
);
break
;
case
NL80211_IFTYPE_ADHOC
:
ieee80211_ibss_quiesce
(
sdata
);
break
;
case
NL80211_IFTYPE_MESH_POINT
:
ieee80211_mesh_quiesce
(
sdata
);
break
;
default:
break
;
}
cancel_work_sync
(
&
sdata
->
work
);
}
int
__ieee80211_suspend
(
struct
ieee80211_hw
*
hw
,
struct
cfg80211_wowlan
*
wowlan
)
{
struct
ieee80211_local
*
local
=
hw_to_local
(
hw
);
struct
ieee80211_sub_if_data
*
sdata
;
struct
sta_info
*
sta
;
struct
ieee80211_chanctx
*
ctx
;
if
(
!
local
->
open_count
)
goto
suspend
;
...
...
@@ -93,19 +72,12 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
return
err
;
}
else
if
(
err
>
0
)
{
WARN_ON
(
err
!=
1
);
local
->
wowlan
=
false
;
return
err
;
}
else
{
list_for_each_entry
(
sdata
,
&
local
->
interfaces
,
list
)
if
(
ieee80211_sdata_running
(
sdata
))
ieee80211_quiesce
(
sdata
);
goto
suspend
;
}
}
/* disable keys */
list_for_each_entry
(
sdata
,
&
local
->
interfaces
,
list
)
ieee80211_disable_keys
(
sdata
);
/* tear down aggregation sessions and remove STAs */
mutex_lock
(
&
local
->
sta_mtx
);
list_for_each_entry
(
sta
,
&
local
->
sta_list
,
list
)
{
...
...
@@ -117,100 +89,25 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
WARN_ON
(
drv_sta_state
(
local
,
sta
->
sdata
,
sta
,
state
,
state
-
1
));
}
mesh_plink_quiesce
(
sta
);
}
mutex_unlock
(
&
local
->
sta_mtx
);
/* remove all interfaces */
list_for_each_entry
(
sdata
,
&
local
->
interfaces
,
list
)
{
static
u8
zero_addr
[
ETH_ALEN
]
=
{};
u32
changed
=
0
;
if
(
!
ieee80211_sdata_running
(
sdata
))
continue
;
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_AP_VLAN
:
case
NL80211_IFTYPE_MONITOR
:
/* skip these */
continue
;
case
NL80211_IFTYPE_STATION
:
if
(
sdata
->
vif
.
bss_conf
.
assoc
)
changed
=
BSS_CHANGED_ASSOC
|
BSS_CHANGED_BSSID
|
BSS_CHANGED_IDLE
;
break
;
case
NL80211_IFTYPE_AP
:
case
NL80211_IFTYPE_ADHOC
:
case
NL80211_IFTYPE_MESH_POINT
:
if
(
sdata
->
vif
.
bss_conf
.
enable_beacon
)
changed
=
BSS_CHANGED_BEACON_ENABLED
;
break
;
default:
break
;
}
ieee80211_quiesce
(
sdata
);
sdata
->
suspend_bss_conf
=
sdata
->
vif
.
bss_conf
;
memset
(
&
sdata
->
vif
.
bss_conf
,
0
,
sizeof
(
sdata
->
vif
.
bss_conf
));
sdata
->
vif
.
bss_conf
.
idle
=
true
;
if
(
sdata
->
suspend_bss_conf
.
bssid
)
sdata
->
vif
.
bss_conf
.
bssid
=
zero_addr
;
/* disable beaconing or remove association */
ieee80211_bss_info_change_notify
(
sdata
,
changed
);
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_AP
&&
rcu_access_pointer
(
sdata
->
u
.
ap
.
beacon
))
drv_stop_ap
(
local
,
sdata
);
if
(
local
->
use_chanctx
)
{
struct
ieee80211_chanctx_conf
*
conf
;
mutex_lock
(
&
local
->
chanctx_mtx
);
conf
=
rcu_dereference_protected
(
sdata
->
vif
.
chanctx_conf
,
lockdep_is_held
(
&
local
->
chanctx_mtx
));
if
(
conf
)
{
ctx
=
container_of
(
conf
,
struct
ieee80211_chanctx
,
conf
);
drv_unassign_vif_chanctx
(
local
,
sdata
,
ctx
);
}
mutex_unlock
(
&
local
->
chanctx_mtx
);
}
drv_remove_interface
(
local
,
sdata
);
}
sdata
=
rtnl_dereference
(
local
->
monitor_sdata
);
if
(
sdata
)
{
if
(
local
->
use_chanctx
)
{
struct
ieee80211_chanctx_conf
*
conf
;
mutex_lock
(
&
local
->
chanctx_mtx
);
conf
=
rcu_dereference_protected
(
sdata
->
vif
.
chanctx_conf
,
lockdep_is_held
(
&
local
->
chanctx_mtx
));
if
(
conf
)
{
ctx
=
container_of
(
conf
,
struct
ieee80211_chanctx
,
conf
);
drv_unassign_vif_chanctx
(
local
,
sdata
,
ctx
);
}
mutex_unlock
(
&
local
->
chanctx_mtx
);
}
if
(
sdata
)
drv_remove_interface
(
local
,
sdata
);
}
mutex_lock
(
&
local
->
chanctx_mtx
);
list_for_each_entry
(
ctx
,
&
local
->
chanctx_list
,
list
)
drv_remove_chanctx
(
local
,
ctx
);
mutex_unlock
(
&
local
->
chanctx_mtx
);
/*
* We disconnected on all interfaces before suspend, all channel
* contexts should be released.
*/
WARN_ON
(
!
list_empty
(
&
local
->
chanctx_list
));
/* stop hardware - this must stop RX */
if
(
local
->
open_count
)
...
...
net/mac80211/rc80211_minstrel.c
浏览文件 @
3d5c2032
...
...
@@ -55,7 +55,6 @@
#include "rate.h"
#include "rc80211_minstrel.h"
#define SAMPLE_COLUMNS 10
#define SAMPLE_TBL(_mi, _idx, _col) \
_mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col]
...
...
@@ -70,16 +69,31 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
return
i
;
}
/* find & sort topmost throughput rates */
static
inline
void
minstrel_sort_best_tp_rates
(
struct
minstrel_sta_info
*
mi
,
int
i
,
u8
*
tp_list
)
{
int
j
=
MAX_THR_RATES
;
while
(
j
>
0
&&
mi
->
r
[
i
].
cur_tp
>
mi
->
r
[
tp_list
[
j
-
1
]].
cur_tp
)
j
--
;
if
(
j
<
MAX_THR_RATES
-
1
)
memmove
(
&
tp_list
[
j
+
1
],
&
tp_list
[
j
],
MAX_THR_RATES
-
(
j
+
1
));
if
(
j
<
MAX_THR_RATES
)
tp_list
[
j
]
=
i
;
}
static
void
minstrel_update_stats
(
struct
minstrel_priv
*
mp
,
struct
minstrel_sta_info
*
mi
)
{
u
32
max_tp
=
0
,
index_max_tp
=
0
,
index_max_tp2
=
0
;
u
32
max_prob
=
0
,
index_max_prob
=
0
;
u
8
tmp_tp_rate
[
MAX_THR_RATES
]
;
u
8
tmp_prob_rate
=
0
;
u32
usecs
;
u32
p
;
int
i
;
mi
->
stats_update
=
jiffies
;
for
(
i
=
0
;
i
<
MAX_THR_RATES
;
i
++
)
tmp_tp_rate
[
i
]
=
0
;
for
(
i
=
0
;
i
<
mi
->
n_rates
;
i
++
)
{
struct
minstrel_rate
*
mr
=
&
mi
->
r
[
i
];
...
...
@@ -87,27 +101,32 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
if
(
!
usecs
)
usecs
=
1000000
;
/* To avoid rounding issues, probabilities scale from 0 (0%)
* to 18000 (100%) */
if
(
mr
->
attempts
)
{
p
=
(
mr
->
success
*
18000
)
/
mr
->
attempts
;
if
(
unlikely
(
mr
->
attempts
>
0
))
{
mr
->
sample_skipped
=
0
;
mr
->
cur_prob
=
MINSTREL_FRAC
(
mr
->
success
,
mr
->
attempts
);
mr
->
succ_hist
+=
mr
->
success
;
mr
->
att_hist
+=
mr
->
attempts
;
mr
->
cur_prob
=
p
;
p
=
((
p
*
(
100
-
mp
->
ewma_level
))
+
(
mr
->
probability
*
mp
->
ewma_level
))
/
100
;
mr
->
probability
=
p
;
mr
->
cur_tp
=
p
*
(
1000000
/
usecs
);
}
mr
->
probability
=
minstrel_ewma
(
mr
->
probability
,
mr
->
cur_prob
,
EWMA_LEVEL
);
}
else
mr
->
sample_skipped
++
;
mr
->
last_success
=
mr
->
success
;
mr
->
last_attempts
=
mr
->
attempts
;
mr
->
success
=
0
;
mr
->
attempts
=
0
;
/* Update throughput per rate, reset thr. below 10% success */
if
(
mr
->
probability
<
MINSTREL_FRAC
(
10
,
100
))
mr
->
cur_tp
=
0
;
else
mr
->
cur_tp
=
mr
->
probability
*
(
1000000
/
usecs
);
/* Sample less often below the 10% chance of success.
* Sample less often above the 95% chance of success. */
if
((
mr
->
probability
>
17100
)
||
(
mr
->
probability
<
1800
))
{
if
(
mr
->
probability
>
MINSTREL_FRAC
(
95
,
100
)
||
mr
->
probability
<
MINSTREL_FRAC
(
10
,
100
))
{
mr
->
adjusted_retry_count
=
mr
->
retry_count
>>
1
;
if
(
mr
->
adjusted_retry_count
>
2
)
mr
->
adjusted_retry_count
=
2
;
...
...
@@ -118,35 +137,30 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
}
if
(
!
mr
->
adjusted_retry_count
)
mr
->
adjusted_retry_count
=
2
;
}
for
(
i
=
0
;
i
<
mi
->
n_rates
;
i
++
)
{
struct
minstrel_rate
*
mr
=
&
mi
->
r
[
i
];
if
(
max_tp
<
mr
->
cur_tp
)
{
index_max_tp
=
i
;
max_tp
=
mr
->
cur_tp
;
}
if
(
max_prob
<
mr
->
probability
)
{
index_max_prob
=
i
;
max_prob
=
mr
->
probability
;
minstrel_sort_best_tp_rates
(
mi
,
i
,
tmp_tp_rate
);
/* To determine the most robust rate (max_prob_rate) used at
* 3rd mmr stage we distinct between two cases:
* (1) if any success probabilitiy >= 95%, out of those rates
* choose the maximum throughput rate as max_prob_rate
* (2) if all success probabilities < 95%, the rate with
* highest success probability is choosen as max_prob_rate */
if
(
mr
->
probability
>=
MINSTREL_FRAC
(
95
,
100
))
{
if
(
mr
->
cur_tp
>=
mi
->
r
[
tmp_prob_rate
].
cur_tp
)
tmp_prob_rate
=
i
;
}
else
{
if
(
mr
->
probability
>=
mi
->
r
[
tmp_prob_rate
].
probability
)
tmp_prob_rate
=
i
;
}
}
max_tp
=
0
;
for
(
i
=
0
;
i
<
mi
->
n_rates
;
i
++
)
{
struct
minstrel_rate
*
mr
=
&
mi
->
r
[
i
];
if
(
i
==
index_max_tp
)
continue
;
/* Assign the new rate set */
memcpy
(
mi
->
max_tp_rate
,
tmp_tp_rate
,
sizeof
(
mi
->
max_tp_rate
));
mi
->
max_prob_rate
=
tmp_prob_rate
;
if
(
max_tp
<
mr
->
cur_tp
)
{
index_max_tp2
=
i
;
max_tp
=
mr
->
cur_tp
;
}
}
mi
->
max_tp_rate
=
index_max_tp
;
mi
->
max_tp_rate2
=
index_max_tp2
;
mi
->
max_prob_rate
=
index_max_prob
;
/* Reset update timer */
mi
->
stats_update
=
jiffies
;
}
static
void
...
...
@@ -207,10 +221,10 @@ static int
minstrel_get_next_sample
(
struct
minstrel_sta_info
*
mi
)
{
unsigned
int
sample_ndx
;
sample_ndx
=
SAMPLE_TBL
(
mi
,
mi
->
sample_
idx
,
mi
->
sample_column
);
mi
->
sample_
idx
++
;
if
((
int
)
mi
->
sample_
idx
>
(
mi
->
n_rates
-
2
)
)
{
mi
->
sample_
idx
=
0
;
sample_ndx
=
SAMPLE_TBL
(
mi
,
mi
->
sample_
row
,
mi
->
sample_column
);
mi
->
sample_
row
++
;
if
((
int
)
mi
->
sample_
row
>=
mi
->
n_rates
)
{
mi
->
sample_
row
=
0
;
mi
->
sample_column
++
;
if
(
mi
->
sample_column
>=
SAMPLE_COLUMNS
)
mi
->
sample_column
=
0
;
...
...
@@ -228,31 +242,37 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
struct
minstrel_priv
*
mp
=
priv
;
struct
ieee80211_tx_rate
*
ar
=
info
->
control
.
rates
;
unsigned
int
ndx
,
sample_ndx
=
0
;
bool
mrr
;
bool
sample_slower
=
false
;
bool
sample
=
false
;
bool
mrr
_capable
;
bool
indirect_rate_sampling
=
false
;
bool
rate_sampling
=
false
;
int
i
,
delta
;
int
mrr_ndx
[
3
];
int
sampl
e_rate
;
int
sampl
ing_ratio
;
/* management/no-ack frames do not use rate control */
if
(
rate_control_send_low
(
sta
,
priv_sta
,
txrc
))
return
;
mrr
=
mp
->
has_mrr
&&
!
txrc
->
rts
&&
!
txrc
->
bss_conf
->
use_cts_prot
;
ndx
=
mi
->
max_tp_rate
;
if
(
mrr
)
sampl
e_rate
=
mp
->
lookaround_rate_mrr
;
/* check multi-rate-retry capabilities & adjust lookaround_rate */
mrr_capable
=
mp
->
has_mrr
&&
!
txrc
->
rts
&&
!
txrc
->
bss_conf
->
use_cts_prot
;
if
(
mrr
_capable
)
sampl
ing_ratio
=
mp
->
lookaround_rate_mrr
;
else
sample_rate
=
mp
->
lookaround_rate
;
sampling_ratio
=
mp
->
lookaround_rate
;
/* init rateindex [ndx] with max throughput rate */
ndx
=
mi
->
max_tp_rate
[
0
];
/* increase sum packet counter */
mi
->
packet_count
++
;
delta
=
(
mi
->
packet_count
*
sample_rate
/
100
)
-
delta
=
(
mi
->
packet_count
*
sampling_ratio
/
100
)
-
(
mi
->
sample_count
+
mi
->
sample_deferred
/
2
);
/* delta > 0: sampling required */
if
((
delta
>
0
)
&&
(
mrr
||
!
mi
->
prev_sample
))
{
if
((
delta
>
0
)
&&
(
mrr
_capable
||
!
mi
->
prev_sample
))
{
struct
minstrel_rate
*
msr
;
if
(
mi
->
packet_count
>=
10000
)
{
mi
->
sample_deferred
=
0
;
...
...
@@ -271,21 +291,28 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
mi
->
sample_count
+=
(
delta
-
mi
->
n_rates
*
2
);
}
/* get next random rate sample */
sample_ndx
=
minstrel_get_next_sample
(
mi
);
msr
=
&
mi
->
r
[
sample_ndx
];
sample
=
true
;
sample_slower
=
mrr
&&
(
msr
->
perfect_tx_time
>
mi
->
r
[
ndx
].
perfect_tx_time
);
if
(
!
sample_slower
)
{
rate_sampling
=
true
;
/* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
* rate sampling method should be used.
* Respect such rates that are not sampled for 20 interations.
*/
if
(
mrr_capable
&&
msr
->
perfect_tx_time
>
mi
->
r
[
ndx
].
perfect_tx_time
&&
msr
->
sample_skipped
<
20
)
indirect_rate_sampling
=
true
;
if
(
!
indirect_rate_sampling
)
{
if
(
msr
->
sample_limit
!=
0
)
{
ndx
=
sample_ndx
;
mi
->
sample_count
++
;
if
(
msr
->
sample_limit
>
0
)
msr
->
sample_limit
--
;
}
else
{
sample
=
false
;
}
}
else
rate_sampling
=
false
;
}
else
{
/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
* packets that have the sampling rate deferred to the
...
...
@@ -297,34 +324,39 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
mi
->
sample_deferred
++
;
}
}
mi
->
prev_sample
=
sample
;
mi
->
prev_sample
=
rate_sampling
;
/* If we're not using MRR and the sampling rate already
* has a probability of >95%, we shouldn't be attempting
* to use it, as this only wastes precious airtime */
if
(
!
mrr
&&
sample
&&
(
mi
->
r
[
ndx
].
probability
>
17100
))
ndx
=
mi
->
max_tp_rate
;
if
(
!
mrr_capable
&&
rate_sampling
&&
(
mi
->
r
[
ndx
].
probability
>
MINSTREL_FRAC
(
95
,
100
)))
ndx
=
mi
->
max_tp_rate
[
0
];
/* mrr setup for 1st stage */
ar
[
0
].
idx
=
mi
->
r
[
ndx
].
rix
;
ar
[
0
].
count
=
minstrel_get_retry_count
(
&
mi
->
r
[
ndx
],
info
);
if
(
!
mrr
)
{
if
(
!
sample
)
/* non mrr setup for 2nd stage */
if
(
!
mrr_capable
)
{
if
(
!
rate_sampling
)
ar
[
0
].
count
=
mp
->
max_retry
;
ar
[
1
].
idx
=
mi
->
lowest_rix
;
ar
[
1
].
count
=
mp
->
max_retry
;
return
;
}
/*
MRR setup
*/
if
(
sample
)
{
if
(
sample_slower
)
/*
mrr setup for 2nd stage
*/
if
(
rate_sampling
)
{
if
(
indirect_rate_sampling
)
mrr_ndx
[
0
]
=
sample_ndx
;
else
mrr_ndx
[
0
]
=
mi
->
max_tp_rate
;
mrr_ndx
[
0
]
=
mi
->
max_tp_rate
[
0
]
;
}
else
{
mrr_ndx
[
0
]
=
mi
->
max_tp_rate
2
;
mrr_ndx
[
0
]
=
mi
->
max_tp_rate
[
1
]
;
}
/* mrr setup for 3rd & 4th stage */
mrr_ndx
[
1
]
=
mi
->
max_prob_rate
;
mrr_ndx
[
2
]
=
0
;
for
(
i
=
1
;
i
<
4
;
i
++
)
{
...
...
@@ -351,26 +383,21 @@ static void
init_sample_table
(
struct
minstrel_sta_info
*
mi
)
{
unsigned
int
i
,
col
,
new_idx
;
unsigned
int
n_srates
=
mi
->
n_rates
-
1
;
u8
rnd
[
8
];
mi
->
sample_column
=
0
;
mi
->
sample_
idx
=
0
;
memset
(
mi
->
sample_table
,
0
,
SAMPLE_COLUMNS
*
mi
->
n_rates
);
mi
->
sample_
row
=
0
;
memset
(
mi
->
sample_table
,
0
xff
,
SAMPLE_COLUMNS
*
mi
->
n_rates
);
for
(
col
=
0
;
col
<
SAMPLE_COLUMNS
;
col
++
)
{
for
(
i
=
0
;
i
<
n_s
rates
;
i
++
)
{
for
(
i
=
0
;
i
<
mi
->
n_
rates
;
i
++
)
{
get_random_bytes
(
rnd
,
sizeof
(
rnd
));
new_idx
=
(
i
+
rnd
[
i
&
7
])
%
n_s
rates
;
new_idx
=
(
i
+
rnd
[
i
&
7
])
%
mi
->
n_
rates
;
while
(
SAMPLE_TBL
(
mi
,
new_idx
,
col
)
!=
0
)
new_idx
=
(
new_idx
+
1
)
%
n_s
rates
;
while
(
SAMPLE_TBL
(
mi
,
new_idx
,
col
)
!=
0
xff
)
new_idx
=
(
new_idx
+
1
)
%
mi
->
n_
rates
;
/* Don't sample the slowest rate (i.e. slowest base
* rate). We must presume that the slowest rate works
* fine, or else other management frames will also be
* failing and the link will break */
SAMPLE_TBL
(
mi
,
new_idx
,
col
)
=
i
+
1
;
SAMPLE_TBL
(
mi
,
new_idx
,
col
)
=
i
;
}
}
}
...
...
@@ -542,9 +569,6 @@ minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
mp
->
lookaround_rate
=
5
;
mp
->
lookaround_rate_mrr
=
10
;
/* moving average weight for EWMA */
mp
->
ewma_level
=
75
;
/* maximum time that the hw is allowed to stay in one MRR segment */
mp
->
segment_size
=
6000
;
...
...
net/mac80211/rc80211_minstrel.h
浏览文件 @
3d5c2032
...
...
@@ -9,6 +9,28 @@
#ifndef __RC_MINSTREL_H
#define __RC_MINSTREL_H
#define EWMA_LEVEL 75
/* ewma weighting factor [%] */
#define SAMPLE_COLUMNS 10
/* number of columns in sample table */
/* scaled fraction values */
#define MINSTREL_SCALE 16
#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
/* number of highest throughput rates to consider*/
#define MAX_THR_RATES 4
/*
* Perform EWMA (Exponentially Weighted Moving Average) calculation
*/
static
inline
int
minstrel_ewma
(
int
old
,
int
new
,
int
weight
)
{
return
(
new
*
(
100
-
weight
)
+
old
*
weight
)
/
100
;
}
struct
minstrel_rate
{
int
bitrate
;
int
rix
;
...
...
@@ -26,6 +48,7 @@ struct minstrel_rate {
u32
attempts
;
u32
last_attempts
;
u32
last_success
;
u8
sample_skipped
;
/* parts per thousand */
u32
cur_prob
;
...
...
@@ -45,14 +68,13 @@ struct minstrel_sta_info {
unsigned
int
lowest_rix
;
unsigned
int
max_tp_rate
;
unsigned
int
max_tp_rate2
;
unsigned
int
max_prob_rate
;
u8
max_tp_rate
[
MAX_THR_RATES
];
u8
max_prob_rate
;
unsigned
int
packet_count
;
unsigned
int
sample_count
;
int
sample_deferred
;
unsigned
int
sample_
idx
;
unsigned
int
sample_
row
;
unsigned
int
sample_column
;
int
n_rates
;
...
...
@@ -73,7 +95,6 @@ struct minstrel_priv {
unsigned
int
cw_min
;
unsigned
int
cw_max
;
unsigned
int
max_retry
;
unsigned
int
ewma_level
;
unsigned
int
segment_size
;
unsigned
int
update_interval
;
unsigned
int
lookaround_rate
;
...
...
net/mac80211/rc80211_minstrel_debugfs.c
浏览文件 @
3d5c2032
...
...
@@ -73,15 +73,17 @@ minstrel_stats_open(struct inode *inode, struct file *file)
for
(
i
=
0
;
i
<
mi
->
n_rates
;
i
++
)
{
struct
minstrel_rate
*
mr
=
&
mi
->
r
[
i
];
*
(
p
++
)
=
(
i
==
mi
->
max_tp_rate
)
?
'T'
:
' '
;
*
(
p
++
)
=
(
i
==
mi
->
max_tp_rate2
)
?
't'
:
' '
;
*
(
p
++
)
=
(
i
==
mi
->
max_tp_rate
[
0
])
?
'A'
:
' '
;
*
(
p
++
)
=
(
i
==
mi
->
max_tp_rate
[
1
])
?
'B'
:
' '
;
*
(
p
++
)
=
(
i
==
mi
->
max_tp_rate
[
2
])
?
'C'
:
' '
;
*
(
p
++
)
=
(
i
==
mi
->
max_tp_rate
[
3
])
?
'D'
:
' '
;
*
(
p
++
)
=
(
i
==
mi
->
max_prob_rate
)
?
'P'
:
' '
;
p
+=
sprintf
(
p
,
"%3u%s"
,
mr
->
bitrate
/
2
,
(
mr
->
bitrate
&
1
?
".5"
:
" "
));
tp
=
mr
->
cur_tp
/
((
18000
<<
10
)
/
96
);
prob
=
mr
->
cur_prob
/
18
;
eprob
=
mr
->
probability
/
18
;
tp
=
MINSTREL_TRUNC
(
mr
->
cur_tp
/
10
);
prob
=
MINSTREL_TRUNC
(
mr
->
cur_prob
*
1000
)
;
eprob
=
MINSTREL_TRUNC
(
mr
->
probability
*
1000
)
;
p
+=
sprintf
(
p
,
" %6u.%1u %6u.%1u %6u.%1u "
"%3u(%3u) %8llu %8llu
\n
"
,
...
...
net/mac80211/rc80211_minstrel_ht.c
浏览文件 @
3d5c2032
...
...
@@ -17,8 +17,6 @@
#include "rc80211_minstrel_ht.h"
#define AVG_PKT_SIZE 1200
#define SAMPLE_COLUMNS 10
#define EWMA_LEVEL 75
/* Number of bits for an average sized packet */
#define MCS_NBITS (AVG_PKT_SIZE << 3)
...
...
@@ -26,11 +24,11 @@
/* Number of symbols for a packet with (bps) bits per symbol */
#define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps))
/* Transmission time for a packet containing (syms) symbols */
/* Transmission time
(nanoseconds)
for a packet containing (syms) symbols */
#define MCS_SYMBOL_TIME(sgi, syms) \
(sgi ? \
((syms) * 18
+ 4
) / 5 :
/* syms * 3.6 us */
\
(
syms) << 2
/* syms * 4 us */
\
((syms) * 18
000 + 4000
) / 5 :
/* syms * 3.6 us */
\
(
(syms) * 1000) << 2
/* syms * 4 us */
\
)
/* Transmit duration for the raw data part of an average sized packet */
...
...
@@ -64,9 +62,9 @@
}
#define CCK_DURATION(_bitrate, _short, _len) \
(10
/* SIFS */
+
\
(10
00 * (10
/* SIFS */
+
\
(_short ? 72 + 24 : 144 + 48 ) + \
(8 * (_len + 4) * 10) / (_bitrate))
(8 * (_len + 4) * 10) / (_bitrate))
)
#define CCK_ACK_DURATION(_bitrate, _short) \
(CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \
...
...
@@ -128,15 +126,6 @@ const struct mcs_group minstrel_mcs_groups[] = {
static
u8
sample_table
[
SAMPLE_COLUMNS
][
MCS_GROUP_RATES
];
/*
* Perform EWMA (Exponentially Weighted Moving Average) calculation
*/
static
int
minstrel_ewma
(
int
old
,
int
new
,
int
weight
)
{
return
(
new
*
(
100
-
weight
)
+
old
*
weight
)
/
100
;
}
/*
* Look up an MCS group index based on mac80211 rate information
*/
...
...
@@ -211,7 +200,8 @@ static void
minstrel_ht_calc_tp
(
struct
minstrel_ht_sta
*
mi
,
int
group
,
int
rate
)
{
struct
minstrel_rate_stats
*
mr
;
unsigned
int
usecs
=
0
;
unsigned
int
nsecs
=
0
;
unsigned
int
tp
;
mr
=
&
mi
->
groups
[
group
].
rates
[
rate
];
...
...
@@ -221,10 +211,12 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
}
if
(
group
!=
MINSTREL_CCK_GROUP
)
usecs
=
mi
->
overhead
/
MINSTREL_TRUNC
(
mi
->
avg_ampdu_len
);
nsecs
=
1000
*
mi
->
overhead
/
MINSTREL_TRUNC
(
mi
->
avg_ampdu_len
);
usecs
+=
minstrel_mcs_groups
[
group
].
duration
[
rate
];
mr
->
cur_tp
=
MINSTREL_TRUNC
((
1000000
/
usecs
)
*
mr
->
probability
);
nsecs
+=
minstrel_mcs_groups
[
group
].
duration
[
rate
];
tp
=
1000000
*
((
mr
->
probability
*
1000
)
/
nsecs
);
mr
->
cur_tp
=
MINSTREL_TRUNC
(
tp
);
}
/*
...
...
@@ -308,8 +300,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
}
}
/* try to sample
up to half of the
available rates during each interval */
mi
->
sample_count
*=
4
;
/* try to sample
all
available rates during each interval */
mi
->
sample_count
*=
8
;
cur_prob
=
0
;
cur_prob_tp
=
0
;
...
...
@@ -320,20 +312,13 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
if
(
!
mg
->
supported
)
continue
;
mr
=
minstrel_get_ratestats
(
mi
,
mg
->
max_prob_rate
);
if
(
cur_prob_tp
<
mr
->
cur_tp
&&
minstrel_mcs_groups
[
group
].
streams
==
1
)
{
mi
->
max_prob_rate
=
mg
->
max_prob_rate
;
cur_prob
=
mr
->
cur_prob
;
cur_prob_tp
=
mr
->
cur_tp
;
}
mr
=
minstrel_get_ratestats
(
mi
,
mg
->
max_tp_rate
);
if
(
cur_tp
<
mr
->
cur_tp
)
{
mi
->
max_tp_rate2
=
mi
->
max_tp_rate
;
cur_tp2
=
cur_tp
;
mi
->
max_tp_rate
=
mg
->
max_tp_rate
;
cur_tp
=
mr
->
cur_tp
;
mi
->
max_prob_streams
=
minstrel_mcs_groups
[
group
].
streams
-
1
;
}
mr
=
minstrel_get_ratestats
(
mi
,
mg
->
max_tp_rate2
);
...
...
@@ -343,6 +328,23 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
}
}
if
(
mi
->
max_prob_streams
<
1
)
mi
->
max_prob_streams
=
1
;
for
(
group
=
0
;
group
<
ARRAY_SIZE
(
minstrel_mcs_groups
);
group
++
)
{
mg
=
&
mi
->
groups
[
group
];
if
(
!
mg
->
supported
)
continue
;
mr
=
minstrel_get_ratestats
(
mi
,
mg
->
max_prob_rate
);
if
(
cur_prob_tp
<
mr
->
cur_tp
&&
minstrel_mcs_groups
[
group
].
streams
<=
mi
->
max_prob_streams
)
{
mi
->
max_prob_rate
=
mg
->
max_prob_rate
;
cur_prob
=
mr
->
cur_prob
;
cur_prob_tp
=
mr
->
cur_tp
;
}
}
mi
->
stats_update
=
jiffies
;
}
...
...
@@ -467,7 +469,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
if
(
!
mi
->
sample_wait
&&
!
mi
->
sample_tries
&&
mi
->
sample_count
>
0
)
{
mi
->
sample_wait
=
16
+
2
*
MINSTREL_TRUNC
(
mi
->
avg_ampdu_len
);
mi
->
sample_tries
=
2
;
mi
->
sample_tries
=
1
;
mi
->
sample_count
--
;
}
...
...
@@ -536,7 +538,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
mr
->
retry_updated
=
true
;
group
=
&
minstrel_mcs_groups
[
index
/
MCS_GROUP_RATES
];
tx_time_data
=
group
->
duration
[
index
%
MCS_GROUP_RATES
]
*
ampdu_len
;
tx_time_data
=
group
->
duration
[
index
%
MCS_GROUP_RATES
]
*
ampdu_len
/
1000
;
/* Contention time for first 2 tries */
ctime
=
(
t_slot
*
cw
)
>>
1
;
...
...
@@ -616,6 +618,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
{
struct
minstrel_rate_stats
*
mr
;
struct
minstrel_mcs_group_data
*
mg
;
unsigned
int
sample_dur
,
sample_group
;
int
sample_idx
=
0
;
if
(
mi
->
sample_wait
>
0
)
{
...
...
@@ -626,11 +629,11 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
if
(
!
mi
->
sample_tries
)
return
-
1
;
mi
->
sample_tries
--
;
mg
=
&
mi
->
groups
[
mi
->
sample_group
];
sample_idx
=
sample_table
[
mg
->
column
][
mg
->
index
];
mr
=
&
mg
->
rates
[
sample_idx
];
sample_idx
+=
mi
->
sample_group
*
MCS_GROUP_RATES
;
sample_group
=
mi
->
sample_group
;
sample_idx
+=
sample_group
*
MCS_GROUP_RATES
;
minstrel_next_sample_idx
(
mi
);
/*
...
...
@@ -651,14 +654,18 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
* Make sure that lower rates get sampled only occasionally,
* if the link is working perfectly.
*/
if
(
minstrel_get_duration
(
sample_idx
)
>
minstrel_get_duration
(
mi
->
max_tp_rate
))
{
sample_dur
=
minstrel_get_duration
(
sample_idx
);
if
(
sample_dur
>=
minstrel_get_duration
(
mi
->
max_tp_rate2
)
&&
(
mi
->
max_prob_streams
<
minstrel_mcs_groups
[
sample_group
].
streams
||
sample_dur
>=
minstrel_get_duration
(
mi
->
max_prob_rate
)))
{
if
(
mr
->
sample_skipped
<
20
)
return
-
1
;
if
(
mi
->
sample_slow
++
>
2
)
return
-
1
;
}
mi
->
sample_tries
--
;
return
sample_idx
;
}
...
...
net/mac80211/rc80211_minstrel_ht.h
浏览文件 @
3d5c2032
...
...
@@ -16,11 +16,6 @@
#define MINSTREL_MAX_STREAMS 3
#define MINSTREL_STREAM_GROUPS 4
/* scaled fraction values */
#define MINSTREL_SCALE 16
#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
#define MCS_GROUP_RATES 8
struct
mcs_group
{
...
...
@@ -85,6 +80,7 @@ struct minstrel_ht_sta {
/* best probability rate */
unsigned
int
max_prob_rate
;
unsigned
int
max_prob_streams
;
/* time of last status update */
unsigned
long
stats_update
;
...
...
net/mac80211/rx.c
浏览文件 @
3d5c2032
...
...
@@ -648,24 +648,6 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
return
RX_CONTINUE
;
}
#define SEQ_MODULO 0x1000
#define SEQ_MASK 0xfff
static
inline
int
seq_less
(
u16
sq1
,
u16
sq2
)
{
return
((
sq1
-
sq2
)
&
SEQ_MASK
)
>
(
SEQ_MODULO
>>
1
);
}
static
inline
u16
seq_inc
(
u16
sq
)
{
return
(
sq
+
1
)
&
SEQ_MASK
;
}
static
inline
u16
seq_sub
(
u16
sq1
,
u16
sq2
)
{
return
(
sq1
-
sq2
)
&
SEQ_MASK
;
}
static
void
ieee80211_release_reorder_frame
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
tid_ampdu_rx
*
tid_agg_rx
,
int
index
,
...
...
@@ -687,7 +669,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
__skb_queue_tail
(
frames
,
skb
);
no_frame:
tid_agg_rx
->
head_seq_num
=
seq
_inc
(
tid_agg_rx
->
head_seq_num
);
tid_agg_rx
->
head_seq_num
=
ieee80211_sn
_inc
(
tid_agg_rx
->
head_seq_num
);
}
static
void
ieee80211_release_reorder_frames
(
struct
ieee80211_sub_if_data
*
sdata
,
...
...
@@ -699,8 +681,9 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata
lockdep_assert_held
(
&
tid_agg_rx
->
reorder_lock
);
while
(
seq_less
(
tid_agg_rx
->
head_seq_num
,
head_seq_num
))
{
index
=
seq_sub
(
tid_agg_rx
->
head_seq_num
,
tid_agg_rx
->
ssn
)
%
while
(
ieee80211_sn_less
(
tid_agg_rx
->
head_seq_num
,
head_seq_num
))
{
index
=
ieee80211_sn_sub
(
tid_agg_rx
->
head_seq_num
,
tid_agg_rx
->
ssn
)
%
tid_agg_rx
->
buf_size
;
ieee80211_release_reorder_frame
(
sdata
,
tid_agg_rx
,
index
,
frames
);
...
...
@@ -727,8 +710,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
lockdep_assert_held
(
&
tid_agg_rx
->
reorder_lock
);
/* release the buffer until next missing frame */
index
=
seq_sub
(
tid_agg_rx
->
head_seq_num
,
tid_agg_rx
->
ssn
)
%
tid_agg_rx
->
buf_size
;
index
=
ieee80211_sn_sub
(
tid_agg_rx
->
head_seq_num
,
tid_agg_rx
->
ssn
)
%
tid_agg_rx
->
buf_size
;
if
(
!
tid_agg_rx
->
reorder_buf
[
index
]
&&
tid_agg_rx
->
stored_mpdu_num
)
{
/*
...
...
@@ -756,19 +739,22 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
* Increment the head seq# also for the skipped slots.
*/
tid_agg_rx
->
head_seq_num
=
(
tid_agg_rx
->
head_seq_num
+
skipped
)
&
SEQ_MASK
;
(
tid_agg_rx
->
head_seq_num
+
skipped
)
&
IEEE80211_SN_MASK
;
skipped
=
0
;
}
}
else
while
(
tid_agg_rx
->
reorder_buf
[
index
])
{
ieee80211_release_reorder_frame
(
sdata
,
tid_agg_rx
,
index
,
frames
);
index
=
seq_sub
(
tid_agg_rx
->
head_seq_num
,
tid_agg_rx
->
ssn
)
%
index
=
ieee80211_sn_sub
(
tid_agg_rx
->
head_seq_num
,
tid_agg_rx
->
ssn
)
%
tid_agg_rx
->
buf_size
;
}
if
(
tid_agg_rx
->
stored_mpdu_num
)
{
j
=
index
=
seq_sub
(
tid_agg_rx
->
head_seq_num
,
tid_agg_rx
->
ssn
)
%
tid_agg_rx
->
buf_size
;
j
=
index
=
ieee80211_sn_sub
(
tid_agg_rx
->
head_seq_num
,
tid_agg_rx
->
ssn
)
%
tid_agg_rx
->
buf_size
;
for
(;
j
!=
(
index
-
1
)
%
tid_agg_rx
->
buf_size
;
j
=
(
j
+
1
)
%
tid_agg_rx
->
buf_size
)
{
...
...
@@ -809,7 +795,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
head_seq_num
=
tid_agg_rx
->
head_seq_num
;
/* frame with out of date sequence number */
if
(
seq
_less
(
mpdu_seq_num
,
head_seq_num
))
{
if
(
ieee80211_sn
_less
(
mpdu_seq_num
,
head_seq_num
))
{
dev_kfree_skb
(
skb
);
goto
out
;
}
...
...
@@ -818,8 +804,9 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
* If frame the sequence number exceeds our buffering window
* size release some previous frames to make room for this one.
*/
if
(
!
seq_less
(
mpdu_seq_num
,
head_seq_num
+
buf_size
))
{
head_seq_num
=
seq_inc
(
seq_sub
(
mpdu_seq_num
,
buf_size
));
if
(
!
ieee80211_sn_less
(
mpdu_seq_num
,
head_seq_num
+
buf_size
))
{
head_seq_num
=
ieee80211_sn_inc
(
ieee80211_sn_sub
(
mpdu_seq_num
,
buf_size
));
/* release stored frames up to new head to stack */
ieee80211_release_reorder_frames
(
sdata
,
tid_agg_rx
,
head_seq_num
,
frames
);
...
...
@@ -827,7 +814,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
/* Now the new frame is always in the range of the reordering buffer */
index
=
seq_sub
(
mpdu_seq_num
,
tid_agg_rx
->
ssn
)
%
tid_agg_rx
->
buf_size
;
index
=
ieee80211_sn_sub
(
mpdu_seq_num
,
tid_agg_rx
->
ssn
)
%
tid_agg_rx
->
buf_size
;
/* check if we already stored this frame */
if
(
tid_agg_rx
->
reorder_buf
[
index
])
{
...
...
@@ -843,7 +831,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
*/
if
(
mpdu_seq_num
==
tid_agg_rx
->
head_seq_num
&&
tid_agg_rx
->
stored_mpdu_num
==
0
)
{
tid_agg_rx
->
head_seq_num
=
seq_inc
(
tid_agg_rx
->
head_seq_num
);
tid_agg_rx
->
head_seq_num
=
ieee80211_sn_inc
(
tid_agg_rx
->
head_seq_num
);
ret
=
false
;
goto
out
;
}
...
...
@@ -1894,8 +1883,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
* 'align' will only take the values 0 or 2 here
* since all frames are required to be aligned
* to 2-byte boundaries when being passed to
* mac80211. That also explains the __skb_push()
* below.
* mac80211; the code here works just as well if
* that isn't true, but mac80211 assumes it can
* access fields as 2-byte aligned (e.g. for
* compare_ether_addr)
*/
align
=
((
unsigned
long
)(
skb
->
data
+
sizeof
(
struct
ethhdr
)))
&
3
;
if
(
align
)
{
...
...
@@ -2552,7 +2543,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
case
WLAN_SP_MESH_PEERING_CONFIRM
:
if
(
!
ieee80211_vif_is_mesh
(
&
sdata
->
vif
))
goto
invalid
;
if
(
sdata
->
u
.
mesh
.
security
!=
IEEE80211_MESH_SEC_NONE
)
if
(
sdata
->
u
.
mesh
.
user_mpm
)
/* userspace handles this frame */
break
;
goto
queue
;
...
...
net/mac80211/sta_info.c
浏览文件 @
3d5c2032
...
...
@@ -342,6 +342,11 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
INIT_WORK
(
&
sta
->
drv_unblock_wk
,
sta_unblock
);
INIT_WORK
(
&
sta
->
ampdu_mlme
.
work
,
ieee80211_ba_session_work
);
mutex_init
(
&
sta
->
ampdu_mlme
.
mtx
);
#ifdef CONFIG_MAC80211_MESH
if
(
ieee80211_vif_is_mesh
(
&
sdata
->
vif
)
&&
!
sdata
->
u
.
mesh
.
user_mpm
)
init_timer
(
&
sta
->
plink_timer
);
#endif
memcpy
(
sta
->
sta
.
addr
,
addr
,
ETH_ALEN
);
sta
->
local
=
local
;
...
...
@@ -794,9 +799,11 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
mutex_lock
(
&
local
->
key_mtx
);
for
(
i
=
0
;
i
<
NUM_DEFAULT_KEYS
;
i
++
)
__ieee80211_key_free
(
key_mtx_dereference
(
local
,
sta
->
gtk
[
i
]));
__ieee80211_key_free
(
key_mtx_dereference
(
local
,
sta
->
gtk
[
i
]),
true
);
if
(
sta
->
ptk
)
__ieee80211_key_free
(
key_mtx_dereference
(
local
,
sta
->
ptk
));
__ieee80211_key_free
(
key_mtx_dereference
(
local
,
sta
->
ptk
),
true
);
mutex_unlock
(
&
local
->
key_mtx
);
sta
->
dead
=
true
;
...
...
net/mac80211/sta_info.h
浏览文件 @
3d5c2032
...
...
@@ -281,7 +281,6 @@ struct sta_ampdu_mlme {
* @plink_state: peer link state
* @plink_timeout: timeout of peer link
* @plink_timer: peer link watch timer
* @plink_timer_was_running: used by suspend/resume to restore timers
* @t_offset: timing offset relative to this host
* @t_offset_setpoint: reference timing offset of this sta to be used when
* calculating clockdrift
...
...
@@ -379,7 +378,6 @@ struct sta_info {
__le16
reason
;
u8
plink_retries
;
bool
ignore_plink_timer
;
bool
plink_timer_was_running
;
enum
nl80211_plink_state
plink_state
;
u32
plink_timeout
;
struct
timer_list
plink_timer
;
...
...
net/mac80211/trace.h
浏览文件 @
3d5c2032
...
...
@@ -1042,15 +1042,17 @@ TRACE_EVENT(drv_remain_on_channel,
TP_PROTO
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_channel
*
chan
,
unsigned
int
duration
),
unsigned
int
duration
,
enum
ieee80211_roc_type
type
),
TP_ARGS
(
local
,
sdata
,
chan
,
duration
),
TP_ARGS
(
local
,
sdata
,
chan
,
duration
,
type
),
TP_STRUCT__entry
(
LOCAL_ENTRY
VIF_ENTRY
__field
(
int
,
center_freq
)
__field
(
unsigned
int
,
duration
)
__field
(
u32
,
type
)
),
TP_fast_assign
(
...
...
@@ -1058,12 +1060,13 @@ TRACE_EVENT(drv_remain_on_channel,
VIF_ASSIGN
;
__entry
->
center_freq
=
chan
->
center_freq
;
__entry
->
duration
=
duration
;
__entry
->
type
=
type
;
),
TP_printk
(
LOCAL_PR_FMT
VIF_PR_FMT
" freq:%dMHz duration:%dms"
,
LOCAL_PR_FMT
VIF_PR_FMT
" freq:%dMHz duration:%dms
type=%d
"
,
LOCAL_PR_ARG
,
VIF_PR_ARG
,
__entry
->
center_freq
,
__entry
->
duration
__entry
->
center_freq
,
__entry
->
duration
,
__entry
->
type
)
);
...
...
net/mac80211/tx.c
浏览文件 @
3d5c2032
...
...
@@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
if
(
local
->
queue_stop_reasons
[
q
]
||
(
!
txpending
&&
!
skb_queue_empty
(
&
local
->
pending
[
q
])))
{
if
(
unlikely
(
info
->
flags
&
IEEE80211_TX_INTFL_OFFCHAN_TX_OK
&&
local
->
queue_stop_reasons
[
q
]
&
~
BIT
(
IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL
)))
{
IEEE80211_TX_INTFL_OFFCHAN_TX_OK
))
{
if
(
local
->
queue_stop_reasons
[
q
]
&
~
BIT
(
IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL
))
{
/*
* Drop off-channel frames if queues
* are stopped for any reason other
* than off-channel operation. Never
* queue them.
*/
spin_unlock_irqrestore
(
&
local
->
queue_stop_reason_lock
,
flags
);
ieee80211_purge_tx_queue
(
&
local
->
hw
,
skbs
);
return
true
;
}
}
else
{
/*
*
Drop off-channel frames if queues are stopped
*
for any reason other than off-channel
*
operation. Never queue them
.
*
Since queue is stopped, queue up frames for
*
later transmission from the tx-pending
*
tasklet when the queue is woken again
.
*/
spin_unlock_irqrestore
(
&
local
->
queue_stop_reason_lock
,
flags
);
ieee80211_purge_tx_queue
(
&
local
->
hw
,
skbs
);
return
true
;
if
(
txpending
)
skb_queue_splice_init
(
skbs
,
&
local
->
pending
[
q
]);
else
skb_queue_splice_tail_init
(
skbs
,
&
local
->
pending
[
q
]);
spin_unlock_irqrestore
(
&
local
->
queue_stop_reason_lock
,
flags
);
return
false
;
}
/*
* Since queue is stopped, queue up frames for later
* transmission from the tx-pending tasklet when the
* queue is woken again.
*/
if
(
txpending
)
skb_queue_splice_init
(
skbs
,
&
local
->
pending
[
q
]);
else
skb_queue_splice_tail_init
(
skbs
,
&
local
->
pending
[
q
]);
spin_unlock_irqrestore
(
&
local
->
queue_stop_reason_lock
,
flags
);
return
false
;
}
spin_unlock_irqrestore
(
&
local
->
queue_stop_reason_lock
,
flags
);
...
...
@@ -1844,9 +1850,24 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
}
if
(
!
is_multicast_ether_addr
(
skb
->
data
))
{
struct
sta_info
*
next_hop
;
bool
mpp_lookup
=
true
;
mpath
=
mesh_path_lookup
(
sdata
,
skb
->
data
);
if
(
!
mpath
)
if
(
mpath
)
{
mpp_lookup
=
false
;
next_hop
=
rcu_dereference
(
mpath
->
next_hop
);
if
(
!
next_hop
||
!
(
mpath
->
flags
&
(
MESH_PATH_ACTIVE
|
MESH_PATH_RESOLVING
)))
mpp_lookup
=
true
;
}
if
(
mpp_lookup
)
mppath
=
mpp_path_lookup
(
sdata
,
skb
->
data
);
if
(
mppath
&&
mpath
)
mesh_path_del
(
mpath
->
sdata
,
mpath
->
dst
);
}
/*
...
...
@@ -2350,9 +2371,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
if
(
local
->
tim_in_locked_section
)
{
__ieee80211_beacon_add_tim
(
sdata
,
ps
,
skb
);
}
else
{
spin_lock
(
&
local
->
tim_lock
);
spin_lock
_bh
(
&
local
->
tim_lock
);
__ieee80211_beacon_add_tim
(
sdata
,
ps
,
skb
);
spin_unlock
(
&
local
->
tim_lock
);
spin_unlock
_bh
(
&
local
->
tim_lock
);
}
return
0
;
...
...
@@ -2724,7 +2745,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
cpu_to_le16
(
IEEE80211_FCTL_MOREDATA
);
}
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
skb
->
dev
);
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_AP_VLAN
)
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
skb
->
dev
);
if
(
!
ieee80211_tx_prepare
(
sdata
,
&
tx
,
skb
))
break
;
dev_kfree_skb_any
(
skb
);
...
...
net/mac80211/util.c
浏览文件 @
3d5c2032
...
...
@@ -1357,6 +1357,25 @@ void ieee80211_stop_device(struct ieee80211_local *local)
drv_stop
(
local
);
}
static
void
ieee80211_assign_chanctx
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_chanctx_conf
*
conf
;
struct
ieee80211_chanctx
*
ctx
;
if
(
!
local
->
use_chanctx
)
return
;
mutex_lock
(
&
local
->
chanctx_mtx
);
conf
=
rcu_dereference_protected
(
sdata
->
vif
.
chanctx_conf
,
lockdep_is_held
(
&
local
->
chanctx_mtx
));
if
(
conf
)
{
ctx
=
container_of
(
conf
,
struct
ieee80211_chanctx
,
conf
);
drv_assign_vif_chanctx
(
local
,
sdata
,
ctx
);
}
mutex_unlock
(
&
local
->
chanctx_mtx
);
}
int
ieee80211_reconfig
(
struct
ieee80211_local
*
local
)
{
struct
ieee80211_hw
*
hw
=
&
local
->
hw
;
...
...
@@ -1445,36 +1464,14 @@ int ieee80211_reconfig(struct ieee80211_local *local)
}
list_for_each_entry
(
sdata
,
&
local
->
interfaces
,
list
)
{
struct
ieee80211_chanctx_conf
*
ctx_conf
;
if
(
!
ieee80211_sdata_running
(
sdata
))
continue
;
mutex_lock
(
&
local
->
chanctx_mtx
);
ctx_conf
=
rcu_dereference_protected
(
sdata
->
vif
.
chanctx_conf
,
lockdep_is_held
(
&
local
->
chanctx_mtx
));
if
(
ctx_conf
)
{
ctx
=
container_of
(
ctx_conf
,
struct
ieee80211_chanctx
,
conf
);
drv_assign_vif_chanctx
(
local
,
sdata
,
ctx
);
}
mutex_unlock
(
&
local
->
chanctx_mtx
);
ieee80211_assign_chanctx
(
local
,
sdata
);
}
sdata
=
rtnl_dereference
(
local
->
monitor_sdata
);
if
(
sdata
&&
local
->
use_chanctx
&&
ieee80211_sdata_running
(
sdata
))
{
struct
ieee80211_chanctx_conf
*
ctx_conf
;
mutex_lock
(
&
local
->
chanctx_mtx
);
ctx_conf
=
rcu_dereference_protected
(
sdata
->
vif
.
chanctx_conf
,
lockdep_is_held
(
&
local
->
chanctx_mtx
));
if
(
ctx_conf
)
{
ctx
=
container_of
(
ctx_conf
,
struct
ieee80211_chanctx
,
conf
);
drv_assign_vif_chanctx
(
local
,
sdata
,
ctx
);
}
mutex_unlock
(
&
local
->
chanctx_mtx
);
}
if
(
sdata
&&
ieee80211_sdata_running
(
sdata
))
ieee80211_assign_chanctx
(
local
,
sdata
);
/* add STAs back */
mutex_lock
(
&
local
->
sta_mtx
);
...
...
@@ -1534,11 +1531,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
BSS_CHANGED_IDLE
|
BSS_CHANGED_TXPOWER
;
#ifdef CONFIG_PM
if
(
local
->
resuming
&&
!
reconfig_due_to_wowlan
)
sdata
->
vif
.
bss_conf
=
sdata
->
suspend_bss_conf
;
#endif
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_STATION
:
changed
|=
BSS_CHANGED_ASSOC
|
...
...
@@ -1678,28 +1670,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
mb
();
local
->
resuming
=
false
;
list_for_each_entry
(
sdata
,
&
local
->
interfaces
,
list
)
{
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_STATION
:
ieee80211_sta_restart
(
sdata
);
break
;
case
NL80211_IFTYPE_ADHOC
:
ieee80211_ibss_restart
(
sdata
);
break
;
case
NL80211_IFTYPE_MESH_POINT
:
ieee80211_mesh_restart
(
sdata
);
break
;
default:
break
;
}
}
mod_timer
(
&
local
->
sta_cleanup
,
jiffies
+
1
);
mutex_lock
(
&
local
->
sta_mtx
);
list_for_each_entry
(
sta
,
&
local
->
sta_list
,
list
)
mesh_plink_restart
(
sta
);
mutex_unlock
(
&
local
->
sta_mtx
);
#else
WARN_ON
(
1
);
#endif
...
...
net/mac80211/vht.c
浏览文件 @
3d5c2032
...
...
@@ -13,6 +13,104 @@
#include "rate.h"
static
void
__check_vhtcap_disable
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_sta_vht_cap
*
vht_cap
,
u32
flag
)
{
__le32
le_flag
=
cpu_to_le32
(
flag
);
if
(
sdata
->
u
.
mgd
.
vht_capa_mask
.
vht_cap_info
&
le_flag
&&
!
(
sdata
->
u
.
mgd
.
vht_capa
.
vht_cap_info
&
le_flag
))
vht_cap
->
cap
&=
~
flag
;
}
void
ieee80211_apply_vhtcap_overrides
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_sta_vht_cap
*
vht_cap
)
{
int
i
;
u16
rxmcs_mask
,
rxmcs_cap
,
rxmcs_n
,
txmcs_mask
,
txmcs_cap
,
txmcs_n
;
if
(
!
vht_cap
->
vht_supported
)
return
;
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
)
return
;
__check_vhtcap_disable
(
sdata
,
vht_cap
,
IEEE80211_VHT_CAP_RXLDPC
);
__check_vhtcap_disable
(
sdata
,
vht_cap
,
IEEE80211_VHT_CAP_SHORT_GI_80
);
__check_vhtcap_disable
(
sdata
,
vht_cap
,
IEEE80211_VHT_CAP_SHORT_GI_160
);
__check_vhtcap_disable
(
sdata
,
vht_cap
,
IEEE80211_VHT_CAP_TXSTBC
);
__check_vhtcap_disable
(
sdata
,
vht_cap
,
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
);
__check_vhtcap_disable
(
sdata
,
vht_cap
,
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
);
__check_vhtcap_disable
(
sdata
,
vht_cap
,
IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN
);
__check_vhtcap_disable
(
sdata
,
vht_cap
,
IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN
);
/* Allow user to decrease AMPDU length exponent */
if
(
sdata
->
u
.
mgd
.
vht_capa_mask
.
vht_cap_info
&
cpu_to_le32
(
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK
))
{
u32
cap
,
n
;
n
=
le32_to_cpu
(
sdata
->
u
.
mgd
.
vht_capa
.
vht_cap_info
)
&
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK
;
n
>>=
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT
;
cap
=
vht_cap
->
cap
&
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK
;
cap
>>=
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT
;
if
(
n
<
cap
)
{
vht_cap
->
cap
&=
~
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK
;
vht_cap
->
cap
|=
n
<<
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT
;
}
}
/* Allow the user to decrease MCSes */
rxmcs_mask
=
le16_to_cpu
(
sdata
->
u
.
mgd
.
vht_capa_mask
.
supp_mcs
.
rx_mcs_map
);
rxmcs_n
=
le16_to_cpu
(
sdata
->
u
.
mgd
.
vht_capa
.
supp_mcs
.
rx_mcs_map
);
rxmcs_n
&=
rxmcs_mask
;
rxmcs_cap
=
le16_to_cpu
(
vht_cap
->
vht_mcs
.
rx_mcs_map
);
txmcs_mask
=
le16_to_cpu
(
sdata
->
u
.
mgd
.
vht_capa_mask
.
supp_mcs
.
tx_mcs_map
);
txmcs_n
=
le16_to_cpu
(
sdata
->
u
.
mgd
.
vht_capa
.
supp_mcs
.
tx_mcs_map
);
txmcs_n
&=
txmcs_mask
;
txmcs_cap
=
le16_to_cpu
(
vht_cap
->
vht_mcs
.
tx_mcs_map
);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
u8
m
,
n
,
c
;
m
=
(
rxmcs_mask
>>
2
*
i
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
n
=
(
rxmcs_n
>>
2
*
i
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
c
=
(
rxmcs_cap
>>
2
*
i
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
if
(
m
&&
((
c
!=
IEEE80211_VHT_MCS_NOT_SUPPORTED
&&
n
<
c
)
||
n
==
IEEE80211_VHT_MCS_NOT_SUPPORTED
))
{
rxmcs_cap
&=
~
(
3
<<
2
*
i
);
rxmcs_cap
|=
(
rxmcs_n
&
(
3
<<
2
*
i
));
}
m
=
(
txmcs_mask
>>
2
*
i
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
n
=
(
txmcs_n
>>
2
*
i
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
c
=
(
txmcs_cap
>>
2
*
i
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
if
(
m
&&
((
c
!=
IEEE80211_VHT_MCS_NOT_SUPPORTED
&&
n
<
c
)
||
n
==
IEEE80211_VHT_MCS_NOT_SUPPORTED
))
{
txmcs_cap
&=
~
(
3
<<
2
*
i
);
txmcs_cap
|=
(
txmcs_n
&
(
3
<<
2
*
i
));
}
}
vht_cap
->
vht_mcs
.
rx_mcs_map
=
cpu_to_le16
(
rxmcs_cap
);
vht_cap
->
vht_mcs
.
tx_mcs_map
=
cpu_to_le16
(
txmcs_cap
);
}
void
ieee80211_vht_cap_ie_to_sta_vht_cap
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_supported_band
*
sband
,
...
...
@@ -20,6 +118,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
struct
sta_info
*
sta
)
{
struct
ieee80211_sta_vht_cap
*
vht_cap
=
&
sta
->
sta
.
vht_cap
;
struct
ieee80211_sta_vht_cap
own_cap
;
u32
cap_info
,
i
;
memset
(
vht_cap
,
0
,
sizeof
(
*
vht_cap
));
...
...
@@ -35,12 +135,122 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
vht_cap
->
vht_supported
=
true
;
vht_cap
->
cap
=
le32_to_cpu
(
vht_cap_ie
->
vht_cap_info
);
own_cap
=
sband
->
vht_cap
;
/*
* If user has specified capability overrides, take care
* of that if the station we're setting up is the AP that
* we advertised a restricted capability set to. Override
* our own capabilities and then use those below.
*/
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_STATION
&&
!
test_sta_flag
(
sta
,
WLAN_STA_TDLS_PEER
))
ieee80211_apply_vhtcap_overrides
(
sdata
,
&
own_cap
);
/* take some capabilities as-is */
cap_info
=
le32_to_cpu
(
vht_cap_ie
->
vht_cap_info
);
vht_cap
->
cap
=
cap_info
;
vht_cap
->
cap
&=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895
|
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991
|
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454
|
IEEE80211_VHT_CAP_RXLDPC
|
IEEE80211_VHT_CAP_VHT_TXOP_PS
|
IEEE80211_VHT_CAP_HTC_VHT
|
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK
|
IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB
|
IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB
|
IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN
|
IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN
;
/* and some based on our own capabilities */
switch
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK
)
{
case
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ
:
vht_cap
->
cap
|=
cap_info
&
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ
;
break
;
case
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ
:
vht_cap
->
cap
|=
cap_info
&
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK
;
break
;
default:
/* nothing */
break
;
}
/* symmetric capabilities */
vht_cap
->
cap
|=
cap_info
&
own_cap
.
cap
&
(
IEEE80211_VHT_CAP_SHORT_GI_80
|
IEEE80211_VHT_CAP_SHORT_GI_160
);
/* remaining ones */
if
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
)
{
vht_cap
->
cap
|=
cap_info
&
(
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
|
IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX
|
IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX
);
}
if
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
)
vht_cap
->
cap
|=
cap_info
&
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
;
if
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE
)
vht_cap
->
cap
|=
cap_info
&
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE
;
if
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE
)
vht_cap
->
cap
|=
cap_info
&
IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE
;
if
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_TXSTBC
)
vht_cap
->
cap
|=
cap_info
&
IEEE80211_VHT_CAP_RXSTBC_MASK
;
if
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_RXSTBC_MASK
)
vht_cap
->
cap
|=
cap_info
&
IEEE80211_VHT_CAP_TXSTBC
;
/* Copy peer MCS info, the driver might need them. */
memcpy
(
&
vht_cap
->
vht_mcs
,
&
vht_cap_ie
->
supp_mcs
,
sizeof
(
struct
ieee80211_vht_mcs_info
));
/* but also restrict MCSes */
for
(
i
=
0
;
i
<
8
;
i
++
)
{
u16
own_rx
,
own_tx
,
peer_rx
,
peer_tx
;
own_rx
=
le16_to_cpu
(
own_cap
.
vht_mcs
.
rx_mcs_map
);
own_rx
=
(
own_rx
>>
i
*
2
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
own_tx
=
le16_to_cpu
(
own_cap
.
vht_mcs
.
tx_mcs_map
);
own_tx
=
(
own_tx
>>
i
*
2
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
peer_rx
=
le16_to_cpu
(
vht_cap
->
vht_mcs
.
rx_mcs_map
);
peer_rx
=
(
peer_rx
>>
i
*
2
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
peer_tx
=
le16_to_cpu
(
vht_cap
->
vht_mcs
.
tx_mcs_map
);
peer_tx
=
(
peer_tx
>>
i
*
2
)
&
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
if
(
peer_tx
!=
IEEE80211_VHT_MCS_NOT_SUPPORTED
)
{
if
(
own_rx
==
IEEE80211_VHT_MCS_NOT_SUPPORTED
)
peer_tx
=
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
else
if
(
own_rx
<
peer_tx
)
peer_tx
=
own_rx
;
}
if
(
peer_rx
!=
IEEE80211_VHT_MCS_NOT_SUPPORTED
)
{
if
(
own_tx
==
IEEE80211_VHT_MCS_NOT_SUPPORTED
)
peer_rx
=
IEEE80211_VHT_MCS_NOT_SUPPORTED
;
else
if
(
own_tx
<
peer_rx
)
peer_rx
=
own_tx
;
}
vht_cap
->
vht_mcs
.
rx_mcs_map
&=
~
cpu_to_le16
(
IEEE80211_VHT_MCS_NOT_SUPPORTED
<<
i
*
2
);
vht_cap
->
vht_mcs
.
rx_mcs_map
|=
cpu_to_le16
(
peer_rx
<<
i
*
2
);
vht_cap
->
vht_mcs
.
tx_mcs_map
&=
~
cpu_to_le16
(
IEEE80211_VHT_MCS_NOT_SUPPORTED
<<
i
*
2
);
vht_cap
->
vht_mcs
.
tx_mcs_map
|=
cpu_to_le16
(
peer_tx
<<
i
*
2
);
}
/* finally set up the bandwidth */
switch
(
vht_cap
->
cap
&
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK
)
{
case
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ
:
case
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ
:
...
...
net/rfkill/rfkill-regulator.c
浏览文件 @
3d5c2032
...
...
@@ -51,7 +51,7 @@ static int rfkill_regulator_set_block(void *data, bool blocked)
return
0
;
}
struct
rfkill_ops
rfkill_regulator_ops
=
{
st
atic
st
ruct
rfkill_ops
rfkill_regulator_ops
=
{
.
set_block
=
rfkill_regulator_set_block
,
};
...
...
net/wireless/ap.c
浏览文件 @
3d5c2032
...
...
@@ -46,65 +46,3 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
return
err
;
}
void
cfg80211_ch_switch_notify
(
struct
net_device
*
dev
,
struct
cfg80211_chan_def
*
chandef
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_ch_switch_notify
(
dev
,
chandef
);
wdev_lock
(
wdev
);
if
(
WARN_ON
(
wdev
->
iftype
!=
NL80211_IFTYPE_AP
&&
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_GO
))
goto
out
;
wdev
->
channel
=
chandef
->
chan
;
nl80211_ch_switch_notify
(
rdev
,
dev
,
chandef
,
GFP_KERNEL
);
out:
wdev_unlock
(
wdev
);
return
;
}
EXPORT_SYMBOL
(
cfg80211_ch_switch_notify
);
bool
cfg80211_rx_spurious_frame
(
struct
net_device
*
dev
,
const
u8
*
addr
,
gfp_t
gfp
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
bool
ret
;
trace_cfg80211_rx_spurious_frame
(
dev
,
addr
);
if
(
WARN_ON
(
wdev
->
iftype
!=
NL80211_IFTYPE_AP
&&
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_GO
))
{
trace_cfg80211_return_bool
(
false
);
return
false
;
}
ret
=
nl80211_unexpected_frame
(
dev
,
addr
,
gfp
);
trace_cfg80211_return_bool
(
ret
);
return
ret
;
}
EXPORT_SYMBOL
(
cfg80211_rx_spurious_frame
);
bool
cfg80211_rx_unexpected_4addr_frame
(
struct
net_device
*
dev
,
const
u8
*
addr
,
gfp_t
gfp
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
bool
ret
;
trace_cfg80211_rx_unexpected_4addr_frame
(
dev
,
addr
);
if
(
WARN_ON
(
wdev
->
iftype
!=
NL80211_IFTYPE_AP
&&
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_GO
&&
wdev
->
iftype
!=
NL80211_IFTYPE_AP_VLAN
))
{
trace_cfg80211_return_bool
(
false
);
return
false
;
}
ret
=
nl80211_unexpected_4addr_frame
(
dev
,
addr
,
gfp
);
trace_cfg80211_return_bool
(
ret
);
return
ret
;
}
EXPORT_SYMBOL
(
cfg80211_rx_unexpected_4addr_frame
);
net/wireless/core.c
浏览文件 @
3d5c2032
...
...
@@ -367,8 +367,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev
->
wiphy
.
rts_threshold
=
(
u32
)
-
1
;
rdev
->
wiphy
.
coverage_class
=
0
;
rdev
->
wiphy
.
features
=
NL80211_FEATURE_SCAN_FLUSH
|
NL80211_FEATURE_ADVERTISE_CHAN_LIMITS
;
rdev
->
wiphy
.
features
=
NL80211_FEATURE_SCAN_FLUSH
;
return
&
rdev
->
wiphy
;
}
...
...
@@ -815,6 +814,46 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
rdev
->
num_running_monitor_ifaces
+=
num
;
}
void
cfg80211_leave
(
struct
cfg80211_registered_device
*
rdev
,
struct
wireless_dev
*
wdev
)
{
struct
net_device
*
dev
=
wdev
->
netdev
;
switch
(
wdev
->
iftype
)
{
case
NL80211_IFTYPE_ADHOC
:
cfg80211_leave_ibss
(
rdev
,
dev
,
true
);
break
;
case
NL80211_IFTYPE_P2P_CLIENT
:
case
NL80211_IFTYPE_STATION
:
mutex_lock
(
&
rdev
->
sched_scan_mtx
);
__cfg80211_stop_sched_scan
(
rdev
,
false
);
mutex_unlock
(
&
rdev
->
sched_scan_mtx
);
wdev_lock
(
wdev
);
#ifdef CONFIG_CFG80211_WEXT
kfree
(
wdev
->
wext
.
ie
);
wdev
->
wext
.
ie
=
NULL
;
wdev
->
wext
.
ie_len
=
0
;
wdev
->
wext
.
connect
.
auth_type
=
NL80211_AUTHTYPE_AUTOMATIC
;
#endif
__cfg80211_disconnect
(
rdev
,
dev
,
WLAN_REASON_DEAUTH_LEAVING
,
true
);
cfg80211_mlme_down
(
rdev
,
dev
);
wdev_unlock
(
wdev
);
break
;
case
NL80211_IFTYPE_MESH_POINT
:
cfg80211_leave_mesh
(
rdev
,
dev
);
break
;
case
NL80211_IFTYPE_AP
:
cfg80211_stop_ap
(
rdev
,
dev
);
break
;
default:
break
;
}
wdev
->
beacon_interval
=
0
;
}
static
int
cfg80211_netdev_notifier_call
(
struct
notifier_block
*
nb
,
unsigned
long
state
,
void
*
ndev
)
...
...
@@ -883,38 +922,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
dev
->
priv_flags
|=
IFF_DONT_BRIDGE
;
break
;
case
NETDEV_GOING_DOWN
:
switch
(
wdev
->
iftype
)
{
case
NL80211_IFTYPE_ADHOC
:
cfg80211_leave_ibss
(
rdev
,
dev
,
true
);
break
;
case
NL80211_IFTYPE_P2P_CLIENT
:
case
NL80211_IFTYPE_STATION
:
mutex_lock
(
&
rdev
->
sched_scan_mtx
);
__cfg80211_stop_sched_scan
(
rdev
,
false
);
mutex_unlock
(
&
rdev
->
sched_scan_mtx
);
wdev_lock
(
wdev
);
#ifdef CONFIG_CFG80211_WEXT
kfree
(
wdev
->
wext
.
ie
);
wdev
->
wext
.
ie
=
NULL
;
wdev
->
wext
.
ie_len
=
0
;
wdev
->
wext
.
connect
.
auth_type
=
NL80211_AUTHTYPE_AUTOMATIC
;
#endif
__cfg80211_disconnect
(
rdev
,
dev
,
WLAN_REASON_DEAUTH_LEAVING
,
true
);
cfg80211_mlme_down
(
rdev
,
dev
);
wdev_unlock
(
wdev
);
break
;
case
NL80211_IFTYPE_MESH_POINT
:
cfg80211_leave_mesh
(
rdev
,
dev
);
break
;
case
NL80211_IFTYPE_AP
:
cfg80211_stop_ap
(
rdev
,
dev
);
break
;
default:
break
;
}
wdev
->
beacon_interval
=
0
;
cfg80211_leave
(
rdev
,
wdev
);
break
;
case
NETDEV_DOWN
:
cfg80211_update_iface_num
(
rdev
,
wdev
->
iftype
,
-
1
);
...
...
net/wireless/core.h
浏览文件 @
3d5c2032
...
...
@@ -330,20 +330,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
int
__cfg80211_mlme_assoc
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
struct
ieee80211_channel
*
chan
,
const
u8
*
bssid
,
const
u8
*
prev_bssid
,
const
u8
*
bssid
,
const
u8
*
ssid
,
int
ssid_len
,
const
u8
*
ie
,
int
ie_len
,
bool
use_mfp
,
struct
cfg80211_crypto_settings
*
crypt
,
u32
assoc_flags
,
struct
ieee80211_ht_cap
*
ht_capa
,
struct
ieee80211_ht_cap
*
ht_capa_mask
);
struct
cfg80211_assoc_request
*
req
);
int
cfg80211_mlme_assoc
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
struct
ieee80211_channel
*
chan
,
const
u8
*
bssid
,
const
u8
*
prev_bssid
,
struct
net_device
*
dev
,
struct
ieee80211_channel
*
chan
,
const
u8
*
bssid
,
const
u8
*
ssid
,
int
ssid_len
,
const
u8
*
ie
,
int
ie_len
,
bool
use_mfp
,
struct
cfg80211_crypto_settings
*
crypt
,
u32
assoc_flags
,
struct
ieee80211_ht_cap
*
ht_capa
,
struct
ieee80211_ht_cap
*
ht_capa_mask
);
struct
cfg80211_assoc_request
*
req
);
int
__cfg80211_mlme_deauth
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
const
u8
*
bssid
,
const
u8
*
ie
,
int
ie_len
,
u16
reason
,
...
...
@@ -375,6 +370,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
bool
no_cck
,
bool
dont_wait_for_ack
,
u64
*
cookie
);
void
cfg80211_oper_and_ht_capa
(
struct
ieee80211_ht_cap
*
ht_capa
,
const
struct
ieee80211_ht_cap
*
ht_capa_mask
);
void
cfg80211_oper_and_vht_capa
(
struct
ieee80211_vht_cap
*
vht_capa
,
const
struct
ieee80211_vht_cap
*
vht_capa_mask
);
/* SME */
int
__cfg80211_connect
(
struct
cfg80211_registered_device
*
rdev
,
...
...
@@ -503,6 +500,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
void
cfg80211_update_iface_num
(
struct
cfg80211_registered_device
*
rdev
,
enum
nl80211_iftype
iftype
,
int
num
);
void
cfg80211_leave
(
struct
cfg80211_registered_device
*
rdev
,
struct
wireless_dev
*
wdev
);
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
...
...
net/wireless/mesh.c
浏览文件 @
3d5c2032
...
...
@@ -85,6 +85,7 @@ const struct mesh_setup default_mesh_setup = {
.
ie
=
NULL
,
.
ie_len
=
0
,
.
is_secure
=
false
,
.
user_mpm
=
false
,
.
beacon_interval
=
MESH_DEFAULT_BEACON_INTERVAL
,
.
dtim_period
=
MESH_DEFAULT_DTIM_PERIOD
,
};
...
...
@@ -233,20 +234,6 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
return
0
;
}
void
cfg80211_notify_new_peer_candidate
(
struct
net_device
*
dev
,
const
u8
*
macaddr
,
const
u8
*
ie
,
u8
ie_len
,
gfp_t
gfp
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
trace_cfg80211_notify_new_peer_candidate
(
dev
,
macaddr
);
if
(
WARN_ON
(
wdev
->
iftype
!=
NL80211_IFTYPE_MESH_POINT
))
return
;
nl80211_send_new_peer_candidate
(
wiphy_to_dev
(
wdev
->
wiphy
),
dev
,
macaddr
,
ie
,
ie_len
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_notify_new_peer_candidate
);
static
int
__cfg80211_leave_mesh
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
)
{
...
...
net/wireless/mlme.c
浏览文件 @
3d5c2032
...
...
@@ -187,30 +187,6 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
}
EXPORT_SYMBOL
(
cfg80211_send_disassoc
);
void
cfg80211_send_unprot_deauth
(
struct
net_device
*
dev
,
const
u8
*
buf
,
size_t
len
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_send_unprot_deauth
(
dev
);
nl80211_send_unprot_deauth
(
rdev
,
dev
,
buf
,
len
,
GFP_ATOMIC
);
}
EXPORT_SYMBOL
(
cfg80211_send_unprot_deauth
);
void
cfg80211_send_unprot_disassoc
(
struct
net_device
*
dev
,
const
u8
*
buf
,
size_t
len
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_send_unprot_disassoc
(
dev
);
nl80211_send_unprot_disassoc
(
rdev
,
dev
,
buf
,
len
,
GFP_ATOMIC
);
}
EXPORT_SYMBOL
(
cfg80211_send_unprot_disassoc
);
void
cfg80211_send_auth_timeout
(
struct
net_device
*
dev
,
const
u8
*
addr
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
...
...
@@ -367,27 +343,38 @@ void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
p1
[
i
]
&=
p2
[
i
];
}
/* Do a logical ht_capa &= ht_capa_mask. */
void
cfg80211_oper_and_vht_capa
(
struct
ieee80211_vht_cap
*
vht_capa
,
const
struct
ieee80211_vht_cap
*
vht_capa_mask
)
{
int
i
;
u8
*
p1
,
*
p2
;
if
(
!
vht_capa_mask
)
{
memset
(
vht_capa
,
0
,
sizeof
(
*
vht_capa
));
return
;
}
p1
=
(
u8
*
)(
vht_capa
);
p2
=
(
u8
*
)(
vht_capa_mask
);
for
(
i
=
0
;
i
<
sizeof
(
*
vht_capa
);
i
++
)
p1
[
i
]
&=
p2
[
i
];
}
int
__cfg80211_mlme_assoc
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
struct
ieee80211_channel
*
chan
,
const
u8
*
bssid
,
const
u8
*
prev_bssid
,
const
u8
*
bssid
,
const
u8
*
ssid
,
int
ssid_len
,
const
u8
*
ie
,
int
ie_len
,
bool
use_mfp
,
struct
cfg80211_crypto_settings
*
crypt
,
u32
assoc_flags
,
struct
ieee80211_ht_cap
*
ht_capa
,
struct
ieee80211_ht_cap
*
ht_capa_mask
)
struct
cfg80211_assoc_request
*
req
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
cfg80211_assoc_request
req
;
int
err
;
bool
was_connected
=
false
;
ASSERT_WDEV_LOCK
(
wdev
);
memset
(
&
req
,
0
,
sizeof
(
req
));
if
(
wdev
->
current_bss
&&
prev_bssid
&&
ether_addr_equal
(
wdev
->
current_bss
->
pub
.
bssid
,
prev_bssid
))
{
if
(
wdev
->
current_bss
&&
req
->
prev_bssid
&&
ether_addr_equal
(
wdev
->
current_bss
->
pub
.
bssid
,
req
->
prev_bssid
))
{
/*
* Trying to reassociate: Allow this to proceed and let the old
* association to be dropped when the new one is completed.
...
...
@@ -399,40 +386,30 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
}
else
if
(
wdev
->
current_bss
)
return
-
EALREADY
;
req
.
ie
=
ie
;
req
.
ie_len
=
ie_len
;
memcpy
(
&
req
.
crypto
,
crypt
,
sizeof
(
req
.
crypto
));
req
.
use_mfp
=
use_mfp
;
req
.
prev_bssid
=
prev_bssid
;
req
.
flags
=
assoc_flags
;
if
(
ht_capa
)
memcpy
(
&
req
.
ht_capa
,
ht_capa
,
sizeof
(
req
.
ht_capa
));
if
(
ht_capa_mask
)
memcpy
(
&
req
.
ht_capa_mask
,
ht_capa_mask
,
sizeof
(
req
.
ht_capa_mask
));
cfg80211_oper_and_ht_capa
(
&
req
.
ht_capa_mask
,
cfg80211_oper_and_ht_capa
(
&
req
->
ht_capa_mask
,
rdev
->
wiphy
.
ht_capa_mod_mask
);
cfg80211_oper_and_vht_capa
(
&
req
->
vht_capa_mask
,
rdev
->
wiphy
.
vht_capa_mod_mask
);
req
.
bss
=
cfg80211_get_bss
(
&
rdev
->
wiphy
,
chan
,
bssid
,
ssid
,
ssid_len
,
WLAN_CAPABILITY_ESS
,
WLAN_CAPABILITY_ESS
);
if
(
!
req
.
bss
)
{
req
->
bss
=
cfg80211_get_bss
(
&
rdev
->
wiphy
,
chan
,
bssid
,
ssid
,
ssid_len
,
WLAN_CAPABILITY_ESS
,
WLAN_CAPABILITY_ESS
);
if
(
!
req
->
bss
)
{
if
(
was_connected
)
wdev
->
sme_state
=
CFG80211_SME_CONNECTED
;
return
-
ENOENT
;
}
err
=
cfg80211_can_use_chan
(
rdev
,
wdev
,
req
.
bss
->
channel
,
CHAN_MODE_SHARED
);
err
=
cfg80211_can_use_chan
(
rdev
,
wdev
,
chan
,
CHAN_MODE_SHARED
);
if
(
err
)
goto
out
;
err
=
rdev_assoc
(
rdev
,
dev
,
&
req
);
err
=
rdev_assoc
(
rdev
,
dev
,
req
);
out:
if
(
err
)
{
if
(
was_connected
)
wdev
->
sme_state
=
CFG80211_SME_CONNECTED
;
cfg80211_put_bss
(
&
rdev
->
wiphy
,
req
.
bss
);
cfg80211_put_bss
(
&
rdev
->
wiphy
,
req
->
bss
);
}
return
err
;
...
...
@@ -441,21 +418,17 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
int
cfg80211_mlme_assoc
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
struct
ieee80211_channel
*
chan
,
const
u8
*
bssid
,
const
u8
*
prev_bssid
,
const
u8
*
bssid
,
const
u8
*
ssid
,
int
ssid_len
,
const
u8
*
ie
,
int
ie_len
,
bool
use_mfp
,
struct
cfg80211_crypto_settings
*
crypt
,
u32
assoc_flags
,
struct
ieee80211_ht_cap
*
ht_capa
,
struct
ieee80211_ht_cap
*
ht_capa_mask
)
struct
cfg80211_assoc_request
*
req
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
int
err
;
mutex_lock
(
&
rdev
->
devlist_mtx
);
wdev_lock
(
wdev
);
err
=
__cfg80211_mlme_assoc
(
rdev
,
dev
,
chan
,
bssid
,
prev_bssid
,
ssid
,
ssid_len
,
ie
,
ie_len
,
use_mfp
,
crypt
,
assoc_flags
,
ht_capa
,
ht_capa_mask
);
err
=
__cfg80211_mlme_assoc
(
rdev
,
dev
,
chan
,
bssid
,
ssid
,
ssid_len
,
req
);
wdev_unlock
(
wdev
);
mutex_unlock
(
&
rdev
->
devlist_mtx
);
...
...
@@ -577,62 +550,6 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
}
}
void
cfg80211_ready_on_channel
(
struct
wireless_dev
*
wdev
,
u64
cookie
,
struct
ieee80211_channel
*
chan
,
unsigned
int
duration
,
gfp_t
gfp
)
{
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_ready_on_channel
(
wdev
,
cookie
,
chan
,
duration
);
nl80211_send_remain_on_channel
(
rdev
,
wdev
,
cookie
,
chan
,
duration
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_ready_on_channel
);
void
cfg80211_remain_on_channel_expired
(
struct
wireless_dev
*
wdev
,
u64
cookie
,
struct
ieee80211_channel
*
chan
,
gfp_t
gfp
)
{
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_ready_on_channel_expired
(
wdev
,
cookie
,
chan
);
nl80211_send_remain_on_channel_cancel
(
rdev
,
wdev
,
cookie
,
chan
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_remain_on_channel_expired
);
void
cfg80211_new_sta
(
struct
net_device
*
dev
,
const
u8
*
mac_addr
,
struct
station_info
*
sinfo
,
gfp_t
gfp
)
{
struct
wiphy
*
wiphy
=
dev
->
ieee80211_ptr
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_new_sta
(
dev
,
mac_addr
,
sinfo
);
nl80211_send_sta_event
(
rdev
,
dev
,
mac_addr
,
sinfo
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_new_sta
);
void
cfg80211_del_sta
(
struct
net_device
*
dev
,
const
u8
*
mac_addr
,
gfp_t
gfp
)
{
struct
wiphy
*
wiphy
=
dev
->
ieee80211_ptr
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_del_sta
(
dev
,
mac_addr
);
nl80211_send_sta_del_event
(
rdev
,
dev
,
mac_addr
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_del_sta
);
void
cfg80211_conn_failed
(
struct
net_device
*
dev
,
const
u8
*
mac_addr
,
enum
nl80211_connect_failed_reason
reason
,
gfp_t
gfp
)
{
struct
wiphy
*
wiphy
=
dev
->
ieee80211_ptr
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
nl80211_send_conn_failed_event
(
rdev
,
dev
,
mac_addr
,
reason
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_conn_failed
);
struct
cfg80211_mgmt_registration
{
struct
list_head
list
;
...
...
@@ -909,85 +826,6 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
}
EXPORT_SYMBOL
(
cfg80211_rx_mgmt
);
void
cfg80211_mgmt_tx_status
(
struct
wireless_dev
*
wdev
,
u64
cookie
,
const
u8
*
buf
,
size_t
len
,
bool
ack
,
gfp_t
gfp
)
{
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_mgmt_tx_status
(
wdev
,
cookie
,
ack
);
/* Indicate TX status of the Action frame to user space */
nl80211_send_mgmt_tx_status
(
rdev
,
wdev
,
cookie
,
buf
,
len
,
ack
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_mgmt_tx_status
);
void
cfg80211_cqm_rssi_notify
(
struct
net_device
*
dev
,
enum
nl80211_cqm_rssi_threshold_event
rssi_event
,
gfp_t
gfp
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_cqm_rssi_notify
(
dev
,
rssi_event
);
/* Indicate roaming trigger event to user space */
nl80211_send_cqm_rssi_notify
(
rdev
,
dev
,
rssi_event
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_cqm_rssi_notify
);
void
cfg80211_cqm_pktloss_notify
(
struct
net_device
*
dev
,
const
u8
*
peer
,
u32
num_packets
,
gfp_t
gfp
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_cqm_pktloss_notify
(
dev
,
peer
,
num_packets
);
/* Indicate roaming trigger event to user space */
nl80211_send_cqm_pktloss_notify
(
rdev
,
dev
,
peer
,
num_packets
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_cqm_pktloss_notify
);
void
cfg80211_cqm_txe_notify
(
struct
net_device
*
dev
,
const
u8
*
peer
,
u32
num_packets
,
u32
rate
,
u32
intvl
,
gfp_t
gfp
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
nl80211_send_cqm_txe_notify
(
rdev
,
dev
,
peer
,
num_packets
,
rate
,
intvl
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_cqm_txe_notify
);
void
cfg80211_gtk_rekey_notify
(
struct
net_device
*
dev
,
const
u8
*
bssid
,
const
u8
*
replay_ctr
,
gfp_t
gfp
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_gtk_rekey_notify
(
dev
,
bssid
);
nl80211_gtk_rekey_notify
(
rdev
,
dev
,
bssid
,
replay_ctr
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_gtk_rekey_notify
);
void
cfg80211_pmksa_candidate_notify
(
struct
net_device
*
dev
,
int
index
,
const
u8
*
bssid
,
bool
preauth
,
gfp_t
gfp
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_pmksa_candidate_notify
(
dev
,
index
,
bssid
,
preauth
);
nl80211_pmksa_candidate_notify
(
rdev
,
dev
,
index
,
bssid
,
preauth
,
gfp
);
}
EXPORT_SYMBOL
(
cfg80211_pmksa_candidate_notify
);
void
cfg80211_dfs_channels_update_work
(
struct
work_struct
*
work
)
{
struct
delayed_work
*
delayed_work
;
...
...
net/wireless/nl80211.c
浏览文件 @
3d5c2032
此差异已折叠。
点击以展开。
net/wireless/nl80211.h
浏览文件 @
3d5c2032
...
...
@@ -29,12 +29,6 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
void
nl80211_send_disassoc
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
buf
,
size_t
len
,
gfp_t
gfp
);
void
nl80211_send_unprot_deauth
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
buf
,
size_t
len
,
gfp_t
gfp
);
void
nl80211_send_unprot_disassoc
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
buf
,
size_t
len
,
gfp_t
gfp
);
void
nl80211_send_auth_timeout
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
addr
,
gfp_t
gfp
);
...
...
@@ -54,10 +48,6 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
struct
net_device
*
netdev
,
u16
reason
,
const
u8
*
ie
,
size_t
ie_len
,
bool
from_ap
);
void
nl80211_send_new_peer_candidate
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
macaddr
,
const
u8
*
ie
,
u8
ie_len
,
gfp_t
gfp
);
void
nl80211_michael_mic_failure
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
addr
,
...
...
@@ -73,41 +63,10 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
struct
net_device
*
netdev
,
const
u8
*
bssid
,
gfp_t
gfp
);
void
nl80211_send_remain_on_channel
(
struct
cfg80211_registered_device
*
rdev
,
struct
wireless_dev
*
wdev
,
u64
cookie
,
struct
ieee80211_channel
*
chan
,
unsigned
int
duration
,
gfp_t
gfp
);
void
nl80211_send_remain_on_channel_cancel
(
struct
cfg80211_registered_device
*
rdev
,
struct
wireless_dev
*
wdev
,
u64
cookie
,
struct
ieee80211_channel
*
chan
,
gfp_t
gfp
);
void
nl80211_send_sta_event
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
const
u8
*
mac_addr
,
struct
station_info
*
sinfo
,
gfp_t
gfp
);
void
nl80211_send_sta_del_event
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
const
u8
*
mac_addr
,
gfp_t
gfp
);
void
nl80211_send_conn_failed_event
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
const
u8
*
mac_addr
,
enum
nl80211_connect_failed_reason
reason
,
gfp_t
gfp
);
int
nl80211_send_mgmt
(
struct
cfg80211_registered_device
*
rdev
,
struct
wireless_dev
*
wdev
,
u32
nlpid
,
int
freq
,
int
sig_dbm
,
const
u8
*
buf
,
size_t
len
,
gfp_t
gfp
);
void
nl80211_send_mgmt_tx_status
(
struct
cfg80211_registered_device
*
rdev
,
struct
wireless_dev
*
wdev
,
u64
cookie
,
const
u8
*
buf
,
size_t
len
,
bool
ack
,
gfp_t
gfp
);
void
nl80211_send_cqm_rssi_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
enum
nl80211_cqm_rssi_threshold_event
rssi_event
,
gfp_t
gfp
);
void
nl80211_radar_notify
(
struct
cfg80211_registered_device
*
rdev
,
...
...
@@ -115,31 +74,4 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
enum
nl80211_radar_event
event
,
struct
net_device
*
netdev
,
gfp_t
gfp
);
void
nl80211_send_cqm_pktloss_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
peer
,
u32
num_packets
,
gfp_t
gfp
);
void
nl80211_send_cqm_txe_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
peer
,
u32
num_packets
,
u32
rate
,
u32
intvl
,
gfp_t
gfp
);
void
nl80211_gtk_rekey_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
const
u8
*
bssid
,
const
u8
*
replay_ctr
,
gfp_t
gfp
);
void
nl80211_pmksa_candidate_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
netdev
,
int
index
,
const
u8
*
bssid
,
bool
preauth
,
gfp_t
gfp
);
void
nl80211_ch_switch_notify
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
struct
cfg80211_chan_def
*
chandef
,
gfp_t
gfp
);
bool
nl80211_unexpected_frame
(
struct
net_device
*
dev
,
const
u8
*
addr
,
gfp_t
gfp
);
bool
nl80211_unexpected_4addr_frame
(
struct
net_device
*
dev
,
const
u8
*
addr
,
gfp_t
gfp
);
#endif
/* __NET_WIRELESS_NL80211_H */
net/wireless/rdev-ops.h
浏览文件 @
3d5c2032
...
...
@@ -6,11 +6,12 @@
#include "core.h"
#include "trace.h"
static
inline
int
rdev_suspend
(
struct
cfg80211_registered_device
*
rdev
)
static
inline
int
rdev_suspend
(
struct
cfg80211_registered_device
*
rdev
,
struct
cfg80211_wowlan
*
wowlan
)
{
int
ret
;
trace_rdev_suspend
(
&
rdev
->
wiphy
,
rdev
->
wowlan
);
ret
=
rdev
->
ops
->
suspend
(
&
rdev
->
wiphy
,
rdev
->
wowlan
);
trace_rdev_suspend
(
&
rdev
->
wiphy
,
wowlan
);
ret
=
rdev
->
ops
->
suspend
(
&
rdev
->
wiphy
,
wowlan
);
trace_rdev_return_int
(
&
rdev
->
wiphy
,
ret
);
return
ret
;
}
...
...
@@ -887,4 +888,17 @@ static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
trace_rdev_return_int
(
&
rdev
->
wiphy
,
ret
);
return
ret
;
}
static
inline
int
rdev_update_ft_ies
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
struct
cfg80211_update_ft_ies_params
*
ftie
)
{
int
ret
;
trace_rdev_update_ft_ies
(
&
rdev
->
wiphy
,
dev
,
ftie
);
ret
=
rdev
->
ops
->
update_ft_ies
(
&
rdev
->
wiphy
,
dev
,
ftie
);
trace_rdev_return_int
(
&
rdev
->
wiphy
,
ret
);
return
ret
;
}
#endif
/* __CFG80211_RDEV_OPS */
net/wireless/reg.c
浏览文件 @
3d5c2032
...
...
@@ -184,14 +184,14 @@ static const struct ieee80211_regdomain world_regdom = {
NL80211_RRF_NO_IBSS
|
NL80211_RRF_NO_OFDM
),
/* IEEE 802.11a, channel 36..48 */
REG_RULE
(
5180
-
10
,
5240
+
10
,
4
0
,
6
,
20
,
REG_RULE
(
5180
-
10
,
5240
+
10
,
8
0
,
6
,
20
,
NL80211_RRF_PASSIVE_SCAN
|
NL80211_RRF_NO_IBSS
),
/* NB: 5260 MHz - 5700 MHz requies DFS */
/* NB: 5260 MHz - 5700 MHz requi
r
es DFS */
/* IEEE 802.11a, channel 149..165 */
REG_RULE
(
5745
-
10
,
5825
+
10
,
4
0
,
6
,
20
,
REG_RULE
(
5745
-
10
,
5825
+
10
,
8
0
,
6
,
20
,
NL80211_RRF_PASSIVE_SCAN
|
NL80211_RRF_NO_IBSS
),
...
...
net/wireless/sme.c
浏览文件 @
3d5c2032
...
...
@@ -159,7 +159,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
{
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wdev
->
wiphy
);
struct
cfg80211_connect_params
*
params
;
const
u8
*
prev_bssid
=
NULL
;
struct
cfg80211_assoc_request
req
=
{}
;
int
err
;
ASSERT_WDEV_LOCK
(
wdev
);
...
...
@@ -186,16 +186,20 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
BUG_ON
(
!
rdev
->
ops
->
assoc
);
wdev
->
conn
->
state
=
CFG80211_CONN_ASSOCIATING
;
if
(
wdev
->
conn
->
prev_bssid_valid
)
prev_bssid
=
wdev
->
conn
->
prev_bssid
;
err
=
__cfg80211_mlme_assoc
(
rdev
,
wdev
->
netdev
,
params
->
channel
,
params
->
bssid
,
prev_bssid
,
params
->
ssid
,
params
->
ssid_len
,
params
->
ie
,
params
->
ie_len
,
params
->
mfp
!=
NL80211_MFP_NO
,
&
params
->
crypto
,
params
->
flags
,
&
params
->
ht_capa
,
&
params
->
ht_capa_mask
);
req
.
prev_bssid
=
wdev
->
conn
->
prev_bssid
;
req
.
ie
=
params
->
ie
;
req
.
ie_len
=
params
->
ie_len
;
req
.
use_mfp
=
params
->
mfp
!=
NL80211_MFP_NO
;
req
.
crypto
=
params
->
crypto
;
req
.
flags
=
params
->
flags
;
req
.
ht_capa
=
params
->
ht_capa
;
req
.
ht_capa_mask
=
params
->
ht_capa_mask
;
req
.
vht_capa
=
params
->
vht_capa
;
req
.
vht_capa_mask
=
params
->
vht_capa_mask
;
err
=
__cfg80211_mlme_assoc
(
rdev
,
wdev
->
netdev
,
params
->
channel
,
params
->
bssid
,
params
->
ssid
,
params
->
ssid_len
,
&
req
);
if
(
err
)
__cfg80211_mlme_deauth
(
rdev
,
wdev
->
netdev
,
params
->
bssid
,
NULL
,
0
,
...
...
net/wireless/sysfs.c
浏览文件 @
3d5c2032
...
...
@@ -83,6 +83,14 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
return
0
;
}
static
void
cfg80211_leave_all
(
struct
cfg80211_registered_device
*
rdev
)
{
struct
wireless_dev
*
wdev
;
list_for_each_entry
(
wdev
,
&
rdev
->
wdev_list
,
list
)
cfg80211_leave
(
rdev
,
wdev
);
}
static
int
wiphy_suspend
(
struct
device
*
dev
,
pm_message_t
state
)
{
struct
cfg80211_registered_device
*
rdev
=
dev_to_rdev
(
dev
);
...
...
@@ -90,12 +98,19 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
rdev
->
suspend_at
=
get_seconds
();
if
(
rdev
->
ops
->
suspend
)
{
rtnl_lock
();
if
(
rdev
->
wiphy
.
registered
)
ret
=
rdev_suspend
(
rdev
);
rtnl_unlock
();
rtnl_lock
();
if
(
rdev
->
wiphy
.
registered
)
{
if
(
!
rdev
->
wowlan
)
cfg80211_leave_all
(
rdev
);
if
(
rdev
->
ops
->
suspend
)
ret
=
rdev_suspend
(
rdev
,
rdev
->
wowlan
);
if
(
ret
==
1
)
{
/* Driver refuse to configure wowlan */
cfg80211_leave_all
(
rdev
);
ret
=
rdev_suspend
(
rdev
,
NULL
);
}
}
rtnl_unlock
();
return
ret
;
}
...
...
net/wireless/trace.h
浏览文件 @
3d5c2032
...
...
@@ -1785,6 +1785,26 @@ TRACE_EVENT(rdev_set_mac_acl,
WIPHY_PR_ARG
,
NETDEV_PR_ARG
,
__entry
->
acl_policy
)
);
TRACE_EVENT
(
rdev_update_ft_ies
,
TP_PROTO
(
struct
wiphy
*
wiphy
,
struct
net_device
*
netdev
,
struct
cfg80211_update_ft_ies_params
*
ftie
),
TP_ARGS
(
wiphy
,
netdev
,
ftie
),
TP_STRUCT__entry
(
WIPHY_ENTRY
NETDEV_ENTRY
__field
(
u16
,
md
)
__dynamic_array
(
u8
,
ie
,
ftie
->
ie_len
)
),
TP_fast_assign
(
WIPHY_ASSIGN
;
NETDEV_ASSIGN
;
__entry
->
md
=
ftie
->
md
;
memcpy
(
__get_dynamic_array
(
ie
),
ftie
->
ie
,
ftie
->
ie_len
);
),
TP_printk
(
WIPHY_PR_FMT
", "
NETDEV_PR_FMT
", md: 0x%x"
,
WIPHY_PR_ARG
,
NETDEV_PR_ARG
,
__entry
->
md
)
);
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/
...
...
@@ -2413,6 +2433,32 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup,
TP_printk
(
WIPHY_PR_FMT
", "
WDEV_PR_FMT
,
WIPHY_PR_ARG
,
WDEV_PR_ARG
)
);
TRACE_EVENT
(
cfg80211_ft_event
,
TP_PROTO
(
struct
wiphy
*
wiphy
,
struct
net_device
*
netdev
,
struct
cfg80211_ft_event_params
*
ft_event
),
TP_ARGS
(
wiphy
,
netdev
,
ft_event
),
TP_STRUCT__entry
(
WIPHY_ENTRY
NETDEV_ENTRY
__dynamic_array
(
u8
,
ies
,
ft_event
->
ies_len
)
MAC_ENTRY
(
target_ap
)
__dynamic_array
(
u8
,
ric_ies
,
ft_event
->
ric_ies_len
)
),
TP_fast_assign
(
WIPHY_ASSIGN
;
NETDEV_ASSIGN
;
if
(
ft_event
->
ies
)
memcpy
(
__get_dynamic_array
(
ies
),
ft_event
->
ies
,
ft_event
->
ies_len
);
MAC_ASSIGN
(
target_ap
,
ft_event
->
target_ap
);
if
(
ft_event
->
ric_ies
)
memcpy
(
__get_dynamic_array
(
ric_ies
),
ft_event
->
ric_ies
,
ft_event
->
ric_ies_len
);
),
TP_printk
(
WIPHY_PR_FMT
", "
NETDEV_PR_FMT
", target_ap: "
MAC_PR_FMT
,
WIPHY_PR_ARG
,
NETDEV_PR_ARG
,
MAC_PR_ARG
(
target_ap
))
);
#endif
/* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录