Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
6475cb05
K
Kernel
项目概览
openeuler
/
Kernel
接近 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
6475cb05
编写于
4月 22, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
上级
e563589f
1eb32179
变更
42
隐藏空白更改
内联
并排
Showing
42 changed file
with
1526 addition
and
616 deletion
+1526
-616
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/4965-mac.c
+15
-17
drivers/net/wireless/iwlegacy/4965.c
drivers/net/wireless/iwlegacy/4965.c
+1
-1
drivers/net/wireless/iwlwifi/dvm/devices.c
drivers/net/wireless/iwlwifi/dvm/devices.c
+6
-4
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
+15
-5
drivers/net/wireless/iwlwifi/dvm/rxon.c
drivers/net/wireless/iwlwifi/dvm/rxon.c
+1
-1
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mac80211_hwsim.c
+60
-9
drivers/net/wireless/ti/wl12xx/cmd.c
drivers/net/wireless/ti/wl12xx/cmd.c
+1
-1
drivers/net/wireless/ti/wl18xx/cmd.c
drivers/net/wireless/ti/wl18xx/cmd.c
+3
-3
include/linux/ieee80211.h
include/linux/ieee80211.h
+40
-3
include/net/cfg80211.h
include/net/cfg80211.h
+34
-0
include/net/mac80211.h
include/net/mac80211.h
+80
-10
include/uapi/linux/nl80211.h
include/uapi/linux/nl80211.h
+39
-0
net/mac80211/cfg.c
net/mac80211/cfg.c
+15
-0
net/mac80211/chan.c
net/mac80211/chan.c
+33
-10
net/mac80211/ibss.c
net/mac80211/ibss.c
+5
-1
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+10
-8
net/mac80211/iface.c
net/mac80211/iface.c
+3
-2
net/mac80211/main.c
net/mac80211/main.c
+12
-11
net/mac80211/mesh.c
net/mac80211/mesh.c
+2
-2
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_hwmp.c
+1
-1
net/mac80211/mesh_plink.c
net/mac80211/mesh_plink.c
+3
-3
net/mac80211/mlme.c
net/mac80211/mlme.c
+233
-101
net/mac80211/pm.c
net/mac80211/pm.c
+2
-1
net/mac80211/rate.c
net/mac80211/rate.c
+268
-56
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel.c
+113
-93
net/mac80211/rc80211_minstrel.h
net/mac80211/rc80211_minstrel.h
+5
-2
net/mac80211/rc80211_minstrel_debugfs.c
net/mac80211/rc80211_minstrel_debugfs.c
+2
-2
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rc80211_minstrel_ht.c
+99
-73
net/mac80211/rc80211_minstrel_ht.h
net/mac80211/rc80211_minstrel_ht.h
+2
-0
net/mac80211/rx.c
net/mac80211/rx.c
+19
-5
net/mac80211/scan.c
net/mac80211/scan.c
+1
-1
net/mac80211/trace.h
net/mac80211/trace.h
+4
-4
net/mac80211/tx.c
net/mac80211/tx.c
+41
-101
net/mac80211/util.c
net/mac80211/util.c
+52
-2
net/rfkill/rfkill-gpio.c
net/rfkill/rfkill-gpio.c
+5
-2
net/wireless/core.h
net/wireless/core.h
+3
-0
net/wireless/mlme.c
net/wireless/mlme.c
+5
-0
net/wireless/nl80211.c
net/wireless/nl80211.c
+210
-75
net/wireless/rdev-ops.h
net/wireless/rdev-ops.h
+23
-1
net/wireless/reg.c
net/wireless/reg.c
+1
-1
net/wireless/trace.h
net/wireless/trace.h
+35
-0
net/wireless/util.c
net/wireless/util.c
+24
-4
未找到文件。
drivers/net/wireless/iwlegacy/4965-mac.c
浏览文件 @
6475cb05
...
@@ -6057,7 +6057,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
...
@@ -6057,7 +6057,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
struct
il_priv
*
il
=
hw
->
priv
;
struct
il_priv
*
il
=
hw
->
priv
;
const
struct
il_channel_info
*
ch_info
;
const
struct
il_channel_info
*
ch_info
;
struct
ieee80211_conf
*
conf
=
&
hw
->
conf
;
struct
ieee80211_conf
*
conf
=
&
hw
->
conf
;
struct
ieee80211_channel
*
channel
=
ch_switch
->
chan
nel
;
struct
ieee80211_channel
*
channel
=
ch_switch
->
chan
def
.
chan
;
struct
il_ht_config
*
ht_conf
=
&
il
->
current_ht_config
;
struct
il_ht_config
*
ht_conf
=
&
il
->
current_ht_config
;
u16
ch
;
u16
ch
;
...
@@ -6094,23 +6094,21 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
...
@@ -6094,23 +6094,21 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
il
->
current_ht_config
.
smps
=
conf
->
smps_mode
;
il
->
current_ht_config
.
smps
=
conf
->
smps_mode
;
/* Configure HT40 channels */
/* Configure HT40 channels */
il
->
ht
.
enabled
=
conf_is_ht
(
conf
);
switch
(
cfg80211_get_chandef_type
(
&
ch_switch
->
chandef
))
{
if
(
il
->
ht
.
enabled
)
{
case
NL80211_CHAN_NO_HT
:
if
(
conf_is_ht40_minus
(
conf
))
{
case
NL80211_CHAN_HT20
:
il
->
ht
.
extension_chan_offset
=
IEEE80211_HT_PARAM_CHA_SEC_BELOW
;
il
->
ht
.
is_40mhz
=
true
;
}
else
if
(
conf_is_ht40_plus
(
conf
))
{
il
->
ht
.
extension_chan_offset
=
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
;
il
->
ht
.
is_40mhz
=
true
;
}
else
{
il
->
ht
.
extension_chan_offset
=
IEEE80211_HT_PARAM_CHA_SEC_NONE
;
il
->
ht
.
is_40mhz
=
false
;
}
}
else
il
->
ht
.
is_40mhz
=
false
;
il
->
ht
.
is_40mhz
=
false
;
il
->
ht
.
extension_chan_offset
=
IEEE80211_HT_PARAM_CHA_SEC_NONE
;
break
;
case
NL80211_CHAN_HT40MINUS
:
il
->
ht
.
extension_chan_offset
=
IEEE80211_HT_PARAM_CHA_SEC_BELOW
;
il
->
ht
.
is_40mhz
=
true
;
break
;
case
NL80211_CHAN_HT40PLUS
:
il
->
ht
.
extension_chan_offset
=
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
;
il
->
ht
.
is_40mhz
=
true
;
break
;
}
if
((
le16_to_cpu
(
il
->
staging
.
channel
)
!=
ch
))
if
((
le16_to_cpu
(
il
->
staging
.
channel
)
!=
ch
))
il
->
staging
.
flags
=
0
;
il
->
staging
.
flags
=
0
;
...
...
drivers/net/wireless/iwlegacy/4965.c
浏览文件 @
6475cb05
...
@@ -1493,7 +1493,7 @@ il4965_hw_channel_switch(struct il_priv *il,
...
@@ -1493,7 +1493,7 @@ il4965_hw_channel_switch(struct il_priv *il,
cmd
.
band
=
band
;
cmd
.
band
=
band
;
cmd
.
expect_beacon
=
0
;
cmd
.
expect_beacon
=
0
;
ch
=
ch_switch
->
chan
nel
->
hw_value
;
ch
=
ch_switch
->
chan
def
.
chan
->
hw_value
;
cmd
.
channel
=
cpu_to_le16
(
ch
);
cmd
.
channel
=
cpu_to_le16
(
ch
);
cmd
.
rxon_flags
=
il
->
staging
.
flags
;
cmd
.
rxon_flags
=
il
->
staging
.
flags
;
cmd
.
rxon_filter_flags
=
il
->
staging
.
filter_flags
;
cmd
.
rxon_filter_flags
=
il
->
staging
.
filter_flags
;
...
...
drivers/net/wireless/iwlwifi/dvm/devices.c
浏览文件 @
6475cb05
...
@@ -379,7 +379,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
...
@@ -379,7 +379,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
};
};
cmd
.
band
=
priv
->
band
==
IEEE80211_BAND_2GHZ
;
cmd
.
band
=
priv
->
band
==
IEEE80211_BAND_2GHZ
;
ch
=
ch_switch
->
chan
nel
->
hw_value
;
ch
=
ch_switch
->
chan
def
.
chan
->
hw_value
;
IWL_DEBUG_11H
(
priv
,
"channel switch from %d to %d
\n
"
,
IWL_DEBUG_11H
(
priv
,
"channel switch from %d to %d
\n
"
,
ctx
->
active
.
channel
,
ch
);
ctx
->
active
.
channel
,
ch
);
cmd
.
channel
=
cpu_to_le16
(
ch
);
cmd
.
channel
=
cpu_to_le16
(
ch
);
...
@@ -414,7 +414,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
...
@@ -414,7 +414,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
}
}
IWL_DEBUG_11H
(
priv
,
"uCode time for the switch is 0x%x
\n
"
,
IWL_DEBUG_11H
(
priv
,
"uCode time for the switch is 0x%x
\n
"
,
cmd
.
switch_time
);
cmd
.
switch_time
);
cmd
.
expect_beacon
=
ch_switch
->
channel
->
flags
&
IEEE80211_CHAN_RADAR
;
cmd
.
expect_beacon
=
ch_switch
->
chandef
.
chan
->
flags
&
IEEE80211_CHAN_RADAR
;
return
iwl_dvm_send_cmd
(
priv
,
&
hcmd
);
return
iwl_dvm_send_cmd
(
priv
,
&
hcmd
);
}
}
...
@@ -540,7 +541,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
...
@@ -540,7 +541,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
hcmd
.
data
[
0
]
=
cmd
;
hcmd
.
data
[
0
]
=
cmd
;
cmd
->
band
=
priv
->
band
==
IEEE80211_BAND_2GHZ
;
cmd
->
band
=
priv
->
band
==
IEEE80211_BAND_2GHZ
;
ch
=
ch_switch
->
chan
nel
->
hw_value
;
ch
=
ch_switch
->
chan
def
.
chan
->
hw_value
;
IWL_DEBUG_11H
(
priv
,
"channel switch from %u to %u
\n
"
,
IWL_DEBUG_11H
(
priv
,
"channel switch from %u to %u
\n
"
,
ctx
->
active
.
channel
,
ch
);
ctx
->
active
.
channel
,
ch
);
cmd
->
channel
=
cpu_to_le16
(
ch
);
cmd
->
channel
=
cpu_to_le16
(
ch
);
...
@@ -575,7 +576,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
...
@@ -575,7 +576,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
}
}
IWL_DEBUG_11H
(
priv
,
"uCode time for the switch is 0x%x
\n
"
,
IWL_DEBUG_11H
(
priv
,
"uCode time for the switch is 0x%x
\n
"
,
cmd
->
switch_time
);
cmd
->
switch_time
);
cmd
->
expect_beacon
=
ch_switch
->
channel
->
flags
&
IEEE80211_CHAN_RADAR
;
cmd
->
expect_beacon
=
ch_switch
->
chandef
.
chan
->
flags
&
IEEE80211_CHAN_RADAR
;
err
=
iwl_dvm_send_cmd
(
priv
,
&
hcmd
);
err
=
iwl_dvm_send_cmd
(
priv
,
&
hcmd
);
kfree
(
cmd
);
kfree
(
cmd
);
...
...
drivers/net/wireless/iwlwifi/dvm/mac80211.c
浏览文件 @
6475cb05
...
@@ -970,7 +970,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
...
@@ -970,7 +970,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
{
{
struct
iwl_priv
*
priv
=
IWL_MAC80211_GET_DVM
(
hw
);
struct
iwl_priv
*
priv
=
IWL_MAC80211_GET_DVM
(
hw
);
struct
ieee80211_conf
*
conf
=
&
hw
->
conf
;
struct
ieee80211_conf
*
conf
=
&
hw
->
conf
;
struct
ieee80211_channel
*
channel
=
ch_switch
->
chan
nel
;
struct
ieee80211_channel
*
channel
=
ch_switch
->
chan
def
.
chan
;
struct
iwl_ht_config
*
ht_conf
=
&
priv
->
current_ht_config
;
struct
iwl_ht_config
*
ht_conf
=
&
priv
->
current_ht_config
;
/*
/*
* MULTI-FIXME
* MULTI-FIXME
...
@@ -1008,11 +1008,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
...
@@ -1008,11 +1008,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
priv
->
current_ht_config
.
smps
=
conf
->
smps_mode
;
priv
->
current_ht_config
.
smps
=
conf
->
smps_mode
;
/* Configure HT40 channels */
/* Configure HT40 channels */
ctx
->
ht
.
enabled
=
conf_is_ht
(
conf
);
switch
(
cfg80211_get_chandef_type
(
&
ch_switch
->
chandef
))
{
if
(
ctx
->
ht
.
enabled
)
case
NL80211_CHAN_NO_HT
:
iwlagn_config_ht40
(
conf
,
ctx
);
case
NL80211_CHAN_HT20
:
else
ctx
->
ht
.
is_40mhz
=
false
;
ctx
->
ht
.
is_40mhz
=
false
;
ctx
->
ht
.
extension_chan_offset
=
IEEE80211_HT_PARAM_CHA_SEC_NONE
;
break
;
case
NL80211_CHAN_HT40MINUS
:
ctx
->
ht
.
extension_chan_offset
=
IEEE80211_HT_PARAM_CHA_SEC_BELOW
;
ctx
->
ht
.
is_40mhz
=
true
;
break
;
case
NL80211_CHAN_HT40PLUS
:
ctx
->
ht
.
extension_chan_offset
=
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
;
ctx
->
ht
.
is_40mhz
=
true
;
break
;
}
if
((
le16_to_cpu
(
ctx
->
staging
.
channel
)
!=
ch
))
if
((
le16_to_cpu
(
ctx
->
staging
.
channel
)
!=
ch
))
ctx
->
staging
.
flags
=
0
;
ctx
->
staging
.
flags
=
0
;
...
...
drivers/net/wireless/iwlwifi/dvm/rxon.c
浏览文件 @
6475cb05
...
@@ -1160,7 +1160,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
...
@@ -1160,7 +1160,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
}
}
void
iwlagn_config_ht40
(
struct
ieee80211_conf
*
conf
,
void
iwlagn_config_ht40
(
struct
ieee80211_conf
*
conf
,
struct
iwl_rxon_context
*
ctx
)
struct
iwl_rxon_context
*
ctx
)
{
{
if
(
conf_is_ht40_minus
(
conf
))
{
if
(
conf_is_ht40_minus
(
conf
))
{
ctx
->
ht
.
extension_chan_offset
=
ctx
->
ht
.
extension_chan_offset
=
...
...
drivers/net/wireless/mac80211_hwsim.c
浏览文件 @
6475cb05
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include <linux/if_arp.h>
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <linux/rtnetlink.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/platform_device.h>
#include <linux/debugfs.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/ktime.h>
#include <linux/ktime.h>
...
@@ -52,6 +53,10 @@ static bool paged_rx = false;
...
@@ -52,6 +53,10 @@ static bool paged_rx = false;
module_param
(
paged_rx
,
bool
,
0644
);
module_param
(
paged_rx
,
bool
,
0644
);
MODULE_PARM_DESC
(
paged_rx
,
"Use paged SKBs for RX instead of linear ones"
);
MODULE_PARM_DESC
(
paged_rx
,
"Use paged SKBs for RX instead of linear ones"
);
static
bool
rctbl
=
false
;
module_param
(
rctbl
,
bool
,
0444
);
MODULE_PARM_DESC
(
rctbl
,
"Handle rate control table"
);
/**
/**
* enum hwsim_regtest - the type of regulatory tests we offer
* enum hwsim_regtest - the type of regulatory tests we offer
*
*
...
@@ -717,9 +722,17 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
...
@@ -717,9 +722,17 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
rx_status
.
flag
|=
RX_FLAG_MACTIME_START
;
rx_status
.
flag
|=
RX_FLAG_MACTIME_START
;
rx_status
.
freq
=
chan
->
center_freq
;
rx_status
.
freq
=
chan
->
center_freq
;
rx_status
.
band
=
chan
->
band
;
rx_status
.
band
=
chan
->
band
;
rx_status
.
rate_idx
=
info
->
control
.
rates
[
0
].
idx
;
if
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_VHT_MCS
)
{
if
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
)
rx_status
.
rate_idx
=
rx_status
.
flag
|=
RX_FLAG_HT
;
ieee80211_rate_get_vht_mcs
(
&
info
->
control
.
rates
[
0
]);
rx_status
.
vht_nss
=
ieee80211_rate_get_vht_nss
(
&
info
->
control
.
rates
[
0
]);
rx_status
.
flag
|=
RX_FLAG_VHT
;
}
else
{
rx_status
.
rate_idx
=
info
->
control
.
rates
[
0
].
idx
;
if
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
)
rx_status
.
flag
|=
RX_FLAG_HT
;
}
if
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_40_MHZ_WIDTH
)
if
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_40_MHZ_WIDTH
)
rx_status
.
flag
|=
RX_FLAG_40MHZ
;
rx_status
.
flag
|=
RX_FLAG_40MHZ
;
if
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_SHORT_GI
)
if
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_SHORT_GI
)
...
@@ -886,8 +899,12 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
...
@@ -886,8 +899,12 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
if
(
control
->
sta
)
if
(
control
->
sta
)
hwsim_check_sta_magic
(
control
->
sta
);
hwsim_check_sta_magic
(
control
->
sta
);
txi
->
rate_driver_data
[
0
]
=
channel
;
if
(
rctbl
)
ieee80211_get_tx_rates
(
txi
->
control
.
vif
,
control
->
sta
,
skb
,
txi
->
control
.
rates
,
ARRAY_SIZE
(
txi
->
control
.
rates
));
txi
->
rate_driver_data
[
0
]
=
channel
;
mac80211_hwsim_monitor_rx
(
hw
,
skb
,
channel
);
mac80211_hwsim_monitor_rx
(
hw
,
skb
,
channel
);
/* wmediumd mode check */
/* wmediumd mode check */
...
@@ -989,6 +1006,13 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
...
@@ -989,6 +1006,13 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
{
{
u32
_pid
=
ACCESS_ONCE
(
wmediumd_portid
);
u32
_pid
=
ACCESS_ONCE
(
wmediumd_portid
);
if
(
rctbl
)
{
struct
ieee80211_tx_info
*
txi
=
IEEE80211_SKB_CB
(
skb
);
ieee80211_get_tx_rates
(
txi
->
control
.
vif
,
NULL
,
skb
,
txi
->
control
.
rates
,
ARRAY_SIZE
(
txi
->
control
.
rates
));
}
mac80211_hwsim_monitor_rx
(
hw
,
skb
,
chan
);
mac80211_hwsim_monitor_rx
(
hw
,
skb
,
chan
);
if
(
_pid
)
if
(
_pid
)
...
@@ -1019,6 +1043,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
...
@@ -1019,6 +1043,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
if
(
skb
==
NULL
)
if
(
skb
==
NULL
)
return
;
return
;
info
=
IEEE80211_SKB_CB
(
skb
);
info
=
IEEE80211_SKB_CB
(
skb
);
if
(
rctbl
)
ieee80211_get_tx_rates
(
vif
,
NULL
,
skb
,
info
->
control
.
rates
,
ARRAY_SIZE
(
info
->
control
.
rates
));
txrate
=
ieee80211_get_tx_rate
(
hw
,
info
);
txrate
=
ieee80211_get_tx_rate
(
hw
,
info
);
mgmt
=
(
struct
ieee80211_mgmt
*
)
skb
->
data
;
mgmt
=
(
struct
ieee80211_mgmt
*
)
skb
->
data
;
...
@@ -1687,6 +1716,7 @@ static void mac80211_hwsim_free(void)
...
@@ -1687,6 +1716,7 @@ static void mac80211_hwsim_free(void)
debugfs_remove
(
data
->
debugfs_ps
);
debugfs_remove
(
data
->
debugfs_ps
);
debugfs_remove
(
data
->
debugfs
);
debugfs_remove
(
data
->
debugfs
);
ieee80211_unregister_hw
(
data
->
hw
);
ieee80211_unregister_hw
(
data
->
hw
);
device_release_driver
(
data
->
dev
);
device_unregister
(
data
->
dev
);
device_unregister
(
data
->
dev
);
ieee80211_free_hw
(
data
->
hw
);
ieee80211_free_hw
(
data
->
hw
);
}
}
...
@@ -1695,7 +1725,9 @@ static void mac80211_hwsim_free(void)
...
@@ -1695,7 +1725,9 @@ static void mac80211_hwsim_free(void)
static
struct
device_driver
mac80211_hwsim_driver
=
{
static
struct
device_driver
mac80211_hwsim_driver
=
{
.
name
=
"mac80211_hwsim"
.
name
=
"mac80211_hwsim"
,
.
bus
=
&
platform_bus_type
,
.
owner
=
THIS_MODULE
,
};
};
static
const
struct
net_device_ops
hwsim_netdev_ops
=
{
static
const
struct
net_device_ops
hwsim_netdev_ops
=
{
...
@@ -2187,9 +2219,15 @@ static int __init init_mac80211_hwsim(void)
...
@@ -2187,9 +2219,15 @@ static int __init init_mac80211_hwsim(void)
spin_lock_init
(
&
hwsim_radio_lock
);
spin_lock_init
(
&
hwsim_radio_lock
);
INIT_LIST_HEAD
(
&
hwsim_radios
);
INIT_LIST_HEAD
(
&
hwsim_radios
);
err
=
driver_register
(
&
mac80211_hwsim_driver
);
if
(
err
)
return
err
;
hwsim_class
=
class_create
(
THIS_MODULE
,
"mac80211_hwsim"
);
hwsim_class
=
class_create
(
THIS_MODULE
,
"mac80211_hwsim"
);
if
(
IS_ERR
(
hwsim_class
))
if
(
IS_ERR
(
hwsim_class
))
{
return
PTR_ERR
(
hwsim_class
);
err
=
PTR_ERR
(
hwsim_class
);
goto
failed_unregister_driver
;
}
memset
(
addr
,
0
,
ETH_ALEN
);
memset
(
addr
,
0
,
ETH_ALEN
);
addr
[
0
]
=
0x02
;
addr
[
0
]
=
0x02
;
...
@@ -2211,12 +2249,20 @@ static int __init init_mac80211_hwsim(void)
...
@@ -2211,12 +2249,20 @@ static int __init init_mac80211_hwsim(void)
"hwsim%d"
,
i
);
"hwsim%d"
,
i
);
if
(
IS_ERR
(
data
->
dev
))
{
if
(
IS_ERR
(
data
->
dev
))
{
printk
(
KERN_DEBUG
printk
(
KERN_DEBUG
"mac80211_hwsim: device_create
"
"mac80211_hwsim: device_create
failed (%ld)
\n
"
,
"failed (%ld)
\n
"
,
PTR_ERR
(
data
->
dev
));
PTR_ERR
(
data
->
dev
));
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
failed_drvdata
;
goto
failed_drvdata
;
}
}
data
->
dev
->
driver
=
&
mac80211_hwsim_driver
;
data
->
dev
->
driver
=
&
mac80211_hwsim_driver
;
err
=
device_bind_driver
(
data
->
dev
);
if
(
err
!=
0
)
{
printk
(
KERN_DEBUG
"mac80211_hwsim: device_bind_driver failed (%d)
\n
"
,
err
);
goto
failed_hw
;
}
skb_queue_head_init
(
&
data
->
pending
);
skb_queue_head_init
(
&
data
->
pending
);
SET_IEEE80211_DEV
(
hw
,
data
->
dev
);
SET_IEEE80211_DEV
(
hw
,
data
->
dev
);
...
@@ -2259,6 +2305,8 @@ static int __init init_mac80211_hwsim(void)
...
@@ -2259,6 +2305,8 @@ static int __init init_mac80211_hwsim(void)
IEEE80211_HW_AMPDU_AGGREGATION
|
IEEE80211_HW_AMPDU_AGGREGATION
|
IEEE80211_HW_WANT_MONITOR_VIF
|
IEEE80211_HW_WANT_MONITOR_VIF
|
IEEE80211_HW_QUEUE_CONTROL
;
IEEE80211_HW_QUEUE_CONTROL
;
if
(
rctbl
)
hw
->
flags
|=
IEEE80211_HW_SUPPORTS_RC_TABLE
;
hw
->
wiphy
->
flags
|=
WIPHY_FLAG_SUPPORTS_TDLS
|
hw
->
wiphy
->
flags
|=
WIPHY_FLAG_SUPPORTS_TDLS
|
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
;
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
;
...
@@ -2515,6 +2563,8 @@ static int __init init_mac80211_hwsim(void)
...
@@ -2515,6 +2563,8 @@ static int __init init_mac80211_hwsim(void)
ieee80211_free_hw
(
hw
);
ieee80211_free_hw
(
hw
);
failed:
failed:
mac80211_hwsim_free
();
mac80211_hwsim_free
();
failed_unregister_driver:
driver_unregister
(
&
mac80211_hwsim_driver
);
return
err
;
return
err
;
}
}
module_init
(
init_mac80211_hwsim
);
module_init
(
init_mac80211_hwsim
);
...
@@ -2527,5 +2577,6 @@ static void __exit exit_mac80211_hwsim(void)
...
@@ -2527,5 +2577,6 @@ static void __exit exit_mac80211_hwsim(void)
mac80211_hwsim_free
();
mac80211_hwsim_free
();
unregister_netdev
(
hwsim_mon
);
unregister_netdev
(
hwsim_mon
);
driver_unregister
(
&
mac80211_hwsim_driver
);
}
}
module_exit
(
exit_mac80211_hwsim
);
module_exit
(
exit_mac80211_hwsim
);
drivers/net/wireless/ti/wl12xx/cmd.c
浏览文件 @
6475cb05
...
@@ -301,7 +301,7 @@ int wl12xx_cmd_channel_switch(struct wl1271 *wl,
...
@@ -301,7 +301,7 @@ int wl12xx_cmd_channel_switch(struct wl1271 *wl,
}
}
cmd
->
role_id
=
wlvif
->
role_id
;
cmd
->
role_id
=
wlvif
->
role_id
;
cmd
->
channel
=
ch_switch
->
chan
nel
->
hw_value
;
cmd
->
channel
=
ch_switch
->
chan
def
.
chan
->
hw_value
;
cmd
->
switch_time
=
ch_switch
->
count
;
cmd
->
switch_time
=
ch_switch
->
count
;
cmd
->
stop_tx
=
ch_switch
->
block_tx
;
cmd
->
stop_tx
=
ch_switch
->
block_tx
;
...
...
drivers/net/wireless/ti/wl18xx/cmd.c
浏览文件 @
6475cb05
...
@@ -42,11 +42,11 @@ int wl18xx_cmd_channel_switch(struct wl1271 *wl,
...
@@ -42,11 +42,11 @@ int wl18xx_cmd_channel_switch(struct wl1271 *wl,
}
}
cmd
->
role_id
=
wlvif
->
role_id
;
cmd
->
role_id
=
wlvif
->
role_id
;
cmd
->
channel
=
ch_switch
->
chan
nel
->
hw_value
;
cmd
->
channel
=
ch_switch
->
chan
def
.
chan
->
hw_value
;
cmd
->
switch_time
=
ch_switch
->
count
;
cmd
->
switch_time
=
ch_switch
->
count
;
cmd
->
stop_tx
=
ch_switch
->
block_tx
;
cmd
->
stop_tx
=
ch_switch
->
block_tx
;
switch
(
ch_switch
->
chan
nel
->
band
)
{
switch
(
ch_switch
->
chan
def
.
chan
->
band
)
{
case
IEEE80211_BAND_2GHZ
:
case
IEEE80211_BAND_2GHZ
:
cmd
->
band
=
WLCORE_BAND_2_4GHZ
;
cmd
->
band
=
WLCORE_BAND_2_4GHZ
;
break
;
break
;
...
@@ -55,7 +55,7 @@ int wl18xx_cmd_channel_switch(struct wl1271 *wl,
...
@@ -55,7 +55,7 @@ int wl18xx_cmd_channel_switch(struct wl1271 *wl,
break
;
break
;
default:
default:
wl1271_error
(
"invalid channel switch band: %d"
,
wl1271_error
(
"invalid channel switch band: %d"
,
ch_switch
->
chan
nel
->
band
);
ch_switch
->
chan
def
.
chan
->
band
);
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
goto
out_free
;
goto
out_free
;
}
}
...
...
include/linux/ieee80211.h
浏览文件 @
6475cb05
...
@@ -672,6 +672,36 @@ struct ieee80211_channel_sw_ie {
...
@@ -672,6 +672,36 @@ struct ieee80211_channel_sw_ie {
u8
count
;
u8
count
;
}
__packed
;
}
__packed
;
/**
* struct ieee80211_ext_chansw_ie
*
* This structure represents the "Extended Channel Switch Announcement element"
*/
struct
ieee80211_ext_chansw_ie
{
u8
mode
;
u8
new_operating_class
;
u8
new_ch_num
;
u8
count
;
}
__packed
;
/**
* struct ieee80211_sec_chan_offs_ie - secondary channel offset IE
* @sec_chan_offs: secondary channel offset, uses IEEE80211_HT_PARAM_CHA_SEC_*
* values here
* This structure represents the "Secondary Channel Offset element"
*/
struct
ieee80211_sec_chan_offs_ie
{
u8
sec_chan_offs
;
}
__packed
;
/**
* struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE
*/
struct
ieee80211_wide_bw_chansw_ie
{
u8
new_channel_width
;
u8
new_center_freq_seg0
,
new_center_freq_seg1
;
}
__packed
;
/**
/**
* struct ieee80211_tim
* struct ieee80211_tim
*
*
...
@@ -840,10 +870,13 @@ struct ieee80211_mgmt {
...
@@ -840,10 +870,13 @@ struct ieee80211_mgmt {
}
__packed
wme_action
;
}
__packed
wme_action
;
struct
{
struct
{
u8
action_code
;
u8
action_code
;
u8
element_id
;
u8
variable
[
0
];
u8
length
;
struct
ieee80211_channel_sw_ie
sw_elem
;
}
__packed
chan_switch
;
}
__packed
chan_switch
;
struct
{
u8
action_code
;
struct
ieee80211_ext_chansw_ie
data
;
u8
variable
[
0
];
}
__packed
ext_chan_switch
;
struct
{
struct
{
u8
action_code
;
u8
action_code
;
u8
dialog_token
;
u8
dialog_token
;
...
@@ -1638,6 +1671,7 @@ enum ieee80211_eid {
...
@@ -1638,6 +1671,7 @@ enum ieee80211_eid {
WLAN_EID_HT_CAPABILITY
=
45
,
WLAN_EID_HT_CAPABILITY
=
45
,
WLAN_EID_HT_OPERATION
=
61
,
WLAN_EID_HT_OPERATION
=
61
,
WLAN_EID_SECONDARY_CHANNEL_OFFSET
=
62
,
WLAN_EID_RSN
=
48
,
WLAN_EID_RSN
=
48
,
WLAN_EID_MMIE
=
76
,
WLAN_EID_MMIE
=
76
,
...
@@ -1672,6 +1706,8 @@ enum ieee80211_eid {
...
@@ -1672,6 +1706,8 @@ enum ieee80211_eid {
WLAN_EID_VHT_CAPABILITY
=
191
,
WLAN_EID_VHT_CAPABILITY
=
191
,
WLAN_EID_VHT_OPERATION
=
192
,
WLAN_EID_VHT_OPERATION
=
192
,
WLAN_EID_OPMODE_NOTIF
=
199
,
WLAN_EID_OPMODE_NOTIF
=
199
,
WLAN_EID_WIDE_BW_CHANNEL_SWITCH
=
194
,
WLAN_EID_CHANNEL_SWITCH_WRAPPER
=
196
,
/* 802.11ad */
/* 802.11ad */
WLAN_EID_NON_TX_BSSID_CAP
=
83
,
WLAN_EID_NON_TX_BSSID_CAP
=
83
,
...
@@ -1795,6 +1831,7 @@ enum ieee80211_key_len {
...
@@ -1795,6 +1831,7 @@ enum ieee80211_key_len {
/* Public action codes */
/* Public action codes */
enum
ieee80211_pub_actioncode
{
enum
ieee80211_pub_actioncode
{
WLAN_PUB_ACTION_EXT_CHANSW_ANN
=
4
,
WLAN_PUB_ACTION_TDLS_DISCOVER_RES
=
14
,
WLAN_PUB_ACTION_TDLS_DISCOVER_RES
=
14
,
};
};
...
...
include/net/cfg80211.h
浏览文件 @
6475cb05
...
@@ -2002,6 +2002,12 @@ struct cfg80211_update_ft_ies_params {
...
@@ -2002,6 +2002,12 @@ struct cfg80211_update_ft_ies_params {
* @update_ft_ies: Provide updated Fast BSS Transition information to the
* @update_ft_ies: Provide updated Fast BSS Transition information to the
* driver. If the SME is in the driver/firmware, this information can be
* driver. If the SME is in the driver/firmware, this information can be
* used in building Authentication and Reassociation Request frames.
* used in building Authentication and Reassociation Request frames.
*
* @crit_proto_start: Indicates a critical protocol needs more link reliability
* for a given duration (milliseconds). The protocol is provided so the
* driver can take the most appropriate actions.
* @crit_proto_stop: Indicates critical protocol no longer needs increased link
* reliability. This operation can not fail.
*/
*/
struct
cfg80211_ops
{
struct
cfg80211_ops
{
int
(
*
suspend
)(
struct
wiphy
*
wiphy
,
struct
cfg80211_wowlan
*
wow
);
int
(
*
suspend
)(
struct
wiphy
*
wiphy
,
struct
cfg80211_wowlan
*
wow
);
...
@@ -2231,6 +2237,12 @@ struct cfg80211_ops {
...
@@ -2231,6 +2237,12 @@ struct cfg80211_ops {
struct
cfg80211_chan_def
*
chandef
);
struct
cfg80211_chan_def
*
chandef
);
int
(
*
update_ft_ies
)(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
int
(
*
update_ft_ies
)(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
cfg80211_update_ft_ies_params
*
ftie
);
struct
cfg80211_update_ft_ies_params
*
ftie
);
int
(
*
crit_proto_start
)(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
enum
nl80211_crit_proto_id
protocol
,
u16
duration
);
void
(
*
crit_proto_stop
)(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
);
};
};
/*
/*
...
@@ -4024,6 +4036,17 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
...
@@ -4024,6 +4036,17 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
void
cfg80211_ch_switch_notify
(
struct
net_device
*
dev
,
void
cfg80211_ch_switch_notify
(
struct
net_device
*
dev
,
struct
cfg80211_chan_def
*
chandef
);
struct
cfg80211_chan_def
*
chandef
);
/**
* ieee80211_operating_class_to_band - convert operating class to band
*
* @operating_class: the operating class to convert
* @band: band pointer to fill
*
* Returns %true if the conversion was successful, %false otherwise.
*/
bool
ieee80211_operating_class_to_band
(
u8
operating_class
,
enum
ieee80211_band
*
band
);
/*
/*
* cfg80211_tdls_oper_request - request userspace to perform TDLS operation
* cfg80211_tdls_oper_request - request userspace to perform TDLS operation
* @dev: the device on which the operation is requested
* @dev: the device on which the operation is requested
...
@@ -4126,6 +4149,17 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
...
@@ -4126,6 +4149,17 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
struct
cfg80211_wowlan_wakeup
*
wakeup
,
struct
cfg80211_wowlan_wakeup
*
wakeup
,
gfp_t
gfp
);
gfp_t
gfp
);
/**
* cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver.
*
* @wdev: the wireless device for which critical protocol is stopped.
*
* This function can be called by the driver to indicate it has reverted
* operation back to normal. One reason could be that the duration given
* by .crit_proto_start() has expired.
*/
void
cfg80211_crit_proto_stopped
(
struct
wireless_dev
*
wdev
,
gfp_t
gfp
);
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
/* wiphy_printk helpers, similar to dev_printk */
...
...
include/net/mac80211.h
浏览文件 @
6475cb05
...
@@ -128,6 +128,7 @@ enum ieee80211_ac_numbers {
...
@@ -128,6 +128,7 @@ enum ieee80211_ac_numbers {
* 2^n-1 in the range 1..32767]
* 2^n-1 in the range 1..32767]
* @cw_max: maximum contention window [like @cw_min]
* @cw_max: maximum contention window [like @cw_min]
* @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
* @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
* @acm: is mandatory admission control required for the access category
* @uapsd: is U-APSD mode enabled for the queue
* @uapsd: is U-APSD mode enabled for the queue
*/
*/
struct
ieee80211_tx_queue_params
{
struct
ieee80211_tx_queue_params
{
...
@@ -135,6 +136,7 @@ struct ieee80211_tx_queue_params {
...
@@ -135,6 +136,7 @@ struct ieee80211_tx_queue_params {
u16
cw_min
;
u16
cw_min
;
u16
cw_max
;
u16
cw_max
;
u8
aifs
;
u8
aifs
;
bool
acm
;
bool
uapsd
;
bool
uapsd
;
};
};
...
@@ -209,7 +211,7 @@ struct ieee80211_chanctx_conf {
...
@@ -209,7 +211,7 @@ struct ieee80211_chanctx_conf {
* @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
* @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
* that it is only ever disabled for station mode.
* that it is only ever disabled for station mode.
* @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
* @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
* @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
* @BSS_CHANGED_SSID: SSID changed for this BSS (AP
and IBSS
mode)
* @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
* @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
* @BSS_CHANGED_PS: PS changed for this BSS (STA mode)
* @BSS_CHANGED_PS: PS changed for this BSS (STA mode)
* @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
* @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
...
@@ -326,7 +328,7 @@ enum ieee80211_rssi_event {
...
@@ -326,7 +328,7 @@ enum ieee80211_rssi_event {
* your driver/device needs to do.
* your driver/device needs to do.
* @ps: power-save mode (STA only). This flag is NOT affected by
* @ps: power-save mode (STA only). This flag is NOT affected by
* offchannel/dynamic_ps operations.
* offchannel/dynamic_ps operations.
* @ssid: The SSID of the current vif.
Only valid in AP-
mode.
* @ssid: The SSID of the current vif.
Valid in AP and IBSS
mode.
* @ssid_len: Length of SSID given in @ssid.
* @ssid_len: Length of SSID given in @ssid.
* @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
* @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
* @txpower: TX power in dBm
* @txpower: TX power in dBm
...
@@ -561,6 +563,9 @@ enum mac80211_rate_control_flags {
...
@@ -561,6 +563,9 @@ enum mac80211_rate_control_flags {
/* maximum number of rate stages */
/* maximum number of rate stages */
#define IEEE80211_TX_MAX_RATES 4
#define IEEE80211_TX_MAX_RATES 4
/* maximum number of rate table entries */
#define IEEE80211_TX_RATE_TABLE_SIZE 4
/**
/**
* struct ieee80211_tx_rate - rate selection/status
* struct ieee80211_tx_rate - rate selection/status
*
*
...
@@ -601,8 +606,8 @@ static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,
...
@@ -601,8 +606,8 @@ static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,
u8
mcs
,
u8
nss
)
u8
mcs
,
u8
nss
)
{
{
WARN_ON
(
mcs
&
~
0xF
);
WARN_ON
(
mcs
&
~
0xF
);
WARN_ON
(
nss
&
~
0x7
);
WARN_ON
(
(
nss
-
1
)
&
~
0x7
);
rate
->
idx
=
(
nss
<<
4
)
|
mcs
;
rate
->
idx
=
(
(
nss
-
1
)
<<
4
)
|
mcs
;
}
}
static
inline
u8
static
inline
u8
...
@@ -614,7 +619,7 @@ ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate)
...
@@ -614,7 +619,7 @@ ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate)
static
inline
u8
static
inline
u8
ieee80211_rate_get_vht_nss
(
const
struct
ieee80211_tx_rate
*
rate
)
ieee80211_rate_get_vht_nss
(
const
struct
ieee80211_tx_rate
*
rate
)
{
{
return
rate
->
idx
>>
4
;
return
(
rate
->
idx
>>
4
)
+
1
;
}
}
/**
/**
...
@@ -655,7 +660,11 @@ struct ieee80211_tx_info {
...
@@ -655,7 +660,11 @@ struct ieee80211_tx_info {
struct
ieee80211_tx_rate
rates
[
struct
ieee80211_tx_rate
rates
[
IEEE80211_TX_MAX_RATES
];
IEEE80211_TX_MAX_RATES
];
s8
rts_cts_rate_idx
;
s8
rts_cts_rate_idx
;
/* 3 bytes free */
u8
use_rts
:
1
;
u8
use_cts_prot
:
1
;
u8
short_preamble
:
1
;
u8
skip_table
:
1
;
/* 2 bytes free */
};
};
/* only needed before rate control */
/* only needed before rate control */
unsigned
long
jiffies
;
unsigned
long
jiffies
;
...
@@ -676,6 +685,8 @@ struct ieee80211_tx_info {
...
@@ -676,6 +685,8 @@ struct ieee80211_tx_info {
struct
{
struct
{
struct
ieee80211_tx_rate
driver_rates
[
struct
ieee80211_tx_rate
driver_rates
[
IEEE80211_TX_MAX_RATES
];
IEEE80211_TX_MAX_RATES
];
u8
pad
[
4
];
void
*
rate_driver_data
[
void
*
rate_driver_data
[
IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE
/
sizeof
(
void
*
)];
IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE
/
sizeof
(
void
*
)];
};
};
...
@@ -1017,13 +1028,13 @@ struct ieee80211_conf {
...
@@ -1017,13 +1028,13 @@ struct ieee80211_conf {
* the driver passed into mac80211.
* the driver passed into mac80211.
* @block_tx: Indicates whether transmission must be blocked before the
* @block_tx: Indicates whether transmission must be blocked before the
* scheduled channel switch, as indicated by the AP.
* scheduled channel switch, as indicated by the AP.
* @chan
nel
: the new channel to switch to
* @chan
def
: the new channel to switch to
* @count: the number of TBTT's until the channel switch event
* @count: the number of TBTT's until the channel switch event
*/
*/
struct
ieee80211_channel_switch
{
struct
ieee80211_channel_switch
{
u64
timestamp
;
u64
timestamp
;
bool
block_tx
;
bool
block_tx
;
struct
ieee80211_channel
*
channel
;
struct
cfg80211_chan_def
chandef
;
u8
count
;
u8
count
;
};
};
...
@@ -1220,6 +1231,24 @@ enum ieee80211_sta_rx_bandwidth {
...
@@ -1220,6 +1231,24 @@ enum ieee80211_sta_rx_bandwidth {
IEEE80211_STA_RX_BW_160
,
IEEE80211_STA_RX_BW_160
,
};
};
/**
* struct ieee80211_sta_rates - station rate selection table
*
* @rcu_head: RCU head used for freeing the table on update
* @rates: transmit rates/flags to be used by default.
* Overriding entries per-packet is possible by using cb tx control.
*/
struct
ieee80211_sta_rates
{
struct
rcu_head
rcu_head
;
struct
{
s8
idx
;
u8
count
;
u8
count_cts
;
u8
count_rts
;
u16
flags
;
}
rate
[
IEEE80211_TX_RATE_TABLE_SIZE
];
};
/**
/**
* struct ieee80211_sta - station table entry
* struct ieee80211_sta - station table entry
*
*
...
@@ -1247,6 +1276,7 @@ enum ieee80211_sta_rx_bandwidth {
...
@@ -1247,6 +1276,7 @@ enum ieee80211_sta_rx_bandwidth {
* notifications and capabilities. The value is only valid after
* notifications and capabilities. The value is only valid after
* the station moves to associated state.
* the station moves to associated state.
* @smps_mode: current SMPS mode (off, static or dynamic)
* @smps_mode: current SMPS mode (off, static or dynamic)
* @tx_rates: rate control selection table
*/
*/
struct
ieee80211_sta
{
struct
ieee80211_sta
{
u32
supp_rates
[
IEEE80211_NUM_BANDS
];
u32
supp_rates
[
IEEE80211_NUM_BANDS
];
...
@@ -1260,6 +1290,7 @@ struct ieee80211_sta {
...
@@ -1260,6 +1290,7 @@ struct ieee80211_sta {
u8
rx_nss
;
u8
rx_nss
;
enum
ieee80211_sta_rx_bandwidth
bandwidth
;
enum
ieee80211_sta_rx_bandwidth
bandwidth
;
enum
ieee80211_smps_mode
smps_mode
;
enum
ieee80211_smps_mode
smps_mode
;
struct
ieee80211_sta_rates
__rcu
*
rates
;
/* must be last */
/* must be last */
u8
drv_priv
[
0
]
__aligned
(
sizeof
(
void
*
));
u8
drv_priv
[
0
]
__aligned
(
sizeof
(
void
*
));
...
@@ -1415,6 +1446,9 @@ struct ieee80211_tx_control {
...
@@ -1415,6 +1446,9 @@ struct ieee80211_tx_control {
* for different virtual interfaces. See the doc section on HW queue
* for different virtual interfaces. See the doc section on HW queue
* control for more details.
* control for more details.
*
*
* @IEEE80211_HW_SUPPORTS_RC_TABLE: The driver supports using a rate
* selection table provided by the rate control algorithm.
*
* @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any
* @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any
* P2P Interface. This will be honoured even if more than one interface
* P2P Interface. This will be honoured even if more than one interface
* is supported.
* is supported.
...
@@ -1447,6 +1481,7 @@ enum ieee80211_hw_flags {
...
@@ -1447,6 +1481,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_PER_STA_GTK
=
1
<<
21
,
IEEE80211_HW_SUPPORTS_PER_STA_GTK
=
1
<<
21
,
IEEE80211_HW_AP_LINK_PS
=
1
<<
22
,
IEEE80211_HW_AP_LINK_PS
=
1
<<
22
,
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW
=
1
<<
23
,
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW
=
1
<<
23
,
IEEE80211_HW_SUPPORTS_RC_TABLE
=
1
<<
24
,
IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF
=
1
<<
25
,
IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF
=
1
<<
25
,
IEEE80211_HW_TIMING_BEACON_ONLY
=
1
<<
26
,
IEEE80211_HW_TIMING_BEACON_ONLY
=
1
<<
26
,
};
};
...
@@ -3132,6 +3167,25 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
...
@@ -3132,6 +3167,25 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
void
ieee80211_sta_set_buffered
(
struct
ieee80211_sta
*
sta
,
void
ieee80211_sta_set_buffered
(
struct
ieee80211_sta
*
sta
,
u8
tid
,
bool
buffered
);
u8
tid
,
bool
buffered
);
/**
* ieee80211_get_tx_rates - get the selected transmit rates for a packet
*
* Call this function in a driver with per-packet rate selection support
* to combine the rate info in the packet tx info with the most recent
* rate selection table for the station entry.
*
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
* @sta: the receiver station to which this packet is sent.
* @skb: the frame to be transmitted.
* @dest: buffer for extracted rate/retry information
* @max_rates: maximum number of rates to fetch
*/
void
ieee80211_get_tx_rates
(
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
sk_buff
*
skb
,
struct
ieee80211_tx_rate
*
dest
,
int
max_rates
);
/**
/**
* ieee80211_tx_status - transmit status callback
* ieee80211_tx_status - transmit status callback
*
*
...
@@ -4107,7 +4161,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
...
@@ -4107,7 +4161,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
* (deprecated; this will be removed once drivers get updated to use
* (deprecated; this will be removed once drivers get updated to use
* rate_idx_mask)
* rate_idx_mask)
* @rate_idx_mask: user-requested (legacy) rate mask
* @rate_idx_mask: user-requested (legacy) rate mask
* @rate_idx_mcs_mask: user-requested MCS rate mask
* @rate_idx_mcs_mask: user-requested MCS rate mask
(NULL if not in use)
* @bss: whether this frame is sent out in AP or IBSS mode
* @bss: whether this frame is sent out in AP or IBSS mode
*/
*/
struct
ieee80211_tx_rate_control
{
struct
ieee80211_tx_rate_control
{
...
@@ -4119,7 +4173,7 @@ struct ieee80211_tx_rate_control {
...
@@ -4119,7 +4173,7 @@ struct ieee80211_tx_rate_control {
bool
rts
,
short_preamble
;
bool
rts
,
short_preamble
;
u8
max_rate_idx
;
u8
max_rate_idx
;
u32
rate_idx_mask
;
u32
rate_idx_mask
;
u8
rate_idx_mcs_mask
[
IEEE80211_HT_MCS_MASK_LEN
]
;
u8
*
rate_idx_mcs_mask
;
bool
bss
;
bool
bss
;
};
};
...
@@ -4208,6 +4262,22 @@ bool rate_usable_index_exists(struct ieee80211_supported_band *sband,
...
@@ -4208,6 +4262,22 @@ bool rate_usable_index_exists(struct ieee80211_supported_band *sband,
return
false
;
return
false
;
}
}
/**
* rate_control_set_rates - pass the sta rate selection to mac80211/driver
*
* When not doing a rate control probe to test rates, rate control should pass
* its rate selection to mac80211. If the driver supports receiving a station
* rate table, it will use it to ensure that frames are always sent based on
* the most recent rate control module decision.
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
* @pubsta: &struct ieee80211_sta pointer to the target destination.
* @rates: new tx rate set to be used for this station.
*/
int
rate_control_set_rates
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_sta
*
pubsta
,
struct
ieee80211_sta_rates
*
rates
);
int
ieee80211_rate_control_register
(
struct
rate_control_ops
*
ops
);
int
ieee80211_rate_control_register
(
struct
rate_control_ops
*
ops
);
void
ieee80211_rate_control_unregister
(
struct
rate_control_ops
*
ops
);
void
ieee80211_rate_control_unregister
(
struct
rate_control_ops
*
ops
);
...
...
include/uapi/linux/nl80211.h
浏览文件 @
6475cb05
...
@@ -639,6 +639,13 @@
...
@@ -639,6 +639,13 @@
* with the relevant Information Elements. This event is used to report
* with the relevant Information Elements. This event is used to report
* received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
* received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
*
*
* @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running
* a critical protocol that needs more reliability in the connection to
* complete.
*
* @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
* return back to normal.
*
* @NL80211_CMD_MAX: highest used command number
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
* @__NL80211_CMD_AFTER_LAST: internal use
*/
*/
...
@@ -798,6 +805,9 @@ enum nl80211_commands {
...
@@ -798,6 +805,9 @@ enum nl80211_commands {
NL80211_CMD_UPDATE_FT_IES
,
NL80211_CMD_UPDATE_FT_IES
,
NL80211_CMD_FT_EVENT
,
NL80211_CMD_FT_EVENT
,
NL80211_CMD_CRIT_PROTOCOL_START
,
NL80211_CMD_CRIT_PROTOCOL_STOP
,
/* add new commands above here */
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
/* used to define NL80211_CMD_MAX below */
...
@@ -1414,6 +1424,11 @@ enum nl80211_commands {
...
@@ -1414,6 +1424,11 @@ enum nl80211_commands {
* @NL80211_ATTR_IE_RIC: Resource Information Container Information
* @NL80211_ATTR_IE_RIC: Resource Information Container Information
* Element
* Element
*
*
* @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased
* reliability, see &enum nl80211_crit_proto_id (u16).
* @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
* the connection should have increased reliability (u16).
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
*/
...
@@ -1709,6 +1724,9 @@ enum nl80211_attrs {
...
@@ -1709,6 +1724,9 @@ enum nl80211_attrs {
NL80211_ATTR_MDID
,
NL80211_ATTR_MDID
,
NL80211_ATTR_IE_RIC
,
NL80211_ATTR_IE_RIC
,
NL80211_ATTR_CRIT_PROT_ID
,
NL80211_ATTR_MAX_CRIT_PROT_DURATION
,
/* add attributes here, update the policy in nl80211.c */
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST
,
__NL80211_ATTR_AFTER_LAST
,
...
@@ -3682,4 +3700,25 @@ enum nl80211_protocol_features {
...
@@ -3682,4 +3700,25 @@ enum nl80211_protocol_features {
NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP
=
1
<<
0
,
NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP
=
1
<<
0
,
};
};
/**
* enum nl80211_crit_proto_id - nl80211 critical protocol identifiers
*
* @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified.
* @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol.
* @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol.
* @NL80211_CRIT_PROTO_APIPA: APIPA protocol.
* @NUM_NL80211_CRIT_PROTO: must be kept last.
*/
enum
nl80211_crit_proto_id
{
NL80211_CRIT_PROTO_UNSPEC
,
NL80211_CRIT_PROTO_DHCP
,
NL80211_CRIT_PROTO_EAPOL
,
NL80211_CRIT_PROTO_APIPA
,
/* add other protocols before this one */
NUM_NL80211_CRIT_PROTO
};
/* maximum duration for critical protocol measures */
#define NL80211_CRIT_PROTO_MAX_DURATION 5000
/* msec */
#endif
/* __LINUX_NL80211_H */
#endif
/* __LINUX_NL80211_H */
net/mac80211/cfg.c
浏览文件 @
6475cb05
...
@@ -1043,6 +1043,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
...
@@ -1043,6 +1043,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
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_defer
(
vlan
);
sta_info_flush_defer
(
vlan
);
sta_info_flush_defer
(
sdata
);
sta_info_flush_defer
(
sdata
);
synchronize_net
();
rcu_barrier
();
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
);
sta_info_flush_cleanup
(
vlan
);
...
@@ -1052,6 +1053,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
...
@@ -1052,6 +1053,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
ieee80211_free_keys
(
sdata
);
ieee80211_free_keys
(
sdata
);
sdata
->
vif
.
bss_conf
.
enable_beacon
=
false
;
sdata
->
vif
.
bss_conf
.
enable_beacon
=
false
;
sdata
->
vif
.
bss_conf
.
ssid_len
=
0
;
clear_bit
(
SDATA_STATE_OFFCHANNEL_BEACON_STOPPED
,
&
sdata
->
state
);
clear_bit
(
SDATA_STATE_OFFCHANNEL_BEACON_STOPPED
,
&
sdata
->
state
);
ieee80211_bss_info_change_notify
(
sdata
,
BSS_CHANGED_BEACON_ENABLED
);
ieee80211_bss_info_change_notify
(
sdata
,
BSS_CHANGED_BEACON_ENABLED
);
...
@@ -2416,9 +2418,22 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
...
@@ -2416,9 +2418,22 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
}
}
for
(
i
=
0
;
i
<
IEEE80211_NUM_BANDS
;
i
++
)
{
for
(
i
=
0
;
i
<
IEEE80211_NUM_BANDS
;
i
++
)
{
struct
ieee80211_supported_band
*
sband
=
wiphy
->
bands
[
i
];
int
j
;
sdata
->
rc_rateidx_mask
[
i
]
=
mask
->
control
[
i
].
legacy
;
sdata
->
rc_rateidx_mask
[
i
]
=
mask
->
control
[
i
].
legacy
;
memcpy
(
sdata
->
rc_rateidx_mcs_mask
[
i
],
mask
->
control
[
i
].
mcs
,
memcpy
(
sdata
->
rc_rateidx_mcs_mask
[
i
],
mask
->
control
[
i
].
mcs
,
sizeof
(
mask
->
control
[
i
].
mcs
));
sizeof
(
mask
->
control
[
i
].
mcs
));
sdata
->
rc_has_mcs_mask
[
i
]
=
false
;
if
(
!
sband
)
continue
;
for
(
j
=
0
;
j
<
IEEE80211_HT_MCS_MASK_LEN
;
j
++
)
if
(
~
sdata
->
rc_rateidx_mcs_mask
[
i
][
j
])
{
sdata
->
rc_has_mcs_mask
[
i
]
=
true
;
break
;
}
}
}
return
0
;
return
0
;
...
...
net/mac80211/chan.c
浏览文件 @
6475cb05
...
@@ -57,6 +57,22 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
...
@@ -57,6 +57,22 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
return
NULL
;
return
NULL
;
}
}
static
bool
ieee80211_is_radar_required
(
struct
ieee80211_local
*
local
)
{
struct
ieee80211_sub_if_data
*
sdata
;
rcu_read_lock
();
list_for_each_entry_rcu
(
sdata
,
&
local
->
interfaces
,
list
)
{
if
(
sdata
->
radar_required
)
{
rcu_read_unlock
();
return
true
;
}
}
rcu_read_unlock
();
return
false
;
}
static
struct
ieee80211_chanctx
*
static
struct
ieee80211_chanctx
*
ieee80211_new_chanctx
(
struct
ieee80211_local
*
local
,
ieee80211_new_chanctx
(
struct
ieee80211_local
*
local
,
const
struct
cfg80211_chan_def
*
chandef
,
const
struct
cfg80211_chan_def
*
chandef
,
...
@@ -76,6 +92,9 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
...
@@ -76,6 +92,9 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
ctx
->
conf
.
rx_chains_static
=
1
;
ctx
->
conf
.
rx_chains_static
=
1
;
ctx
->
conf
.
rx_chains_dynamic
=
1
;
ctx
->
conf
.
rx_chains_dynamic
=
1
;
ctx
->
mode
=
mode
;
ctx
->
mode
=
mode
;
ctx
->
conf
.
radar_enabled
=
ieee80211_is_radar_required
(
local
);
if
(
!
local
->
use_chanctx
)
local
->
hw
.
conf
.
radar_enabled
=
ctx
->
conf
.
radar_enabled
;
/* acquire mutex to prevent idle from changing */
/* acquire mutex to prevent idle from changing */
mutex_lock
(
&
local
->
mtx
);
mutex_lock
(
&
local
->
mtx
);
...
@@ -110,6 +129,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
...
@@ -110,6 +129,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
static
void
ieee80211_free_chanctx
(
struct
ieee80211_local
*
local
,
static
void
ieee80211_free_chanctx
(
struct
ieee80211_local
*
local
,
struct
ieee80211_chanctx
*
ctx
)
struct
ieee80211_chanctx
*
ctx
)
{
{
bool
check_single_channel
=
false
;
lockdep_assert_held
(
&
local
->
chanctx_mtx
);
lockdep_assert_held
(
&
local
->
chanctx_mtx
);
WARN_ON_ONCE
(
ctx
->
refcount
!=
0
);
WARN_ON_ONCE
(
ctx
->
refcount
!=
0
);
...
@@ -119,6 +139,14 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
...
@@ -119,6 +139,14 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
chandef
->
width
=
NL80211_CHAN_WIDTH_20_NOHT
;
chandef
->
width
=
NL80211_CHAN_WIDTH_20_NOHT
;
chandef
->
center_freq1
=
chandef
->
chan
->
center_freq
;
chandef
->
center_freq1
=
chandef
->
chan
->
center_freq
;
chandef
->
center_freq2
=
0
;
chandef
->
center_freq2
=
0
;
/* NOTE: Disabling radar is only valid here for
* single channel context. To be sure, check it ...
*/
if
(
local
->
hw
.
conf
.
radar_enabled
)
check_single_channel
=
true
;
local
->
hw
.
conf
.
radar_enabled
=
false
;
ieee80211_hw_config
(
local
,
0
);
ieee80211_hw_config
(
local
,
0
);
}
else
{
}
else
{
drv_remove_chanctx
(
local
,
ctx
);
drv_remove_chanctx
(
local
,
ctx
);
...
@@ -127,6 +155,9 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
...
@@ -127,6 +155,9 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
list_del_rcu
(
&
ctx
->
list
);
list_del_rcu
(
&
ctx
->
list
);
kfree_rcu
(
ctx
,
rcu_head
);
kfree_rcu
(
ctx
,
rcu_head
);
/* throw a warning if this wasn't the only channel context. */
WARN_ON
(
check_single_channel
&&
!
list_empty
(
&
local
->
chanctx_list
));
mutex_lock
(
&
local
->
mtx
);
mutex_lock
(
&
local
->
mtx
);
ieee80211_recalc_idle
(
local
);
ieee80211_recalc_idle
(
local
);
mutex_unlock
(
&
local
->
mtx
);
mutex_unlock
(
&
local
->
mtx
);
...
@@ -238,19 +269,11 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
...
@@ -238,19 +269,11 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
void
ieee80211_recalc_radar_chanctx
(
struct
ieee80211_local
*
local
,
void
ieee80211_recalc_radar_chanctx
(
struct
ieee80211_local
*
local
,
struct
ieee80211_chanctx
*
chanctx
)
struct
ieee80211_chanctx
*
chanctx
)
{
{
struct
ieee80211_sub_if_data
*
sdata
;
bool
radar_enabled
;
bool
radar_enabled
=
false
;
lockdep_assert_held
(
&
local
->
chanctx_mtx
);
lockdep_assert_held
(
&
local
->
chanctx_mtx
);
rcu_read_lock
();
radar_enabled
=
ieee80211_is_radar_required
(
local
);
list_for_each_entry_rcu
(
sdata
,
&
local
->
interfaces
,
list
)
{
if
(
sdata
->
radar_required
)
{
radar_enabled
=
true
;
break
;
}
}
rcu_read_unlock
();
if
(
radar_enabled
==
chanctx
->
conf
.
radar_enabled
)
if
(
radar_enabled
==
chanctx
->
conf
.
radar_enabled
)
return
;
return
;
...
...
net/mac80211/ibss.c
浏览文件 @
6475cb05
...
@@ -209,6 +209,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
...
@@ -209,6 +209,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sdata
->
vif
.
bss_conf
.
enable_beacon
=
true
;
sdata
->
vif
.
bss_conf
.
enable_beacon
=
true
;
sdata
->
vif
.
bss_conf
.
beacon_int
=
beacon_int
;
sdata
->
vif
.
bss_conf
.
beacon_int
=
beacon_int
;
sdata
->
vif
.
bss_conf
.
basic_rates
=
basic_rates
;
sdata
->
vif
.
bss_conf
.
basic_rates
=
basic_rates
;
sdata
->
vif
.
bss_conf
.
ssid_len
=
ifibss
->
ssid_len
;
memcpy
(
sdata
->
vif
.
bss_conf
.
ssid
,
ifibss
->
ssid
,
ifibss
->
ssid_len
);
bss_change
=
BSS_CHANGED_BEACON_INT
;
bss_change
=
BSS_CHANGED_BEACON_INT
;
bss_change
|=
ieee80211_reset_erp_info
(
sdata
);
bss_change
|=
ieee80211_reset_erp_info
(
sdata
);
bss_change
|=
BSS_CHANGED_BSSID
;
bss_change
|=
BSS_CHANGED_BSSID
;
...
@@ -217,6 +219,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
...
@@ -217,6 +219,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
bss_change
|=
BSS_CHANGED_BASIC_RATES
;
bss_change
|=
BSS_CHANGED_BASIC_RATES
;
bss_change
|=
BSS_CHANGED_HT
;
bss_change
|=
BSS_CHANGED_HT
;
bss_change
|=
BSS_CHANGED_IBSS
;
bss_change
|=
BSS_CHANGED_IBSS
;
bss_change
|=
BSS_CHANGED_SSID
;
/*
/*
* In 5 GHz/802.11a, we can always use short slot time.
* In 5 GHz/802.11a, we can always use short slot time.
...
@@ -911,7 +914,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
...
@@ -911,7 +914,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
return
;
return
;
ieee802_11_parse_elems
(
mgmt
->
u
.
probe_resp
.
variable
,
len
-
baselen
,
ieee802_11_parse_elems
(
mgmt
->
u
.
probe_resp
.
variable
,
len
-
baselen
,
&
elems
);
false
,
&
elems
);
ieee80211_rx_bss_info
(
sdata
,
mgmt
,
len
,
rx_status
,
&
elems
);
ieee80211_rx_bss_info
(
sdata
,
mgmt
,
len
,
rx_status
,
&
elems
);
}
}
...
@@ -1159,6 +1162,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
...
@@ -1159,6 +1162,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
sdata
->
vif
.
bss_conf
.
ibss_joined
=
false
;
sdata
->
vif
.
bss_conf
.
ibss_joined
=
false
;
sdata
->
vif
.
bss_conf
.
ibss_creator
=
false
;
sdata
->
vif
.
bss_conf
.
ibss_creator
=
false
;
sdata
->
vif
.
bss_conf
.
enable_beacon
=
false
;
sdata
->
vif
.
bss_conf
.
enable_beacon
=
false
;
sdata
->
vif
.
bss_conf
.
ssid_len
=
0
;
clear_bit
(
SDATA_STATE_OFFCHANNEL_BEACON_STOPPED
,
&
sdata
->
state
);
clear_bit
(
SDATA_STATE_OFFCHANNEL_BEACON_STOPPED
,
&
sdata
->
state
);
ieee80211_bss_info_change_notify
(
sdata
,
BSS_CHANGED_BEACON_ENABLED
|
ieee80211_bss_info_change_notify
(
sdata
,
BSS_CHANGED_BEACON_ENABLED
|
BSS_CHANGED_IBSS
);
BSS_CHANGED_IBSS
);
...
...
net/mac80211/ieee80211_i.h
浏览文件 @
6475cb05
...
@@ -156,6 +156,7 @@ struct ieee80211_tx_data {
...
@@ -156,6 +156,7 @@ struct ieee80211_tx_data {
struct
ieee80211_sub_if_data
*
sdata
;
struct
ieee80211_sub_if_data
*
sdata
;
struct
sta_info
*
sta
;
struct
sta_info
*
sta
;
struct
ieee80211_key
*
key
;
struct
ieee80211_key
*
key
;
struct
ieee80211_tx_rate
rate
;
unsigned
int
flags
;
unsigned
int
flags
;
};
};
...
@@ -740,6 +741,8 @@ struct ieee80211_sub_if_data {
...
@@ -740,6 +741,8 @@ struct ieee80211_sub_if_data {
/* bitmap of allowed (non-MCS) rate indexes for rate control */
/* bitmap of allowed (non-MCS) rate indexes for rate control */
u32
rc_rateidx_mask
[
IEEE80211_NUM_BANDS
];
u32
rc_rateidx_mask
[
IEEE80211_NUM_BANDS
];
bool
rc_has_mcs_mask
[
IEEE80211_NUM_BANDS
];
u8
rc_rateidx_mcs_mask
[
IEEE80211_NUM_BANDS
][
IEEE80211_HT_MCS_MASK_LEN
];
u8
rc_rateidx_mcs_mask
[
IEEE80211_NUM_BANDS
][
IEEE80211_HT_MCS_MASK_LEN
];
union
{
union
{
...
@@ -1020,7 +1023,7 @@ struct ieee80211_local {
...
@@ -1020,7 +1023,7 @@ struct ieee80211_local {
enum
mac80211_scan_state
next_scan_state
;
enum
mac80211_scan_state
next_scan_state
;
struct
delayed_work
scan_work
;
struct
delayed_work
scan_work
;
struct
ieee80211_sub_if_data
__rcu
*
scan_sdata
;
struct
ieee80211_sub_if_data
__rcu
*
scan_sdata
;
struct
ieee80211_channel
*
csa_channel
;
struct
cfg80211_chan_def
csa_chandef
;
/* For backward compatibility only -- do not use */
/* For backward compatibility only -- do not use */
struct
cfg80211_chan_def
_oper_chandef
;
struct
cfg80211_chan_def
_oper_chandef
;
...
@@ -1179,10 +1182,13 @@ struct ieee802_11_elems {
...
@@ -1179,10 +1182,13 @@ struct ieee802_11_elems {
const
u8
*
perr
;
const
u8
*
perr
;
const
struct
ieee80211_rann_ie
*
rann
;
const
struct
ieee80211_rann_ie
*
rann
;
const
struct
ieee80211_channel_sw_ie
*
ch_switch_ie
;
const
struct
ieee80211_channel_sw_ie
*
ch_switch_ie
;
const
struct
ieee80211_ext_chansw_ie
*
ext_chansw_ie
;
const
struct
ieee80211_wide_bw_chansw_ie
*
wide_bw_chansw_ie
;
const
u8
*
country_elem
;
const
u8
*
country_elem
;
const
u8
*
pwr_constr_elem
;
const
u8
*
pwr_constr_elem
;
const
struct
ieee80211_timeout_interval_ie
*
timeout_int
;
const
struct
ieee80211_timeout_interval_ie
*
timeout_int
;
const
u8
*
opmode_notif
;
const
u8
*
opmode_notif
;
const
struct
ieee80211_sec_chan_offs_ie
*
sec_chan_offs
;
/* length of them, respectively */
/* length of them, respectively */
u8
ssid_len
;
u8
ssid_len
;
...
@@ -1253,10 +1259,6 @@ void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata);
...
@@ -1253,10 +1259,6 @@ void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata);
int
ieee80211_max_network_latency
(
struct
notifier_block
*
nb
,
int
ieee80211_max_network_latency
(
struct
notifier_block
*
nb
,
unsigned
long
data
,
void
*
dummy
);
unsigned
long
data
,
void
*
dummy
);
int
ieee80211_set_arp_filter
(
struct
ieee80211_sub_if_data
*
sdata
);
int
ieee80211_set_arp_filter
(
struct
ieee80211_sub_if_data
*
sdata
);
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_work
(
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
,
void
ieee80211_sta_rx_queued_mgmt
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
sk_buff
*
skb
);
struct
sk_buff
*
skb
);
...
@@ -1494,13 +1496,13 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
...
@@ -1494,13 +1496,13 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
ieee80211_tx_skb_tid
(
sdata
,
skb
,
7
);
ieee80211_tx_skb_tid
(
sdata
,
skb
,
7
);
}
}
u32
ieee802_11_parse_elems_crc
(
u8
*
start
,
size_t
len
,
u32
ieee802_11_parse_elems_crc
(
u8
*
start
,
size_t
len
,
bool
action
,
struct
ieee802_11_elems
*
elems
,
struct
ieee802_11_elems
*
elems
,
u64
filter
,
u32
crc
);
u64
filter
,
u32
crc
);
static
inline
void
ieee802_11_parse_elems
(
u8
*
start
,
size_t
len
,
static
inline
void
ieee802_11_parse_elems
(
u8
*
start
,
size_t
len
,
bool
action
,
struct
ieee802_11_elems
*
elems
)
struct
ieee802_11_elems
*
elems
)
{
{
ieee802_11_parse_elems_crc
(
start
,
len
,
elems
,
0
,
0
);
ieee802_11_parse_elems_crc
(
start
,
len
,
action
,
elems
,
0
,
0
);
}
}
u32
ieee80211_mandatory_rates
(
struct
ieee80211_local
*
local
,
u32
ieee80211_mandatory_rates
(
struct
ieee80211_local
*
local
,
...
...
net/mac80211/iface.c
浏览文件 @
6475cb05
...
@@ -839,11 +839,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
...
@@ -839,11 +839,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
*
*
* sta_info_flush_cleanup() requires rcu_barrier()
* sta_info_flush_cleanup() requires rcu_barrier()
* first to wait for the station call_rcu() calls
* first to wait for the station call_rcu() calls
* to complete,
here we need at least sy
chronize_rcu()
* to complete,
and we also need syn
chronize_rcu()
*
it
to wait for the RX path in case it is using the
* to wait for the RX path in case it is using the
* interface and enqueuing frames at this very time on
* interface and enqueuing frames at this very time on
* another CPU.
* another CPU.
*/
*/
synchronize_rcu
();
rcu_barrier
();
rcu_barrier
();
sta_info_flush_cleanup
(
sdata
);
sta_info_flush_cleanup
(
sdata
);
...
...
net/mac80211/main.c
浏览文件 @
6475cb05
...
@@ -668,6 +668,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
...
@@ -668,6 +668,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
int
channels
,
max_bitrates
;
int
channels
,
max_bitrates
;
bool
supp_ht
,
supp_vht
;
bool
supp_ht
,
supp_vht
;
netdev_features_t
feature_whitelist
;
netdev_features_t
feature_whitelist
;
struct
cfg80211_chan_def
dflt_chandef
=
{};
static
const
u32
cipher_suites
[]
=
{
static
const
u32
cipher_suites
[]
=
{
/* keep WEP first, it may be removed below */
/* keep WEP first, it may be removed below */
WLAN_CIPHER_SUITE_WEP40
,
WLAN_CIPHER_SUITE_WEP40
,
...
@@ -745,19 +746,19 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
...
@@ -745,19 +746,19 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
sband
=
local
->
hw
.
wiphy
->
bands
[
band
];
sband
=
local
->
hw
.
wiphy
->
bands
[
band
];
if
(
!
sband
)
if
(
!
sband
)
continue
;
continue
;
if
(
!
local
->
use_chanctx
&&
!
local
->
_oper_chandef
.
chan
)
{
if
(
!
dflt_chandef
.
chan
)
{
cfg80211_chandef_create
(
&
dflt_chandef
,
&
sband
->
channels
[
0
],
NL80211_CHAN_NO_HT
);
/* init channel we're on */
/* init channel we're on */
struct
cfg80211_chan_def
chandef
=
{
if
(
!
local
->
use_chanctx
&&
!
local
->
_oper_chandef
.
chan
)
{
.
chan
=
&
sband
->
channels
[
0
],
local
->
hw
.
conf
.
chandef
=
dflt_chandef
;
.
width
=
NL80211_CHAN_NO_HT
,
local
->
_oper_chandef
=
dflt_chandef
;
.
center_freq1
=
sband
->
channels
[
0
].
center_freq
,
}
.
center_freq2
=
0
local
->
monitor_chandef
=
dflt_chandef
;
};
local
->
hw
.
conf
.
chandef
=
local
->
_oper_chandef
=
chandef
;
}
}
cfg80211_chandef_create
(
&
local
->
monitor_chandef
,
&
sband
->
channels
[
0
],
NL80211_CHAN_NO_HT
);
channels
+=
sband
->
n_channels
;
channels
+=
sband
->
n_channels
;
if
(
max_bitrates
<
sband
->
n_bitrates
)
if
(
max_bitrates
<
sband
->
n_bitrates
)
...
...
net/mac80211/mesh.c
浏览文件 @
6475cb05
...
@@ -838,7 +838,7 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
...
@@ -838,7 +838,7 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
if
(
baselen
>
len
)
if
(
baselen
>
len
)
return
;
return
;
ieee802_11_parse_elems
(
pos
,
len
-
baselen
,
&
elems
);
ieee802_11_parse_elems
(
pos
,
len
-
baselen
,
false
,
&
elems
);
/* 802.11-2012 10.1.4.3.2 */
/* 802.11-2012 10.1.4.3.2 */
if
((
!
ether_addr_equal
(
mgmt
->
da
,
sdata
->
vif
.
addr
)
&&
if
((
!
ether_addr_equal
(
mgmt
->
da
,
sdata
->
vif
.
addr
)
&&
...
@@ -899,7 +899,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
...
@@ -899,7 +899,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
return
;
return
;
ieee802_11_parse_elems
(
mgmt
->
u
.
probe_resp
.
variable
,
len
-
baselen
,
ieee802_11_parse_elems
(
mgmt
->
u
.
probe_resp
.
variable
,
len
-
baselen
,
&
elems
);
false
,
&
elems
);
/* ignore non-mesh or secure / unsecure mismatch */
/* ignore non-mesh or secure / unsecure mismatch */
if
((
!
elems
.
mesh_id
||
!
elems
.
mesh_config
)
||
if
((
!
elems
.
mesh_id
||
!
elems
.
mesh_config
)
||
...
...
net/mac80211/mesh_hwmp.c
浏览文件 @
6475cb05
...
@@ -880,7 +880,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
...
@@ -880,7 +880,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
baselen
=
(
u8
*
)
mgmt
->
u
.
action
.
u
.
mesh_action
.
variable
-
(
u8
*
)
mgmt
;
baselen
=
(
u8
*
)
mgmt
->
u
.
action
.
u
.
mesh_action
.
variable
-
(
u8
*
)
mgmt
;
ieee802_11_parse_elems
(
mgmt
->
u
.
action
.
u
.
mesh_action
.
variable
,
ieee802_11_parse_elems
(
mgmt
->
u
.
action
.
u
.
mesh_action
.
variable
,
len
-
baselen
,
&
elems
);
len
-
baselen
,
false
,
&
elems
);
if
(
elems
.
preq
)
{
if
(
elems
.
preq
)
{
if
(
elems
.
preq_len
!=
37
)
if
(
elems
.
preq_len
!=
37
)
...
...
net/mac80211/mesh_plink.c
浏览文件 @
6475cb05
...
@@ -544,8 +544,8 @@ static void mesh_plink_timer(unsigned long data)
...
@@ -544,8 +544,8 @@ static void mesh_plink_timer(unsigned long data)
return
;
return
;
}
}
mpl_dbg
(
sta
->
sdata
,
mpl_dbg
(
sta
->
sdata
,
"Mesh plink timer for %pM fired on state %
d
\n
"
,
"Mesh plink timer for %pM fired on state %
s
\n
"
,
sta
->
sta
.
addr
,
sta
->
plink_state
);
sta
->
sta
.
addr
,
mplstates
[
sta
->
plink_state
]
);
reason
=
0
;
reason
=
0
;
llid
=
sta
->
llid
;
llid
=
sta
->
llid
;
plid
=
sta
->
plid
;
plid
=
sta
->
plid
;
...
@@ -687,7 +687,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
...
@@ -687,7 +687,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
baseaddr
+=
4
;
baseaddr
+=
4
;
baselen
+=
4
;
baselen
+=
4
;
}
}
ieee802_11_parse_elems
(
baseaddr
,
len
-
baselen
,
&
elems
);
ieee802_11_parse_elems
(
baseaddr
,
len
-
baselen
,
true
,
&
elems
);
if
(
!
elems
.
peering
)
{
if
(
!
elems
.
peering
)
{
mpl_dbg
(
sdata
,
mpl_dbg
(
sdata
,
...
...
net/mac80211/mlme.c
浏览文件 @
6475cb05
...
@@ -289,6 +289,8 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
...
@@ -289,6 +289,8 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
}
else
{
}
else
{
/* 40 MHz (and 80 MHz) must be supported for VHT */
/* 40 MHz (and 80 MHz) must be supported for VHT */
ret
=
IEEE80211_STA_DISABLE_VHT
;
ret
=
IEEE80211_STA_DISABLE_VHT
;
/* also mark 40 MHz disabled */
ret
|=
IEEE80211_STA_DISABLE_40MHZ
;
goto
out
;
goto
out
;
}
}
...
@@ -303,12 +305,6 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
...
@@ -303,12 +305,6 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
channel
->
band
);
channel
->
band
);
vht_chandef
.
center_freq2
=
0
;
vht_chandef
.
center_freq2
=
0
;
if
(
vht_oper
->
center_freq_seg2_idx
)
vht_chandef
.
center_freq2
=
ieee80211_channel_to_frequency
(
vht_oper
->
center_freq_seg2_idx
,
channel
->
band
);
switch
(
vht_oper
->
chan_width
)
{
switch
(
vht_oper
->
chan_width
)
{
case
IEEE80211_VHT_CHANWIDTH_USE_HT
:
case
IEEE80211_VHT_CHANWIDTH_USE_HT
:
vht_chandef
.
width
=
chandef
->
width
;
vht_chandef
.
width
=
chandef
->
width
;
...
@@ -321,6 +317,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
...
@@ -321,6 +317,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
break
;
break
;
case
IEEE80211_VHT_CHANWIDTH_80P80MHZ
:
case
IEEE80211_VHT_CHANWIDTH_80P80MHZ
:
vht_chandef
.
width
=
NL80211_CHAN_WIDTH_80P80
;
vht_chandef
.
width
=
NL80211_CHAN_WIDTH_80P80
;
vht_chandef
.
center_freq2
=
ieee80211_channel_to_frequency
(
vht_oper
->
center_freq_seg2_idx
,
channel
->
band
);
break
;
break
;
default:
default:
if
(
verbose
)
if
(
verbose
)
...
@@ -604,7 +604,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
...
@@ -604,7 +604,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
u8
*
pos
;
u8
*
pos
;
u32
cap
;
u32
cap
;
struct
ieee80211_sta_vht_cap
vht_cap
;
struct
ieee80211_sta_vht_cap
vht_cap
;
int
i
;
BUILD_BUG_ON
(
sizeof
(
vht_cap
)
!=
sizeof
(
sband
->
vht_cap
));
BUILD_BUG_ON
(
sizeof
(
vht_cap
)
!=
sizeof
(
sband
->
vht_cap
));
...
@@ -632,37 +631,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
...
@@ -632,37 +631,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
cpu_to_le32
(
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
)))
cpu_to_le32
(
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
)))
cap
&=
~
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
;
cap
&=
~
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
;
if
(
!
(
ap_vht_cap
->
vht_cap_info
&
cpu_to_le32
(
IEEE80211_VHT_CAP_TXSTBC
)))
cap
&=
~
(
IEEE80211_VHT_CAP_RXSTBC_1
|
IEEE80211_VHT_CAP_RXSTBC_3
|
IEEE80211_VHT_CAP_RXSTBC_4
);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
int
shift
=
i
*
2
;
u16
mask
=
IEEE80211_VHT_MCS_NOT_SUPPORTED
<<
shift
;
u16
ap_mcs
,
our_mcs
;
ap_mcs
=
(
le16_to_cpu
(
ap_vht_cap
->
supp_mcs
.
tx_mcs_map
)
&
mask
)
>>
shift
;
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
)
break
;
/* fall through */
case
IEEE80211_VHT_MCS_NOT_SUPPORTED
:
vht_cap
.
vht_mcs
.
rx_mcs_map
&=
cpu_to_le16
(
~
mask
);
vht_cap
.
vht_mcs
.
rx_mcs_map
|=
cpu_to_le16
(
ap_mcs
<<
shift
);
}
}
/* reserve and fill IE */
/* reserve and fill IE */
pos
=
skb_put
(
skb
,
sizeof
(
struct
ieee80211_vht_cap
)
+
2
);
pos
=
skb_put
(
skb
,
sizeof
(
struct
ieee80211_vht_cap
)
+
2
);
ieee80211_ie_build_vht_cap
(
pos
,
&
vht_cap
,
cap
);
ieee80211_ie_build_vht_cap
(
pos
,
&
vht_cap
,
cap
);
...
@@ -998,16 +966,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
...
@@ -998,16 +966,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
if
(
!
ifmgd
->
associated
)
if
(
!
ifmgd
->
associated
)
goto
out
;
goto
out
;
/*
local
->
_oper_chandef
=
local
->
csa_chandef
;
* FIXME: Here we are downgrading to NL80211_CHAN_WIDTH_20_NOHT
* and don't adjust our ht/vht settings
* This is wrong - we should behave according to the CSA params
*/
local
->
_oper_chandef
.
chan
=
local
->
csa_channel
;
local
->
_oper_chandef
.
width
=
NL80211_CHAN_WIDTH_20_NOHT
;
local
->
_oper_chandef
.
center_freq1
=
local
->
_oper_chandef
.
chan
->
center_freq
;
local
->
_oper_chandef
.
center_freq2
=
0
;
if
(
!
local
->
ops
->
channel_switch
)
{
if
(
!
local
->
ops
->
channel_switch
)
{
/* call "hw_config" only if doing sw channel switch */
/* call "hw_config" only if doing sw channel switch */
...
@@ -1054,56 +1013,193 @@ static void ieee80211_chswitch_timer(unsigned long data)
...
@@ -1054,56 +1013,193 @@ static void ieee80211_chswitch_timer(unsigned long data)
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
u
.
mgd
.
chswitch_work
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
u
.
mgd
.
chswitch_work
);
}
}
void
static
void
ieee80211_sta_process_chanswitch
(
struct
ieee80211_sub_if_data
*
sdata
,
ieee80211_sta_process_chanswitch
(
struct
ieee80211_sub_if_data
*
sdata
,
const
struct
ieee80211_channel_sw_ie
*
sw_elem
,
u64
timestamp
,
struct
ieee802_11_elems
*
elems
)
struct
ieee80211_bss
*
bss
,
u64
timestamp
)
{
{
struct
cfg80211_bss
*
cbss
=
struct
ieee80211_local
*
local
=
sdata
->
local
;
container_of
((
void
*
)
bss
,
struct
cfg80211_bss
,
priv
);
struct
ieee80211_channel
*
new_ch
;
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
int
new_freq
=
ieee80211_channel_to_frequency
(
sw_elem
->
new_ch_num
,
struct
cfg80211_bss
*
cbss
=
ifmgd
->
associated
;
cbss
->
channel
->
band
)
;
struct
ieee80211_bss
*
bss
;
struct
ieee80211_chanctx
*
chanctx
;
struct
ieee80211_chanctx
*
chanctx
;
enum
ieee80211_band
new_band
;
int
new_freq
;
u8
new_chan_no
;
u8
count
;
u8
mode
;
struct
ieee80211_channel
*
new_chan
;
struct
cfg80211_chan_def
new_chandef
=
{};
struct
cfg80211_chan_def
new_vht_chandef
=
{};
const
struct
ieee80211_sec_chan_offs_ie
*
sec_chan_offs
;
const
struct
ieee80211_wide_bw_chansw_ie
*
wide_bw_chansw_ie
;
int
secondary_channel_offset
=
-
1
;
ASSERT_MGD_MTX
(
ifmgd
);
ASSERT_MGD_MTX
(
ifmgd
);
if
(
!
ifmgd
->
associated
)
if
(
!
cbss
)
return
;
return
;
if
(
sdata
->
local
->
scanning
)
if
(
local
->
scanning
)
return
;
return
;
/* Disregard subsequent beacons if we are already running a timer
/* disregard subsequent announcements if we are already processing */
processing a CSA */
if
(
ifmgd
->
flags
&
IEEE80211_STA_CSA_RECEIVED
)
if
(
ifmgd
->
flags
&
IEEE80211_STA_CSA_RECEIVED
)
return
;
return
;
new_ch
=
ieee80211_get_channel
(
sdata
->
local
->
hw
.
wiphy
,
new_freq
);
sec_chan_offs
=
elems
->
sec_chan_offs
;
if
(
!
new_ch
||
new_ch
->
flags
&
IEEE80211_CHAN_DISABLED
)
{
wide_bw_chansw_ie
=
elems
->
wide_bw_chansw_ie
;
if
(
ifmgd
->
flags
&
(
IEEE80211_STA_DISABLE_HT
|
IEEE80211_STA_DISABLE_40MHZ
))
{
sec_chan_offs
=
NULL
;
wide_bw_chansw_ie
=
NULL
;
}
if
(
ifmgd
->
flags
&
IEEE80211_STA_DISABLE_VHT
)
wide_bw_chansw_ie
=
NULL
;
if
(
elems
->
ext_chansw_ie
)
{
if
(
!
ieee80211_operating_class_to_band
(
elems
->
ext_chansw_ie
->
new_operating_class
,
&
new_band
))
{
sdata_info
(
sdata
,
"cannot understand ECSA IE operating class %d, disconnecting
\n
"
,
elems
->
ext_chansw_ie
->
new_operating_class
);
ieee80211_queue_work
(
&
local
->
hw
,
&
ifmgd
->
csa_connection_drop_work
);
}
new_chan_no
=
elems
->
ext_chansw_ie
->
new_ch_num
;
count
=
elems
->
ext_chansw_ie
->
count
;
mode
=
elems
->
ext_chansw_ie
->
mode
;
}
else
if
(
elems
->
ch_switch_ie
)
{
new_band
=
cbss
->
channel
->
band
;
new_chan_no
=
elems
->
ch_switch_ie
->
new_ch_num
;
count
=
elems
->
ch_switch_ie
->
count
;
mode
=
elems
->
ch_switch_ie
->
mode
;
}
else
{
/* nothing here we understand */
return
;
}
bss
=
(
void
*
)
cbss
->
priv
;
new_freq
=
ieee80211_channel_to_frequency
(
new_chan_no
,
new_band
);
new_chan
=
ieee80211_get_channel
(
sdata
->
local
->
hw
.
wiphy
,
new_freq
);
if
(
!
new_chan
||
new_chan
->
flags
&
IEEE80211_CHAN_DISABLED
)
{
sdata_info
(
sdata
,
sdata_info
(
sdata
,
"AP %pM switches to unsupported channel (%d MHz), disconnecting
\n
"
,
"AP %pM switches to unsupported channel (%d MHz), disconnecting
\n
"
,
ifmgd
->
associated
->
bssid
,
new_freq
);
ifmgd
->
associated
->
bssid
,
new_freq
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
ieee80211_queue_work
(
&
local
->
hw
,
&
ifmgd
->
csa_connection_drop_work
);
return
;
}
if
(
sec_chan_offs
)
{
secondary_channel_offset
=
sec_chan_offs
->
sec_chan_offs
;
}
else
if
(
!
(
ifmgd
->
flags
&
IEEE80211_STA_DISABLE_HT
))
{
/* if HT is enabled and the IE not present, it's still HT */
secondary_channel_offset
=
IEEE80211_HT_PARAM_CHA_SEC_NONE
;
}
switch
(
secondary_channel_offset
)
{
default:
/* secondary_channel_offset was present but is invalid */
case
IEEE80211_HT_PARAM_CHA_SEC_NONE
:
cfg80211_chandef_create
(
&
new_chandef
,
new_chan
,
NL80211_CHAN_HT20
);
break
;
case
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
:
cfg80211_chandef_create
(
&
new_chandef
,
new_chan
,
NL80211_CHAN_HT40PLUS
);
break
;
case
IEEE80211_HT_PARAM_CHA_SEC_BELOW
:
cfg80211_chandef_create
(
&
new_chandef
,
new_chan
,
NL80211_CHAN_HT40MINUS
);
break
;
case
-
1
:
cfg80211_chandef_create
(
&
new_chandef
,
new_chan
,
NL80211_CHAN_NO_HT
);
break
;
}
if
(
wide_bw_chansw_ie
)
{
new_vht_chandef
.
chan
=
new_chan
;
new_vht_chandef
.
center_freq1
=
ieee80211_channel_to_frequency
(
wide_bw_chansw_ie
->
new_center_freq_seg0
,
new_band
);
switch
(
wide_bw_chansw_ie
->
new_channel_width
)
{
default:
/* hmmm, ignore VHT and use HT if present */
case
IEEE80211_VHT_CHANWIDTH_USE_HT
:
new_vht_chandef
.
chan
=
NULL
;
break
;
case
IEEE80211_VHT_CHANWIDTH_80MHZ
:
new_vht_chandef
.
width
=
NL80211_CHAN_WIDTH_80
;
break
;
case
IEEE80211_VHT_CHANWIDTH_160MHZ
:
new_vht_chandef
.
width
=
NL80211_CHAN_WIDTH_160
;
break
;
case
IEEE80211_VHT_CHANWIDTH_80P80MHZ
:
/* field is otherwise reserved */
new_vht_chandef
.
center_freq2
=
ieee80211_channel_to_frequency
(
wide_bw_chansw_ie
->
new_center_freq_seg1
,
new_band
);
new_vht_chandef
.
width
=
NL80211_CHAN_WIDTH_80P80
;
break
;
}
if
(
ifmgd
->
flags
&
IEEE80211_STA_DISABLE_80P80MHZ
&&
new_vht_chandef
.
width
==
NL80211_CHAN_WIDTH_80P80
)
chandef_downgrade
(
&
new_vht_chandef
);
if
(
ifmgd
->
flags
&
IEEE80211_STA_DISABLE_160MHZ
&&
new_vht_chandef
.
width
==
NL80211_CHAN_WIDTH_160
)
chandef_downgrade
(
&
new_vht_chandef
);
if
(
ifmgd
->
flags
&
IEEE80211_STA_DISABLE_40MHZ
&&
new_vht_chandef
.
width
>
NL80211_CHAN_WIDTH_20
)
chandef_downgrade
(
&
new_vht_chandef
);
}
/* if VHT data is there validate & use it */
if
(
new_vht_chandef
.
chan
)
{
if
(
!
cfg80211_chandef_compatible
(
&
new_vht_chandef
,
&
new_chandef
))
{
sdata_info
(
sdata
,
"AP %pM CSA has inconsistent channel data, disconnecting
\n
"
,
ifmgd
->
associated
->
bssid
);
ieee80211_queue_work
(
&
local
->
hw
,
&
ifmgd
->
csa_connection_drop_work
);
return
;
}
new_chandef
=
new_vht_chandef
;
}
if
(
!
cfg80211_chandef_usable
(
local
->
hw
.
wiphy
,
&
new_chandef
,
IEEE80211_CHAN_DISABLED
))
{
sdata_info
(
sdata
,
"AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting
\n
"
,
ifmgd
->
associated
->
bssid
,
new_freq
,
new_chandef
.
width
,
new_chandef
.
center_freq1
,
new_chandef
.
center_freq2
);
ieee80211_queue_work
(
&
local
->
hw
,
&
ifmgd
->
csa_connection_drop_work
);
&
ifmgd
->
csa_connection_drop_work
);
return
;
return
;
}
}
ifmgd
->
flags
|=
IEEE80211_STA_CSA_RECEIVED
;
ifmgd
->
flags
|=
IEEE80211_STA_CSA_RECEIVED
;
if
(
sdata
->
local
->
use_chanctx
)
{
if
(
local
->
use_chanctx
)
{
sdata_info
(
sdata
,
sdata_info
(
sdata
,
"not handling channel switch with channel contexts
\n
"
);
"not handling channel switch with channel contexts
\n
"
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
ieee80211_queue_work
(
&
local
->
hw
,
&
ifmgd
->
csa_connection_drop_work
);
&
ifmgd
->
csa_connection_drop_work
);
return
;
return
;
}
}
mutex_lock
(
&
sdata
->
local
->
chanctx_mtx
);
mutex_lock
(
&
local
->
chanctx_mtx
);
if
(
WARN_ON
(
!
rcu_access_pointer
(
sdata
->
vif
.
chanctx_conf
)))
{
if
(
WARN_ON
(
!
rcu_access_pointer
(
sdata
->
vif
.
chanctx_conf
)))
{
mutex_unlock
(
&
sdata
->
local
->
chanctx_mtx
);
mutex_unlock
(
&
local
->
chanctx_mtx
);
return
;
return
;
}
}
chanctx
=
container_of
(
rcu_access_pointer
(
sdata
->
vif
.
chanctx_conf
),
chanctx
=
container_of
(
rcu_access_pointer
(
sdata
->
vif
.
chanctx_conf
),
...
@@ -1111,40 +1207,39 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
...
@@ -1111,40 +1207,39 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
if
(
chanctx
->
refcount
>
1
)
{
if
(
chanctx
->
refcount
>
1
)
{
sdata_info
(
sdata
,
sdata_info
(
sdata
,
"channel switch with multiple interfaces on the same channel, disconnecting
\n
"
);
"channel switch with multiple interfaces on the same channel, disconnecting
\n
"
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
ieee80211_queue_work
(
&
local
->
hw
,
&
ifmgd
->
csa_connection_drop_work
);
&
ifmgd
->
csa_connection_drop_work
);
mutex_unlock
(
&
sdata
->
local
->
chanctx_mtx
);
mutex_unlock
(
&
local
->
chanctx_mtx
);
return
;
return
;
}
}
mutex_unlock
(
&
sdata
->
local
->
chanctx_mtx
);
mutex_unlock
(
&
local
->
chanctx_mtx
);
sdata
->
local
->
csa_channel
=
new_ch
;
local
->
csa_chandef
=
new_chandef
;
if
(
sw_elem
->
mode
)
if
(
mode
)
ieee80211_stop_queues_by_reason
(
&
sdata
->
local
->
hw
,
ieee80211_stop_queues_by_reason
(
&
local
->
hw
,
IEEE80211_MAX_QUEUE_MAP
,
IEEE80211_MAX_QUEUE_MAP
,
IEEE80211_QUEUE_STOP_REASON_CSA
);
IEEE80211_QUEUE_STOP_REASON_CSA
);
if
(
sdata
->
local
->
ops
->
channel_switch
)
{
if
(
local
->
ops
->
channel_switch
)
{
/* use driver's channel switch callback */
/* use driver's channel switch callback */
struct
ieee80211_channel_switch
ch_switch
=
{
struct
ieee80211_channel_switch
ch_switch
=
{
.
timestamp
=
timestamp
,
.
timestamp
=
timestamp
,
.
block_tx
=
sw_elem
->
mode
,
.
block_tx
=
mode
,
.
chan
nel
=
new_ch
,
.
chan
def
=
new_chandef
,
.
count
=
sw_elem
->
count
,
.
count
=
count
,
};
};
drv_channel_switch
(
sdata
->
local
,
&
ch_switch
);
drv_channel_switch
(
local
,
&
ch_switch
);
return
;
return
;
}
}
/* channel switch handled in software */
/* channel switch handled in software */
if
(
sw_elem
->
count
<=
1
)
if
(
count
<=
1
)
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
ifmgd
->
chswitch_work
);
ieee80211_queue_work
(
&
local
->
hw
,
&
ifmgd
->
chswitch_work
);
else
else
mod_timer
(
&
ifmgd
->
chswitch_timer
,
mod_timer
(
&
ifmgd
->
chswitch_timer
,
TU_TO_EXP_TIME
(
sw_elem
->
count
*
TU_TO_EXP_TIME
(
count
*
cbss
->
beacon_interval
));
cbss
->
beacon_interval
));
}
}
static
u32
ieee80211_handle_pwr_constr
(
struct
ieee80211_sub_if_data
*
sdata
,
static
u32
ieee80211_handle_pwr_constr
(
struct
ieee80211_sub_if_data
*
sdata
,
...
@@ -1566,6 +1661,7 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
...
@@ -1566,6 +1661,7 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
params
.
cw_max
=
ecw2cw
((
pos
[
1
]
&
0xf0
)
>>
4
);
params
.
cw_max
=
ecw2cw
((
pos
[
1
]
&
0xf0
)
>>
4
);
params
.
cw_min
=
ecw2cw
(
pos
[
1
]
&
0x0f
);
params
.
cw_min
=
ecw2cw
(
pos
[
1
]
&
0x0f
);
params
.
txop
=
get_unaligned_le16
(
pos
+
2
);
params
.
txop
=
get_unaligned_le16
(
pos
+
2
);
params
.
acm
=
acm
;
params
.
uapsd
=
uapsd
;
params
.
uapsd
=
uapsd
;
mlme_dbg
(
sdata
,
mlme_dbg
(
sdata
,
...
@@ -2120,7 +2216,6 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
...
@@ -2120,7 +2216,6 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
trace_api_beacon_loss
(
sdata
);
trace_api_beacon_loss
(
sdata
);
WARN_ON
(
hw
->
flags
&
IEEE80211_HW_CONNECTION_MONITOR
);
sdata
->
u
.
mgd
.
connection_loss
=
false
;
sdata
->
u
.
mgd
.
connection_loss
=
false
;
ieee80211_queue_work
(
hw
,
&
sdata
->
u
.
mgd
.
beacon_connection_loss_work
);
ieee80211_queue_work
(
hw
,
&
sdata
->
u
.
mgd
.
beacon_connection_loss_work
);
}
}
...
@@ -2170,7 +2265,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
...
@@ -2170,7 +2265,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
u32
tx_flags
=
0
;
u32
tx_flags
=
0
;
pos
=
mgmt
->
u
.
auth
.
variable
;
pos
=
mgmt
->
u
.
auth
.
variable
;
ieee802_11_parse_elems
(
pos
,
len
-
(
pos
-
(
u8
*
)
mgmt
),
&
elems
);
ieee802_11_parse_elems
(
pos
,
len
-
(
pos
-
(
u8
*
)
mgmt
),
false
,
&
elems
);
if
(
!
elems
.
challenge
)
if
(
!
elems
.
challenge
)
return
;
return
;
auth_data
->
expected_transaction
=
4
;
auth_data
->
expected_transaction
=
4
;
...
@@ -2435,7 +2530,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
...
@@ -2435,7 +2530,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
}
}
pos
=
mgmt
->
u
.
assoc_resp
.
variable
;
pos
=
mgmt
->
u
.
assoc_resp
.
variable
;
ieee802_11_parse_elems
(
pos
,
len
-
(
pos
-
(
u8
*
)
mgmt
),
&
elems
);
ieee802_11_parse_elems
(
pos
,
len
-
(
pos
-
(
u8
*
)
mgmt
),
false
,
&
elems
);
if
(
!
elems
.
supp_rates
)
{
if
(
!
elems
.
supp_rates
)
{
sdata_info
(
sdata
,
"no SuppRates element in AssocResp
\n
"
);
sdata_info
(
sdata
,
"no SuppRates element in AssocResp
\n
"
);
...
@@ -2604,7 +2699,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
...
@@ -2604,7 +2699,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
capab_info
,
status_code
,
(
u16
)(
aid
&
~
(
BIT
(
15
)
|
BIT
(
14
))));
capab_info
,
status_code
,
(
u16
)(
aid
&
~
(
BIT
(
15
)
|
BIT
(
14
))));
pos
=
mgmt
->
u
.
assoc_resp
.
variable
;
pos
=
mgmt
->
u
.
assoc_resp
.
variable
;
ieee802_11_parse_elems
(
pos
,
len
-
(
pos
-
(
u8
*
)
mgmt
),
&
elems
);
ieee802_11_parse_elems
(
pos
,
len
-
(
pos
-
(
u8
*
)
mgmt
),
false
,
&
elems
);
if
(
status_code
==
WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY
&&
if
(
status_code
==
WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY
&&
elems
.
timeout_int
&&
elems
.
timeout_int
&&
...
@@ -2659,6 +2754,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
...
@@ -2659,6 +2754,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct
ieee80211_channel
*
channel
;
struct
ieee80211_channel
*
channel
;
bool
need_ps
=
false
;
bool
need_ps
=
false
;
lockdep_assert_held
(
&
sdata
->
u
.
mgd
.
mtx
);
if
((
sdata
->
u
.
mgd
.
associated
&&
if
((
sdata
->
u
.
mgd
.
associated
&&
ether_addr_equal
(
mgmt
->
bssid
,
sdata
->
u
.
mgd
.
associated
->
bssid
))
||
ether_addr_equal
(
mgmt
->
bssid
,
sdata
->
u
.
mgd
.
associated
->
bssid
))
||
(
sdata
->
u
.
mgd
.
assoc_data
&&
(
sdata
->
u
.
mgd
.
assoc_data
&&
...
@@ -2689,7 +2786,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
...
@@ -2689,7 +2786,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
if
(
bss
)
if
(
bss
)
ieee80211_rx_bss_put
(
local
,
bss
);
ieee80211_rx_bss_put
(
local
,
bss
);
if
(
!
sdata
->
u
.
mgd
.
associated
)
if
(
!
sdata
->
u
.
mgd
.
associated
||
!
ether_addr_equal
(
mgmt
->
bssid
,
sdata
->
u
.
mgd
.
associated
->
bssid
))
return
;
return
;
if
(
need_ps
)
{
if
(
need_ps
)
{
...
@@ -2698,10 +2796,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
...
@@ -2698,10 +2796,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
mutex_unlock
(
&
local
->
iflist_mtx
);
mutex_unlock
(
&
local
->
iflist_mtx
);
}
}
if
(
elems
->
ch_switch_ie
&&
ieee80211_sta_process_chanswitch
(
sdata
,
rx_status
->
mactime
,
elems
);
memcmp
(
mgmt
->
bssid
,
sdata
->
u
.
mgd
.
associated
->
bssid
,
ETH_ALEN
)
==
0
)
ieee80211_sta_process_chanswitch
(
sdata
,
elems
->
ch_switch_ie
,
bss
,
rx_status
->
mactime
);
}
}
...
@@ -2726,7 +2822,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
...
@@ -2726,7 +2822,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
return
;
return
;
ieee802_11_parse_elems
(
mgmt
->
u
.
probe_resp
.
variable
,
len
-
baselen
,
ieee802_11_parse_elems
(
mgmt
->
u
.
probe_resp
.
variable
,
len
-
baselen
,
&
elems
);
false
,
&
elems
);
ieee80211_rx_bss_info
(
sdata
,
mgmt
,
len
,
rx_status
,
&
elems
);
ieee80211_rx_bss_info
(
sdata
,
mgmt
,
len
,
rx_status
,
&
elems
);
...
@@ -2809,7 +2905,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
...
@@ -2809,7 +2905,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if
(
ifmgd
->
assoc_data
&&
ifmgd
->
assoc_data
->
need_beacon
&&
if
(
ifmgd
->
assoc_data
&&
ifmgd
->
assoc_data
->
need_beacon
&&
ether_addr_equal
(
mgmt
->
bssid
,
ifmgd
->
assoc_data
->
bss
->
bssid
))
{
ether_addr_equal
(
mgmt
->
bssid
,
ifmgd
->
assoc_data
->
bss
->
bssid
))
{
ieee802_11_parse_elems
(
mgmt
->
u
.
beacon
.
variable
,
ieee802_11_parse_elems
(
mgmt
->
u
.
beacon
.
variable
,
len
-
baselen
,
&
elems
);
len
-
baselen
,
false
,
&
elems
);
ieee80211_rx_bss_info
(
sdata
,
mgmt
,
len
,
rx_status
,
&
elems
);
ieee80211_rx_bss_info
(
sdata
,
mgmt
,
len
,
rx_status
,
&
elems
);
ifmgd
->
assoc_data
->
have_beacon
=
true
;
ifmgd
->
assoc_data
->
have_beacon
=
true
;
...
@@ -2919,7 +3015,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
...
@@ -2919,7 +3015,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
ncrc
=
crc32_be
(
0
,
(
void
*
)
&
mgmt
->
u
.
beacon
.
beacon_int
,
4
);
ncrc
=
crc32_be
(
0
,
(
void
*
)
&
mgmt
->
u
.
beacon
.
beacon_int
,
4
);
ncrc
=
ieee802_11_parse_elems_crc
(
mgmt
->
u
.
beacon
.
variable
,
ncrc
=
ieee802_11_parse_elems_crc
(
mgmt
->
u
.
beacon
.
variable
,
len
-
baselen
,
&
elems
,
len
-
baselen
,
false
,
&
elems
,
care_about_ies
,
ncrc
);
care_about_ies
,
ncrc
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_PS_NULLFUNC_STACK
)
{
if
(
local
->
hw
.
flags
&
IEEE80211_HW_PS_NULLFUNC_STACK
)
{
...
@@ -3066,6 +3162,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
...
@@ -3066,6 +3162,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
enum
rx_mgmt_action
rma
=
RX_MGMT_NONE
;
enum
rx_mgmt_action
rma
=
RX_MGMT_NONE
;
u8
deauth_buf
[
IEEE80211_DEAUTH_FRAME_LEN
];
u8
deauth_buf
[
IEEE80211_DEAUTH_FRAME_LEN
];
u16
fc
;
u16
fc
;
struct
ieee802_11_elems
elems
;
int
ies_len
;
rx_status
=
(
struct
ieee80211_rx_status
*
)
skb
->
cb
;
rx_status
=
(
struct
ieee80211_rx_status
*
)
skb
->
cb
;
mgmt
=
(
struct
ieee80211_mgmt
*
)
skb
->
data
;
mgmt
=
(
struct
ieee80211_mgmt
*
)
skb
->
data
;
...
@@ -3095,14 +3193,48 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
...
@@ -3095,14 +3193,48 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
rma
=
ieee80211_rx_mgmt_assoc_resp
(
sdata
,
mgmt
,
skb
->
len
,
&
bss
);
rma
=
ieee80211_rx_mgmt_assoc_resp
(
sdata
,
mgmt
,
skb
->
len
,
&
bss
);
break
;
break
;
case
IEEE80211_STYPE_ACTION
:
case
IEEE80211_STYPE_ACTION
:
switch
(
mgmt
->
u
.
action
.
category
)
{
if
(
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_SPECTRUM_MGMT
)
{
case
WLAN_CATEGORY_SPECTRUM_MGMT
:
ies_len
=
skb
->
len
-
offsetof
(
struct
ieee80211_mgmt
,
u
.
action
.
u
.
chan_switch
.
variable
);
if
(
ies_len
<
0
)
break
;
ieee802_11_parse_elems
(
mgmt
->
u
.
action
.
u
.
chan_switch
.
variable
,
ies_len
,
true
,
&
elems
);
if
(
elems
.
parse_error
)
break
;
ieee80211_sta_process_chanswitch
(
sdata
,
ieee80211_sta_process_chanswitch
(
sdata
,
&
mgmt
->
u
.
action
.
u
.
chan_switch
.
sw_elem
,
rx_status
->
mactime
,
(
void
*
)
ifmgd
->
associated
->
priv
,
&
elems
);
rx_status
->
mactime
);
}
else
if
(
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_PUBLIC
)
{
break
;
ies_len
=
skb
->
len
-
offsetof
(
struct
ieee80211_mgmt
,
u
.
action
.
u
.
ext_chan_switch
.
variable
);
if
(
ies_len
<
0
)
break
;
ieee802_11_parse_elems
(
mgmt
->
u
.
action
.
u
.
ext_chan_switch
.
variable
,
ies_len
,
true
,
&
elems
);
if
(
elems
.
parse_error
)
break
;
/* for the handling code pretend this was also an IE */
elems
.
ext_chansw_ie
=
&
mgmt
->
u
.
action
.
u
.
ext_chan_switch
.
data
;
ieee80211_sta_process_chanswitch
(
sdata
,
rx_status
->
mactime
,
&
elems
);
}
}
break
;
}
}
mutex_unlock
(
&
ifmgd
->
mtx
);
mutex_unlock
(
&
ifmgd
->
mtx
);
...
...
net/mac80211/pm.c
浏览文件 @
6475cb05
...
@@ -37,8 +37,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
...
@@ -37,8 +37,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
IEEE80211_MAX_QUEUE_MAP
,
IEEE80211_MAX_QUEUE_MAP
,
IEEE80211_QUEUE_STOP_REASON_SUSPEND
);
IEEE80211_QUEUE_STOP_REASON_SUSPEND
);
/* flush out all packets */
/* flush out all packets
and station cleanup call_rcu()s
*/
synchronize_net
();
synchronize_net
();
rcu_barrier
();
ieee80211_flush_queues
(
local
,
NULL
);
ieee80211_flush_queues
(
local
,
NULL
);
...
...
net/mac80211/rate.c
浏览文件 @
6475cb05
...
@@ -252,6 +252,25 @@ rate_lowest_non_cck_index(struct ieee80211_supported_band *sband,
...
@@ -252,6 +252,25 @@ rate_lowest_non_cck_index(struct ieee80211_supported_band *sband,
return
0
;
return
0
;
}
}
static
void
__rate_control_send_low
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_supported_band
*
sband
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_tx_info
*
info
)
{
if
((
sband
->
band
!=
IEEE80211_BAND_2GHZ
)
||
!
(
info
->
flags
&
IEEE80211_TX_CTL_NO_CCK_RATE
))
info
->
control
.
rates
[
0
].
idx
=
rate_lowest_index
(
sband
,
sta
);
else
info
->
control
.
rates
[
0
].
idx
=
rate_lowest_non_cck_index
(
sband
,
sta
);
info
->
control
.
rates
[
0
].
count
=
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
)
?
1
:
hw
->
max_rate_tries
;
info
->
control
.
skip_table
=
1
;
}
bool
rate_control_send_low
(
struct
ieee80211_sta
*
sta
,
bool
rate_control_send_low
(
struct
ieee80211_sta
*
sta
,
void
*
priv_sta
,
void
*
priv_sta
,
...
@@ -262,16 +281,8 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
...
@@ -262,16 +281,8 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
int
mcast_rate
;
int
mcast_rate
;
if
(
!
sta
||
!
priv_sta
||
rc_no_data_or_no_ack_use_min
(
txrc
))
{
if
(
!
sta
||
!
priv_sta
||
rc_no_data_or_no_ack_use_min
(
txrc
))
{
if
((
sband
->
band
!=
IEEE80211_BAND_2GHZ
)
||
__rate_control_send_low
(
txrc
->
hw
,
sband
,
sta
,
info
);
!
(
info
->
flags
&
IEEE80211_TX_CTL_NO_CCK_RATE
))
info
->
control
.
rates
[
0
].
idx
=
rate_lowest_index
(
txrc
->
sband
,
sta
);
else
info
->
control
.
rates
[
0
].
idx
=
rate_lowest_non_cck_index
(
txrc
->
sband
,
sta
);
info
->
control
.
rates
[
0
].
count
=
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
)
?
1
:
txrc
->
hw
->
max_rate_tries
;
if
(
!
sta
&&
txrc
->
bss
)
{
if
(
!
sta
&&
txrc
->
bss
)
{
mcast_rate
=
txrc
->
bss_conf
->
mcast_rate
[
sband
->
band
];
mcast_rate
=
txrc
->
bss_conf
->
mcast_rate
[
sband
->
band
];
if
(
mcast_rate
>
0
)
{
if
(
mcast_rate
>
0
)
{
...
@@ -355,7 +366,8 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate,
...
@@ -355,7 +366,8 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate,
static
void
rate_idx_match_mask
(
struct
ieee80211_tx_rate
*
rate
,
static
void
rate_idx_match_mask
(
struct
ieee80211_tx_rate
*
rate
,
struct
ieee80211_tx_rate_control
*
txrc
,
struct
ieee80211_supported_band
*
sband
,
enum
nl80211_chan_width
chan_width
,
u32
mask
,
u32
mask
,
u8
mcs_mask
[
IEEE80211_HT_MCS_MASK_LEN
])
u8
mcs_mask
[
IEEE80211_HT_MCS_MASK_LEN
])
{
{
...
@@ -375,27 +387,17 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
...
@@ -375,27 +387,17 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
IEEE80211_TX_RC_USE_SHORT_PREAMBLE
);
IEEE80211_TX_RC_USE_SHORT_PREAMBLE
);
alt_rate
.
count
=
rate
->
count
;
alt_rate
.
count
=
rate
->
count
;
if
(
rate_idx_match_legacy_mask
(
&
alt_rate
,
if
(
rate_idx_match_legacy_mask
(
&
alt_rate
,
txrc
->
sband
->
n_bitrates
,
sband
->
n_bitrates
,
mask
))
{
mask
))
{
*
rate
=
alt_rate
;
*
rate
=
alt_rate
;
return
;
return
;
}
}
}
else
{
}
else
{
struct
sk_buff
*
skb
=
txrc
->
skb
;
struct
ieee80211_hdr
*
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
__le16
fc
;
/* handle legacy rates */
/* handle legacy rates */
if
(
rate_idx_match_legacy_mask
(
rate
,
txrc
->
sband
->
n_bitrates
,
if
(
rate_idx_match_legacy_mask
(
rate
,
sband
->
n_bitrates
,
mask
))
mask
))
return
;
return
;
/* if HT BSS, and we handle a data frame, also try HT rates */
/* if HT BSS, and we handle a data frame, also try HT rates */
if
(
txrc
->
bss_conf
->
chandef
.
width
==
NL80211_CHAN_WIDTH_20_NOHT
)
if
(
chan_width
==
NL80211_CHAN_WIDTH_20_NOHT
)
return
;
fc
=
hdr
->
frame_control
;
if
(
!
ieee80211_is_data
(
fc
))
return
;
return
;
alt_rate
.
idx
=
0
;
alt_rate
.
idx
=
0
;
...
@@ -408,7 +410,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
...
@@ -408,7 +410,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
alt_rate
.
flags
|=
IEEE80211_TX_RC_MCS
;
alt_rate
.
flags
|=
IEEE80211_TX_RC_MCS
;
if
(
txrc
->
bss_conf
->
chandef
.
width
==
NL80211_CHAN_WIDTH_40
)
if
(
chan_
width
==
NL80211_CHAN_WIDTH_40
)
alt_rate
.
flags
|=
IEEE80211_TX_RC_40_MHZ_WIDTH
;
alt_rate
.
flags
|=
IEEE80211_TX_RC_40_MHZ_WIDTH
;
if
(
rate_idx_match_mcs_mask
(
&
alt_rate
,
mcs_mask
))
{
if
(
rate_idx_match_mcs_mask
(
&
alt_rate
,
mcs_mask
))
{
...
@@ -426,6 +428,228 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
...
@@ -426,6 +428,228 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
*/
*/
}
}
static
void
rate_fixup_ratelist
(
struct
ieee80211_vif
*
vif
,
struct
ieee80211_supported_band
*
sband
,
struct
ieee80211_tx_info
*
info
,
struct
ieee80211_tx_rate
*
rates
,
int
max_rates
)
{
struct
ieee80211_rate
*
rate
;
bool
inval
=
false
;
int
i
;
/*
* Set up the RTS/CTS rate as the fastest basic rate
* that is not faster than the data rate unless there
* is no basic rate slower than the data rate, in which
* case we pick the slowest basic rate
*
* XXX: Should this check all retry rates?
*/
if
(
!
(
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
))
{
u32
basic_rates
=
vif
->
bss_conf
.
basic_rates
;
s8
baserate
=
basic_rates
?
ffs
(
basic_rates
-
1
)
:
0
;
rate
=
&
sband
->
bitrates
[
rates
[
0
].
idx
];
for
(
i
=
0
;
i
<
sband
->
n_bitrates
;
i
++
)
{
/* must be a basic rate */
if
(
!
(
basic_rates
&
BIT
(
i
)))
continue
;
/* must not be faster than the data rate */
if
(
sband
->
bitrates
[
i
].
bitrate
>
rate
->
bitrate
)
continue
;
/* maximum */
if
(
sband
->
bitrates
[
baserate
].
bitrate
<
sband
->
bitrates
[
i
].
bitrate
)
baserate
=
i
;
}
info
->
control
.
rts_cts_rate_idx
=
baserate
;
}
for
(
i
=
0
;
i
<
max_rates
;
i
++
)
{
/*
* make sure there's no valid rate following
* an invalid one, just in case drivers don't
* take the API seriously to stop at -1.
*/
if
(
inval
)
{
rates
[
i
].
idx
=
-
1
;
continue
;
}
if
(
rates
[
i
].
idx
<
0
)
{
inval
=
true
;
continue
;
}
/*
* For now assume MCS is already set up correctly, this
* needs to be fixed.
*/
if
(
rates
[
i
].
flags
&
IEEE80211_TX_RC_MCS
)
{
WARN_ON
(
rates
[
i
].
idx
>
76
);
if
(
!
(
rates
[
i
].
flags
&
IEEE80211_TX_RC_USE_RTS_CTS
)
&&
info
->
control
.
use_cts_prot
)
rates
[
i
].
flags
|=
IEEE80211_TX_RC_USE_CTS_PROTECT
;
continue
;
}
if
(
rates
[
i
].
flags
&
IEEE80211_TX_RC_VHT_MCS
)
{
WARN_ON
(
ieee80211_rate_get_vht_mcs
(
&
rates
[
i
])
>
9
);
continue
;
}
/* set up RTS protection if desired */
if
(
info
->
control
.
use_rts
)
{
rates
[
i
].
flags
|=
IEEE80211_TX_RC_USE_RTS_CTS
;
info
->
control
.
use_cts_prot
=
false
;
}
/* RC is busted */
if
(
WARN_ON_ONCE
(
rates
[
i
].
idx
>=
sband
->
n_bitrates
))
{
rates
[
i
].
idx
=
-
1
;
continue
;
}
rate
=
&
sband
->
bitrates
[
rates
[
i
].
idx
];
/* set up short preamble */
if
(
info
->
control
.
short_preamble
&&
rate
->
flags
&
IEEE80211_RATE_SHORT_PREAMBLE
)
rates
[
i
].
flags
|=
IEEE80211_TX_RC_USE_SHORT_PREAMBLE
;
/* set up G protection */
if
(
!
(
rates
[
i
].
flags
&
IEEE80211_TX_RC_USE_RTS_CTS
)
&&
info
->
control
.
use_cts_prot
&&
rate
->
flags
&
IEEE80211_RATE_ERP_G
)
rates
[
i
].
flags
|=
IEEE80211_TX_RC_USE_CTS_PROTECT
;
}
}
static
void
rate_control_fill_sta_table
(
struct
ieee80211_sta
*
sta
,
struct
ieee80211_tx_info
*
info
,
struct
ieee80211_tx_rate
*
rates
,
int
max_rates
)
{
struct
ieee80211_sta_rates
*
ratetbl
=
NULL
;
int
i
;
if
(
sta
&&
!
info
->
control
.
skip_table
)
ratetbl
=
rcu_dereference
(
sta
->
rates
);
/* Fill remaining rate slots with data from the sta rate table. */
max_rates
=
min_t
(
int
,
max_rates
,
IEEE80211_TX_RATE_TABLE_SIZE
);
for
(
i
=
0
;
i
<
max_rates
;
i
++
)
{
if
(
i
<
ARRAY_SIZE
(
info
->
control
.
rates
)
&&
info
->
control
.
rates
[
i
].
idx
>=
0
&&
info
->
control
.
rates
[
i
].
count
)
{
if
(
rates
!=
info
->
control
.
rates
)
rates
[
i
]
=
info
->
control
.
rates
[
i
];
}
else
if
(
ratetbl
)
{
rates
[
i
].
idx
=
ratetbl
->
rate
[
i
].
idx
;
rates
[
i
].
flags
=
ratetbl
->
rate
[
i
].
flags
;
if
(
info
->
control
.
use_rts
)
rates
[
i
].
count
=
ratetbl
->
rate
[
i
].
count_rts
;
else
if
(
info
->
control
.
use_cts_prot
)
rates
[
i
].
count
=
ratetbl
->
rate
[
i
].
count_cts
;
else
rates
[
i
].
count
=
ratetbl
->
rate
[
i
].
count
;
}
else
{
rates
[
i
].
idx
=
-
1
;
rates
[
i
].
count
=
0
;
}
if
(
rates
[
i
].
idx
<
0
||
!
rates
[
i
].
count
)
break
;
}
}
static
void
rate_control_apply_mask
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_supported_band
*
sband
,
struct
ieee80211_tx_info
*
info
,
struct
ieee80211_tx_rate
*
rates
,
int
max_rates
)
{
enum
nl80211_chan_width
chan_width
;
u8
mcs_mask
[
IEEE80211_HT_MCS_MASK_LEN
];
bool
has_mcs_mask
;
u32
mask
;
int
i
;
/*
* Try to enforce the rateidx mask the user wanted. skip this if the
* default mask (allow all rates) is used to save some processing for
* the common case.
*/
mask
=
sdata
->
rc_rateidx_mask
[
info
->
band
];
has_mcs_mask
=
sdata
->
rc_has_mcs_mask
[
info
->
band
];
if
(
mask
==
(
1
<<
sband
->
n_bitrates
)
-
1
&&
!
has_mcs_mask
)
return
;
if
(
has_mcs_mask
)
memcpy
(
mcs_mask
,
sdata
->
rc_rateidx_mcs_mask
[
info
->
band
],
sizeof
(
mcs_mask
));
else
memset
(
mcs_mask
,
0xff
,
sizeof
(
mcs_mask
));
if
(
sta
)
{
/* Filter out rates that the STA does not support */
mask
&=
sta
->
supp_rates
[
info
->
band
];
for
(
i
=
0
;
i
<
sizeof
(
mcs_mask
);
i
++
)
mcs_mask
[
i
]
&=
sta
->
ht_cap
.
mcs
.
rx_mask
[
i
];
}
/*
* Make sure the rate index selected for each TX rate is
* included in the configured mask and change the rate indexes
* if needed.
*/
chan_width
=
sdata
->
vif
.
bss_conf
.
chandef
.
width
;
for
(
i
=
0
;
i
<
max_rates
;
i
++
)
{
/* Skip invalid rates */
if
(
rates
[
i
].
idx
<
0
)
break
;
rate_idx_match_mask
(
&
rates
[
i
],
sband
,
mask
,
chan_width
,
mcs_mask
);
}
}
void
ieee80211_get_tx_rates
(
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
sk_buff
*
skb
,
struct
ieee80211_tx_rate
*
dest
,
int
max_rates
)
{
struct
ieee80211_sub_if_data
*
sdata
;
struct
ieee80211_hdr
*
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
skb
);
struct
ieee80211_supported_band
*
sband
;
rate_control_fill_sta_table
(
sta
,
info
,
dest
,
max_rates
);
if
(
!
vif
)
return
;
sdata
=
vif_to_sdata
(
vif
);
sband
=
sdata
->
local
->
hw
.
wiphy
->
bands
[
info
->
band
];
if
(
ieee80211_is_data
(
hdr
->
frame_control
))
rate_control_apply_mask
(
sdata
,
sta
,
sband
,
info
,
dest
,
max_rates
);
if
(
dest
[
0
].
idx
<
0
)
__rate_control_send_low
(
&
sdata
->
local
->
hw
,
sband
,
sta
,
info
);
if
(
sta
)
rate_fixup_ratelist
(
vif
,
sband
,
info
,
dest
,
max_rates
);
}
EXPORT_SYMBOL
(
ieee80211_get_tx_rates
);
void
rate_control_get_rate
(
struct
ieee80211_sub_if_data
*
sdata
,
void
rate_control_get_rate
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
sta_info
*
sta
,
struct
sta_info
*
sta
,
struct
ieee80211_tx_rate_control
*
txrc
)
struct
ieee80211_tx_rate_control
*
txrc
)
...
@@ -435,8 +659,6 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
...
@@ -435,8 +659,6 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct
ieee80211_sta
*
ista
=
NULL
;
struct
ieee80211_sta
*
ista
=
NULL
;
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
txrc
->
skb
);
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
txrc
->
skb
);
int
i
;
int
i
;
u32
mask
;
u8
mcs_mask
[
IEEE80211_HT_MCS_MASK_LEN
];
if
(
sta
&&
test_sta_flag
(
sta
,
WLAN_STA_RATE_CONTROL
))
{
if
(
sta
&&
test_sta_flag
(
sta
,
WLAN_STA_RATE_CONTROL
))
{
ista
=
&
sta
->
sta
;
ista
=
&
sta
->
sta
;
...
@@ -454,37 +676,27 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
...
@@ -454,37 +676,27 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
ref
->
ops
->
get_rate
(
ref
->
priv
,
ista
,
priv_sta
,
txrc
);
ref
->
ops
->
get_rate
(
ref
->
priv
,
ista
,
priv_sta
,
txrc
);
/*
if
(
sdata
->
local
->
hw
.
flags
&
IEEE80211_HW_SUPPORTS_RC_TABLE
)
* Try to enforce the rateidx mask the user wanted. skip this if the
return
;
* default mask (allow all rates) is used to save some processing for
* the common case.
ieee80211_get_tx_rates
(
&
sdata
->
vif
,
ista
,
txrc
->
skb
,
*/
info
->
control
.
rates
,
mask
=
sdata
->
rc_rateidx_mask
[
info
->
band
];
ARRAY_SIZE
(
info
->
control
.
rates
));
memcpy
(
mcs_mask
,
sdata
->
rc_rateidx_mcs_mask
[
info
->
band
],
}
sizeof
(
mcs_mask
));
if
(
mask
!=
(
1
<<
txrc
->
sband
->
n_bitrates
)
-
1
)
{
if
(
sta
)
{
/* Filter out rates that the STA does not support */
mask
&=
sta
->
sta
.
supp_rates
[
info
->
band
];
for
(
i
=
0
;
i
<
sizeof
(
mcs_mask
);
i
++
)
mcs_mask
[
i
]
&=
sta
->
sta
.
ht_cap
.
mcs
.
rx_mask
[
i
];
}
/*
* Make sure the rate index selected for each TX rate is
* included in the configured mask and change the rate indexes
* if needed.
*/
for
(
i
=
0
;
i
<
IEEE80211_TX_MAX_RATES
;
i
++
)
{
/* Skip invalid rates */
if
(
info
->
control
.
rates
[
i
].
idx
<
0
)
break
;
rate_idx_match_mask
(
&
info
->
control
.
rates
[
i
],
txrc
,
mask
,
mcs_mask
);
}
}
BUG_ON
(
info
->
control
.
rates
[
0
].
idx
<
0
);
int
rate_control_set_rates
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_sta
*
pubsta
,
struct
ieee80211_sta_rates
*
rates
)
{
struct
ieee80211_sta_rates
*
old
=
rcu_dereference
(
pubsta
->
rates
);
rcu_assign_pointer
(
pubsta
->
rates
,
rates
);
if
(
old
)
kfree_rcu
(
old
,
rcu_head
);
return
0
;
}
}
EXPORT_SYMBOL
(
rate_control_set_rates
);
int
ieee80211_init_rate_ctrl_alg
(
struct
ieee80211_local
*
local
,
int
ieee80211_init_rate_ctrl_alg
(
struct
ieee80211_local
*
local
,
const
char
*
name
)
const
char
*
name
)
...
...
net/mac80211/rc80211_minstrel.c
浏览文件 @
6475cb05
...
@@ -83,6 +83,50 @@ minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
...
@@ -83,6 +83,50 @@ minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
tp_list
[
j
]
=
i
;
tp_list
[
j
]
=
i
;
}
}
static
void
minstrel_set_rate
(
struct
minstrel_sta_info
*
mi
,
struct
ieee80211_sta_rates
*
ratetbl
,
int
offset
,
int
idx
)
{
struct
minstrel_rate
*
r
=
&
mi
->
r
[
idx
];
ratetbl
->
rate
[
offset
].
idx
=
r
->
rix
;
ratetbl
->
rate
[
offset
].
count
=
r
->
adjusted_retry_count
;
ratetbl
->
rate
[
offset
].
count_cts
=
r
->
retry_count_cts
;
ratetbl
->
rate
[
offset
].
count_rts
=
r
->
retry_count_rtscts
;
}
static
void
minstrel_update_rates
(
struct
minstrel_priv
*
mp
,
struct
minstrel_sta_info
*
mi
)
{
struct
ieee80211_sta_rates
*
ratetbl
;
int
i
=
0
;
ratetbl
=
kzalloc
(
sizeof
(
*
ratetbl
),
GFP_ATOMIC
);
if
(
!
ratetbl
)
return
;
/* Start with max_tp_rate */
minstrel_set_rate
(
mi
,
ratetbl
,
i
++
,
mi
->
max_tp_rate
[
0
]);
if
(
mp
->
hw
->
max_rates
>=
3
)
{
/* At least 3 tx rates supported, use max_tp_rate2 next */
minstrel_set_rate
(
mi
,
ratetbl
,
i
++
,
mi
->
max_tp_rate
[
1
]);
}
if
(
mp
->
hw
->
max_rates
>=
2
)
{
/* At least 2 tx rates supported, use max_prob_rate next */
minstrel_set_rate
(
mi
,
ratetbl
,
i
++
,
mi
->
max_prob_rate
);
}
/* Use lowest rate last */
ratetbl
->
rate
[
i
].
idx
=
mi
->
lowest_rix
;
ratetbl
->
rate
[
i
].
count
=
mp
->
max_retry
;
ratetbl
->
rate
[
i
].
count_cts
=
mp
->
max_retry
;
ratetbl
->
rate
[
i
].
count_rts
=
mp
->
max_retry
;
rate_control_set_rates
(
mp
->
hw
,
mi
->
sta
,
ratetbl
);
}
static
void
static
void
minstrel_update_stats
(
struct
minstrel_priv
*
mp
,
struct
minstrel_sta_info
*
mi
)
minstrel_update_stats
(
struct
minstrel_priv
*
mp
,
struct
minstrel_sta_info
*
mi
)
{
{
...
@@ -161,6 +205,8 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
...
@@ -161,6 +205,8 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
/* Reset update timer */
/* Reset update timer */
mi
->
stats_update
=
jiffies
;
mi
->
stats_update
=
jiffies
;
minstrel_update_rates
(
mp
,
mi
);
}
}
static
void
static
void
...
@@ -209,9 +255,9 @@ minstrel_get_retry_count(struct minstrel_rate *mr,
...
@@ -209,9 +255,9 @@ minstrel_get_retry_count(struct minstrel_rate *mr,
{
{
unsigned
int
retry
=
mr
->
adjusted_retry_count
;
unsigned
int
retry
=
mr
->
adjusted_retry_count
;
if
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_USE_RTS_CTS
)
if
(
info
->
control
.
use_rts
)
retry
=
max
(
2U
,
min
(
mr
->
retry_count_rtscts
,
retry
));
retry
=
max
(
2U
,
min
(
mr
->
retry_count_rtscts
,
retry
));
else
if
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_USE_CTS_PROTECT
)
else
if
(
info
->
control
.
use_cts_prot
)
retry
=
max
(
2U
,
min
(
mr
->
retry_count_cts
,
retry
));
retry
=
max
(
2U
,
min
(
mr
->
retry_count_cts
,
retry
));
return
retry
;
return
retry
;
}
}
...
@@ -240,13 +286,12 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
...
@@ -240,13 +286,12 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
skb
);
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
skb
);
struct
minstrel_sta_info
*
mi
=
priv_sta
;
struct
minstrel_sta_info
*
mi
=
priv_sta
;
struct
minstrel_priv
*
mp
=
priv
;
struct
minstrel_priv
*
mp
=
priv
;
struct
ieee80211_tx_rate
*
ar
=
info
->
control
.
rates
;
struct
ieee80211_tx_rate
*
rate
=
&
info
->
control
.
rates
[
0
];
unsigned
int
ndx
,
sample_ndx
=
0
;
struct
minstrel_rate
*
msr
,
*
mr
;
unsigned
int
ndx
;
bool
mrr_capable
;
bool
mrr_capable
;
bool
indirect_rate_sampling
=
false
;
bool
prev_sample
=
mi
->
prev_sample
;
bool
rate_sampling
=
false
;
int
delta
;
int
i
,
delta
;
int
mrr_ndx
[
3
];
int
sampling_ratio
;
int
sampling_ratio
;
/* management/no-ack frames do not use rate control */
/* management/no-ack frames do not use rate control */
...
@@ -262,107 +307,75 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
...
@@ -262,107 +307,75 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
else
else
sampling_ratio
=
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 */
/* increase sum packet counter */
mi
->
packet_count
++
;
mi
->
packet_count
++
;
delta
=
(
mi
->
packet_count
*
sampling_ratio
/
100
)
-
delta
=
(
mi
->
packet_count
*
sampling_ratio
/
100
)
-
(
mi
->
sample_count
+
mi
->
sample_deferred
/
2
);
(
mi
->
sample_count
+
mi
->
sample_deferred
/
2
);
/* delta > 0: sampling required */
/* delta < 0: no sampling required */
if
((
delta
>
0
)
&&
(
mrr_capable
||
!
mi
->
prev_sample
))
{
mi
->
prev_sample
=
false
;
struct
minstrel_rate
*
msr
;
if
(
delta
<
0
||
(
!
mrr_capable
&&
prev_sample
))
if
(
mi
->
packet_count
>=
10000
)
{
return
;
mi
->
sample_deferred
=
0
;
mi
->
sample_count
=
0
;
mi
->
packet_count
=
0
;
}
else
if
(
delta
>
mi
->
n_rates
*
2
)
{
/* With multi-rate retry, not every planned sample
* attempt actually gets used, due to the way the retry
* chain is set up - [max_tp,sample,prob,lowest] for
* sample_rate < max_tp.
*
* If there's too much sampling backlog and the link
* starts getting worse, minstrel would start bursting
* out lots of sampling frames, which would result
* in a large throughput loss. */
mi
->
sample_count
+=
(
delta
-
mi
->
n_rates
*
2
);
}
/* get next random rate sample */
if
(
mi
->
packet_count
>=
10000
)
{
sample_ndx
=
minstrel_get_next_sample
(
mi
);
mi
->
sample_deferred
=
0
;
msr
=
&
mi
->
r
[
sample_ndx
];
mi
->
sample_count
=
0
;
rate_sampling
=
true
;
mi
->
packet_count
=
0
;
}
else
if
(
delta
>
mi
->
n_rates
*
2
)
{
/* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
/* With multi-rate retry, not every planned sample
* rate sampling method should be used.
* attempt actually gets used, due to the way the retry
* Respect such rates that are not sampled for 20 interations.
* chain is set up - [max_tp,sample,prob,lowest] for
*/
* sample_rate < max_tp.
if
(
mrr_capable
&&
*
msr
->
perfect_tx_time
>
mi
->
r
[
ndx
].
perfect_tx_time
&&
* If there's too much sampling backlog and the link
msr
->
sample_skipped
<
20
)
* starts getting worse, minstrel would start bursting
indirect_rate_sampling
=
true
;
* out lots of sampling frames, which would result
* in a large throughput loss. */
if
(
!
indirect_rate_sampling
)
{
mi
->
sample_count
+=
(
delta
-
mi
->
n_rates
*
2
);
if
(
msr
->
sample_limit
!=
0
)
{
}
ndx
=
sample_ndx
;
mi
->
sample_count
++
;
/* get next random rate sample */
if
(
msr
->
sample_limit
>
0
)
ndx
=
minstrel_get_next_sample
(
mi
);
msr
->
sample_limit
--
;
msr
=
&
mi
->
r
[
ndx
];
}
else
mr
=
&
mi
->
r
[
mi
->
max_tp_rate
[
0
]];
rate_sampling
=
false
;
}
else
{
/* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
* rate sampling method should be used.
* packets that have the sampling rate deferred to the
* Respect such rates that are not sampled for 20 interations.
* second MRR stage. Increase the sample counter only
*/
* if the deferred sample rate was actually used.
if
(
mrr_capable
&&
* Use the sample_deferred counter to make sure that
msr
->
perfect_tx_time
>
mr
->
perfect_tx_time
&&
* the sampling is not done in large bursts */
msr
->
sample_skipped
<
20
)
{
info
->
flags
|=
IEEE80211_TX_CTL_RATE_CTRL_PROBE
;
/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
mi
->
sample_deferred
++
;
* packets that have the sampling rate deferred to the
}
* second MRR stage. Increase the sample counter only
* if the deferred sample rate was actually used.
* Use the sample_deferred counter to make sure that
* the sampling is not done in large bursts */
info
->
flags
|=
IEEE80211_TX_CTL_RATE_CTRL_PROBE
;
rate
++
;
mi
->
sample_deferred
++
;
}
else
{
if
(
!
msr
->
sample_limit
!=
0
)
return
;
mi
->
sample_count
++
;
if
(
msr
->
sample_limit
>
0
)
msr
->
sample_limit
--
;
}
}
mi
->
prev_sample
=
rate_sampling
;
/* If we're not using MRR and the sampling rate already
/* If we're not using MRR and the sampling rate already
* has a probability of >95%, we shouldn't be attempting
* has a probability of >95%, we shouldn't be attempting
* to use it, as this only wastes precious airtime */
* to use it, as this only wastes precious airtime */
if
(
!
mrr_capable
&&
rate_sampling
&&
if
(
!
mrr_capable
&&
(
mi
->
r
[
ndx
].
probability
>
MINSTREL_FRAC
(
95
,
100
)))
(
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
);
/* 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
;
return
;
}
/* mrr setup for 2nd stage */
mi
->
prev_sample
=
true
;
if
(
rate_sampling
)
{
if
(
indirect_rate_sampling
)
mrr_ndx
[
0
]
=
sample_ndx
;
else
mrr_ndx
[
0
]
=
mi
->
max_tp_rate
[
0
];
}
else
{
mrr_ndx
[
0
]
=
mi
->
max_tp_rate
[
1
];
}
/* mrr setup for 3rd & 4th stage */
rate
->
idx
=
mi
->
r
[
ndx
].
rix
;
mrr_ndx
[
1
]
=
mi
->
max_prob_rate
;
rate
->
count
=
minstrel_get_retry_count
(
&
mi
->
r
[
ndx
],
info
);
mrr_ndx
[
2
]
=
0
;
for
(
i
=
1
;
i
<
4
;
i
++
)
{
ar
[
i
].
idx
=
mi
->
r
[
mrr_ndx
[
i
-
1
]].
rix
;
ar
[
i
].
count
=
mi
->
r
[
mrr_ndx
[
i
-
1
]].
adjusted_retry_count
;
}
}
}
...
@@ -412,12 +425,16 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
...
@@ -412,12 +425,16 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
unsigned
int
i
,
n
=
0
;
unsigned
int
i
,
n
=
0
;
unsigned
int
t_slot
=
9
;
/* FIXME: get real slot time */
unsigned
int
t_slot
=
9
;
/* FIXME: get real slot time */
mi
->
sta
=
sta
;
mi
->
lowest_rix
=
rate_lowest_index
(
sband
,
sta
);
mi
->
lowest_rix
=
rate_lowest_index
(
sband
,
sta
);
ctl_rate
=
&
sband
->
bitrates
[
mi
->
lowest_rix
];
ctl_rate
=
&
sband
->
bitrates
[
mi
->
lowest_rix
];
mi
->
sp_ack_dur
=
ieee80211_frame_duration
(
sband
->
band
,
10
,
mi
->
sp_ack_dur
=
ieee80211_frame_duration
(
sband
->
band
,
10
,
ctl_rate
->
bitrate
,
ctl_rate
->
bitrate
,
!!
(
ctl_rate
->
flags
&
IEEE80211_RATE_ERP_G
),
1
);
!!
(
ctl_rate
->
flags
&
IEEE80211_RATE_ERP_G
),
1
);
memset
(
mi
->
max_tp_rate
,
0
,
sizeof
(
mi
->
max_tp_rate
));
mi
->
max_prob_rate
=
0
;
for
(
i
=
0
;
i
<
sband
->
n_bitrates
;
i
++
)
{
for
(
i
=
0
;
i
<
sband
->
n_bitrates
;
i
++
)
{
struct
minstrel_rate
*
mr
=
&
mi
->
r
[
n
];
struct
minstrel_rate
*
mr
=
&
mi
->
r
[
n
];
unsigned
int
tx_time
=
0
,
tx_time_cts
=
0
,
tx_time_rtscts
=
0
;
unsigned
int
tx_time
=
0
,
tx_time_cts
=
0
,
tx_time_rtscts
=
0
;
...
@@ -460,6 +477,8 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
...
@@ -460,6 +477,8 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
}
while
((
tx_time
<
mp
->
segment_size
)
&&
}
while
((
tx_time
<
mp
->
segment_size
)
&&
(
++
mr
->
retry_count
<
mp
->
max_retry
));
(
++
mr
->
retry_count
<
mp
->
max_retry
));
mr
->
adjusted_retry_count
=
mr
->
retry_count
;
mr
->
adjusted_retry_count
=
mr
->
retry_count
;
if
(
!
(
sband
->
bitrates
[
i
].
flags
&
IEEE80211_RATE_ERP_G
))
mr
->
retry_count_cts
=
mr
->
retry_count
;
}
}
for
(
i
=
n
;
i
<
sband
->
n_bitrates
;
i
++
)
{
for
(
i
=
n
;
i
<
sband
->
n_bitrates
;
i
++
)
{
...
@@ -471,6 +490,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
...
@@ -471,6 +490,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
mi
->
stats_update
=
jiffies
;
mi
->
stats_update
=
jiffies
;
init_sample_table
(
mi
);
init_sample_table
(
mi
);
minstrel_update_rates
(
mp
,
mi
);
}
}
static
void
*
static
void
*
...
...
net/mac80211/rc80211_minstrel.h
浏览文件 @
6475cb05
...
@@ -9,7 +9,8 @@
...
@@ -9,7 +9,8 @@
#ifndef __RC_MINSTREL_H
#ifndef __RC_MINSTREL_H
#define __RC_MINSTREL_H
#define __RC_MINSTREL_H
#define EWMA_LEVEL 75
/* ewma weighting factor [%] */
#define EWMA_LEVEL 96
/* ewma weighting factor [/EWMA_DIV] */
#define EWMA_DIV 128
#define SAMPLE_COLUMNS 10
/* number of columns in sample table */
#define SAMPLE_COLUMNS 10
/* number of columns in sample table */
...
@@ -27,7 +28,7 @@
...
@@ -27,7 +28,7 @@
static
inline
int
static
inline
int
minstrel_ewma
(
int
old
,
int
new
,
int
weight
)
minstrel_ewma
(
int
old
,
int
new
,
int
weight
)
{
{
return
(
new
*
(
100
-
weight
)
+
old
*
weight
)
/
100
;
return
(
new
*
(
EWMA_DIV
-
weight
)
+
old
*
weight
)
/
EWMA_DIV
;
}
}
...
@@ -62,6 +63,8 @@ struct minstrel_rate {
...
@@ -62,6 +63,8 @@ struct minstrel_rate {
};
};
struct
minstrel_sta_info
{
struct
minstrel_sta_info
{
struct
ieee80211_sta
*
sta
;
unsigned
long
stats_update
;
unsigned
long
stats_update
;
unsigned
int
sp_ack_dur
;
unsigned
int
sp_ack_dur
;
unsigned
int
rate_avg
;
unsigned
int
rate_avg
;
...
...
net/mac80211/rc80211_minstrel_debugfs.c
浏览文件 @
6475cb05
...
@@ -68,7 +68,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
...
@@ -68,7 +68,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
file
->
private_data
=
ms
;
file
->
private_data
=
ms
;
p
=
ms
->
buf
;
p
=
ms
->
buf
;
p
+=
sprintf
(
p
,
"rate
throughput ewma prob
this prob "
p
+=
sprintf
(
p
,
"rate
throughput ewma prob
this prob "
"this succ/attempt success attempts
\n
"
);
"this succ/attempt success attempts
\n
"
);
for
(
i
=
0
;
i
<
mi
->
n_rates
;
i
++
)
{
for
(
i
=
0
;
i
<
mi
->
n_rates
;
i
++
)
{
struct
minstrel_rate
*
mr
=
&
mi
->
r
[
i
];
struct
minstrel_rate
*
mr
=
&
mi
->
r
[
i
];
...
@@ -86,7 +86,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
...
@@ -86,7 +86,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
eprob
=
MINSTREL_TRUNC
(
mr
->
probability
*
1000
);
eprob
=
MINSTREL_TRUNC
(
mr
->
probability
*
1000
);
p
+=
sprintf
(
p
,
" %6u.%1u %6u.%1u %6u.%1u "
p
+=
sprintf
(
p
,
" %6u.%1u %6u.%1u %6u.%1u "
"
%3u(%3u)
%8llu %8llu
\n
"
,
"
%3u(%3u)
%8llu %8llu
\n
"
,
tp
/
10
,
tp
%
10
,
tp
/
10
,
tp
%
10
,
eprob
/
10
,
eprob
%
10
,
eprob
/
10
,
eprob
%
10
,
prob
/
10
,
prob
%
10
,
prob
/
10
,
prob
%
10
,
...
...
net/mac80211/rc80211_minstrel_ht.c
浏览文件 @
6475cb05
...
@@ -126,6 +126,9 @@ const struct mcs_group minstrel_mcs_groups[] = {
...
@@ -126,6 +126,9 @@ const struct mcs_group minstrel_mcs_groups[] = {
static
u8
sample_table
[
SAMPLE_COLUMNS
][
MCS_GROUP_RATES
];
static
u8
sample_table
[
SAMPLE_COLUMNS
][
MCS_GROUP_RATES
];
static
void
minstrel_ht_update_rates
(
struct
minstrel_priv
*
mp
,
struct
minstrel_ht_sta
*
mi
);
/*
/*
* Look up an MCS group index based on mac80211 rate information
* Look up an MCS group index based on mac80211 rate information
*/
*/
...
@@ -244,6 +247,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
...
@@ -244,6 +247,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
struct
minstrel_rate_stats
*
mr
;
struct
minstrel_rate_stats
*
mr
;
int
cur_prob
,
cur_prob_tp
,
cur_tp
,
cur_tp2
;
int
cur_prob
,
cur_prob_tp
,
cur_tp
,
cur_tp2
;
int
group
,
i
,
index
;
int
group
,
i
,
index
;
bool
mi_rates_valid
=
false
;
if
(
mi
->
ampdu_packets
>
0
)
{
if
(
mi
->
ampdu_packets
>
0
)
{
mi
->
avg_ampdu_len
=
minstrel_ewma
(
mi
->
avg_ampdu_len
,
mi
->
avg_ampdu_len
=
minstrel_ewma
(
mi
->
avg_ampdu_len
,
...
@@ -254,11 +258,10 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
...
@@ -254,11 +258,10 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
mi
->
sample_slow
=
0
;
mi
->
sample_slow
=
0
;
mi
->
sample_count
=
0
;
mi
->
sample_count
=
0
;
mi
->
max_tp_rate
=
0
;
mi
->
max_tp_rate2
=
0
;
mi
->
max_prob_rate
=
0
;
for
(
group
=
0
;
group
<
ARRAY_SIZE
(
minstrel_mcs_groups
);
group
++
)
{
for
(
group
=
0
;
group
<
ARRAY_SIZE
(
minstrel_mcs_groups
);
group
++
)
{
bool
mg_rates_valid
=
false
;
cur_prob
=
0
;
cur_prob
=
0
;
cur_prob_tp
=
0
;
cur_prob_tp
=
0
;
cur_tp
=
0
;
cur_tp
=
0
;
...
@@ -268,15 +271,24 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
...
@@ -268,15 +271,24 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
if
(
!
mg
->
supported
)
if
(
!
mg
->
supported
)
continue
;
continue
;
mg
->
max_tp_rate
=
0
;
mg
->
max_tp_rate2
=
0
;
mg
->
max_prob_rate
=
0
;
mi
->
sample_count
++
;
mi
->
sample_count
++
;
for
(
i
=
0
;
i
<
MCS_GROUP_RATES
;
i
++
)
{
for
(
i
=
0
;
i
<
MCS_GROUP_RATES
;
i
++
)
{
if
(
!
(
mg
->
supported
&
BIT
(
i
)))
if
(
!
(
mg
->
supported
&
BIT
(
i
)))
continue
;
continue
;
/* initialize rates selections starting indexes */
if
(
!
mg_rates_valid
)
{
mg
->
max_tp_rate
=
mg
->
max_tp_rate2
=
mg
->
max_prob_rate
=
i
;
if
(
!
mi_rates_valid
)
{
mi
->
max_tp_rate
=
mi
->
max_tp_rate2
=
mi
->
max_prob_rate
=
i
;
mi_rates_valid
=
true
;
}
mg_rates_valid
=
true
;
}
mr
=
&
mg
->
rates
[
i
];
mr
=
&
mg
->
rates
[
i
];
mr
->
retry_updated
=
false
;
mr
->
retry_updated
=
false
;
index
=
MCS_GROUP_RATES
*
group
+
i
;
index
=
MCS_GROUP_RATES
*
group
+
i
;
...
@@ -456,7 +468,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
...
@@ -456,7 +468,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct
ieee80211_tx_rate
*
ar
=
info
->
status
.
rates
;
struct
ieee80211_tx_rate
*
ar
=
info
->
status
.
rates
;
struct
minstrel_rate_stats
*
rate
,
*
rate2
;
struct
minstrel_rate_stats
*
rate
,
*
rate2
;
struct
minstrel_priv
*
mp
=
priv
;
struct
minstrel_priv
*
mp
=
priv
;
bool
last
;
bool
last
,
update
=
false
;
int
i
;
int
i
;
if
(
!
msp
->
is_ht
)
if
(
!
msp
->
is_ht
)
...
@@ -505,21 +517,29 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
...
@@ -505,21 +517,29 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
rate
=
minstrel_get_ratestats
(
mi
,
mi
->
max_tp_rate
);
rate
=
minstrel_get_ratestats
(
mi
,
mi
->
max_tp_rate
);
if
(
rate
->
attempts
>
30
&&
if
(
rate
->
attempts
>
30
&&
MINSTREL_FRAC
(
rate
->
success
,
rate
->
attempts
)
<
MINSTREL_FRAC
(
rate
->
success
,
rate
->
attempts
)
<
MINSTREL_FRAC
(
20
,
100
))
MINSTREL_FRAC
(
20
,
100
))
{
minstrel_downgrade_rate
(
mi
,
&
mi
->
max_tp_rate
,
true
);
minstrel_downgrade_rate
(
mi
,
&
mi
->
max_tp_rate
,
true
);
update
=
true
;
}
rate2
=
minstrel_get_ratestats
(
mi
,
mi
->
max_tp_rate2
);
rate2
=
minstrel_get_ratestats
(
mi
,
mi
->
max_tp_rate2
);
if
(
rate2
->
attempts
>
30
&&
if
(
rate2
->
attempts
>
30
&&
MINSTREL_FRAC
(
rate2
->
success
,
rate2
->
attempts
)
<
MINSTREL_FRAC
(
rate2
->
success
,
rate2
->
attempts
)
<
MINSTREL_FRAC
(
20
,
100
))
MINSTREL_FRAC
(
20
,
100
))
{
minstrel_downgrade_rate
(
mi
,
&
mi
->
max_tp_rate2
,
false
);
minstrel_downgrade_rate
(
mi
,
&
mi
->
max_tp_rate2
,
false
);
update
=
true
;
}
if
(
time_after
(
jiffies
,
mi
->
stats_update
+
(
mp
->
update_interval
/
2
*
HZ
)
/
1000
))
{
if
(
time_after
(
jiffies
,
mi
->
stats_update
+
(
mp
->
update_interval
/
2
*
HZ
)
/
1000
))
{
update
=
true
;
minstrel_ht_update_stats
(
mp
,
mi
);
minstrel_ht_update_stats
(
mp
,
mi
);
if
(
!
(
info
->
flags
&
IEEE80211_TX_CTL_AMPDU
)
&&
if
(
!
(
info
->
flags
&
IEEE80211_TX_CTL_AMPDU
)
&&
mi
->
max_prob_rate
/
MCS_GROUP_RATES
!=
MINSTREL_CCK_GROUP
)
mi
->
max_prob_rate
/
MCS_GROUP_RATES
!=
MINSTREL_CCK_GROUP
)
minstrel_aggr_check
(
sta
,
skb
);
minstrel_aggr_check
(
sta
,
skb
);
}
}
if
(
update
)
minstrel_ht_update_rates
(
mp
,
mi
);
}
}
static
void
static
void
...
@@ -583,36 +603,71 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
...
@@ -583,36 +603,71 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
static
void
static
void
minstrel_ht_set_rate
(
struct
minstrel_priv
*
mp
,
struct
minstrel_ht_sta
*
mi
,
minstrel_ht_set_rate
(
struct
minstrel_priv
*
mp
,
struct
minstrel_ht_sta
*
mi
,
struct
ieee80211_tx_rate
*
rate
,
int
index
,
struct
ieee80211_sta_rates
*
ratetbl
,
int
offset
,
int
index
)
bool
sample
,
bool
rtscts
)
{
{
const
struct
mcs_group
*
group
=
&
minstrel_mcs_groups
[
index
/
MCS_GROUP_RATES
];
const
struct
mcs_group
*
group
=
&
minstrel_mcs_groups
[
index
/
MCS_GROUP_RATES
];
struct
minstrel_rate_stats
*
mr
;
struct
minstrel_rate_stats
*
mr
;
u8
idx
;
u16
flags
;
mr
=
minstrel_get_ratestats
(
mi
,
index
);
mr
=
minstrel_get_ratestats
(
mi
,
index
);
if
(
!
mr
->
retry_updated
)
if
(
!
mr
->
retry_updated
)
minstrel_calc_retransmit
(
mp
,
mi
,
index
);
minstrel_calc_retransmit
(
mp
,
mi
,
index
);
if
(
sample
)
if
(
mr
->
probability
<
MINSTREL_FRAC
(
20
,
100
)
||
!
mr
->
retry_count
)
{
rate
->
count
=
1
;
ratetbl
->
rate
[
offset
].
count
=
2
;
else
if
(
mr
->
probability
<
MINSTREL_FRAC
(
20
,
100
))
ratetbl
->
rate
[
offset
].
count_rts
=
2
;
rate
->
count
=
2
;
ratetbl
->
rate
[
offset
].
count_cts
=
2
;
else
if
(
rtscts
)
}
else
{
rate
->
count
=
mr
->
retry_count_rtscts
;
ratetbl
->
rate
[
offset
].
count
=
mr
->
retry_count
;
else
ratetbl
->
rate
[
offset
].
count_cts
=
mr
->
retry_count
;
rate
->
count
=
mr
->
retry_count
;
ratetbl
->
rate
[
offset
].
count_rts
=
mr
->
retry_count_rtscts
;
}
rate
->
flags
=
0
;
if
(
rtscts
)
rate
->
flags
|=
IEEE80211_TX_RC_USE_RTS_CTS
;
if
(
index
/
MCS_GROUP_RATES
==
MINSTREL_CCK_GROUP
)
{
if
(
index
/
MCS_GROUP_RATES
==
MINSTREL_CCK_GROUP
)
{
rate
->
idx
=
mp
->
cck_rates
[
index
%
ARRAY_SIZE
(
mp
->
cck_rates
)];
idx
=
mp
->
cck_rates
[
index
%
ARRAY_SIZE
(
mp
->
cck_rates
)];
flags
=
0
;
}
else
{
idx
=
index
%
MCS_GROUP_RATES
+
(
group
->
streams
-
1
)
*
MCS_GROUP_RATES
;
flags
=
IEEE80211_TX_RC_MCS
|
group
->
flags
;
}
if
(
offset
>
0
)
{
ratetbl
->
rate
[
offset
].
count
=
ratetbl
->
rate
[
offset
].
count_rts
;
flags
|=
IEEE80211_TX_RC_USE_RTS_CTS
;
}
ratetbl
->
rate
[
offset
].
idx
=
idx
;
ratetbl
->
rate
[
offset
].
flags
=
flags
;
}
static
void
minstrel_ht_update_rates
(
struct
minstrel_priv
*
mp
,
struct
minstrel_ht_sta
*
mi
)
{
struct
ieee80211_sta_rates
*
rates
;
int
i
=
0
;
rates
=
kzalloc
(
sizeof
(
*
rates
),
GFP_ATOMIC
);
if
(
!
rates
)
return
;
return
;
/* Start with max_tp_rate */
minstrel_ht_set_rate
(
mp
,
mi
,
rates
,
i
++
,
mi
->
max_tp_rate
);
if
(
mp
->
hw
->
max_rates
>=
3
)
{
/* At least 3 tx rates supported, use max_tp_rate2 next */
minstrel_ht_set_rate
(
mp
,
mi
,
rates
,
i
++
,
mi
->
max_tp_rate2
);
}
if
(
mp
->
hw
->
max_rates
>=
2
)
{
/*
* At least 2 tx rates supported, use max_prob_rate next */
minstrel_ht_set_rate
(
mp
,
mi
,
rates
,
i
++
,
mi
->
max_prob_rate
);
}
}
rate
->
flags
|=
IEEE80211_TX_RC_MCS
|
group
->
flags
;
rate
s
->
rate
[
i
].
idx
=
-
1
;
rate
->
idx
=
index
%
MCS_GROUP_RATES
+
(
group
->
streams
-
1
)
*
MCS_GROUP_RATES
;
rate
_control_set_rates
(
mp
->
hw
,
mi
->
sta
,
rates
)
;
}
}
static
inline
int
static
inline
int
...
@@ -702,13 +757,13 @@ static void
...
@@ -702,13 +757,13 @@ static void
minstrel_ht_get_rate
(
void
*
priv
,
struct
ieee80211_sta
*
sta
,
void
*
priv_sta
,
minstrel_ht_get_rate
(
void
*
priv
,
struct
ieee80211_sta
*
sta
,
void
*
priv_sta
,
struct
ieee80211_tx_rate_control
*
txrc
)
struct
ieee80211_tx_rate_control
*
txrc
)
{
{
const
struct
mcs_group
*
sample_group
;
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
txrc
->
skb
);
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
txrc
->
skb
);
struct
ieee80211_tx_rate
*
ar
=
info
->
status
.
rates
;
struct
ieee80211_tx_rate
*
rate
=
&
info
->
status
.
rates
[
0
]
;
struct
minstrel_ht_sta_priv
*
msp
=
priv_sta
;
struct
minstrel_ht_sta_priv
*
msp
=
priv_sta
;
struct
minstrel_ht_sta
*
mi
=
&
msp
->
ht
;
struct
minstrel_ht_sta
*
mi
=
&
msp
->
ht
;
struct
minstrel_priv
*
mp
=
priv
;
struct
minstrel_priv
*
mp
=
priv
;
int
sample_idx
;
int
sample_idx
;
bool
sample
=
false
;
if
(
rate_control_send_low
(
sta
,
priv_sta
,
txrc
))
if
(
rate_control_send_low
(
sta
,
priv_sta
,
txrc
))
return
;
return
;
...
@@ -736,51 +791,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
...
@@ -736,51 +791,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
}
}
#endif
#endif
if
(
sample_idx
>=
0
)
{
sample
=
true
;
minstrel_ht_set_rate
(
mp
,
mi
,
&
ar
[
0
],
sample_idx
,
true
,
false
);
info
->
flags
|=
IEEE80211_TX_CTL_RATE_CTRL_PROBE
;
}
else
{
minstrel_ht_set_rate
(
mp
,
mi
,
&
ar
[
0
],
mi
->
max_tp_rate
,
false
,
false
);
}
if
(
mp
->
hw
->
max_rates
>=
3
)
{
/*
* At least 3 tx rates supported, use
* sample_rate -> max_tp_rate -> max_prob_rate for sampling and
* max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
*/
if
(
sample_idx
>=
0
)
minstrel_ht_set_rate
(
mp
,
mi
,
&
ar
[
1
],
mi
->
max_tp_rate
,
false
,
false
);
else
minstrel_ht_set_rate
(
mp
,
mi
,
&
ar
[
1
],
mi
->
max_tp_rate2
,
false
,
true
);
minstrel_ht_set_rate
(
mp
,
mi
,
&
ar
[
2
],
mi
->
max_prob_rate
,
false
,
!
sample
);
ar
[
3
].
count
=
0
;
ar
[
3
].
idx
=
-
1
;
}
else
if
(
mp
->
hw
->
max_rates
==
2
)
{
/*
* Only 2 tx rates supported, use
* sample_rate -> max_prob_rate for sampling and
* max_tp_rate -> max_prob_rate by default.
*/
minstrel_ht_set_rate
(
mp
,
mi
,
&
ar
[
1
],
mi
->
max_prob_rate
,
false
,
!
sample
);
ar
[
2
].
count
=
0
;
ar
[
2
].
idx
=
-
1
;
}
else
{
/* Not using MRR, only use the first rate */
ar
[
1
].
count
=
0
;
ar
[
1
].
idx
=
-
1
;
}
mi
->
total_packets
++
;
mi
->
total_packets
++
;
/* wraparound */
/* wraparound */
...
@@ -788,6 +798,16 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
...
@@ -788,6 +798,16 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
mi
->
total_packets
=
0
;
mi
->
total_packets
=
0
;
mi
->
sample_packets
=
0
;
mi
->
sample_packets
=
0
;
}
}
if
(
sample_idx
<
0
)
return
;
sample_group
=
&
minstrel_mcs_groups
[
sample_idx
/
MCS_GROUP_RATES
];
info
->
flags
|=
IEEE80211_TX_CTL_RATE_CTRL_PROBE
;
rate
->
idx
=
sample_idx
%
MCS_GROUP_RATES
+
(
sample_group
->
streams
-
1
)
*
MCS_GROUP_RATES
;
rate
->
flags
=
IEEE80211_TX_RC_MCS
|
sample_group
->
flags
;
rate
->
count
=
1
;
}
}
static
void
static
void
...
@@ -837,6 +857,8 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
...
@@ -837,6 +857,8 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
msp
->
is_ht
=
true
;
msp
->
is_ht
=
true
;
memset
(
mi
,
0
,
sizeof
(
*
mi
));
memset
(
mi
,
0
,
sizeof
(
*
mi
));
mi
->
sta
=
sta
;
mi
->
stats_update
=
jiffies
;
mi
->
stats_update
=
jiffies
;
ack_dur
=
ieee80211_frame_duration
(
sband
->
band
,
10
,
60
,
1
,
1
);
ack_dur
=
ieee80211_frame_duration
(
sband
->
band
,
10
,
60
,
1
,
1
);
...
@@ -898,6 +920,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
...
@@ -898,6 +920,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
if
(
!
n_supported
)
if
(
!
n_supported
)
goto
use_legacy
;
goto
use_legacy
;
/* create an initial rate table with the lowest supported rates */
minstrel_ht_update_stats
(
mp
,
mi
);
minstrel_ht_update_rates
(
mp
,
mi
);
return
;
return
;
use_legacy:
use_legacy:
...
...
net/mac80211/rc80211_minstrel_ht.h
浏览文件 @
6475cb05
...
@@ -65,6 +65,8 @@ struct minstrel_mcs_group_data {
...
@@ -65,6 +65,8 @@ struct minstrel_mcs_group_data {
};
};
struct
minstrel_ht_sta
{
struct
minstrel_ht_sta
{
struct
ieee80211_sta
*
sta
;
/* ampdu length (average, per sampling interval) */
/* ampdu length (average, per sampling interval) */
unsigned
int
ampdu_len
;
unsigned
int
ampdu_len
;
unsigned
int
ampdu_packets
;
unsigned
int
ampdu_packets
;
...
...
net/mac80211/rx.c
浏览文件 @
6475cb05
...
@@ -2085,6 +2085,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
...
@@ -2085,6 +2085,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
}
}
fwd_hdr
=
(
struct
ieee80211_hdr
*
)
fwd_skb
->
data
;
fwd_hdr
=
(
struct
ieee80211_hdr
*
)
fwd_skb
->
data
;
fwd_hdr
->
frame_control
&=
~
cpu_to_le16
(
IEEE80211_FCTL_RETRY
);
info
=
IEEE80211_SKB_CB
(
fwd_skb
);
info
=
IEEE80211_SKB_CB
(
fwd_skb
);
memset
(
info
,
0
,
sizeof
(
*
info
));
memset
(
info
,
0
,
sizeof
(
*
info
));
info
->
flags
|=
IEEE80211_TX_INTFL_NEED_TXPROCESSING
;
info
->
flags
|=
IEEE80211_TX_INTFL_NEED_TXPROCESSING
;
...
@@ -2423,6 +2424,22 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
...
@@ -2423,6 +2424,22 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
}
}
break
;
break
;
case
WLAN_CATEGORY_PUBLIC
:
if
(
len
<
IEEE80211_MIN_ACTION_SIZE
+
1
)
goto
invalid
;
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
)
break
;
if
(
!
rx
->
sta
)
break
;
if
(
!
ether_addr_equal
(
mgmt
->
bssid
,
sdata
->
u
.
mgd
.
bssid
))
break
;
if
(
mgmt
->
u
.
action
.
u
.
ext_chan_switch
.
action_code
!=
WLAN_PUB_ACTION_EXT_CHANSW_ANN
)
break
;
if
(
len
<
offsetof
(
struct
ieee80211_mgmt
,
u
.
action
.
u
.
ext_chan_switch
.
variable
))
goto
invalid
;
goto
queue
;
case
WLAN_CATEGORY_VHT
:
case
WLAN_CATEGORY_VHT
:
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
&&
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
&&
sdata
->
vif
.
type
!=
NL80211_IFTYPE_MESH_POINT
&&
sdata
->
vif
.
type
!=
NL80211_IFTYPE_MESH_POINT
&&
...
@@ -2506,10 +2523,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
...
@@ -2506,10 +2523,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
ieee80211_process_measurement_req
(
sdata
,
mgmt
,
len
);
ieee80211_process_measurement_req
(
sdata
,
mgmt
,
len
);
goto
handled
;
goto
handled
;
case
WLAN_ACTION_SPCT_CHL_SWITCH
:
case
WLAN_ACTION_SPCT_CHL_SWITCH
:
if
(
len
<
(
IEEE80211_MIN_ACTION_SIZE
+
sizeof
(
mgmt
->
u
.
action
.
u
.
chan_switch
)))
break
;
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
)
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
)
break
;
break
;
...
@@ -3042,7 +3055,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
...
@@ -3042,7 +3055,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
!
ieee80211_is_probe_resp
(
hdr
->
frame_control
)
&&
!
ieee80211_is_probe_resp
(
hdr
->
frame_control
)
&&
!
ieee80211_is_beacon
(
hdr
->
frame_control
))
!
ieee80211_is_beacon
(
hdr
->
frame_control
))
return
0
;
return
0
;
if
(
!
ether_addr_equal
(
sdata
->
vif
.
addr
,
hdr
->
addr1
))
if
(
!
ether_addr_equal
(
sdata
->
vif
.
addr
,
hdr
->
addr1
)
&&
!
multicast
)
status
->
rx_flags
&=
~
IEEE80211_RX_RA_MATCH
;
status
->
rx_flags
&=
~
IEEE80211_RX_RA_MATCH
;
break
;
break
;
default:
default:
...
...
net/mac80211/scan.c
浏览文件 @
6475cb05
...
@@ -181,7 +181,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
...
@@ -181,7 +181,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
if
(
baselen
>
skb
->
len
)
if
(
baselen
>
skb
->
len
)
return
;
return
;
ieee802_11_parse_elems
(
elements
,
skb
->
len
-
baselen
,
&
elems
);
ieee802_11_parse_elems
(
elements
,
skb
->
len
-
baselen
,
false
,
&
elems
);
channel
=
ieee80211_get_channel
(
local
->
hw
.
wiphy
,
rx_status
->
freq
);
channel
=
ieee80211_get_channel
(
local
->
hw
.
wiphy
,
rx_status
->
freq
);
...
...
net/mac80211/trace.h
浏览文件 @
6475cb05
...
@@ -990,23 +990,23 @@ TRACE_EVENT(drv_channel_switch,
...
@@ -990,23 +990,23 @@ TRACE_EVENT(drv_channel_switch,
TP_STRUCT__entry
(
TP_STRUCT__entry
(
LOCAL_ENTRY
LOCAL_ENTRY
CHANDEF_ENTRY
__field
(
u64
,
timestamp
)
__field
(
u64
,
timestamp
)
__field
(
bool
,
block_tx
)
__field
(
bool
,
block_tx
)
__field
(
u16
,
freq
)
__field
(
u8
,
count
)
__field
(
u8
,
count
)
),
),
TP_fast_assign
(
TP_fast_assign
(
LOCAL_ASSIGN
;
LOCAL_ASSIGN
;
CHANDEF_ASSIGN
(
&
ch_switch
->
chandef
)
__entry
->
timestamp
=
ch_switch
->
timestamp
;
__entry
->
timestamp
=
ch_switch
->
timestamp
;
__entry
->
block_tx
=
ch_switch
->
block_tx
;
__entry
->
block_tx
=
ch_switch
->
block_tx
;
__entry
->
freq
=
ch_switch
->
channel
->
center_freq
;
__entry
->
count
=
ch_switch
->
count
;
__entry
->
count
=
ch_switch
->
count
;
),
),
TP_printk
(
TP_printk
(
LOCAL_PR_FMT
" new
freq:%u
count:%d"
,
LOCAL_PR_FMT
" new
"
CHANDEF_PR_FMT
"
count:%d"
,
LOCAL_PR_ARG
,
__entry
->
freq
,
__entry
->
count
LOCAL_PR_ARG
,
CHANDEF_PR_ARG
,
__entry
->
count
)
)
);
);
...
...
net/mac80211/tx.c
浏览文件 @
6475cb05
...
@@ -48,15 +48,15 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
...
@@ -48,15 +48,15 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
skb
);
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
skb
);
/* assume HW handles this */
/* assume HW handles this */
if
(
info
->
control
.
rates
[
0
]
.
flags
&
IEEE80211_TX_RC_MCS
)
if
(
tx
->
rate
.
flags
&
IEEE80211_TX_RC_MCS
)
return
0
;
return
0
;
/* uh huh? */
/* uh huh? */
if
(
WARN_ON_ONCE
(
info
->
control
.
rates
[
0
]
.
idx
<
0
))
if
(
WARN_ON_ONCE
(
tx
->
rate
.
idx
<
0
))
return
0
;
return
0
;
sband
=
local
->
hw
.
wiphy
->
bands
[
info
->
band
];
sband
=
local
->
hw
.
wiphy
->
bands
[
info
->
band
];
txrate
=
&
sband
->
bitrates
[
info
->
control
.
rates
[
0
]
.
idx
];
txrate
=
&
sband
->
bitrates
[
tx
->
rate
.
idx
];
erp
=
txrate
->
flags
&
IEEE80211_RATE_ERP_G
;
erp
=
txrate
->
flags
&
IEEE80211_RATE_ERP_G
;
...
@@ -617,11 +617,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
...
@@ -617,11 +617,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
tx
->
skb
);
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
tx
->
skb
);
struct
ieee80211_hdr
*
hdr
=
(
void
*
)
tx
->
skb
->
data
;
struct
ieee80211_hdr
*
hdr
=
(
void
*
)
tx
->
skb
->
data
;
struct
ieee80211_supported_band
*
sband
;
struct
ieee80211_supported_band
*
sband
;
struct
ieee80211_rate
*
rate
;
int
i
;
u32
len
;
u32
len
;
bool
inval
=
false
,
rts
=
false
,
short_preamble
=
false
;
struct
ieee80211_tx_rate_control
txrc
;
struct
ieee80211_tx_rate_control
txrc
;
struct
ieee80211_sta_rates
*
ratetbl
=
NULL
;
bool
assoc
=
false
;
bool
assoc
=
false
;
memset
(
&
txrc
,
0
,
sizeof
(
txrc
));
memset
(
&
txrc
,
0
,
sizeof
(
txrc
));
...
@@ -642,18 +640,23 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
...
@@ -642,18 +640,23 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
txrc
.
max_rate_idx
=
-
1
;
txrc
.
max_rate_idx
=
-
1
;
else
else
txrc
.
max_rate_idx
=
fls
(
txrc
.
rate_idx_mask
)
-
1
;
txrc
.
max_rate_idx
=
fls
(
txrc
.
rate_idx_mask
)
-
1
;
memcpy
(
txrc
.
rate_idx_mcs_mask
,
tx
->
sdata
->
rc_rateidx_mcs_mask
[
info
->
band
],
if
(
tx
->
sdata
->
rc_has_mcs_mask
[
info
->
band
])
sizeof
(
txrc
.
rate_idx_mcs_mask
));
txrc
.
rate_idx_mcs_mask
=
tx
->
sdata
->
rc_rateidx_mcs_mask
[
info
->
band
];
txrc
.
bss
=
(
tx
->
sdata
->
vif
.
type
==
NL80211_IFTYPE_AP
||
txrc
.
bss
=
(
tx
->
sdata
->
vif
.
type
==
NL80211_IFTYPE_AP
||
tx
->
sdata
->
vif
.
type
==
NL80211_IFTYPE_MESH_POINT
||
tx
->
sdata
->
vif
.
type
==
NL80211_IFTYPE_MESH_POINT
||
tx
->
sdata
->
vif
.
type
==
NL80211_IFTYPE_ADHOC
);
tx
->
sdata
->
vif
.
type
==
NL80211_IFTYPE_ADHOC
);
/* set up RTS protection if desired */
/* set up RTS protection if desired */
if
(
len
>
tx
->
local
->
hw
.
wiphy
->
rts_threshold
)
{
if
(
len
>
tx
->
local
->
hw
.
wiphy
->
rts_threshold
)
{
txrc
.
rts
=
rts
=
true
;
txrc
.
rts
=
true
;
}
}
info
->
control
.
use_rts
=
txrc
.
rts
;
info
->
control
.
use_cts_prot
=
tx
->
sdata
->
vif
.
bss_conf
.
use_cts_prot
;
/*
/*
* Use short preamble if the BSS can handle it, but not for
* Use short preamble if the BSS can handle it, but not for
* management frames unless we know the receiver can handle
* management frames unless we know the receiver can handle
...
@@ -663,7 +666,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
...
@@ -663,7 +666,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
if
(
tx
->
sdata
->
vif
.
bss_conf
.
use_short_preamble
&&
if
(
tx
->
sdata
->
vif
.
bss_conf
.
use_short_preamble
&&
(
ieee80211_is_data
(
hdr
->
frame_control
)
||
(
ieee80211_is_data
(
hdr
->
frame_control
)
||
(
tx
->
sta
&&
test_sta_flag
(
tx
->
sta
,
WLAN_STA_SHORT_PREAMBLE
))))
(
tx
->
sta
&&
test_sta_flag
(
tx
->
sta
,
WLAN_STA_SHORT_PREAMBLE
))))
txrc
.
short_preamble
=
short_preamble
=
true
;
txrc
.
short_preamble
=
true
;
info
->
control
.
short_preamble
=
txrc
.
short_preamble
;
if
(
tx
->
sta
)
if
(
tx
->
sta
)
assoc
=
test_sta_flag
(
tx
->
sta
,
WLAN_STA_ASSOC
);
assoc
=
test_sta_flag
(
tx
->
sta
,
WLAN_STA_ASSOC
);
...
@@ -687,16 +692,38 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
...
@@ -687,16 +692,38 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
*/
*/
rate_control_get_rate
(
tx
->
sdata
,
tx
->
sta
,
&
txrc
);
rate_control_get_rate
(
tx
->
sdata
,
tx
->
sta
,
&
txrc
);
if
(
unlikely
(
info
->
control
.
rates
[
0
].
idx
<
0
))
if
(
tx
->
sta
&&
!
info
->
control
.
skip_table
)
return
TX_DROP
;
ratetbl
=
rcu_dereference
(
tx
->
sta
->
sta
.
rates
);
if
(
unlikely
(
info
->
control
.
rates
[
0
].
idx
<
0
))
{
if
(
ratetbl
)
{
struct
ieee80211_tx_rate
rate
=
{
.
idx
=
ratetbl
->
rate
[
0
].
idx
,
.
flags
=
ratetbl
->
rate
[
0
].
flags
,
.
count
=
ratetbl
->
rate
[
0
].
count
};
if
(
ratetbl
->
rate
[
0
].
idx
<
0
)
return
TX_DROP
;
tx
->
rate
=
rate
;
}
else
{
return
TX_DROP
;
}
}
else
{
tx
->
rate
=
info
->
control
.
rates
[
0
];
}
if
(
txrc
.
reported_rate
.
idx
<
0
)
{
if
(
txrc
.
reported_rate
.
idx
<
0
)
{
txrc
.
reported_rate
=
info
->
control
.
rates
[
0
]
;
txrc
.
reported_rate
=
tx
->
rate
;
if
(
tx
->
sta
&&
ieee80211_is_data
(
hdr
->
frame_control
))
if
(
tx
->
sta
&&
ieee80211_is_data
(
hdr
->
frame_control
))
tx
->
sta
->
last_tx_rate
=
txrc
.
reported_rate
;
tx
->
sta
->
last_tx_rate
=
txrc
.
reported_rate
;
}
else
if
(
tx
->
sta
)
}
else
if
(
tx
->
sta
)
tx
->
sta
->
last_tx_rate
=
txrc
.
reported_rate
;
tx
->
sta
->
last_tx_rate
=
txrc
.
reported_rate
;
if
(
ratetbl
)
return
TX_CONTINUE
;
if
(
unlikely
(
!
info
->
control
.
rates
[
0
].
count
))
if
(
unlikely
(
!
info
->
control
.
rates
[
0
].
count
))
info
->
control
.
rates
[
0
].
count
=
1
;
info
->
control
.
rates
[
0
].
count
=
1
;
...
@@ -704,91 +731,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
...
@@ -704,91 +731,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
)))
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
)))
info
->
control
.
rates
[
0
].
count
=
1
;
info
->
control
.
rates
[
0
].
count
=
1
;
if
(
is_multicast_ether_addr
(
hdr
->
addr1
))
{
/*
* XXX: verify the rate is in the basic rateset
*/
return
TX_CONTINUE
;
}
/*
* set up the RTS/CTS rate as the fastest basic rate
* that is not faster than the data rate
*
* XXX: Should this check all retry rates?
*/
if
(
!
(
info
->
control
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
))
{
s8
baserate
=
0
;
rate
=
&
sband
->
bitrates
[
info
->
control
.
rates
[
0
].
idx
];
for
(
i
=
0
;
i
<
sband
->
n_bitrates
;
i
++
)
{
/* must be a basic rate */
if
(
!
(
tx
->
sdata
->
vif
.
bss_conf
.
basic_rates
&
BIT
(
i
)))
continue
;
/* must not be faster than the data rate */
if
(
sband
->
bitrates
[
i
].
bitrate
>
rate
->
bitrate
)
continue
;
/* maximum */
if
(
sband
->
bitrates
[
baserate
].
bitrate
<
sband
->
bitrates
[
i
].
bitrate
)
baserate
=
i
;
}
info
->
control
.
rts_cts_rate_idx
=
baserate
;
}
for
(
i
=
0
;
i
<
IEEE80211_TX_MAX_RATES
;
i
++
)
{
/*
* make sure there's no valid rate following
* an invalid one, just in case drivers don't
* take the API seriously to stop at -1.
*/
if
(
inval
)
{
info
->
control
.
rates
[
i
].
idx
=
-
1
;
continue
;
}
if
(
info
->
control
.
rates
[
i
].
idx
<
0
)
{
inval
=
true
;
continue
;
}
/*
* For now assume MCS is already set up correctly, this
* needs to be fixed.
*/
if
(
info
->
control
.
rates
[
i
].
flags
&
IEEE80211_TX_RC_MCS
)
{
WARN_ON
(
info
->
control
.
rates
[
i
].
idx
>
76
);
continue
;
}
/* set up RTS protection if desired */
if
(
rts
)
info
->
control
.
rates
[
i
].
flags
|=
IEEE80211_TX_RC_USE_RTS_CTS
;
/* RC is busted */
if
(
WARN_ON_ONCE
(
info
->
control
.
rates
[
i
].
idx
>=
sband
->
n_bitrates
))
{
info
->
control
.
rates
[
i
].
idx
=
-
1
;
continue
;
}
rate
=
&
sband
->
bitrates
[
info
->
control
.
rates
[
i
].
idx
];
/* set up short preamble */
if
(
short_preamble
&&
rate
->
flags
&
IEEE80211_RATE_SHORT_PREAMBLE
)
info
->
control
.
rates
[
i
].
flags
|=
IEEE80211_TX_RC_USE_SHORT_PREAMBLE
;
/* set up G protection */
if
(
!
rts
&&
tx
->
sdata
->
vif
.
bss_conf
.
use_cts_prot
&&
rate
->
flags
&
IEEE80211_RATE_ERP_G
)
info
->
control
.
rates
[
i
].
flags
|=
IEEE80211_TX_RC_USE_CTS_PROTECT
;
}
return
TX_CONTINUE
;
return
TX_CONTINUE
;
}
}
...
@@ -2502,8 +2444,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
...
@@ -2502,8 +2444,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
txrc
.
max_rate_idx
=
-
1
;
txrc
.
max_rate_idx
=
-
1
;
else
else
txrc
.
max_rate_idx
=
fls
(
txrc
.
rate_idx_mask
)
-
1
;
txrc
.
max_rate_idx
=
fls
(
txrc
.
rate_idx_mask
)
-
1
;
memcpy
(
txrc
.
rate_idx_mcs_mask
,
sdata
->
rc_rateidx_mcs_mask
[
band
],
sizeof
(
txrc
.
rate_idx_mcs_mask
));
txrc
.
bss
=
true
;
txrc
.
bss
=
true
;
rate_control_get_rate
(
sdata
,
NULL
,
&
txrc
);
rate_control_get_rate
(
sdata
,
NULL
,
&
txrc
);
...
...
net/mac80211/util.c
浏览文件 @
6475cb05
...
@@ -485,7 +485,8 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
...
@@ -485,7 +485,8 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
return
true
;
return
true
;
spin_lock_irqsave
(
&
local
->
queue_stop_reason_lock
,
flags
);
spin_lock_irqsave
(
&
local
->
queue_stop_reason_lock
,
flags
);
ret
=
!!
local
->
queue_stop_reasons
[
queue
];
ret
=
test_bit
(
IEEE80211_QUEUE_STOP_REASON_DRIVER
,
&
local
->
queue_stop_reasons
[
queue
]);
spin_unlock_irqrestore
(
&
local
->
queue_stop_reason_lock
,
flags
);
spin_unlock_irqrestore
(
&
local
->
queue_stop_reason_lock
,
flags
);
return
ret
;
return
ret
;
}
}
...
@@ -660,7 +661,7 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
...
@@ -660,7 +661,7 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
}
}
EXPORT_SYMBOL
(
ieee80211_queue_delayed_work
);
EXPORT_SYMBOL
(
ieee80211_queue_delayed_work
);
u32
ieee802_11_parse_elems_crc
(
u8
*
start
,
size_t
len
,
u32
ieee802_11_parse_elems_crc
(
u8
*
start
,
size_t
len
,
bool
action
,
struct
ieee802_11_elems
*
elems
,
struct
ieee802_11_elems
*
elems
,
u64
filter
,
u32
crc
)
u64
filter
,
u32
crc
)
{
{
...
@@ -668,6 +669,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
...
@@ -668,6 +669,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
u8
*
pos
=
start
;
u8
*
pos
=
start
;
bool
calc_crc
=
filter
!=
0
;
bool
calc_crc
=
filter
!=
0
;
DECLARE_BITMAP
(
seen_elems
,
256
);
DECLARE_BITMAP
(
seen_elems
,
256
);
const
u8
*
ie
;
bitmap_zero
(
seen_elems
,
256
);
bitmap_zero
(
seen_elems
,
256
);
memset
(
elems
,
0
,
sizeof
(
*
elems
));
memset
(
elems
,
0
,
sizeof
(
*
elems
));
...
@@ -715,6 +717,12 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
...
@@ -715,6 +717,12 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
case
WLAN_EID_COUNTRY
:
case
WLAN_EID_COUNTRY
:
case
WLAN_EID_PWR_CONSTRAINT
:
case
WLAN_EID_PWR_CONSTRAINT
:
case
WLAN_EID_TIMEOUT_INTERVAL
:
case
WLAN_EID_TIMEOUT_INTERVAL
:
case
WLAN_EID_SECONDARY_CHANNEL_OFFSET
:
case
WLAN_EID_WIDE_BW_CHANNEL_SWITCH
:
/*
* not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
* that if the content gets bigger it might be needed more than once
*/
if
(
test_bit
(
id
,
seen_elems
))
{
if
(
test_bit
(
id
,
seen_elems
))
{
elems
->
parse_error
=
true
;
elems
->
parse_error
=
true
;
left
-=
elen
;
left
-=
elen
;
...
@@ -862,6 +870,48 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
...
@@ -862,6 +870,48 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
}
}
elems
->
ch_switch_ie
=
(
void
*
)
pos
;
elems
->
ch_switch_ie
=
(
void
*
)
pos
;
break
;
break
;
case
WLAN_EID_EXT_CHANSWITCH_ANN
:
if
(
elen
!=
sizeof
(
struct
ieee80211_ext_chansw_ie
))
{
elem_parse_failed
=
true
;
break
;
}
elems
->
ext_chansw_ie
=
(
void
*
)
pos
;
break
;
case
WLAN_EID_SECONDARY_CHANNEL_OFFSET
:
if
(
elen
!=
sizeof
(
struct
ieee80211_sec_chan_offs_ie
))
{
elem_parse_failed
=
true
;
break
;
}
elems
->
sec_chan_offs
=
(
void
*
)
pos
;
break
;
case
WLAN_EID_WIDE_BW_CHANNEL_SWITCH
:
if
(
!
action
||
elen
!=
sizeof
(
*
elems
->
wide_bw_chansw_ie
))
{
elem_parse_failed
=
true
;
break
;
}
elems
->
wide_bw_chansw_ie
=
(
void
*
)
pos
;
break
;
case
WLAN_EID_CHANNEL_SWITCH_WRAPPER
:
if
(
action
)
{
elem_parse_failed
=
true
;
break
;
}
/*
* This is a bit tricky, but as we only care about
* the wide bandwidth channel switch element, so
* just parse it out manually.
*/
ie
=
cfg80211_find_ie
(
WLAN_EID_WIDE_BW_CHANNEL_SWITCH
,
pos
,
elen
);
if
(
ie
)
{
if
(
ie
[
1
]
==
sizeof
(
*
elems
->
wide_bw_chansw_ie
))
elems
->
wide_bw_chansw_ie
=
(
void
*
)(
ie
+
2
);
else
elem_parse_failed
=
true
;
}
break
;
case
WLAN_EID_COUNTRY
:
case
WLAN_EID_COUNTRY
:
elems
->
country_elem
=
pos
;
elems
->
country_elem
=
pos
;
elems
->
country_elem_len
=
elen
;
elems
->
country_elem_len
=
elen
;
...
...
net/rfkill/rfkill-gpio.c
浏览文件 @
6475cb05
...
@@ -131,6 +131,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
...
@@ -131,6 +131,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
rfkill
->
pwr_clk
=
clk_get
(
&
pdev
->
dev
,
pdata
->
power_clk_name
);
rfkill
->
pwr_clk
=
clk_get
(
&
pdev
->
dev
,
pdata
->
power_clk_name
);
if
(
IS_ERR
(
rfkill
->
pwr_clk
))
{
if
(
IS_ERR
(
rfkill
->
pwr_clk
))
{
pr_warn
(
"%s: can't find pwr_clk.
\n
"
,
__func__
);
pr_warn
(
"%s: can't find pwr_clk.
\n
"
,
__func__
);
ret
=
PTR_ERR
(
rfkill
->
pwr_clk
);
goto
fail_shutdown_name
;
goto
fail_shutdown_name
;
}
}
}
}
...
@@ -152,9 +153,11 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
...
@@ -152,9 +153,11 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
}
}
rfkill
->
rfkill_dev
=
rfkill_alloc
(
pdata
->
name
,
&
pdev
->
dev
,
pdata
->
type
,
rfkill
->
rfkill_dev
=
rfkill_alloc
(
pdata
->
name
,
&
pdev
->
dev
,
pdata
->
type
,
&
rfkill_gpio_ops
,
rfkill
);
&
rfkill_gpio_ops
,
rfkill
);
if
(
!
rfkill
->
rfkill_dev
)
if
(
!
rfkill
->
rfkill_dev
)
{
ret
=
-
ENOMEM
;
goto
fail_shutdown
;
goto
fail_shutdown
;
}
ret
=
rfkill_register
(
rfkill
->
rfkill_dev
);
ret
=
rfkill_register
(
rfkill
->
rfkill_dev
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
...
net/wireless/core.h
浏览文件 @
6475cb05
...
@@ -88,6 +88,9 @@ struct cfg80211_registered_device {
...
@@ -88,6 +88,9 @@ struct cfg80211_registered_device {
struct
delayed_work
dfs_update_channels_wk
;
struct
delayed_work
dfs_update_channels_wk
;
/* netlink port which started critical protocol (0 means not started) */
u32
crit_proto_nlportid
;
/* must be last because of the way we do wiphy_priv(),
/* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */
* and it should at least be aligned to NETDEV_ALIGN */
struct
wiphy
wiphy
__aligned
(
NETDEV_ALIGN
);
struct
wiphy
wiphy
__aligned
(
NETDEV_ALIGN
);
...
...
net/wireless/mlme.c
浏览文件 @
6475cb05
...
@@ -648,6 +648,11 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
...
@@ -648,6 +648,11 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
spin_unlock_bh
(
&
wdev
->
mgmt_registrations_lock
);
spin_unlock_bh
(
&
wdev
->
mgmt_registrations_lock
);
if
(
nlportid
&&
rdev
->
crit_proto_nlportid
==
nlportid
)
{
rdev
->
crit_proto_nlportid
=
0
;
rdev_crit_proto_stop
(
rdev
,
wdev
);
}
if
(
nlportid
==
wdev
->
ap_unexpected_nlportid
)
if
(
nlportid
==
wdev
->
ap_unexpected_nlportid
)
wdev
->
ap_unexpected_nlportid
=
0
;
wdev
->
ap_unexpected_nlportid
=
0
;
}
}
...
...
net/wireless/nl80211.c
浏览文件 @
6475cb05
...
@@ -447,62 +447,69 @@ nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
...
@@ -447,62 +447,69 @@ nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
[
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI
]
=
{
.
type
=
NLA_U32
},
[
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI
]
=
{
.
type
=
NLA_U32
},
};
};
/* ifidx get helper */
static
int
nl80211_prepare_wdev_dump
(
struct
sk_buff
*
skb
,
static
int
nl80211_get_ifidx
(
struct
netlink_callback
*
cb
)
struct
netlink_callback
*
cb
,
struct
cfg80211_registered_device
**
rdev
,
struct
wireless_dev
**
wdev
)
{
{
int
res
;
int
err
;
res
=
nlmsg_parse
(
cb
->
nlh
,
GENL_HDRLEN
+
nl80211_fam
.
hdrsize
,
nl80211_fam
.
attrbuf
,
nl80211_fam
.
maxattr
,
nl80211_policy
);
if
(
res
)
return
res
;
if
(
!
nl80211_fam
.
attrbuf
[
NL80211_ATTR_IFINDEX
])
return
-
EINVAL
;
res
=
nla_get_u32
(
nl80211_fam
.
attrbuf
[
NL80211_ATTR_IFINDEX
]);
rtnl_lock
();
if
(
!
res
)
mutex_lock
(
&
cfg80211_mutex
);
return
-
EINVAL
;
return
res
;
}
static
int
nl80211_prepare_netdev_dump
(
struct
sk_buff
*
skb
,
if
(
!
cb
->
args
[
0
])
{
struct
netlink_callback
*
cb
,
err
=
nlmsg_parse
(
cb
->
nlh
,
GENL_HDRLEN
+
nl80211_fam
.
hdrsize
,
struct
cfg80211_registered_device
**
rdev
,
nl80211_fam
.
attrbuf
,
nl80211_fam
.
maxattr
,
struct
net_device
**
dev
)
nl80211_policy
);
{
if
(
err
)
int
ifidx
=
cb
->
args
[
0
];
goto
out_unlock
;
int
err
;
if
(
!
ifidx
)
*
wdev
=
__cfg80211_wdev_from_attrs
(
sock_net
(
skb
->
sk
),
ifidx
=
nl80211_get_ifidx
(
cb
);
nl80211_fam
.
attrbuf
);
if
(
ifidx
<
0
)
if
(
IS_ERR
(
*
wdev
))
{
return
ifidx
;
err
=
PTR_ERR
(
*
wdev
);
goto
out_unlock
;
}
*
rdev
=
wiphy_to_dev
((
*
wdev
)
->
wiphy
);
cb
->
args
[
0
]
=
(
*
rdev
)
->
wiphy_idx
;
cb
->
args
[
1
]
=
(
*
wdev
)
->
identifier
;
}
else
{
struct
wiphy
*
wiphy
=
wiphy_idx_to_wiphy
(
cb
->
args
[
0
]);
struct
wireless_dev
*
tmp
;
cb
->
args
[
0
]
=
ifidx
;
if
(
!
wiphy
)
{
err
=
-
ENODEV
;
goto
out_unlock
;
}
*
rdev
=
wiphy_to_dev
(
wiphy
);
*
wdev
=
NULL
;
rtnl_lock
();
mutex_lock
(
&
(
*
rdev
)
->
devlist_mtx
);
list_for_each_entry
(
tmp
,
&
(
*
rdev
)
->
wdev_list
,
list
)
{
if
(
tmp
->
identifier
==
cb
->
args
[
1
])
{
*
wdev
=
tmp
;
break
;
}
}
mutex_unlock
(
&
(
*
rdev
)
->
devlist_mtx
);
*
dev
=
__dev_get_by_index
(
sock_net
(
skb
->
sk
),
ifidx
);
if
(
!*
wdev
)
{
if
(
!*
dev
)
{
err
=
-
ENODEV
;
err
=
-
ENODEV
;
goto
out_unlock
;
goto
out_rtnl
;
}
}
}
*
rdev
=
cfg80211_get_dev_from_ifindex
(
sock_net
(
skb
->
sk
),
ifidx
);
cfg80211_lock_rdev
(
*
rdev
);
if
(
IS_ERR
(
*
rdev
))
{
err
=
PTR_ERR
(
*
rdev
);
goto
out_rtnl
;
}
mutex_unlock
(
&
cfg80211_mutex
);
return
0
;
return
0
;
out_rtnl:
out_unlock:
mutex_unlock
(
&
cfg80211_mutex
);
rtnl_unlock
();
rtnl_unlock
();
return
err
;
return
err
;
}
}
static
void
nl80211_finish_
net
dev_dump
(
struct
cfg80211_registered_device
*
rdev
)
static
void
nl80211_finish_
w
dev_dump
(
struct
cfg80211_registered_device
*
rdev
)
{
{
cfg80211_unlock_rdev
(
rdev
);
cfg80211_unlock_rdev
(
rdev
);
rtnl_unlock
();
rtnl_unlock
();
...
@@ -1417,6 +1424,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
...
@@ -1417,6 +1424,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
}
}
CMD
(
start_p2p_device
,
START_P2P_DEVICE
);
CMD
(
start_p2p_device
,
START_P2P_DEVICE
);
CMD
(
set_mcast_rate
,
SET_MCAST_RATE
);
CMD
(
set_mcast_rate
,
SET_MCAST_RATE
);
if
(
split
)
{
CMD
(
crit_proto_start
,
CRIT_PROTOCOL_START
);
CMD
(
crit_proto_stop
,
CRIT_PROTOCOL_STOP
);
}
#ifdef CONFIG_NL80211_TESTMODE
#ifdef CONFIG_NL80211_TESTMODE
CMD
(
testmode_cmd
,
TESTMODE
);
CMD
(
testmode_cmd
,
TESTMODE
);
...
@@ -3525,15 +3536,20 @@ static int nl80211_dump_station(struct sk_buff *skb,
...
@@ -3525,15 +3536,20 @@ static int nl80211_dump_station(struct sk_buff *skb,
{
{
struct
station_info
sinfo
;
struct
station_info
sinfo
;
struct
cfg80211_registered_device
*
dev
;
struct
cfg80211_registered_device
*
dev
;
struct
net_device
*
net
dev
;
struct
wireless_dev
*
w
dev
;
u8
mac_addr
[
ETH_ALEN
];
u8
mac_addr
[
ETH_ALEN
];
int
sta_idx
=
cb
->
args
[
1
];
int
sta_idx
=
cb
->
args
[
2
];
int
err
;
int
err
;
err
=
nl80211_prepare_
netdev_dump
(
skb
,
cb
,
&
dev
,
&
net
dev
);
err
=
nl80211_prepare_
wdev_dump
(
skb
,
cb
,
&
dev
,
&
w
dev
);
if
(
err
)
if
(
err
)
return
err
;
return
err
;
if
(
!
wdev
->
netdev
)
{
err
=
-
EINVAL
;
goto
out_err
;
}
if
(
!
dev
->
ops
->
dump_station
)
{
if
(
!
dev
->
ops
->
dump_station
)
{
err
=
-
EOPNOTSUPP
;
err
=
-
EOPNOTSUPP
;
goto
out_err
;
goto
out_err
;
...
@@ -3541,7 +3557,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
...
@@ -3541,7 +3557,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
while
(
1
)
{
while
(
1
)
{
memset
(
&
sinfo
,
0
,
sizeof
(
sinfo
));
memset
(
&
sinfo
,
0
,
sizeof
(
sinfo
));
err
=
rdev_dump_station
(
dev
,
netdev
,
sta_idx
,
err
=
rdev_dump_station
(
dev
,
wdev
->
netdev
,
sta_idx
,
mac_addr
,
&
sinfo
);
mac_addr
,
&
sinfo
);
if
(
err
==
-
ENOENT
)
if
(
err
==
-
ENOENT
)
break
;
break
;
...
@@ -3551,7 +3567,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
...
@@ -3551,7 +3567,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
if
(
nl80211_send_station
(
skb
,
if
(
nl80211_send_station
(
skb
,
NETLINK_CB
(
cb
->
skb
).
portid
,
NETLINK_CB
(
cb
->
skb
).
portid
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
dev
,
netdev
,
mac_addr
,
dev
,
wdev
->
netdev
,
mac_addr
,
&
sinfo
)
<
0
)
&
sinfo
)
<
0
)
goto
out
;
goto
out
;
...
@@ -3560,10 +3576,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
...
@@ -3560,10 +3576,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
out:
out:
cb
->
args
[
1
]
=
sta_idx
;
cb
->
args
[
2
]
=
sta_idx
;
err
=
skb
->
len
;
err
=
skb
->
len
;
out_err:
out_err:
nl80211_finish_
net
dev_dump
(
dev
);
nl80211_finish_
w
dev_dump
(
dev
);
return
err
;
return
err
;
}
}
...
@@ -4167,13 +4183,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
...
@@ -4167,13 +4183,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
{
{
struct
mpath_info
pinfo
;
struct
mpath_info
pinfo
;
struct
cfg80211_registered_device
*
dev
;
struct
cfg80211_registered_device
*
dev
;
struct
net_device
*
net
dev
;
struct
wireless_dev
*
w
dev
;
u8
dst
[
ETH_ALEN
];
u8
dst
[
ETH_ALEN
];
u8
next_hop
[
ETH_ALEN
];
u8
next_hop
[
ETH_ALEN
];
int
path_idx
=
cb
->
args
[
1
];
int
path_idx
=
cb
->
args
[
2
];
int
err
;
int
err
;
err
=
nl80211_prepare_
netdev_dump
(
skb
,
cb
,
&
dev
,
&
net
dev
);
err
=
nl80211_prepare_
wdev_dump
(
skb
,
cb
,
&
dev
,
&
w
dev
);
if
(
err
)
if
(
err
)
return
err
;
return
err
;
...
@@ -4182,14 +4198,14 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
...
@@ -4182,14 +4198,14 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
goto
out_err
;
goto
out_err
;
}
}
if
(
netdev
->
ieee80211_ptr
->
iftype
!=
NL80211_IFTYPE_MESH_POINT
)
{
if
(
wdev
->
iftype
!=
NL80211_IFTYPE_MESH_POINT
)
{
err
=
-
EOPNOTSUPP
;
err
=
-
EOPNOTSUPP
;
goto
out_err
;
goto
out_err
;
}
}
while
(
1
)
{
while
(
1
)
{
err
=
rdev_dump_mpath
(
dev
,
netdev
,
path_idx
,
dst
,
next_hop
,
err
=
rdev_dump_mpath
(
dev
,
wdev
->
netdev
,
path_idx
,
dst
,
&
pinfo
);
next_hop
,
&
pinfo
);
if
(
err
==
-
ENOENT
)
if
(
err
==
-
ENOENT
)
break
;
break
;
if
(
err
)
if
(
err
)
...
@@ -4197,7 +4213,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
...
@@ -4197,7 +4213,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
if
(
nl80211_send_mpath
(
skb
,
NETLINK_CB
(
cb
->
skb
).
portid
,
if
(
nl80211_send_mpath
(
skb
,
NETLINK_CB
(
cb
->
skb
).
portid
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
netdev
,
dst
,
next_hop
,
wdev
->
netdev
,
dst
,
next_hop
,
&
pinfo
)
<
0
)
&
pinfo
)
<
0
)
goto
out
;
goto
out
;
...
@@ -4206,10 +4222,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
...
@@ -4206,10 +4222,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
out:
out:
cb
->
args
[
1
]
=
path_idx
;
cb
->
args
[
2
]
=
path_idx
;
err
=
skb
->
len
;
err
=
skb
->
len
;
out_err:
out_err:
nl80211_finish_
net
dev_dump
(
dev
);
nl80211_finish_
w
dev_dump
(
dev
);
return
err
;
return
err
;
}
}
...
@@ -5565,9 +5581,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
...
@@ -5565,9 +5581,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
genl_dump_check_consistent
(
cb
,
hdr
,
&
nl80211_fam
);
genl_dump_check_consistent
(
cb
,
hdr
,
&
nl80211_fam
);
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_GENERATION
,
rdev
->
bss_generation
)
||
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_GENERATION
,
rdev
->
bss_generation
))
goto
nla_put_failure
;
if
(
wdev
->
netdev
&&
nla_put_u32
(
msg
,
NL80211_ATTR_IFINDEX
,
wdev
->
netdev
->
ifindex
))
nla_put_u32
(
msg
,
NL80211_ATTR_IFINDEX
,
wdev
->
netdev
->
ifindex
))
goto
nla_put_failure
;
goto
nla_put_failure
;
if
(
nla_put_u64
(
msg
,
NL80211_ATTR_WDEV
,
wdev_id
(
wdev
)))
goto
nla_put_failure
;
bss
=
nla_nest_start
(
msg
,
NL80211_ATTR_BSS
);
bss
=
nla_nest_start
(
msg
,
NL80211_ATTR_BSS
);
if
(
!
bss
)
if
(
!
bss
)
...
@@ -5647,22 +5667,18 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
...
@@ -5647,22 +5667,18 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
return
-
EMSGSIZE
;
return
-
EMSGSIZE
;
}
}
static
int
nl80211_dump_scan
(
struct
sk_buff
*
skb
,
static
int
nl80211_dump_scan
(
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
)
struct
netlink_callback
*
cb
)
{
{
struct
cfg80211_registered_device
*
rdev
;
struct
cfg80211_registered_device
*
rdev
;
struct
net_device
*
dev
;
struct
cfg80211_internal_bss
*
scan
;
struct
cfg80211_internal_bss
*
scan
;
struct
wireless_dev
*
wdev
;
struct
wireless_dev
*
wdev
;
int
start
=
cb
->
args
[
1
],
idx
=
0
;
int
start
=
cb
->
args
[
2
],
idx
=
0
;
int
err
;
int
err
;
err
=
nl80211_prepare_
netdev_dump
(
skb
,
cb
,
&
rdev
,
&
dev
);
err
=
nl80211_prepare_
wdev_dump
(
skb
,
cb
,
&
rdev
,
&
w
dev
);
if
(
err
)
if
(
err
)
return
err
;
return
err
;
wdev
=
dev
->
ieee80211_ptr
;
wdev_lock
(
wdev
);
wdev_lock
(
wdev
);
spin_lock_bh
(
&
rdev
->
bss_lock
);
spin_lock_bh
(
&
rdev
->
bss_lock
);
cfg80211_bss_expire
(
rdev
);
cfg80211_bss_expire
(
rdev
);
...
@@ -5683,8 +5699,8 @@ static int nl80211_dump_scan(struct sk_buff *skb,
...
@@ -5683,8 +5699,8 @@ static int nl80211_dump_scan(struct sk_buff *skb,
spin_unlock_bh
(
&
rdev
->
bss_lock
);
spin_unlock_bh
(
&
rdev
->
bss_lock
);
wdev_unlock
(
wdev
);
wdev_unlock
(
wdev
);
cb
->
args
[
1
]
=
idx
;
cb
->
args
[
2
]
=
idx
;
nl80211_finish_
net
dev_dump
(
rdev
);
nl80211_finish_
w
dev_dump
(
rdev
);
return
skb
->
len
;
return
skb
->
len
;
}
}
...
@@ -5753,14 +5769,19 @@ static int nl80211_dump_survey(struct sk_buff *skb,
...
@@ -5753,14 +5769,19 @@ static int nl80211_dump_survey(struct sk_buff *skb,
{
{
struct
survey_info
survey
;
struct
survey_info
survey
;
struct
cfg80211_registered_device
*
dev
;
struct
cfg80211_registered_device
*
dev
;
struct
net_device
*
net
dev
;
struct
wireless_dev
*
w
dev
;
int
survey_idx
=
cb
->
args
[
1
];
int
survey_idx
=
cb
->
args
[
2
];
int
res
;
int
res
;
res
=
nl80211_prepare_
netdev_dump
(
skb
,
cb
,
&
dev
,
&
net
dev
);
res
=
nl80211_prepare_
wdev_dump
(
skb
,
cb
,
&
dev
,
&
w
dev
);
if
(
res
)
if
(
res
)
return
res
;
return
res
;
if
(
!
wdev
->
netdev
)
{
res
=
-
EINVAL
;
goto
out_err
;
}
if
(
!
dev
->
ops
->
dump_survey
)
{
if
(
!
dev
->
ops
->
dump_survey
)
{
res
=
-
EOPNOTSUPP
;
res
=
-
EOPNOTSUPP
;
goto
out_err
;
goto
out_err
;
...
@@ -5769,7 +5790,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
...
@@ -5769,7 +5790,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
while
(
1
)
{
while
(
1
)
{
struct
ieee80211_channel
*
chan
;
struct
ieee80211_channel
*
chan
;
res
=
rdev_dump_survey
(
dev
,
netdev
,
survey_idx
,
&
survey
);
res
=
rdev_dump_survey
(
dev
,
wdev
->
netdev
,
survey_idx
,
&
survey
);
if
(
res
==
-
ENOENT
)
if
(
res
==
-
ENOENT
)
break
;
break
;
if
(
res
)
if
(
res
)
...
@@ -5791,17 +5812,16 @@ static int nl80211_dump_survey(struct sk_buff *skb,
...
@@ -5791,17 +5812,16 @@ static int nl80211_dump_survey(struct sk_buff *skb,
if
(
nl80211_send_survey
(
skb
,
if
(
nl80211_send_survey
(
skb
,
NETLINK_CB
(
cb
->
skb
).
portid
,
NETLINK_CB
(
cb
->
skb
).
portid
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
netdev
,
wdev
->
netdev
,
&
survey
)
<
0
)
&
survey
)
<
0
)
goto
out
;
goto
out
;
survey_idx
++
;
survey_idx
++
;
}
}
out:
out:
cb
->
args
[
1
]
=
survey_idx
;
cb
->
args
[
2
]
=
survey_idx
;
res
=
skb
->
len
;
res
=
skb
->
len
;
out_err:
out_err:
nl80211_finish_
net
dev_dump
(
dev
);
nl80211_finish_
w
dev_dump
(
dev
);
return
res
;
return
res
;
}
}
...
@@ -8143,9 +8163,11 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
...
@@ -8143,9 +8163,11 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
if
(
!
rdev
->
ops
->
stop_p2p_device
)
if
(
!
rdev
->
ops
->
stop_p2p_device
)
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
mutex_lock
(
&
rdev
->
devlist_mtx
);
mutex_lock
(
&
rdev
->
sched_scan_mtx
);
mutex_lock
(
&
rdev
->
sched_scan_mtx
);
cfg80211_stop_p2p_device
(
rdev
,
wdev
);
cfg80211_stop_p2p_device
(
rdev
,
wdev
);
mutex_unlock
(
&
rdev
->
sched_scan_mtx
);
mutex_unlock
(
&
rdev
->
sched_scan_mtx
);
mutex_unlock
(
&
rdev
->
devlist_mtx
);
return
0
;
return
0
;
}
}
...
@@ -8198,6 +8220,64 @@ static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
...
@@ -8198,6 +8220,64 @@ static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
return
rdev_update_ft_ies
(
rdev
,
dev
,
&
ft_params
);
return
rdev_update_ft_ies
(
rdev
,
dev
,
&
ft_params
);
}
}
static
int
nl80211_crit_protocol_start
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
struct
cfg80211_registered_device
*
rdev
=
info
->
user_ptr
[
0
];
struct
wireless_dev
*
wdev
=
info
->
user_ptr
[
1
];
enum
nl80211_crit_proto_id
proto
=
NL80211_CRIT_PROTO_UNSPEC
;
u16
duration
;
int
ret
;
if
(
!
rdev
->
ops
->
crit_proto_start
)
return
-
EOPNOTSUPP
;
if
(
WARN_ON
(
!
rdev
->
ops
->
crit_proto_stop
))
return
-
EINVAL
;
if
(
rdev
->
crit_proto_nlportid
)
return
-
EBUSY
;
/* determine protocol if provided */
if
(
info
->
attrs
[
NL80211_ATTR_CRIT_PROT_ID
])
proto
=
nla_get_u16
(
info
->
attrs
[
NL80211_ATTR_CRIT_PROT_ID
]);
if
(
proto
>=
NUM_NL80211_CRIT_PROTO
)
return
-
EINVAL
;
/* timeout must be provided */
if
(
!
info
->
attrs
[
NL80211_ATTR_MAX_CRIT_PROT_DURATION
])
return
-
EINVAL
;
duration
=
nla_get_u16
(
info
->
attrs
[
NL80211_ATTR_MAX_CRIT_PROT_DURATION
]);
if
(
duration
>
NL80211_CRIT_PROTO_MAX_DURATION
)
return
-
ERANGE
;
ret
=
rdev_crit_proto_start
(
rdev
,
wdev
,
proto
,
duration
);
if
(
!
ret
)
rdev
->
crit_proto_nlportid
=
info
->
snd_portid
;
return
ret
;
}
static
int
nl80211_crit_protocol_stop
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
struct
cfg80211_registered_device
*
rdev
=
info
->
user_ptr
[
0
];
struct
wireless_dev
*
wdev
=
info
->
user_ptr
[
1
];
if
(
!
rdev
->
ops
->
crit_proto_stop
)
return
-
EOPNOTSUPP
;
if
(
rdev
->
crit_proto_nlportid
)
{
rdev
->
crit_proto_nlportid
=
0
;
rdev_crit_proto_stop
(
rdev
,
wdev
);
}
return
0
;
}
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
#define NL80211_FLAG_NEED_RTNL 0x04
...
@@ -8887,6 +8967,22 @@ static struct genl_ops nl80211_ops[] = {
...
@@ -8887,6 +8967,22 @@ static struct genl_ops nl80211_ops[] = {
.
internal_flags
=
NL80211_FLAG_NEED_NETDEV_UP
|
.
internal_flags
=
NL80211_FLAG_NEED_NETDEV_UP
|
NL80211_FLAG_NEED_RTNL
,
NL80211_FLAG_NEED_RTNL
,
},
},
{
.
cmd
=
NL80211_CMD_CRIT_PROTOCOL_START
,
.
doit
=
nl80211_crit_protocol_start
,
.
policy
=
nl80211_policy
,
.
flags
=
GENL_ADMIN_PERM
,
.
internal_flags
=
NL80211_FLAG_NEED_WDEV_UP
|
NL80211_FLAG_NEED_RTNL
,
},
{
.
cmd
=
NL80211_CMD_CRIT_PROTOCOL_STOP
,
.
doit
=
nl80211_crit_protocol_stop
,
.
policy
=
nl80211_policy
,
.
flags
=
GENL_ADMIN_PERM
,
.
internal_flags
=
NL80211_FLAG_NEED_WDEV_UP
|
NL80211_FLAG_NEED_RTNL
,
}
};
};
static
struct
genl_multicast_group
nl80211_mlme_mcgrp
=
{
static
struct
genl_multicast_group
nl80211_mlme_mcgrp
=
{
...
@@ -10632,6 +10728,45 @@ void cfg80211_ft_event(struct net_device *netdev,
...
@@ -10632,6 +10728,45 @@ void cfg80211_ft_event(struct net_device *netdev,
}
}
EXPORT_SYMBOL
(
cfg80211_ft_event
);
EXPORT_SYMBOL
(
cfg80211_ft_event
);
void
cfg80211_crit_proto_stopped
(
struct
wireless_dev
*
wdev
,
gfp_t
gfp
)
{
struct
cfg80211_registered_device
*
rdev
;
struct
sk_buff
*
msg
;
void
*
hdr
;
u32
nlportid
;
rdev
=
wiphy_to_dev
(
wdev
->
wiphy
);
if
(
!
rdev
->
crit_proto_nlportid
)
return
;
nlportid
=
rdev
->
crit_proto_nlportid
;
rdev
->
crit_proto_nlportid
=
0
;
msg
=
nlmsg_new
(
NLMSG_DEFAULT_SIZE
,
gfp
);
if
(
!
msg
)
return
;
hdr
=
nl80211hdr_put
(
msg
,
0
,
0
,
0
,
NL80211_CMD_CRIT_PROTOCOL_STOP
);
if
(
!
hdr
)
goto
nla_put_failure
;
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_WIPHY
,
rdev
->
wiphy_idx
)
||
nla_put_u64
(
msg
,
NL80211_ATTR_WDEV
,
wdev_id
(
wdev
)))
goto
nla_put_failure
;
genlmsg_end
(
msg
,
hdr
);
genlmsg_unicast
(
wiphy_net
(
&
rdev
->
wiphy
),
msg
,
nlportid
);
return
;
nla_put_failure:
if
(
hdr
)
genlmsg_cancel
(
msg
,
hdr
);
nlmsg_free
(
msg
);
}
EXPORT_SYMBOL
(
cfg80211_crit_proto_stopped
);
/* initialisation/exit functions */
/* initialisation/exit functions */
int
nl80211_init
(
void
)
int
nl80211_init
(
void
)
...
...
net/wireless/rdev-ops.h
浏览文件 @
6475cb05
...
@@ -875,7 +875,7 @@ static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev,
...
@@ -875,7 +875,7 @@ static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev,
trace_rdev_stop_p2p_device
(
&
rdev
->
wiphy
,
wdev
);
trace_rdev_stop_p2p_device
(
&
rdev
->
wiphy
,
wdev
);
rdev
->
ops
->
stop_p2p_device
(
&
rdev
->
wiphy
,
wdev
);
rdev
->
ops
->
stop_p2p_device
(
&
rdev
->
wiphy
,
wdev
);
trace_rdev_return_void
(
&
rdev
->
wiphy
);
trace_rdev_return_void
(
&
rdev
->
wiphy
);
}
}
static
inline
int
rdev_set_mac_acl
(
struct
cfg80211_registered_device
*
rdev
,
static
inline
int
rdev_set_mac_acl
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
struct
net_device
*
dev
,
...
@@ -901,4 +901,26 @@ static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev,
...
@@ -901,4 +901,26 @@ static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev,
return
ret
;
return
ret
;
}
}
static
inline
int
rdev_crit_proto_start
(
struct
cfg80211_registered_device
*
rdev
,
struct
wireless_dev
*
wdev
,
enum
nl80211_crit_proto_id
protocol
,
u16
duration
)
{
int
ret
;
trace_rdev_crit_proto_start
(
&
rdev
->
wiphy
,
wdev
,
protocol
,
duration
);
ret
=
rdev
->
ops
->
crit_proto_start
(
&
rdev
->
wiphy
,
wdev
,
protocol
,
duration
);
trace_rdev_return_int
(
&
rdev
->
wiphy
,
ret
);
return
ret
;
}
static
inline
void
rdev_crit_proto_stop
(
struct
cfg80211_registered_device
*
rdev
,
struct
wireless_dev
*
wdev
)
{
trace_rdev_crit_proto_stop
(
&
rdev
->
wiphy
,
wdev
);
rdev
->
ops
->
crit_proto_stop
(
&
rdev
->
wiphy
,
wdev
);
trace_rdev_return_void
(
&
rdev
->
wiphy
);
}
#endif
/* __CFG80211_RDEV_OPS */
#endif
/* __CFG80211_RDEV_OPS */
net/wireless/reg.c
浏览文件 @
6475cb05
...
@@ -855,7 +855,7 @@ static void handle_channel(struct wiphy *wiphy,
...
@@ -855,7 +855,7 @@ static void handle_channel(struct wiphy *wiphy,
return
;
return
;
REG_DBG_PRINT
(
"Disabling freq %d MHz
\n
"
,
chan
->
center_freq
);
REG_DBG_PRINT
(
"Disabling freq %d MHz
\n
"
,
chan
->
center_freq
);
chan
->
flags
=
IEEE80211_CHAN_DISABLED
;
chan
->
flags
|
=
IEEE80211_CHAN_DISABLED
;
return
;
return
;
}
}
...
...
net/wireless/trace.h
浏览文件 @
6475cb05
...
@@ -1806,6 +1806,41 @@ TRACE_EVENT(rdev_update_ft_ies,
...
@@ -1806,6 +1806,41 @@ TRACE_EVENT(rdev_update_ft_ies,
WIPHY_PR_ARG
,
NETDEV_PR_ARG
,
__entry
->
md
)
WIPHY_PR_ARG
,
NETDEV_PR_ARG
,
__entry
->
md
)
);
);
TRACE_EVENT
(
rdev_crit_proto_start
,
TP_PROTO
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
enum
nl80211_crit_proto_id
protocol
,
u16
duration
),
TP_ARGS
(
wiphy
,
wdev
,
protocol
,
duration
),
TP_STRUCT__entry
(
WIPHY_ENTRY
WDEV_ENTRY
__field
(
u16
,
proto
)
__field
(
u16
,
duration
)
),
TP_fast_assign
(
WIPHY_ASSIGN
;
WDEV_ASSIGN
;
__entry
->
proto
=
protocol
;
__entry
->
duration
=
duration
;
),
TP_printk
(
WIPHY_PR_FMT
", "
WDEV_PR_FMT
", proto=%x, duration=%u"
,
WIPHY_PR_ARG
,
WDEV_PR_ARG
,
__entry
->
proto
,
__entry
->
duration
)
);
TRACE_EVENT
(
rdev_crit_proto_stop
,
TP_PROTO
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
),
TP_ARGS
(
wiphy
,
wdev
),
TP_STRUCT__entry
(
WIPHY_ENTRY
WDEV_ENTRY
),
TP_fast_assign
(
WIPHY_ASSIGN
;
WDEV_ASSIGN
;
),
TP_printk
(
WIPHY_PR_FMT
", "
WDEV_PR_FMT
,
WIPHY_PR_ARG
,
WDEV_PR_ARG
)
);
/*************************************************************
/*************************************************************
* cfg80211 exported functions traces *
* cfg80211 exported functions traces *
*************************************************************/
*************************************************************/
...
...
net/wireless/util.c
浏览文件 @
6475cb05
...
@@ -1155,6 +1155,26 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
...
@@ -1155,6 +1155,26 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
}
}
EXPORT_SYMBOL
(
cfg80211_get_p2p_attr
);
EXPORT_SYMBOL
(
cfg80211_get_p2p_attr
);
bool
ieee80211_operating_class_to_band
(
u8
operating_class
,
enum
ieee80211_band
*
band
)
{
switch
(
operating_class
)
{
case
112
:
case
115
...
127
:
*
band
=
IEEE80211_BAND_5GHZ
;
return
true
;
case
81
:
case
82
:
case
83
:
case
84
:
*
band
=
IEEE80211_BAND_2GHZ
;
return
true
;
}
return
false
;
}
EXPORT_SYMBOL
(
ieee80211_operating_class_to_band
);
int
cfg80211_validate_beacon_int
(
struct
cfg80211_registered_device
*
rdev
,
int
cfg80211_validate_beacon_int
(
struct
cfg80211_registered_device
*
rdev
,
u32
beacon_int
)
u32
beacon_int
)
{
{
...
@@ -1258,12 +1278,12 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
...
@@ -1258,12 +1278,12 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
list_for_each_entry
(
wdev_iter
,
&
rdev
->
wdev_list
,
list
)
{
list_for_each_entry
(
wdev_iter
,
&
rdev
->
wdev_list
,
list
)
{
if
(
wdev_iter
==
wdev
)
if
(
wdev_iter
==
wdev
)
continue
;
continue
;
if
(
wdev_iter
->
netdev
)
{
if
(
wdev_iter
->
iftype
==
NL80211_IFTYPE_P2P_DEVICE
)
{
if
(
!
netif_running
(
wdev_iter
->
netdev
))
continue
;
}
else
if
(
wdev_iter
->
iftype
==
NL80211_IFTYPE_P2P_DEVICE
)
{
if
(
!
wdev_iter
->
p2p_started
)
if
(
!
wdev_iter
->
p2p_started
)
continue
;
continue
;
}
else
if
(
wdev_iter
->
netdev
)
{
if
(
!
netif_running
(
wdev_iter
->
netdev
))
continue
;
}
else
{
}
else
{
WARN_ON
(
1
);
WARN_ON
(
1
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录