Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
d0746663
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
163
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d0746663
编写于
8月 16, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
上级
41caa760
27b3eb9c
变更
28
隐藏空白更改
内联
并排
Showing
28 changed file
with
707 addition
and
372 deletion
+707
-372
Documentation/DocBook/80211.tmpl
Documentation/DocBook/80211.tmpl
+1
-0
drivers/net/wireless/ath/ath6kl/testmode.c
drivers/net/wireless/ath/ath6kl/testmode.c
+2
-1
drivers/net/wireless/ath/ath6kl/testmode.h
drivers/net/wireless/ath/ath6kl/testmode.h
+5
-2
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+3
-1
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/dvm/tx.c
+1
-1
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwlwifi/iwl-devtrace.h
+4
-3
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
+2
-5
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/tx.c
+4
-5
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mac80211_hwsim.c
+1
-0
drivers/net/wireless/ti/wlcore/testmode.c
drivers/net/wireless/ti/wlcore/testmode.c
+2
-1
drivers/net/wireless/ti/wlcore/testmode.h
drivers/net/wireless/ti/wlcore/testmode.h
+2
-1
include/linux/ieee80211.h
include/linux/ieee80211.h
+4
-0
include/net/cfg80211.h
include/net/cfg80211.h
+3
-2
include/net/mac80211.h
include/net/mac80211.h
+103
-6
net/mac80211/cfg.c
net/mac80211/cfg.c
+13
-2
net/mac80211/ibss.c
net/mac80211/ibss.c
+120
-76
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+0
-3
net/mac80211/key.c
net/mac80211/key.c
+147
-7
net/mac80211/mlme.c
net/mac80211/mlme.c
+9
-0
net/mac80211/rate.c
net/mac80211/rate.c
+16
-7
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rc80211_minstrel_ht.c
+3
-2
net/mac80211/rx.c
net/mac80211/rx.c
+202
-202
net/mac80211/tx.c
net/mac80211/tx.c
+5
-3
net/mac80211/util.c
net/mac80211/util.c
+1
-1
net/rfkill/rfkill-regulator.c
net/rfkill/rfkill-regulator.c
+5
-3
net/wireless/nl80211.c
net/wireless/nl80211.c
+41
-33
net/wireless/rdev-ops.h
net/wireless/rdev-ops.h
+3
-2
net/wireless/trace.h
net/wireless/trace.h
+5
-3
未找到文件。
Documentation/DocBook/80211.tmpl
浏览文件 @
d0746663
...
...
@@ -325,6 +325,7 @@
<title>
functions/definitions
</title>
!Finclude/net/mac80211.h ieee80211_rx_status
!Finclude/net/mac80211.h mac80211_rx_flags
!Finclude/net/mac80211.h mac80211_tx_info_flags
!Finclude/net/mac80211.h mac80211_tx_control_flags
!Finclude/net/mac80211.h mac80211_rate_control_flags
!Finclude/net/mac80211.h ieee80211_tx_rate
...
...
drivers/net/wireless/ath/ath6kl/testmode.c
浏览文件 @
d0746663
...
...
@@ -66,7 +66,8 @@ void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, size_t buf_len)
ath6kl_warn
(
"nla_put failed on testmode rx skb!
\n
"
);
}
int
ath6kl_tm_cmd
(
struct
wiphy
*
wiphy
,
void
*
data
,
int
len
)
int
ath6kl_tm_cmd
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
void
*
data
,
int
len
)
{
struct
ath6kl
*
ar
=
wiphy_priv
(
wiphy
);
struct
nlattr
*
tb
[
ATH6KL_TM_ATTR_MAX
+
1
];
...
...
drivers/net/wireless/ath/ath6kl/testmode.h
浏览文件 @
d0746663
...
...
@@ -20,7 +20,8 @@
#ifdef CONFIG_NL80211_TESTMODE
void
ath6kl_tm_rx_event
(
struct
ath6kl
*
ar
,
void
*
buf
,
size_t
buf_len
);
int
ath6kl_tm_cmd
(
struct
wiphy
*
wiphy
,
void
*
data
,
int
len
);
int
ath6kl_tm_cmd
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
void
*
data
,
int
len
);
#else
...
...
@@ -29,7 +30,9 @@ static inline void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf,
{
}
static
inline
int
ath6kl_tm_cmd
(
struct
wiphy
*
wiphy
,
void
*
data
,
int
len
)
static
inline
int
ath6kl_tm_cmd
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
void
*
data
,
int
len
)
{
return
0
;
}
...
...
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
浏览文件 @
d0746663
...
...
@@ -3155,7 +3155,9 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
}
#ifdef CONFIG_NL80211_TESTMODE
static
int
brcmf_cfg80211_testmode
(
struct
wiphy
*
wiphy
,
void
*
data
,
int
len
)
static
int
brcmf_cfg80211_testmode
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
void
*
data
,
int
len
)
{
struct
brcmf_cfg80211_info
*
cfg
=
wiphy_to_cfg
(
wiphy
);
struct
net_device
*
ndev
=
cfg_to_ndev
(
cfg
);
...
...
drivers/net/wireless/iwlwifi/dvm/tx.c
浏览文件 @
d0746663
...
...
@@ -87,7 +87,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
priv
->
lib
->
bt_params
->
advanced_bt_coexist
&&
(
ieee80211_is_auth
(
fc
)
||
ieee80211_is_assoc_req
(
fc
)
||
ieee80211_is_reassoc_req
(
fc
)
||
skb
->
protocol
==
cpu_to_be16
(
ETH_P_PAE
)
))
info
->
control
.
flags
&
IEEE80211_TX_CTRL_PORT_CTRL_PROTO
))
tx_flags
|=
TX_CMD_FLG_IGNORE_BT
;
...
...
drivers/net/wireless/iwlwifi/iwl-devtrace.h
浏览文件 @
d0746663
...
...
@@ -33,10 +33,11 @@
static
inline
bool
iwl_trace_data
(
struct
sk_buff
*
skb
)
{
struct
ieee80211_hdr
*
hdr
=
(
void
*
)
skb
->
data
;
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
skb
);
if
(
ieee80211_is_data
(
hdr
->
frame_control
))
return
skb
->
protocol
!=
cpu_to_be16
(
ETH_P_PAE
)
;
return
false
;
if
(
!
ieee80211_is_data
(
hdr
->
frame_control
))
return
false
;
return
!
(
info
->
control
.
flags
&
IEEE80211_TX_CTRL_PORT_CTRL_PROTO
)
;
}
static
inline
size_t
iwl_rx_trace_len
(
const
struct
iwl_trans
*
trans
,
...
...
drivers/net/wireless/iwlwifi/mvm/time-event.c
浏览文件 @
d0746663
...
...
@@ -73,7 +73,6 @@
#include "iwl-prph.h"
/* A TimeUnit is 1024 microsecond */
#define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024))
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
/*
...
...
@@ -191,8 +190,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
iwl_mvm_te_clear_data
(
mvm
,
te_data
);
}
else
if
(
le32_to_cpu
(
notif
->
action
)
&
TE_NOTIF_HOST_EVENT_START
)
{
te_data
->
running
=
true
;
te_data
->
end_jiffies
=
jiffies
+
TU_TO_JIFFIES
(
te_data
->
duration
);
te_data
->
end_jiffies
=
TU_TO_EXP_TIME
(
te_data
->
duration
);
if
(
te_data
->
vif
->
type
==
NL80211_IFTYPE_P2P_DEVICE
)
{
set_bit
(
IWL_MVM_STATUS_ROC_RUNNING
,
&
mvm
->
status
);
...
...
@@ -329,8 +327,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
lockdep_assert_held
(
&
mvm
->
mutex
);
if
(
te_data
->
running
&&
time_after
(
te_data
->
end_jiffies
,
jiffies
+
TU_TO_JIFFIES
(
min_duration
)))
{
time_after
(
te_data
->
end_jiffies
,
TU_TO_EXP_TIME
(
min_duration
)))
{
IWL_DEBUG_TE
(
mvm
,
"We have enough time in the current TE: %u
\n
"
,
jiffies_to_msecs
(
te_data
->
end_jiffies
-
jiffies
));
return
;
...
...
drivers/net/wireless/iwlwifi/mvm/tx.c
浏览文件 @
d0746663
...
...
@@ -91,11 +91,10 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
tx_flags
|=
TX_CMD_FLG_ACK
|
TX_CMD_FLG_BAR
;
/* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */
if
(
info
->
band
==
IEEE80211_BAND_2GHZ
&&
(
skb
->
protocol
==
cpu_to_be16
(
ETH_P_PAE
)
||
is_multicast_ether_addr
(
hdr
->
addr1
)
||
ieee80211_is_back_req
(
fc
)
||
ieee80211_is_mgmt
(
fc
)))
if
(
info
->
band
==
IEEE80211_BAND_2GHZ
&&
(
info
->
control
.
flags
&
IEEE80211_TX_CTRL_PORT_CTRL_PROTO
||
is_multicast_ether_addr
(
hdr
->
addr1
)
||
ieee80211_is_back_req
(
fc
)
||
ieee80211_is_mgmt
(
fc
)))
tx_flags
|=
TX_CMD_FLG_BT_DIS
;
if
(
ieee80211_has_morefrags
(
fc
))
...
...
drivers/net/wireless/mac80211_hwsim.c
浏览文件 @
d0746663
...
...
@@ -1364,6 +1364,7 @@ static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = {
static
int
hwsim_fops_ps_write
(
void
*
dat
,
u64
val
);
static
int
mac80211_hwsim_testmode_cmd
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
void
*
data
,
int
len
)
{
struct
mac80211_hwsim_data
*
hwsim
=
hw
->
priv
;
...
...
drivers/net/wireless/ti/wlcore/testmode.c
浏览文件 @
d0746663
...
...
@@ -356,7 +356,8 @@ static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
return
ret
;
}
int
wl1271_tm_cmd
(
struct
ieee80211_hw
*
hw
,
void
*
data
,
int
len
)
int
wl1271_tm_cmd
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
void
*
data
,
int
len
)
{
struct
wl1271
*
wl
=
hw
->
priv
;
struct
nlattr
*
tb
[
WL1271_TM_ATTR_MAX
+
1
];
...
...
drivers/net/wireless/ti/wlcore/testmode.h
浏览文件 @
d0746663
...
...
@@ -26,6 +26,7 @@
#include <net/mac80211.h>
int
wl1271_tm_cmd
(
struct
ieee80211_hw
*
hw
,
void
*
data
,
int
len
);
int
wl1271_tm_cmd
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
void
*
data
,
int
len
);
#endif
/* __WL1271_TESTMODE_H__ */
include/linux/ieee80211.h
浏览文件 @
d0746663
...
...
@@ -2288,4 +2288,8 @@ static inline bool ieee80211_check_tim(const struct ieee80211_tim_ie *tim,
return
!!
(
tim
->
virtual_map
[
index
]
&
mask
);
}
/* convert time units */
#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
#endif
/* LINUX_IEEE80211_H */
include/net/cfg80211.h
浏览文件 @
d0746663
...
...
@@ -2081,7 +2081,7 @@ struct cfg80211_update_ft_ies_params {
* @mgmt_tx_cancel_wait: Cancel the wait time from transmitting a management
* frame on another channel
*
* @testmode_cmd: run a test mode command
* @testmode_cmd: run a test mode command
; @wdev may be %NULL
* @testmode_dump: Implement a test mode dump. The cb->args[2] and up may be
* used by the function, but 0 and 1 must not be touched. Additionally,
* return error codes other than -ENOBUFS and -ENOENT will terminate the
...
...
@@ -2290,7 +2290,8 @@ struct cfg80211_ops {
void
(
*
rfkill_poll
)(
struct
wiphy
*
wiphy
);
#ifdef CONFIG_NL80211_TESTMODE
int
(
*
testmode_cmd
)(
struct
wiphy
*
wiphy
,
void
*
data
,
int
len
);
int
(
*
testmode_cmd
)(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
void
*
data
,
int
len
);
int
(
*
testmode_dump
)(
struct
wiphy
*
wiphy
,
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
,
void
*
data
,
int
len
);
...
...
include/net/mac80211.h
浏览文件 @
d0746663
...
...
@@ -375,7 +375,7 @@ struct ieee80211_bss_conf {
};
/**
* enum mac80211_tx_
control
_flags - flags to describe transmission information/status
* enum mac80211_tx_
info
_flags - flags to describe transmission information/status
*
* These flags are used with the @flags member of &ieee80211_tx_info.
*
...
...
@@ -471,7 +471,7 @@ struct ieee80211_bss_conf {
* Note: If you have to add new flags to the enumeration, then don't
* forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
*/
enum
mac80211_tx_
control
_flags
{
enum
mac80211_tx_
info
_flags
{
IEEE80211_TX_CTL_REQ_TX_STATUS
=
BIT
(
0
),
IEEE80211_TX_CTL_ASSIGN_SEQ
=
BIT
(
1
),
IEEE80211_TX_CTL_NO_ACK
=
BIT
(
2
),
...
...
@@ -507,6 +507,18 @@ enum mac80211_tx_control_flags {
#define IEEE80211_TX_CTL_STBC_SHIFT 23
/**
* enum mac80211_tx_control_flags - flags to describe transmit control
*
* @IEEE80211_TX_CTRL_PORT_CTRL_PROTO: this frame is a port control
* protocol frame (e.g. EAP)
*
* These flags are used in tx_info->control.flags.
*/
enum
mac80211_tx_control_flags
{
IEEE80211_TX_CTRL_PORT_CTRL_PROTO
=
BIT
(
0
),
};
/*
* This definition is used as a mask to clear all temporary flags, which are
* set by the tx handlers for each transmission attempt by the mac80211 stack.
...
...
@@ -680,7 +692,8 @@ struct ieee80211_tx_info {
/* NB: vif can be NULL for injected frames */
struct
ieee80211_vif
*
vif
;
struct
ieee80211_key_conf
*
hw_key
;
/* 8 bytes free */
u32
flags
;
/* 4 bytes free */
}
control
;
struct
{
struct
ieee80211_tx_rate
rates
[
IEEE80211_TX_MAX_RATES
];
...
...
@@ -2503,8 +2516,8 @@ enum ieee80211_roc_type {
* in IEEE 802.11-2007 section 17.3.8.6 and modify ACK timeout
* accordingly. This callback is not required and may sleep.
*
* @testmode_cmd: Implement a cfg80211 test mode command.
* The callback can sleep.
* @testmode_cmd: Implement a cfg80211 test mode command.
The passed @vif may
*
be %NULL.
The callback can sleep.
* @testmode_dump: Implement a cfg80211 test mode dump. The callback can sleep.
*
* @flush: Flush all pending frames from the hardware queue, making sure
...
...
@@ -2765,7 +2778,8 @@ struct ieee80211_ops {
void
(
*
rfkill_poll
)(
struct
ieee80211_hw
*
hw
);
void
(
*
set_coverage_class
)(
struct
ieee80211_hw
*
hw
,
u8
coverage_class
);
#ifdef CONFIG_NL80211_TESTMODE
int
(
*
testmode_cmd
)(
struct
ieee80211_hw
*
hw
,
void
*
data
,
int
len
);
int
(
*
testmode_cmd
)(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
void
*
data
,
int
len
);
int
(
*
testmode_dump
)(
struct
ieee80211_hw
*
hw
,
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
,
void
*
data
,
int
len
);
...
...
@@ -3673,6 +3687,89 @@ void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
void
ieee80211_get_key_rx_seq
(
struct
ieee80211_key_conf
*
keyconf
,
int
tid
,
struct
ieee80211_key_seq
*
seq
);
/**
* ieee80211_set_key_tx_seq - set key TX sequence counter
*
* @keyconf: the parameter passed with the set key
* @seq: new sequence data
*
* This function allows a driver to set the current TX IV/PNs for the
* given key. This is useful when resuming from WoWLAN sleep and the
* device may have transmitted frames using the PTK, e.g. replies to
* ARP requests.
*
* Note that this function may only be called when no TX processing
* can be done concurrently.
*/
void
ieee80211_set_key_tx_seq
(
struct
ieee80211_key_conf
*
keyconf
,
struct
ieee80211_key_seq
*
seq
);
/**
* ieee80211_set_key_rx_seq - set key RX sequence counter
*
* @keyconf: the parameter passed with the set key
* @tid: The TID, or -1 for the management frame value (CCMP only);
* the value on TID 0 is also used for non-QoS frames. For
* CMAC, only TID 0 is valid.
* @seq: new sequence data
*
* This function allows a driver to set the current RX IV/PNs for the
* given key. This is useful when resuming from WoWLAN sleep and GTK
* rekey may have been done while suspended. It should not be called
* if IV checking is done by the device and not by mac80211.
*
* Note that this function may only be called when no RX processing
* can be done concurrently.
*/
void
ieee80211_set_key_rx_seq
(
struct
ieee80211_key_conf
*
keyconf
,
int
tid
,
struct
ieee80211_key_seq
*
seq
);
/**
* ieee80211_remove_key - remove the given key
* @keyconf: the parameter passed with the set key
*
* Remove the given key. If the key was uploaded to the hardware at the
* time this function is called, it is not deleted in the hardware but
* instead assumed to have been removed already.
*
* Note that due to locking considerations this function can (currently)
* only be called during key iteration (ieee80211_iter_keys().)
*/
void
ieee80211_remove_key
(
struct
ieee80211_key_conf
*
keyconf
);
/**
* ieee80211_gtk_rekey_add - add a GTK key from rekeying during WoWLAN
* @vif: the virtual interface to add the key on
* @keyconf: new key data
*
* When GTK rekeying was done while the system was suspended, (a) new
* key(s) will be available. These will be needed by mac80211 for proper
* RX processing, so this function allows setting them.
*
* The function returns the newly allocated key structure, which will
* have similar contents to the passed key configuration but point to
* mac80211-owned memory. In case of errors, the function returns an
* ERR_PTR(), use IS_ERR() etc.
*
* Note that this function assumes the key isn't added to hardware
* acceleration, so no TX will be done with the key. Since it's a GTK
* on managed (station) networks, this is true anyway. If the driver
* calls this function from the resume callback and subsequently uses
* the return code 1 to reconfigure the device, this key will be part
* of the reconfiguration.
*
* Note that the driver should also call ieee80211_set_key_rx_seq()
* for the new key for each TID to set up sequence counters properly.
*
* IMPORTANT: If this replaces a key that is present in the hardware,
* then it will attempt to remove it during this call. In many cases
* this isn't what you want, so call ieee80211_remove_key() first for
* the key that's being replaced.
*/
struct
ieee80211_key_conf
*
ieee80211_gtk_rekey_add
(
struct
ieee80211_vif
*
vif
,
struct
ieee80211_key_conf
*
keyconf
);
/**
* ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying
* @vif: virtual interface the rekeying was done on
...
...
net/mac80211/cfg.c
浏览文件 @
d0746663
...
...
@@ -2302,14 +2302,25 @@ static void ieee80211_rfkill_poll(struct wiphy *wiphy)
}
#ifdef CONFIG_NL80211_TESTMODE
static
int
ieee80211_testmode_cmd
(
struct
wiphy
*
wiphy
,
void
*
data
,
int
len
)
static
int
ieee80211_testmode_cmd
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
void
*
data
,
int
len
)
{
struct
ieee80211_local
*
local
=
wiphy_priv
(
wiphy
);
struct
ieee80211_vif
*
vif
=
NULL
;
if
(
!
local
->
ops
->
testmode_cmd
)
return
-
EOPNOTSUPP
;
return
local
->
ops
->
testmode_cmd
(
&
local
->
hw
,
data
,
len
);
if
(
wdev
)
{
struct
ieee80211_sub_if_data
*
sdata
;
sdata
=
IEEE80211_WDEV_TO_SUB_IF
(
wdev
);
if
(
sdata
->
flags
&
IEEE80211_SDATA_IN_DRIVER
)
vif
=
&
sdata
->
vif
;
}
return
local
->
ops
->
testmode_cmd
(
&
local
->
hw
,
vif
,
data
,
len
);
}
static
int
ieee80211_testmode_dump
(
struct
wiphy
*
wiphy
,
...
...
net/mac80211/ibss.c
浏览文件 @
d0746663
...
...
@@ -34,13 +34,12 @@
#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
static
void
__ieee80211_sta_join_ibss
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
bssid
,
const
int
beacon_int
,
struct
ieee80211_channel
*
chan
,
const
u32
basic_rates
,
const
u16
capability
,
u64
tsf
,
bool
creator
)
static
struct
beacon_data
*
ieee80211_ibss_build_presp
(
struct
ieee80211_sub_if_data
*
sdata
,
const
int
beacon_int
,
const
u32
basic_rates
,
const
u16
capability
,
u64
tsf
,
struct
cfg80211_chan_def
*
chandef
,
bool
*
have_higher_than_11mbit
)
{
struct
ieee80211_if_ibss
*
ifibss
=
&
sdata
->
u
.
ibss
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
...
...
@@ -48,70 +47,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct
ieee80211_mgmt
*
mgmt
;
u8
*
pos
;
struct
ieee80211_supported_band
*
sband
;
struct
cfg80211_bss
*
bss
;
u32
bss_change
,
rate_flags
,
rates
=
0
,
rates_added
=
0
;
struct
cfg80211_chan_def
chandef
;
enum
nl80211_bss_scan_width
scan_width
;
bool
have_higher_than_11mbit
=
false
;
u32
rate_flags
,
rates
=
0
,
rates_added
=
0
;
struct
beacon_data
*
presp
;
int
frame_len
;
int
shift
;
sdata_assert_lock
(
sdata
);
/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf
(
local
,
sdata
);
if
(
!
ether_addr_equal
(
ifibss
->
bssid
,
bssid
))
sta_info_flush
(
sdata
);
/* if merging, indicate to driver that we leave the old IBSS */
if
(
sdata
->
vif
.
bss_conf
.
ibss_joined
)
{
sdata
->
vif
.
bss_conf
.
ibss_joined
=
false
;
sdata
->
vif
.
bss_conf
.
ibss_creator
=
false
;
sdata
->
vif
.
bss_conf
.
enable_beacon
=
false
;
netif_carrier_off
(
sdata
->
dev
);
ieee80211_bss_info_change_notify
(
sdata
,
BSS_CHANGED_IBSS
|
BSS_CHANGED_BEACON_ENABLED
);
}
presp
=
rcu_dereference_protected
(
ifibss
->
presp
,
lockdep_is_held
(
&
sdata
->
wdev
.
mtx
));
rcu_assign_pointer
(
ifibss
->
presp
,
NULL
);
if
(
presp
)
kfree_rcu
(
presp
,
rcu_head
);
sdata
->
drop_unencrypted
=
capability
&
WLAN_CAPABILITY_PRIVACY
?
1
:
0
;
chandef
=
ifibss
->
chandef
;
if
(
!
cfg80211_reg_can_beacon
(
local
->
hw
.
wiphy
,
&
chandef
))
{
if
(
chandef
.
width
==
NL80211_CHAN_WIDTH_5
||
chandef
.
width
==
NL80211_CHAN_WIDTH_10
||
chandef
.
width
==
NL80211_CHAN_WIDTH_20_NOHT
||
chandef
.
width
==
NL80211_CHAN_WIDTH_20
)
{
sdata_info
(
sdata
,
"Failed to join IBSS, beacons forbidden
\n
"
);
return
;
}
chandef
.
width
=
NL80211_CHAN_WIDTH_20
;
chandef
.
center_freq1
=
chan
->
center_freq
;
}
ieee80211_vif_release_channel
(
sdata
);
if
(
ieee80211_vif_use_channel
(
sdata
,
&
chandef
,
ifibss
->
fixed_channel
?
IEEE80211_CHANCTX_SHARED
:
IEEE80211_CHANCTX_EXCLUSIVE
))
{
sdata_info
(
sdata
,
"Failed to join IBSS, no channel context
\n
"
);
return
;
}
memcpy
(
ifibss
->
bssid
,
bssid
,
ETH_ALEN
);
sband
=
local
->
hw
.
wiphy
->
bands
[
chan
->
band
];
shift
=
ieee80211_vif_get_shift
(
&
sdata
->
vif
);
/* Build IBSS probe response */
frame_len
=
sizeof
(
struct
ieee80211_hdr_3addr
)
+
12
/* struct ieee80211_mgmt.u.beacon */
+
...
...
@@ -125,7 +65,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
ifibss
->
ie_len
;
presp
=
kzalloc
(
sizeof
(
*
presp
)
+
frame_len
,
GFP_KERNEL
);
if
(
!
presp
)
return
;
return
NULL
;
presp
->
head
=
(
void
*
)(
presp
+
1
);
...
...
@@ -146,12 +86,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
memcpy
(
pos
,
ifibss
->
ssid
,
ifibss
->
ssid_len
);
pos
+=
ifibss
->
ssid_len
;
rate_flags
=
ieee80211_chandef_rate_flags
(
&
chandef
);
sband
=
local
->
hw
.
wiphy
->
bands
[
chandef
->
chan
->
band
];
rate_flags
=
ieee80211_chandef_rate_flags
(
chandef
);
shift
=
ieee80211_chandef_get_shift
(
chandef
);
rates_n
=
0
;
if
(
have_higher_than_11mbit
)
*
have_higher_than_11mbit
=
false
;
for
(
i
=
0
;
i
<
sband
->
n_bitrates
;
i
++
)
{
if
((
rate_flags
&
sband
->
bitrates
[
i
].
flags
)
!=
rate_flags
)
continue
;
if
(
sband
->
bitrates
[
i
].
bitrate
>
110
)
have_higher_than_11mbit
=
true
;
if
(
sband
->
bitrates
[
i
].
bitrate
>
110
&&
have_higher_than_11mbit
)
*
have_higher_than_11mbit
=
true
;
rates
|=
BIT
(
i
);
rates_n
++
;
...
...
@@ -178,7 +125,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
if
(
sband
->
band
==
IEEE80211_BAND_2GHZ
)
{
*
pos
++
=
WLAN_EID_DS_PARAMS
;
*
pos
++
=
1
;
*
pos
++
=
ieee80211_frequency_to_channel
(
chan
->
center_freq
);
*
pos
++
=
ieee80211_frequency_to_channel
(
chandef
->
chan
->
center_freq
);
}
*
pos
++
=
WLAN_EID_IBSS_PARAMS
;
...
...
@@ -210,9 +158,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
}
/* add HT capability and information IEs */
if
(
chandef
.
width
!=
NL80211_CHAN_WIDTH_20_NOHT
&&
chandef
.
width
!=
NL80211_CHAN_WIDTH_5
&&
chandef
.
width
!=
NL80211_CHAN_WIDTH_10
&&
if
(
chandef
->
width
!=
NL80211_CHAN_WIDTH_20_NOHT
&&
chandef
->
width
!=
NL80211_CHAN_WIDTH_5
&&
chandef
->
width
!=
NL80211_CHAN_WIDTH_10
&&
sband
->
ht_cap
.
ht_supported
)
{
struct
ieee80211_sta_ht_cap
ht_cap
;
...
...
@@ -226,7 +174,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
* keep them at 0
*/
pos
=
ieee80211_ie_build_ht_oper
(
pos
,
&
sband
->
ht_cap
,
&
chandef
,
0
);
chandef
,
0
);
}
if
(
local
->
hw
.
queues
>=
IEEE80211_NUM_ACS
)
{
...
...
@@ -243,9 +191,94 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
presp
->
head_len
=
pos
-
presp
->
head
;
if
(
WARN_ON
(
presp
->
head_len
>
frame_len
))
goto
error
;
return
presp
;
error:
kfree
(
presp
);
return
NULL
;
}
static
void
__ieee80211_sta_join_ibss
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
bssid
,
const
int
beacon_int
,
struct
ieee80211_channel
*
chan
,
const
u32
basic_rates
,
const
u16
capability
,
u64
tsf
,
bool
creator
)
{
struct
ieee80211_if_ibss
*
ifibss
=
&
sdata
->
u
.
ibss
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_supported_band
*
sband
;
struct
ieee80211_mgmt
*
mgmt
;
struct
cfg80211_bss
*
bss
;
u32
bss_change
;
struct
cfg80211_chan_def
chandef
;
struct
beacon_data
*
presp
;
enum
nl80211_bss_scan_width
scan_width
;
bool
have_higher_than_11mbit
;
sdata_assert_lock
(
sdata
);
/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf
(
local
,
sdata
);
if
(
!
ether_addr_equal
(
ifibss
->
bssid
,
bssid
))
sta_info_flush
(
sdata
);
/* if merging, indicate to driver that we leave the old IBSS */
if
(
sdata
->
vif
.
bss_conf
.
ibss_joined
)
{
sdata
->
vif
.
bss_conf
.
ibss_joined
=
false
;
sdata
->
vif
.
bss_conf
.
ibss_creator
=
false
;
sdata
->
vif
.
bss_conf
.
enable_beacon
=
false
;
netif_carrier_off
(
sdata
->
dev
);
ieee80211_bss_info_change_notify
(
sdata
,
BSS_CHANGED_IBSS
|
BSS_CHANGED_BEACON_ENABLED
);
}
presp
=
rcu_dereference_protected
(
ifibss
->
presp
,
lockdep_is_held
(
&
sdata
->
wdev
.
mtx
));
rcu_assign_pointer
(
ifibss
->
presp
,
NULL
);
if
(
presp
)
kfree_rcu
(
presp
,
rcu_head
);
sdata
->
drop_unencrypted
=
capability
&
WLAN_CAPABILITY_PRIVACY
?
1
:
0
;
chandef
=
ifibss
->
chandef
;
if
(
!
cfg80211_reg_can_beacon
(
local
->
hw
.
wiphy
,
&
chandef
))
{
if
(
chandef
.
width
==
NL80211_CHAN_WIDTH_5
||
chandef
.
width
==
NL80211_CHAN_WIDTH_10
||
chandef
.
width
==
NL80211_CHAN_WIDTH_20_NOHT
||
chandef
.
width
==
NL80211_CHAN_WIDTH_20
)
{
sdata_info
(
sdata
,
"Failed to join IBSS, beacons forbidden
\n
"
);
return
;
}
chandef
.
width
=
NL80211_CHAN_WIDTH_20
;
chandef
.
center_freq1
=
chan
->
center_freq
;
}
ieee80211_vif_release_channel
(
sdata
);
if
(
ieee80211_vif_use_channel
(
sdata
,
&
chandef
,
ifibss
->
fixed_channel
?
IEEE80211_CHANCTX_SHARED
:
IEEE80211_CHANCTX_EXCLUSIVE
))
{
sdata_info
(
sdata
,
"Failed to join IBSS, no channel context
\n
"
);
return
;
}
memcpy
(
ifibss
->
bssid
,
bssid
,
ETH_ALEN
);
sband
=
local
->
hw
.
wiphy
->
bands
[
chan
->
band
];
presp
=
ieee80211_ibss_build_presp
(
sdata
,
beacon_int
,
basic_rates
,
capability
,
tsf
,
&
chandef
,
&
have_higher_than_11mbit
);
if
(
!
presp
)
return
;
rcu_assign_pointer
(
ifibss
->
presp
,
presp
);
mgmt
=
(
void
*
)
presp
->
head
;
sdata
->
vif
.
bss_conf
.
enable_beacon
=
true
;
sdata
->
vif
.
bss_conf
.
beacon_int
=
beacon_int
;
...
...
@@ -891,6 +924,17 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
return
;
}
/* if a fixed bssid and a fixed freq have been provided create the IBSS
* directly and do not waste time scanning
*/
if
(
ifibss
->
fixed_bssid
&&
ifibss
->
fixed_channel
)
{
sdata_info
(
sdata
,
"Created IBSS using preconfigured BSSID %pM
\n
"
,
bssid
);
ieee80211_sta_create_ibss
(
sdata
);
return
;
}
ibss_dbg
(
sdata
,
"sta_find_ibss: did not try to join ibss
\n
"
);
/* Selected IBSS not found in current scan results - try to scan */
...
...
net/mac80211/ieee80211_i.h
浏览文件 @
d0746663
...
...
@@ -53,9 +53,6 @@ struct ieee80211_local;
* increased memory use (about 2 kB of RAM per entry). */
#define IEEE80211_FRAGMENT_MAX 4
#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
/* power level hasn't been configured (or set to automatic) */
#define IEEE80211_UNSET_POWER_LEVEL INT_MIN
...
...
net/mac80211/key.c
浏览文件 @
d0746663
...
...
@@ -93,6 +93,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
might_sleep
();
if
(
key
->
flags
&
KEY_FLAG_TAINTED
)
return
-
EINVAL
;
if
(
!
key
->
local
->
ops
->
set_key
)
goto
out_unsupported
;
...
...
@@ -455,6 +458,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
struct
ieee80211_sub_if_data
*
sdata
,
struct
sta_info
*
sta
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_key
*
old_key
;
int
idx
,
ret
;
bool
pairwise
;
...
...
@@ -484,10 +488,13 @@ int ieee80211_key_link(struct ieee80211_key *key,
ieee80211_debugfs_key_add
(
key
);
ret
=
ieee80211_key_enable_hw_accel
(
key
);
if
(
ret
)
ieee80211_key_free
(
key
,
true
);
if
(
!
local
->
wowlan
)
{
ret
=
ieee80211_key_enable_hw_accel
(
key
);
if
(
ret
)
ieee80211_key_free
(
key
,
true
);
}
else
{
ret
=
0
;
}
mutex_unlock
(
&
sdata
->
local
->
key_mtx
);
...
...
@@ -540,7 +547,7 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
void
*
iter_data
)
{
struct
ieee80211_local
*
local
=
hw_to_local
(
hw
);
struct
ieee80211_key
*
key
;
struct
ieee80211_key
*
key
,
*
tmp
;
struct
ieee80211_sub_if_data
*
sdata
;
ASSERT_RTNL
();
...
...
@@ -548,13 +555,14 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
mutex_lock
(
&
local
->
key_mtx
);
if
(
vif
)
{
sdata
=
vif_to_sdata
(
vif
);
list_for_each_entry
(
key
,
&
sdata
->
key_list
,
list
)
list_for_each_entry
_safe
(
key
,
tmp
,
&
sdata
->
key_list
,
list
)
iter
(
hw
,
&
sdata
->
vif
,
key
->
sta
?
&
key
->
sta
->
sta
:
NULL
,
&
key
->
conf
,
iter_data
);
}
else
{
list_for_each_entry
(
sdata
,
&
local
->
interfaces
,
list
)
list_for_each_entry
(
key
,
&
sdata
->
key_list
,
list
)
list_for_each_entry_safe
(
key
,
tmp
,
&
sdata
->
key_list
,
list
)
iter
(
hw
,
&
sdata
->
vif
,
key
->
sta
?
&
key
->
sta
->
sta
:
NULL
,
&
key
->
conf
,
iter_data
);
...
...
@@ -751,3 +759,135 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
}
}
EXPORT_SYMBOL
(
ieee80211_get_key_rx_seq
);
void
ieee80211_set_key_tx_seq
(
struct
ieee80211_key_conf
*
keyconf
,
struct
ieee80211_key_seq
*
seq
)
{
struct
ieee80211_key
*
key
;
u64
pn64
;
key
=
container_of
(
keyconf
,
struct
ieee80211_key
,
conf
);
switch
(
key
->
conf
.
cipher
)
{
case
WLAN_CIPHER_SUITE_TKIP
:
key
->
u
.
tkip
.
tx
.
iv32
=
seq
->
tkip
.
iv32
;
key
->
u
.
tkip
.
tx
.
iv16
=
seq
->
tkip
.
iv16
;
break
;
case
WLAN_CIPHER_SUITE_CCMP
:
pn64
=
(
u64
)
seq
->
ccmp
.
pn
[
5
]
|
((
u64
)
seq
->
ccmp
.
pn
[
4
]
<<
8
)
|
((
u64
)
seq
->
ccmp
.
pn
[
3
]
<<
16
)
|
((
u64
)
seq
->
ccmp
.
pn
[
2
]
<<
24
)
|
((
u64
)
seq
->
ccmp
.
pn
[
1
]
<<
32
)
|
((
u64
)
seq
->
ccmp
.
pn
[
0
]
<<
40
);
atomic64_set
(
&
key
->
u
.
ccmp
.
tx_pn
,
pn64
);
break
;
case
WLAN_CIPHER_SUITE_AES_CMAC
:
pn64
=
(
u64
)
seq
->
aes_cmac
.
pn
[
5
]
|
((
u64
)
seq
->
aes_cmac
.
pn
[
4
]
<<
8
)
|
((
u64
)
seq
->
aes_cmac
.
pn
[
3
]
<<
16
)
|
((
u64
)
seq
->
aes_cmac
.
pn
[
2
]
<<
24
)
|
((
u64
)
seq
->
aes_cmac
.
pn
[
1
]
<<
32
)
|
((
u64
)
seq
->
aes_cmac
.
pn
[
0
]
<<
40
);
atomic64_set
(
&
key
->
u
.
aes_cmac
.
tx_pn
,
pn64
);
break
;
default:
WARN_ON
(
1
);
break
;
}
}
EXPORT_SYMBOL_GPL
(
ieee80211_set_key_tx_seq
);
void
ieee80211_set_key_rx_seq
(
struct
ieee80211_key_conf
*
keyconf
,
int
tid
,
struct
ieee80211_key_seq
*
seq
)
{
struct
ieee80211_key
*
key
;
u8
*
pn
;
key
=
container_of
(
keyconf
,
struct
ieee80211_key
,
conf
);
switch
(
key
->
conf
.
cipher
)
{
case
WLAN_CIPHER_SUITE_TKIP
:
if
(
WARN_ON
(
tid
<
0
||
tid
>=
IEEE80211_NUM_TIDS
))
return
;
key
->
u
.
tkip
.
rx
[
tid
].
iv32
=
seq
->
tkip
.
iv32
;
key
->
u
.
tkip
.
rx
[
tid
].
iv16
=
seq
->
tkip
.
iv16
;
break
;
case
WLAN_CIPHER_SUITE_CCMP
:
if
(
WARN_ON
(
tid
<
-
1
||
tid
>=
IEEE80211_NUM_TIDS
))
return
;
if
(
tid
<
0
)
pn
=
key
->
u
.
ccmp
.
rx_pn
[
IEEE80211_NUM_TIDS
];
else
pn
=
key
->
u
.
ccmp
.
rx_pn
[
tid
];
memcpy
(
pn
,
seq
->
ccmp
.
pn
,
IEEE80211_CCMP_PN_LEN
);
break
;
case
WLAN_CIPHER_SUITE_AES_CMAC
:
if
(
WARN_ON
(
tid
!=
0
))
return
;
pn
=
key
->
u
.
aes_cmac
.
rx_pn
;
memcpy
(
pn
,
seq
->
aes_cmac
.
pn
,
IEEE80211_CMAC_PN_LEN
);
break
;
default:
WARN_ON
(
1
);
break
;
}
}
EXPORT_SYMBOL_GPL
(
ieee80211_set_key_rx_seq
);
void
ieee80211_remove_key
(
struct
ieee80211_key_conf
*
keyconf
)
{
struct
ieee80211_key
*
key
;
key
=
container_of
(
keyconf
,
struct
ieee80211_key
,
conf
);
assert_key_lock
(
key
->
local
);
/*
* if key was uploaded, we assume the driver will/has remove(d)
* it, so adjust bookkeeping accordingly
*/
if
(
key
->
flags
&
KEY_FLAG_UPLOADED_TO_HARDWARE
)
{
key
->
flags
&=
~
KEY_FLAG_UPLOADED_TO_HARDWARE
;
if
(
!
((
key
->
conf
.
flags
&
IEEE80211_KEY_FLAG_GENERATE_MMIC
)
||
(
key
->
conf
.
flags
&
IEEE80211_KEY_FLAG_GENERATE_IV
)
||
(
key
->
conf
.
flags
&
IEEE80211_KEY_FLAG_PUT_IV_SPACE
)))
increment_tailroom_need_count
(
key
->
sdata
);
}
ieee80211_key_free
(
key
,
false
);
}
EXPORT_SYMBOL_GPL
(
ieee80211_remove_key
);
struct
ieee80211_key_conf
*
ieee80211_gtk_rekey_add
(
struct
ieee80211_vif
*
vif
,
struct
ieee80211_key_conf
*
keyconf
)
{
struct
ieee80211_sub_if_data
*
sdata
=
vif_to_sdata
(
vif
);
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_key
*
key
;
int
err
;
if
(
WARN_ON
(
!
local
->
wowlan
))
return
ERR_PTR
(
-
EINVAL
);
if
(
WARN_ON
(
vif
->
type
!=
NL80211_IFTYPE_STATION
))
return
ERR_PTR
(
-
EINVAL
);
key
=
ieee80211_key_alloc
(
keyconf
->
cipher
,
keyconf
->
keyidx
,
keyconf
->
keylen
,
keyconf
->
key
,
0
,
NULL
);
if
(
IS_ERR
(
key
))
return
ERR_PTR
(
PTR_ERR
(
key
));
if
(
sdata
->
u
.
mgd
.
mfp
!=
IEEE80211_MFP_DISABLED
)
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_RX_MGMT
;
err
=
ieee80211_key_link
(
key
,
sdata
,
NULL
);
if
(
err
)
return
ERR_PTR
(
err
);
return
&
key
->
conf
;
}
EXPORT_SYMBOL_GPL
(
ieee80211_gtk_rekey_add
);
net/mac80211/mlme.c
浏览文件 @
d0746663
...
...
@@ -1113,6 +1113,15 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
case
-
1
:
cfg80211_chandef_create
(
&
new_chandef
,
new_chan
,
NL80211_CHAN_NO_HT
);
/* keep width for 5/10 MHz channels */
switch
(
sdata
->
vif
.
bss_conf
.
chandef
.
width
)
{
case
NL80211_CHAN_WIDTH_5
:
case
NL80211_CHAN_WIDTH_10
:
new_chandef
.
width
=
sdata
->
vif
.
bss_conf
.
chandef
.
width
;
break
;
default:
break
;
}
break
;
}
...
...
net/mac80211/rate.c
浏览文件 @
d0746663
...
...
@@ -210,7 +210,7 @@ static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc)
!
ieee80211_is_data
(
fc
);
}
static
void
rc_send_low_b
roadcast
(
s8
*
idx
,
u32
basic_rates
,
static
void
rc_send_low_b
asicrate
(
s8
*
idx
,
u32
basic_rates
,
struct
ieee80211_supported_band
*
sband
)
{
u8
i
;
...
...
@@ -263,28 +263,37 @@ static void __rate_control_send_low(struct ieee80211_hw *hw,
}
bool
rate_control_send_low
(
struct
ieee80211_sta
*
sta
,
bool
rate_control_send_low
(
struct
ieee80211_sta
*
pub
sta
,
void
*
priv_sta
,
struct
ieee80211_tx_rate_control
*
txrc
)
{
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
txrc
->
skb
);
struct
ieee80211_supported_band
*
sband
=
txrc
->
sband
;
struct
sta_info
*
sta
;
int
mcast_rate
;
bool
use_basicrate
=
false
;
if
(
!
sta
||
!
priv_sta
||
rc_no_data_or_no_ack_use_min
(
txrc
))
{
__rate_control_send_low
(
txrc
->
hw
,
sband
,
sta
,
info
);
if
(
!
pub
sta
||
!
priv_sta
||
rc_no_data_or_no_ack_use_min
(
txrc
))
{
__rate_control_send_low
(
txrc
->
hw
,
sband
,
pub
sta
,
info
);
if
(
!
sta
&&
txrc
->
bss
)
{
if
(
!
pub
sta
&&
txrc
->
bss
)
{
mcast_rate
=
txrc
->
bss_conf
->
mcast_rate
[
sband
->
band
];
if
(
mcast_rate
>
0
)
{
info
->
control
.
rates
[
0
].
idx
=
mcast_rate
-
1
;
return
true
;
}
use_basicrate
=
true
;
}
else
if
(
pubsta
)
{
sta
=
container_of
(
pubsta
,
struct
sta_info
,
sta
);
if
(
ieee80211_vif_is_mesh
(
&
sta
->
sdata
->
vif
))
use_basicrate
=
true
;
}
rc_send_low_broadcast
(
&
info
->
control
.
rates
[
0
].
idx
,
if
(
use_basicrate
)
rc_send_low_basicrate
(
&
info
->
control
.
rates
[
0
].
idx
,
txrc
->
bss_conf
->
basic_rates
,
sband
);
}
return
true
;
}
return
false
;
...
...
net/mac80211/rc80211_minstrel_ht.c
浏览文件 @
d0746663
...
...
@@ -439,12 +439,13 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb)
{
struct
ieee80211_hdr
*
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
struct
sta_info
*
sta
=
container_of
(
pubsta
,
struct
sta_info
,
sta
);
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
skb
);
u16
tid
;
if
(
unlikely
(
!
ieee80211_is_data_qos
(
hdr
->
frame_control
)))
return
;
if
(
unlikely
(
skb
->
protocol
==
cpu_to_be16
(
ETH_P_PAE
)
))
if
(
unlikely
(
info
->
control
.
flags
&
IEEE80211_TX_CTRL_PORT_CTRL_PROTO
))
return
;
tid
=
*
ieee80211_get_qos_ctl
(
hdr
)
&
IEEE80211_QOS_CTL_TID_MASK
;
...
...
@@ -776,7 +777,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
/* Don't use EAPOL frames for sampling on non-mrr hw */
if
(
mp
->
hw
->
max_rates
==
1
&&
txrc
->
skb
->
protocol
==
cpu_to_be16
(
ETH_P_PAE
))
(
info
->
control
.
flags
&
IEEE80211_TX_CTRL_PORT_CTRL_PROTO
))
sample_idx
=
-
1
;
else
sample_idx
=
minstrel_get_sample_rate
(
mp
,
mi
);
...
...
net/mac80211/rx.c
浏览文件 @
d0746663
...
...
@@ -1054,207 +1054,6 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
}
static
ieee80211_rx_result
debug_noinline
ieee80211_rx_h_decrypt
(
struct
ieee80211_rx_data
*
rx
)
{
struct
sk_buff
*
skb
=
rx
->
skb
;
struct
ieee80211_rx_status
*
status
=
IEEE80211_SKB_RXCB
(
skb
);
struct
ieee80211_hdr
*
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
int
keyidx
;
int
hdrlen
;
ieee80211_rx_result
result
=
RX_DROP_UNUSABLE
;
struct
ieee80211_key
*
sta_ptk
=
NULL
;
int
mmie_keyidx
=
-
1
;
__le16
fc
;
/*
* Key selection 101
*
* There are four types of keys:
* - GTK (group keys)
* - IGTK (group keys for management frames)
* - PTK (pairwise keys)
* - STK (station-to-station pairwise keys)
*
* When selecting a key, we have to distinguish between multicast
* (including broadcast) and unicast frames, the latter can only
* use PTKs and STKs while the former always use GTKs and IGTKs.
* Unless, of course, actual WEP keys ("pre-RSNA") are used, then
* unicast frames can also use key indices like GTKs. Hence, if we
* don't have a PTK/STK we check the key index for a WEP key.
*
* Note that in a regular BSS, multicast frames are sent by the
* AP only, associated stations unicast the frame to the AP first
* which then multicasts it on their behalf.
*
* There is also a slight problem in IBSS mode: GTKs are negotiated
* with each station, that is something we don't currently handle.
* The spec seems to expect that one negotiates the same key with
* every station but there's no such requirement; VLANs could be
* possible.
*/
/*
* No point in finding a key and decrypting if the frame is neither
* addressed to us nor a multicast frame.
*/
if
(
!
(
status
->
rx_flags
&
IEEE80211_RX_RA_MATCH
))
return
RX_CONTINUE
;
/* start without a key */
rx
->
key
=
NULL
;
if
(
rx
->
sta
)
sta_ptk
=
rcu_dereference
(
rx
->
sta
->
ptk
);
fc
=
hdr
->
frame_control
;
if
(
!
ieee80211_has_protected
(
fc
))
mmie_keyidx
=
ieee80211_get_mmie_keyidx
(
rx
->
skb
);
if
(
!
is_multicast_ether_addr
(
hdr
->
addr1
)
&&
sta_ptk
)
{
rx
->
key
=
sta_ptk
;
if
((
status
->
flag
&
RX_FLAG_DECRYPTED
)
&&
(
status
->
flag
&
RX_FLAG_IV_STRIPPED
))
return
RX_CONTINUE
;
/* Skip decryption if the frame is not protected. */
if
(
!
ieee80211_has_protected
(
fc
))
return
RX_CONTINUE
;
}
else
if
(
mmie_keyidx
>=
0
)
{
/* Broadcast/multicast robust management frame / BIP */
if
((
status
->
flag
&
RX_FLAG_DECRYPTED
)
&&
(
status
->
flag
&
RX_FLAG_IV_STRIPPED
))
return
RX_CONTINUE
;
if
(
mmie_keyidx
<
NUM_DEFAULT_KEYS
||
mmie_keyidx
>=
NUM_DEFAULT_KEYS
+
NUM_DEFAULT_MGMT_KEYS
)
return
RX_DROP_MONITOR
;
/* unexpected BIP keyidx */
if
(
rx
->
sta
)
rx
->
key
=
rcu_dereference
(
rx
->
sta
->
gtk
[
mmie_keyidx
]);
if
(
!
rx
->
key
)
rx
->
key
=
rcu_dereference
(
rx
->
sdata
->
keys
[
mmie_keyidx
]);
}
else
if
(
!
ieee80211_has_protected
(
fc
))
{
/*
* The frame was not protected, so skip decryption. However, we
* need to set rx->key if there is a key that could have been
* used so that the frame may be dropped if encryption would
* have been expected.
*/
struct
ieee80211_key
*
key
=
NULL
;
struct
ieee80211_sub_if_data
*
sdata
=
rx
->
sdata
;
int
i
;
if
(
ieee80211_is_mgmt
(
fc
)
&&
is_multicast_ether_addr
(
hdr
->
addr1
)
&&
(
key
=
rcu_dereference
(
rx
->
sdata
->
default_mgmt_key
)))
rx
->
key
=
key
;
else
{
if
(
rx
->
sta
)
{
for
(
i
=
0
;
i
<
NUM_DEFAULT_KEYS
;
i
++
)
{
key
=
rcu_dereference
(
rx
->
sta
->
gtk
[
i
]);
if
(
key
)
break
;
}
}
if
(
!
key
)
{
for
(
i
=
0
;
i
<
NUM_DEFAULT_KEYS
;
i
++
)
{
key
=
rcu_dereference
(
sdata
->
keys
[
i
]);
if
(
key
)
break
;
}
}
if
(
key
)
rx
->
key
=
key
;
}
return
RX_CONTINUE
;
}
else
{
u8
keyid
;
/*
* The device doesn't give us the IV so we won't be
* able to look up the key. That's ok though, we
* don't need to decrypt the frame, we just won't
* be able to keep statistics accurate.
* Except for key threshold notifications, should
* we somehow allow the driver to tell us which key
* the hardware used if this flag is set?
*/
if
((
status
->
flag
&
RX_FLAG_DECRYPTED
)
&&
(
status
->
flag
&
RX_FLAG_IV_STRIPPED
))
return
RX_CONTINUE
;
hdrlen
=
ieee80211_hdrlen
(
fc
);
if
(
rx
->
skb
->
len
<
8
+
hdrlen
)
return
RX_DROP_UNUSABLE
;
/* TODO: count this? */
/*
* no need to call ieee80211_wep_get_keyidx,
* it verifies a bunch of things we've done already
*/
skb_copy_bits
(
rx
->
skb
,
hdrlen
+
3
,
&
keyid
,
1
);
keyidx
=
keyid
>>
6
;
/* check per-station GTK first, if multicast packet */
if
(
is_multicast_ether_addr
(
hdr
->
addr1
)
&&
rx
->
sta
)
rx
->
key
=
rcu_dereference
(
rx
->
sta
->
gtk
[
keyidx
]);
/* if not found, try default key */
if
(
!
rx
->
key
)
{
rx
->
key
=
rcu_dereference
(
rx
->
sdata
->
keys
[
keyidx
]);
/*
* RSNA-protected unicast frames should always be
* sent with pairwise or station-to-station keys,
* but for WEP we allow using a key index as well.
*/
if
(
rx
->
key
&&
rx
->
key
->
conf
.
cipher
!=
WLAN_CIPHER_SUITE_WEP40
&&
rx
->
key
->
conf
.
cipher
!=
WLAN_CIPHER_SUITE_WEP104
&&
!
is_multicast_ether_addr
(
hdr
->
addr1
))
rx
->
key
=
NULL
;
}
}
if
(
rx
->
key
)
{
if
(
unlikely
(
rx
->
key
->
flags
&
KEY_FLAG_TAINTED
))
return
RX_DROP_MONITOR
;
rx
->
key
->
tx_rx_count
++
;
/* TODO: add threshold stuff again */
}
else
{
return
RX_DROP_MONITOR
;
}
switch
(
rx
->
key
->
conf
.
cipher
)
{
case
WLAN_CIPHER_SUITE_WEP40
:
case
WLAN_CIPHER_SUITE_WEP104
:
result
=
ieee80211_crypto_wep_decrypt
(
rx
);
break
;
case
WLAN_CIPHER_SUITE_TKIP
:
result
=
ieee80211_crypto_tkip_decrypt
(
rx
);
break
;
case
WLAN_CIPHER_SUITE_CCMP
:
result
=
ieee80211_crypto_ccmp_decrypt
(
rx
);
break
;
case
WLAN_CIPHER_SUITE_AES_CMAC
:
result
=
ieee80211_crypto_aes_cmac_decrypt
(
rx
);
break
;
default:
/*
* We can reach here only with HW-only algorithms
* but why didn't it decrypt the frame?!
*/
return
RX_DROP_UNUSABLE
;
}
/* the hdr variable is invalid after the decrypt handlers */
/* either the frame has been decrypted or will be dropped */
status
->
flag
|=
RX_FLAG_DECRYPTED
;
return
result
;
}
static
ieee80211_rx_result
debug_noinline
ieee80211_rx_h_check_more_data
(
struct
ieee80211_rx_data
*
rx
)
{
...
...
@@ -1556,6 +1355,207 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
return
RX_CONTINUE
;
}
/* ieee80211_rx_h_sta_process */
static
ieee80211_rx_result
debug_noinline
ieee80211_rx_h_decrypt
(
struct
ieee80211_rx_data
*
rx
)
{
struct
sk_buff
*
skb
=
rx
->
skb
;
struct
ieee80211_rx_status
*
status
=
IEEE80211_SKB_RXCB
(
skb
);
struct
ieee80211_hdr
*
hdr
=
(
struct
ieee80211_hdr
*
)
skb
->
data
;
int
keyidx
;
int
hdrlen
;
ieee80211_rx_result
result
=
RX_DROP_UNUSABLE
;
struct
ieee80211_key
*
sta_ptk
=
NULL
;
int
mmie_keyidx
=
-
1
;
__le16
fc
;
/*
* Key selection 101
*
* There are four types of keys:
* - GTK (group keys)
* - IGTK (group keys for management frames)
* - PTK (pairwise keys)
* - STK (station-to-station pairwise keys)
*
* When selecting a key, we have to distinguish between multicast
* (including broadcast) and unicast frames, the latter can only
* use PTKs and STKs while the former always use GTKs and IGTKs.
* Unless, of course, actual WEP keys ("pre-RSNA") are used, then
* unicast frames can also use key indices like GTKs. Hence, if we
* don't have a PTK/STK we check the key index for a WEP key.
*
* Note that in a regular BSS, multicast frames are sent by the
* AP only, associated stations unicast the frame to the AP first
* which then multicasts it on their behalf.
*
* There is also a slight problem in IBSS mode: GTKs are negotiated
* with each station, that is something we don't currently handle.
* The spec seems to expect that one negotiates the same key with
* every station but there's no such requirement; VLANs could be
* possible.
*/
/*
* No point in finding a key and decrypting if the frame is neither
* addressed to us nor a multicast frame.
*/
if
(
!
(
status
->
rx_flags
&
IEEE80211_RX_RA_MATCH
))
return
RX_CONTINUE
;
/* start without a key */
rx
->
key
=
NULL
;
if
(
rx
->
sta
)
sta_ptk
=
rcu_dereference
(
rx
->
sta
->
ptk
);
fc
=
hdr
->
frame_control
;
if
(
!
ieee80211_has_protected
(
fc
))
mmie_keyidx
=
ieee80211_get_mmie_keyidx
(
rx
->
skb
);
if
(
!
is_multicast_ether_addr
(
hdr
->
addr1
)
&&
sta_ptk
)
{
rx
->
key
=
sta_ptk
;
if
((
status
->
flag
&
RX_FLAG_DECRYPTED
)
&&
(
status
->
flag
&
RX_FLAG_IV_STRIPPED
))
return
RX_CONTINUE
;
/* Skip decryption if the frame is not protected. */
if
(
!
ieee80211_has_protected
(
fc
))
return
RX_CONTINUE
;
}
else
if
(
mmie_keyidx
>=
0
)
{
/* Broadcast/multicast robust management frame / BIP */
if
((
status
->
flag
&
RX_FLAG_DECRYPTED
)
&&
(
status
->
flag
&
RX_FLAG_IV_STRIPPED
))
return
RX_CONTINUE
;
if
(
mmie_keyidx
<
NUM_DEFAULT_KEYS
||
mmie_keyidx
>=
NUM_DEFAULT_KEYS
+
NUM_DEFAULT_MGMT_KEYS
)
return
RX_DROP_MONITOR
;
/* unexpected BIP keyidx */
if
(
rx
->
sta
)
rx
->
key
=
rcu_dereference
(
rx
->
sta
->
gtk
[
mmie_keyidx
]);
if
(
!
rx
->
key
)
rx
->
key
=
rcu_dereference
(
rx
->
sdata
->
keys
[
mmie_keyidx
]);
}
else
if
(
!
ieee80211_has_protected
(
fc
))
{
/*
* The frame was not protected, so skip decryption. However, we
* need to set rx->key if there is a key that could have been
* used so that the frame may be dropped if encryption would
* have been expected.
*/
struct
ieee80211_key
*
key
=
NULL
;
struct
ieee80211_sub_if_data
*
sdata
=
rx
->
sdata
;
int
i
;
if
(
ieee80211_is_mgmt
(
fc
)
&&
is_multicast_ether_addr
(
hdr
->
addr1
)
&&
(
key
=
rcu_dereference
(
rx
->
sdata
->
default_mgmt_key
)))
rx
->
key
=
key
;
else
{
if
(
rx
->
sta
)
{
for
(
i
=
0
;
i
<
NUM_DEFAULT_KEYS
;
i
++
)
{
key
=
rcu_dereference
(
rx
->
sta
->
gtk
[
i
]);
if
(
key
)
break
;
}
}
if
(
!
key
)
{
for
(
i
=
0
;
i
<
NUM_DEFAULT_KEYS
;
i
++
)
{
key
=
rcu_dereference
(
sdata
->
keys
[
i
]);
if
(
key
)
break
;
}
}
if
(
key
)
rx
->
key
=
key
;
}
return
RX_CONTINUE
;
}
else
{
u8
keyid
;
/*
* The device doesn't give us the IV so we won't be
* able to look up the key. That's ok though, we
* don't need to decrypt the frame, we just won't
* be able to keep statistics accurate.
* Except for key threshold notifications, should
* we somehow allow the driver to tell us which key
* the hardware used if this flag is set?
*/
if
((
status
->
flag
&
RX_FLAG_DECRYPTED
)
&&
(
status
->
flag
&
RX_FLAG_IV_STRIPPED
))
return
RX_CONTINUE
;
hdrlen
=
ieee80211_hdrlen
(
fc
);
if
(
rx
->
skb
->
len
<
8
+
hdrlen
)
return
RX_DROP_UNUSABLE
;
/* TODO: count this? */
/*
* no need to call ieee80211_wep_get_keyidx,
* it verifies a bunch of things we've done already
*/
skb_copy_bits
(
rx
->
skb
,
hdrlen
+
3
,
&
keyid
,
1
);
keyidx
=
keyid
>>
6
;
/* check per-station GTK first, if multicast packet */
if
(
is_multicast_ether_addr
(
hdr
->
addr1
)
&&
rx
->
sta
)
rx
->
key
=
rcu_dereference
(
rx
->
sta
->
gtk
[
keyidx
]);
/* if not found, try default key */
if
(
!
rx
->
key
)
{
rx
->
key
=
rcu_dereference
(
rx
->
sdata
->
keys
[
keyidx
]);
/*
* RSNA-protected unicast frames should always be
* sent with pairwise or station-to-station keys,
* but for WEP we allow using a key index as well.
*/
if
(
rx
->
key
&&
rx
->
key
->
conf
.
cipher
!=
WLAN_CIPHER_SUITE_WEP40
&&
rx
->
key
->
conf
.
cipher
!=
WLAN_CIPHER_SUITE_WEP104
&&
!
is_multicast_ether_addr
(
hdr
->
addr1
))
rx
->
key
=
NULL
;
}
}
if
(
rx
->
key
)
{
if
(
unlikely
(
rx
->
key
->
flags
&
KEY_FLAG_TAINTED
))
return
RX_DROP_MONITOR
;
rx
->
key
->
tx_rx_count
++
;
/* TODO: add threshold stuff again */
}
else
{
return
RX_DROP_MONITOR
;
}
switch
(
rx
->
key
->
conf
.
cipher
)
{
case
WLAN_CIPHER_SUITE_WEP40
:
case
WLAN_CIPHER_SUITE_WEP104
:
result
=
ieee80211_crypto_wep_decrypt
(
rx
);
break
;
case
WLAN_CIPHER_SUITE_TKIP
:
result
=
ieee80211_crypto_tkip_decrypt
(
rx
);
break
;
case
WLAN_CIPHER_SUITE_CCMP
:
result
=
ieee80211_crypto_ccmp_decrypt
(
rx
);
break
;
case
WLAN_CIPHER_SUITE_AES_CMAC
:
result
=
ieee80211_crypto_aes_cmac_decrypt
(
rx
);
break
;
default:
/*
* We can reach here only with HW-only algorithms
* but why didn't it decrypt the frame?!
*/
return
RX_DROP_UNUSABLE
;
}
/* the hdr variable is invalid after the decrypt handlers */
/* either the frame has been decrypted or will be dropped */
status
->
flag
|=
RX_FLAG_DECRYPTED
;
return
result
;
}
static
inline
struct
ieee80211_fragment_entry
*
ieee80211_reassemble_add
(
struct
ieee80211_sub_if_data
*
sdata
,
unsigned
int
frag
,
unsigned
int
seq
,
int
rx_queue
,
...
...
@@ -2939,10 +2939,10 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
*/
rx
->
skb
=
skb
;
CALL_RXH
(
ieee80211_rx_h_decrypt
)
CALL_RXH
(
ieee80211_rx_h_check_more_data
)
CALL_RXH
(
ieee80211_rx_h_uapsd_and_pspoll
)
CALL_RXH
(
ieee80211_rx_h_sta_process
)
CALL_RXH
(
ieee80211_rx_h_decrypt
)
CALL_RXH
(
ieee80211_rx_h_defragment
)
CALL_RXH
(
ieee80211_rx_h_michael_mic_verify
)
/* must be after MMIC verify so header is counted in MPDU mic */
...
...
net/mac80211/tx.c
浏览文件 @
d0746663
...
...
@@ -539,9 +539,11 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
{
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
tx
->
skb
);
if
(
unlikely
(
tx
->
sdata
->
control_port_protocol
==
tx
->
skb
->
protocol
&&
tx
->
sdata
->
control_port_no_encrypt
))
info
->
flags
|=
IEEE80211_TX_INTFL_DONT_ENCRYPT
;
if
(
unlikely
(
tx
->
sdata
->
control_port_protocol
==
tx
->
skb
->
protocol
))
{
if
(
tx
->
sdata
->
control_port_no_encrypt
)
info
->
flags
|=
IEEE80211_TX_INTFL_DONT_ENCRYPT
;
info
->
control
.
flags
|=
IEEE80211_TX_CTRL_PORT_CTRL_PROTO
;
}
return
TX_CONTINUE
;
}
...
...
net/mac80211/util.c
浏览文件 @
d0746663
...
...
@@ -1453,8 +1453,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
local
->
resuming
=
true
;
if
(
local
->
wowlan
)
{
local
->
wowlan
=
false
;
res
=
drv_resume
(
local
);
local
->
wowlan
=
false
;
if
(
res
<
0
)
{
local
->
resuming
=
false
;
return
res
;
...
...
net/rfkill/rfkill-regulator.c
浏览文件 @
d0746663
...
...
@@ -30,6 +30,7 @@ struct rfkill_regulator_data {
static
int
rfkill_regulator_set_block
(
void
*
data
,
bool
blocked
)
{
struct
rfkill_regulator_data
*
rfkill_data
=
data
;
int
ret
=
0
;
pr_debug
(
"%s: blocked: %d
\n
"
,
__func__
,
blocked
);
...
...
@@ -40,15 +41,16 @@ static int rfkill_regulator_set_block(void *data, bool blocked)
}
}
else
{
if
(
!
rfkill_data
->
reg_enabled
)
{
regulator_enable
(
rfkill_data
->
vcc
);
rfkill_data
->
reg_enabled
=
true
;
ret
=
regulator_enable
(
rfkill_data
->
vcc
);
if
(
!
ret
)
rfkill_data
->
reg_enabled
=
true
;
}
}
pr_debug
(
"%s: regulator_is_enabled after set_block: %d
\n
"
,
__func__
,
regulator_is_enabled
(
rfkill_data
->
vcc
));
return
0
;
return
ret
;
}
static
struct
rfkill_ops
rfkill_regulator_ops
=
{
...
...
net/wireless/nl80211.c
浏览文件 @
d0746663
...
...
@@ -6593,19 +6593,30 @@ static struct genl_multicast_group nl80211_testmode_mcgrp = {
static
int
nl80211_testmode_do
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
struct
cfg80211_registered_device
*
rdev
=
info
->
user_ptr
[
0
];
struct
wireless_dev
*
wdev
=
__cfg80211_wdev_from_attrs
(
genl_info_net
(
info
),
info
->
attrs
);
int
err
;
if
(
!
rdev
->
ops
->
testmode_cmd
)
return
-
EOPNOTSUPP
;
if
(
IS_ERR
(
wdev
))
{
err
=
PTR_ERR
(
wdev
);
if
(
err
!=
-
EINVAL
)
return
err
;
wdev
=
NULL
;
}
else
if
(
wdev
->
wiphy
!=
&
rdev
->
wiphy
)
{
return
-
EINVAL
;
}
if
(
!
info
->
attrs
[
NL80211_ATTR_TESTDATA
])
return
-
EINVAL
;
err
=
-
EOPNOTSUPP
;
if
(
rdev
->
ops
->
testmode_cmd
)
{
rdev
->
testmode_info
=
info
;
err
=
rdev_testmode_cmd
(
rdev
,
rdev
->
testmode_info
=
info
;
err
=
rdev_testmode_cmd
(
rdev
,
wdev
,
nla_data
(
info
->
attrs
[
NL80211_ATTR_TESTDATA
]),
nla_len
(
info
->
attrs
[
NL80211_ATTR_TESTDATA
]));
rdev
->
testmode_info
=
NULL
;
}
rdev
->
testmode_info
=
NULL
;
return
err
;
}
...
...
@@ -7566,14 +7577,12 @@ static int nl80211_set_cqm_txe(struct genl_info *info,
u32
rate
,
u32
pkts
,
u32
intvl
)
{
struct
cfg80211_registered_device
*
rdev
=
info
->
user_ptr
[
0
];
struct
wireless_dev
*
wdev
;
struct
net_device
*
dev
=
info
->
user_ptr
[
1
];
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
if
(
rate
>
100
||
intvl
>
NL80211_CQM_TXE_MAX_INTVL
)
return
-
EINVAL
;
wdev
=
dev
->
ieee80211_ptr
;
if
(
!
rdev
->
ops
->
set_cqm_txe_config
)
return
-
EOPNOTSUPP
;
...
...
@@ -7588,13 +7597,15 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
s32
threshold
,
u32
hysteresis
)
{
struct
cfg80211_registered_device
*
rdev
=
info
->
user_ptr
[
0
];
struct
wireless_dev
*
wdev
;
struct
net_device
*
dev
=
info
->
user_ptr
[
1
];
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
if
(
threshold
>
0
)
return
-
EINVAL
;
wdev
=
dev
->
ieee80211_ptr
;
/* disabling - hysteresis should also be zero then */
if
(
threshold
==
0
)
hysteresis
=
0
;
if
(
!
rdev
->
ops
->
set_cqm_rssi_config
)
return
-
EOPNOTSUPP
;
...
...
@@ -7613,36 +7624,33 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
int
err
;
cqm
=
info
->
attrs
[
NL80211_ATTR_CQM
];
if
(
!
cqm
)
{
err
=
-
EINVAL
;
goto
out
;
}
if
(
!
cqm
)
return
-
EINVAL
;
err
=
nla_parse_nested
(
attrs
,
NL80211_ATTR_CQM_MAX
,
cqm
,
nl80211_attr_cqm_policy
);
if
(
err
)
goto
out
;
return
err
;
if
(
attrs
[
NL80211_ATTR_CQM_RSSI_THOLD
]
&&
attrs
[
NL80211_ATTR_CQM_RSSI_HYST
])
{
s32
threshold
;
u32
hysteresis
;
threshold
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_RSSI_THOLD
]);
hysteresis
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_RSSI_HYST
]);
err
=
nl80211_set_cqm_rssi
(
info
,
threshold
,
hysteresis
);
}
else
if
(
attrs
[
NL80211_ATTR_CQM_TXE_RATE
]
&&
attrs
[
NL80211_ATTR_CQM_TXE_PKTS
]
&&
attrs
[
NL80211_ATTR_CQM_TXE_INTVL
])
{
u32
rate
,
pkts
,
intvl
;
rate
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_TXE_RATE
]);
pkts
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_TXE_PKTS
]);
intvl
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_TXE_INTVL
]);
err
=
nl80211_set_cqm_txe
(
info
,
rate
,
pkts
,
intvl
);
}
else
err
=
-
EINVAL
;
s32
threshold
=
nla_get_s32
(
attrs
[
NL80211_ATTR_CQM_RSSI_THOLD
]);
u32
hysteresis
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_RSSI_HYST
]);
out:
return
err
;
return
nl80211_set_cqm_rssi
(
info
,
threshold
,
hysteresis
);
}
if
(
attrs
[
NL80211_ATTR_CQM_TXE_RATE
]
&&
attrs
[
NL80211_ATTR_CQM_TXE_PKTS
]
&&
attrs
[
NL80211_ATTR_CQM_TXE_INTVL
])
{
u32
rate
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_TXE_RATE
]);
u32
pkts
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_TXE_PKTS
]);
u32
intvl
=
nla_get_u32
(
attrs
[
NL80211_ATTR_CQM_TXE_INTVL
]);
return
nl80211_set_cqm_txe
(
info
,
rate
,
pkts
,
intvl
);
}
return
-
EINVAL
;
}
static
int
nl80211_join_mesh
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
...
...
net/wireless/rdev-ops.h
浏览文件 @
d0746663
...
...
@@ -516,11 +516,12 @@ static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev)
#ifdef CONFIG_NL80211_TESTMODE
static
inline
int
rdev_testmode_cmd
(
struct
cfg80211_registered_device
*
rdev
,
struct
wireless_dev
*
wdev
,
void
*
data
,
int
len
)
{
int
ret
;
trace_rdev_testmode_cmd
(
&
rdev
->
wiphy
);
ret
=
rdev
->
ops
->
testmode_cmd
(
&
rdev
->
wiphy
,
data
,
len
);
trace_rdev_testmode_cmd
(
&
rdev
->
wiphy
,
wdev
);
ret
=
rdev
->
ops
->
testmode_cmd
(
&
rdev
->
wiphy
,
wdev
,
data
,
len
);
trace_rdev_return_int
(
&
rdev
->
wiphy
,
ret
);
return
ret
;
}
...
...
net/wireless/trace.h
浏览文件 @
d0746663
...
...
@@ -1293,15 +1293,17 @@ TRACE_EVENT(rdev_return_int_int,
#ifdef CONFIG_NL80211_TESTMODE
TRACE_EVENT
(
rdev_testmode_cmd
,
TP_PROTO
(
struct
wiphy
*
wiphy
),
TP_ARGS
(
wiphy
),
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
,
WIPHY
_PR_ARG
)
TP_printk
(
WIPHY_PR_FMT
WDEV_PR_FMT
,
WIPHY_PR_ARG
,
WDEV
_PR_ARG
)
);
TRACE_EVENT
(
rdev_testmode_dump
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录