Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
9b4e9e75
Commit
9b4e9e75
authored
Sep 24, 2012
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
parents
7a5f799b
9385d04f
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
429 additions
and
334 deletions
+429
-334
drivers/net/wireless/ath/ath5k/mac80211-ops.c
drivers/net/wireless/ath/ath5k/mac80211-ops.c
+1
-1
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
+1
-1
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/main.c
+1
-1
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mac80211_hwsim.c
+1
-4
include/linux/ieee80211.h
include/linux/ieee80211.h
+0
-80
include/net/mac80211.h
include/net/mac80211.h
+10
-2
net/mac80211/cfg.c
net/mac80211/cfg.c
+32
-2
net/mac80211/chan.c
net/mac80211/chan.c
+48
-19
net/mac80211/ibss.c
net/mac80211/ibss.c
+32
-1
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+7
-16
net/mac80211/iface.c
net/mac80211/iface.c
+12
-3
net/mac80211/key.c
net/mac80211/key.c
+1
-1
net/mac80211/main.c
net/mac80211/main.c
+3
-7
net/mac80211/mesh_plink.c
net/mac80211/mesh_plink.c
+2
-1
net/mac80211/mlme.c
net/mac80211/mlme.c
+115
-90
net/mac80211/offchannel.c
net/mac80211/offchannel.c
+1
-2
net/mac80211/scan.c
net/mac80211/scan.c
+15
-26
net/mac80211/sta_info.c
net/mac80211/sta_info.c
+67
-54
net/mac80211/sta_info.h
net/mac80211/sta_info.h
+2
-0
net/mac80211/status.c
net/mac80211/status.c
+30
-18
net/mac80211/tx.c
net/mac80211/tx.c
+1
-1
net/mac80211/util.c
net/mac80211/util.c
+47
-4
No files found.
drivers/net/wireless/ath/ath5k/mac80211-ops.c
View file @
9b4e9e75
...
...
@@ -523,7 +523,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if
(
key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
key
->
flags
|=
IEEE80211_KEY_FLAG_GENERATE_MMIC
;
if
(
key
->
cipher
==
WLAN_CIPHER_SUITE_CCMP
)
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
;
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
_TX
;
ret
=
0
;
}
break
;
...
...
drivers/net/wireless/ath/ath9k/htc_drv_main.c
View file @
9b4e9e75
...
...
@@ -1445,7 +1445,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
key
->
flags
|=
IEEE80211_KEY_FLAG_GENERATE_MMIC
;
if
(
priv
->
ah
->
sw_mgmt_crypto
&&
key
->
cipher
==
WLAN_CIPHER_SUITE_CCMP
)
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
;
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
_TX
;
ret
=
0
;
}
break
;
...
...
drivers/net/wireless/ath/ath9k/main.c
View file @
9b4e9e75
...
...
@@ -1406,7 +1406,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
key
->
flags
|=
IEEE80211_KEY_FLAG_GENERATE_MMIC
;
if
(
sc
->
sc_ah
->
sw_mgmt_crypto
&&
key
->
cipher
==
WLAN_CIPHER_SUITE_CCMP
)
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
;
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
_TX
;
ret
=
0
;
}
break
;
...
...
drivers/net/wireless/mac80211_hwsim.c
View file @
9b4e9e75
...
...
@@ -2056,7 +2056,7 @@ static int __init init_mac80211_hwsim(void)
mac80211_hwsim_free
();
return
err
;
}
module_init
(
init_mac80211_hwsim
);
static
void
__exit
exit_mac80211_hwsim
(
void
)
{
...
...
@@ -2067,7 +2067,4 @@ static void __exit exit_mac80211_hwsim(void)
mac80211_hwsim_free
();
unregister_netdev
(
hwsim_mon
);
}
module_init
(
init_mac80211_hwsim
);
module_exit
(
exit_mac80211_hwsim
);
include/linux/ieee80211.h
View file @
9b4e9e75
...
...
@@ -1934,36 +1934,6 @@ static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr,
return
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_PUBLIC
;
}
/**
* ieee80211_fhss_chan_to_freq - get channel frequency
* @channel: the FHSS channel
*
* Convert IEEE802.11 FHSS channel to frequency (MHz)
* Ref IEEE 802.11-2007 section 14.6
*/
static
inline
int
ieee80211_fhss_chan_to_freq
(
int
channel
)
{
if
((
channel
>
1
)
&&
(
channel
<
96
))
return
channel
+
2400
;
else
return
-
1
;
}
/**
* ieee80211_freq_to_fhss_chan - get channel
* @freq: the channels frequency
*
* Convert frequency (MHz) to IEEE802.11 FHSS channel
* Ref IEEE 802.11-2007 section 14.6
*/
static
inline
int
ieee80211_freq_to_fhss_chan
(
int
freq
)
{
if
((
freq
>
2401
)
&&
(
freq
<
2496
))
return
freq
-
2400
;
else
return
-
1
;
}
/**
* ieee80211_dsss_chan_to_freq - get channel center frequency
* @channel: the DSSS channel
...
...
@@ -2000,56 +1970,6 @@ static inline int ieee80211_freq_to_dsss_chan(int freq)
return
-
1
;
}
/* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back
* Ref IEEE 802.11-2007 section 18.4.6.2
*
* The channels and frequencies are the same as those defined for DSSS
*/
#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan)
#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq)
/* Convert IEEE802.11 ERP channel to frequency (MHz) and back
* Ref IEEE 802.11-2007 section 19.4.2
*/
#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan)
#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq)
/**
* ieee80211_ofdm_chan_to_freq - get channel center frequency
* @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz
* @channel: the OFDM channel
*
* Convert IEEE802.11 OFDM channel to center frequency (MHz)
* Ref IEEE 802.11-2007 section 17.3.8.3.2
*/
static
inline
int
ieee80211_ofdm_chan_to_freq
(
int
s_freq
,
int
channel
)
{
if
((
channel
>
0
)
&&
(
channel
<=
200
)
&&
(
s_freq
>=
4000
))
return
s_freq
+
(
channel
*
5
);
else
return
-
1
;
}
/**
* ieee80211_freq_to_ofdm_channel - get channel
* @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz
* @freq: the frequency
*
* Convert frequency (MHz) to IEEE802.11 OFDM channel
* Ref IEEE 802.11-2007 section 17.3.8.3.2
*
* This routine selects the channel with the closest center frequency.
*/
static
inline
int
ieee80211_freq_to_ofdm_chan
(
int
s_freq
,
int
freq
)
{
if
((
freq
>
(
s_freq
+
2
))
&&
(
freq
<=
(
s_freq
+
1202
))
&&
(
s_freq
>=
4000
))
return
(
freq
+
2
-
s_freq
)
/
5
;
else
return
-
1
;
}
/**
* ieee80211_tu_to_usec - convert time units (TU) to microseconds
* @tu: the TUs
...
...
include/net/mac80211.h
View file @
9b4e9e75
...
...
@@ -973,21 +973,29 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
* generation in software.
* @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates
* that the key is pairwise rather then a shared key.
* @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a
* @IEEE80211_KEY_FLAG_SW_MGMT
_TX
: This flag should be set by the driver for a
* CCMP key if it requires CCMP encryption of management frames (MFP) to
* be done in software.
* @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver
* if space should be prepared for the IV, but the IV
* itself should not be generated. Do not set together with
* @IEEE80211_KEY_FLAG_GENERATE_IV on the same key.
* @IEEE80211_KEY_FLAG_RX_MGMT: This key will be used to decrypt received
* management frames. The flag can help drivers that have a hardware
* crypto implementation that doesn't deal with management frames
* properly by allowing them to not upload the keys to hardware and
* fall back to software crypto. Note that this flag deals only with
* RX, if your crypto engine can't deal with TX you can also set the
* %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW.
*/
enum
ieee80211_key_flags
{
IEEE80211_KEY_FLAG_WMM_STA
=
1
<<
0
,
IEEE80211_KEY_FLAG_GENERATE_IV
=
1
<<
1
,
IEEE80211_KEY_FLAG_GENERATE_MMIC
=
1
<<
2
,
IEEE80211_KEY_FLAG_PAIRWISE
=
1
<<
3
,
IEEE80211_KEY_FLAG_SW_MGMT
=
1
<<
4
,
IEEE80211_KEY_FLAG_SW_MGMT
_TX
=
1
<<
4
,
IEEE80211_KEY_FLAG_PUT_IV_SPACE
=
1
<<
5
,
IEEE80211_KEY_FLAG_RX_MGMT
=
1
<<
6
,
};
/**
...
...
net/mac80211/cfg.c
View file @
9b4e9e75
...
...
@@ -170,6 +170,38 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
}
}
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_STATION
:
if
(
sdata
->
u
.
mgd
.
mfp
!=
IEEE80211_MFP_DISABLED
)
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_RX_MGMT
;
break
;
case
NL80211_IFTYPE_AP
:
case
NL80211_IFTYPE_AP_VLAN
:
/* Keys without a station are used for TX only */
if
(
key
->
sta
&&
test_sta_flag
(
key
->
sta
,
WLAN_STA_MFP
))
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_RX_MGMT
;
break
;
case
NL80211_IFTYPE_ADHOC
:
/* no MFP (yet) */
break
;
case
NL80211_IFTYPE_MESH_POINT
:
#ifdef CONFIG_MAC80211_MESH
if
(
sdata
->
u
.
mesh
.
security
!=
IEEE80211_MESH_SEC_NONE
)
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_RX_MGMT
;
break
;
#endif
case
NL80211_IFTYPE_WDS
:
case
NL80211_IFTYPE_MONITOR
:
case
NL80211_IFTYPE_P2P_DEVICE
:
case
NL80211_IFTYPE_UNSPECIFIED
:
case
NUM_NL80211_IFTYPES
:
case
NL80211_IFTYPE_P2P_CLIENT
:
case
NL80211_IFTYPE_P2P_GO
:
/* shouldn't happen */
WARN_ON_ONCE
(
1
);
break
;
}
err
=
ieee80211_key_link
(
key
,
sdata
,
sta
);
if
(
err
)
ieee80211_key_free
(
sdata
->
local
,
key
);
...
...
@@ -2038,9 +2070,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
*/
if
(
!
sdata
->
u
.
mgd
.
associated
||
sdata
->
vif
.
bss_conf
.
channel_type
==
NL80211_CHAN_NO_HT
)
{
mutex_lock
(
&
sdata
->
local
->
iflist_mtx
);
ieee80211_recalc_smps
(
sdata
->
local
);
mutex_unlock
(
&
sdata
->
local
->
iflist_mtx
);
return
0
;
}
...
...
net/mac80211/chan.c
View file @
9b4e9e75
...
...
@@ -68,16 +68,14 @@ ieee80211_get_channel_mode(struct ieee80211_local *local,
return
mode
;
}
bool
ieee80211_set_channel_type
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
,
enum
nl80211_channel_type
chantype
)
static
enum
nl80211_channel_type
ieee80211_get_superchan
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_sub_if_data
*
tmp
;
enum
nl80211_channel_type
superchan
=
NL80211_CHAN_NO_HT
;
bool
result
;
struct
ieee80211_sub_if_data
*
tmp
;
mutex_lock
(
&
local
->
iflist_mtx
);
list_for_each_entry
(
tmp
,
&
local
->
interfaces
,
list
)
{
if
(
tmp
==
sdata
)
continue
;
...
...
@@ -103,39 +101,70 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local,
break
;
}
}
mutex_unlock
(
&
local
->
iflist_mtx
);
switch
(
superchan
)
{
return
superchan
;
}
static
bool
ieee80211_channel_types_are_compatible
(
enum
nl80211_channel_type
chantype1
,
enum
nl80211_channel_type
chantype2
,
enum
nl80211_channel_type
*
compat
)
{
/*
* start out with chantype1 being the result,
* overwriting later if needed
*/
if
(
compat
)
*
compat
=
chantype1
;
switch
(
chantype1
)
{
case
NL80211_CHAN_NO_HT
:
if
(
compat
)
*
compat
=
chantype2
;
break
;
case
NL80211_CHAN_HT20
:
/*
* allow any change that doesn't go to no-HT
* (if it already is no-HT no change is needed)
*/
if
(
chantype
==
NL80211_CHAN_NO_HT
)
if
(
chantype
2
==
NL80211_CHAN_NO_HT
)
break
;
superchan
=
chantype
;
if
(
compat
)
*
compat
=
chantype2
;
break
;
case
NL80211_CHAN_HT40PLUS
:
case
NL80211_CHAN_HT40MINUS
:
/* allow smaller bandwidth and same */
if
(
chantype
==
NL80211_CHAN_NO_HT
)
if
(
chantype
2
==
NL80211_CHAN_NO_HT
)
break
;
if
(
chantype
==
NL80211_CHAN_HT20
)
if
(
chantype
2
==
NL80211_CHAN_HT20
)
break
;
if
(
superchan
==
chantype
)
if
(
chantype2
==
chantype1
)
break
;
result
=
false
;
goto
out
;
return
false
;
}
local
->
_oper_channel_type
=
superchan
;
return
true
;
}
bool
ieee80211_set_channel_type
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
,
enum
nl80211_channel_type
chantype
)
{
enum
nl80211_channel_type
superchan
;
enum
nl80211_channel_type
compatchan
;
superchan
=
ieee80211_get_superchan
(
local
,
sdata
);
if
(
!
ieee80211_channel_types_are_compatible
(
superchan
,
chantype
,
&
compatchan
))
return
false
;
local
->
_oper_channel_type
=
compatchan
;
if
(
sdata
)
sdata
->
vif
.
bss_conf
.
channel_type
=
chantype
;
result
=
true
;
out:
mutex_unlock
(
&
local
->
iflist_mtx
);
return
true
;
return
result
;
}
net/mac80211/ibss.c
View file @
9b4e9e75
...
...
@@ -332,11 +332,27 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
return
ieee80211_ibss_finish_sta
(
sta
,
auth
);
}
static
void
ieee80211_rx_mgmt_deauth_ibss
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_mgmt
*
mgmt
,
size_t
len
)
{
u16
reason
=
le16_to_cpu
(
mgmt
->
u
.
deauth
.
reason_code
);
if
(
len
<
IEEE80211_DEAUTH_FRAME_LEN
)
return
;
ibss_dbg
(
sdata
,
"RX DeAuth SA=%pM DA=%pM BSSID=%pM (reason: %d)
\n
"
,
mgmt
->
sa
,
mgmt
->
da
,
mgmt
->
bssid
,
reason
);
sta_info_destroy_addr
(
sdata
,
mgmt
->
sa
);
}
static
void
ieee80211_rx_mgmt_auth_ibss
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_mgmt
*
mgmt
,
size_t
len
)
{
u16
auth_alg
,
auth_transaction
;
struct
sta_info
*
sta
;
u8
deauth_frame_buf
[
IEEE80211_DEAUTH_FRAME_LEN
];
lockdep_assert_held
(
&
sdata
->
u
.
ibss
.
mtx
);
...
...
@@ -352,9 +368,21 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
"RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)
\n
"
,
mgmt
->
sa
,
mgmt
->
da
,
mgmt
->
bssid
,
auth_transaction
);
sta_info_destroy_addr
(
sdata
,
mgmt
->
sa
);
ieee80211_ibss_add_sta
(
sdata
,
mgmt
->
bssid
,
mgmt
->
sa
,
0
,
false
);
sta
=
ieee80211_ibss_add_sta
(
sdata
,
mgmt
->
bssid
,
mgmt
->
sa
,
0
,
false
);
rcu_read_unlock
();
/*
* if we have any problem in allocating the new station, we reply with a
* DEAUTH frame to tell the other end that we had a problem
*/
if
(
!
sta
)
{
ieee80211_send_deauth_disassoc
(
sdata
,
sdata
->
u
.
ibss
.
bssid
,
IEEE80211_STYPE_DEAUTH
,
WLAN_REASON_UNSPECIFIED
,
true
,
deauth_frame_buf
);
return
;
}
/*
* IEEE 802.11 standard does not require authentication in IBSS
* networks and most implementations do not seem to use it.
...
...
@@ -902,6 +930,9 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
case
IEEE80211_STYPE_AUTH
:
ieee80211_rx_mgmt_auth_ibss
(
sdata
,
mgmt
,
skb
->
len
);
break
;
case
IEEE80211_STYPE_DEAUTH
:
ieee80211_rx_mgmt_deauth_ibss
(
sdata
,
mgmt
,
skb
->
len
);
break
;
}
mgmt_out:
...
...
net/mac80211/ieee80211_i.h
View file @
9b4e9e75
...
...
@@ -68,6 +68,8 @@ struct ieee80211_local;
#define IEEE80211_DEFAULT_MAX_SP_LEN \
IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
#define IEEE80211_DEAUTH_FRAME_LEN (24
/* hdr */
+ 2
/* reason */
)
struct
ieee80211_fragment_entry
{
unsigned
long
first_frag_time
;
unsigned
int
seq
;
...
...
@@ -411,6 +413,7 @@ struct ieee80211_if_managed {
struct
work_struct
monitor_work
;
struct
work_struct
chswitch_work
;
struct
work_struct
beacon_connection_loss_work
;
struct
work_struct
csa_connection_drop_work
;
unsigned
long
beacon_timeout
;
unsigned
long
probe_timeout
;
...
...
@@ -970,7 +973,6 @@ struct ieee80211_local {
int
scan_channel_idx
;
int
scan_ies_len
;
struct
ieee80211_sched_scan_ies
sched_scan_ies
;
struct
work_struct
sched_scan_stopped_work
;
struct
ieee80211_sub_if_data
__rcu
*
sched_scan_sdata
;
...
...
@@ -1057,7 +1059,7 @@ struct ieee80211_local {
bool
disable_dynamic_ps
;
int
user_power_level
;
/* in dBm */
int
power_const
r_level
;
/* in dBm */
int
ap_powe
r_level
;
/* in dBm */
enum
ieee80211_smps_mode
smps_mode
;
...
...
@@ -1165,7 +1167,6 @@ struct ieee802_11_elems {
u8
prep_len
;
u8
perr_len
;
u8
country_elem_len
;
u8
pwr_constr_elem_len
;
u8
quiet_elem_len
;
u8
num_of_quiet_elem
;
/* can be more the one */
u8
timeout_int_len
;
...
...
@@ -1367,7 +1368,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
int
ieee80211_reconfig
(
struct
ieee80211_local
*
local
);
void
ieee80211_stop_device
(
struct
ieee80211_local
*
local
);
#ifdef CONFIG_PM
int
__ieee80211_suspend
(
struct
ieee80211_hw
*
hw
,
struct
cfg80211_wowlan
*
wowlan
);
...
...
@@ -1381,18 +1381,6 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw)
return
ieee80211_reconfig
(
hw_to_local
(
hw
));
}
#else
static
inline
int
__ieee80211_suspend
(
struct
ieee80211_hw
*
hw
,
struct
cfg80211_wowlan
*
wowlan
)
{
return
0
;
}
static
inline
int
__ieee80211_resume
(
struct
ieee80211_hw
*
hw
)
{
return
0
;
}
#endif
/* utility functions/constants */
extern
void
*
mac80211_wiphy_privid
;
/* for wiphy privid */
...
...
@@ -1459,6 +1447,9 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u16
transaction
,
u16
auth_alg
,
u8
*
extra
,
size_t
extra_len
,
const
u8
*
bssid
,
const
u8
*
da
,
const
u8
*
key
,
u8
key_len
,
u8
key_idx
);
void
ieee80211_send_deauth_disassoc
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
bssid
,
u16
stype
,
u16
reason
,
bool
send_frame
,
u8
*
frame_buf
);
int
ieee80211_build_preq_ies
(
struct
ieee80211_local
*
local
,
u8
*
buffer
,
const
u8
*
ie
,
size_t
ie_len
,
enum
ieee80211_band
band
,
u32
rate_mask
,
...
...
net/mac80211/iface.c
View file @
9b4e9e75
...
...
@@ -793,11 +793,20 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
flush_work
(
&
sdata
->
work
);
/*
* When we get here, the interface is marked down.
* Call
synchronize_rcu() to wait
for the RX path
* Call
rcu_barrier() to wait both
for the RX path
* should it be using the interface and enqueuing
* frames at this very time on another CPU.
* frames at this very time on another CPU, and
* for the sta free call_rcu callbacks.
*/
synchronize_rcu
();
rcu_barrier
();
/*
* free_sta_rcu() enqueues a work for the actual
* sta cleanup, so we need to flush it while
* sdata is still valid.
*/
flush_workqueue
(
local
->
workqueue
);
skb_queue_purge
(
&
sdata
->
skb_queue
);
/*
...
...
net/mac80211/key.c
View file @
9b4e9e75
...
...
@@ -402,7 +402,7 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
* Synchronize so the TX path can no longer be using
* this key before we free/remove it.
*/
synchronize_
rcu
();
synchronize_
net
();
if
(
key
->
local
)
ieee80211_key_disable_hw_accel
(
key
);
...
...
net/mac80211/main.c
View file @
9b4e9e75
...
...
@@ -150,13 +150,11 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
if
(
test_bit
(
SCAN_SW_SCANNING
,
&
local
->
scanning
)
||
test_bit
(
SCAN_ONCHANNEL_SCANNING
,
&
local
->
scanning
)
||
test_bit
(
SCAN_HW_SCANNING
,
&
local
->
scanning
))
test_bit
(
SCAN_HW_SCANNING
,
&
local
->
scanning
)
||
!
local
->
ap_power_level
)
power
=
chan
->
max_power
;
else
power
=
local
->
power_constr_level
?
min
(
chan
->
max_power
,
(
chan
->
max_reg_power
-
local
->
power_constr_level
))
:
chan
->
max_power
;
power
=
min
(
chan
->
max_power
,
local
->
ap_power_level
);
if
(
local
->
user_power_level
>=
0
)
power
=
min
(
power
,
local
->
user_power_level
);
...
...
@@ -366,9 +364,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
struct
ieee80211_local
*
local
=
container_of
(
work
,
struct
ieee80211_local
,
recalc_smps
);
mutex_lock
(
&
local
->
iflist_mtx
);
ieee80211_recalc_smps
(
local
);
mutex_unlock
(
&
local
->
iflist_mtx
);
}
#ifdef CONFIG_INET
...
...
net/mac80211/mesh_plink.c
View file @
9b4e9e75
...
...
@@ -537,7 +537,8 @@ int mesh_plink_open(struct sta_info *sta)
spin_lock_bh
(
&
sta
->
lock
);
get_random_bytes
(
&
llid
,
2
);
sta
->
llid
=
llid
;
if
(
sta
->
plink_state
!=
NL80211_PLINK_LISTEN
)
{
if
(
sta
->
plink_state
!=
NL80211_PLINK_LISTEN
&&
sta
->
plink_state
!=
NL80211_PLINK_BLOCKED
)
{
spin_unlock_bh
(
&
sta
->
lock
);
return
-
EBUSY
;
}
...
...
net/mac80211/mlme.c
View file @
9b4e9e75
This diff is collapsed.
Click to expand it.
net/mac80211/offchannel.c
View file @
9b4e9e75
...
...
@@ -233,8 +233,7 @@ static void ieee80211_hw_roc_start(struct work_struct *work)
u32
dur
=
dep
->
duration
;
dep
->
duration
=
dur
-
roc
->
duration
;
roc
->
duration
=
dur
;
list_del
(
&
dep
->
list
);
list_add
(
&
dep
->
list
,
&
roc
->
list
);
list_move
(
&
dep
->
list
,
&
roc
->
list
);
}
}
out_unlock:
...
...
net/mac80211/scan.c
View file @
9b4e9e75
...
...
@@ -407,7 +407,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
enum
ieee80211_band
band
=
local
->
hw
.
conf
.
channel
->
band
;
sdata
=
rcu_dereference_protected
(
local
->
scan_sdata
,
lockdep_is_held
(
&
local
->
mtx
));
;
lockdep_is_held
(
&
local
->
mtx
));
for
(
i
=
0
;
i
<
local
->
scan_req
->
n_ssids
;
i
++
)
ieee80211_send_probe_req
(
...
...
@@ -917,6 +917,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
struct
cfg80211_sched_scan_request
*
req
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_sched_scan_ies
sched_scan_ies
;
int
ret
,
i
;
mutex_lock
(
&
local
->
mtx
);
...
...
@@ -935,33 +936,28 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
if
(
!
local
->
hw
.
wiphy
->
bands
[
i
])
continue
;
local
->
sched_scan_ies
.
ie
[
i
]
=
kzalloc
(
2
+
IEEE80211_MAX_SSID_LEN
+
local
->
scan_ies_len
+
req
->
ie_len
,
GFP_KERNEL
);
if
(
!
local
->
sched_scan_ies
.
ie
[
i
])
{
sched_scan_ies
.
ie
[
i
]
=
kzalloc
(
2
+
IEEE80211_MAX_SSID_LEN
+
local
->
scan_ies_len
+
req
->
ie_len
,
GFP_KERNEL
);
if
(
!
sched_scan_ies
.
ie
[
i
])
{
ret
=
-
ENOMEM
;
goto
out_free
;
}
local
->
sched_scan_ies
.
len
[
i
]
=
ieee80211_build_preq_ies
(
local
,
local
->
sched_scan_ies
.
ie
[
i
],
sched_scan_ies
.
len
[
i
]
=
ieee80211_build_preq_ies
(
local
,
sched_scan_ies
.
ie
[
i
],
req
->
ie
,
req
->
ie_len
,
i
,
(
u32
)
-
1
,
0
);
}
ret
=
drv_sched_scan_start
(
local
,
sdata
,
req
,
&
local
->
sched_scan_ies
);
if
(
ret
==
0
)
{
ret
=
drv_sched_scan_start
(
local
,
sdata
,
req
,
&
sched_scan_ies
);
if
(
ret
==
0
)
rcu_assign_pointer
(
local
->
sched_scan_sdata
,
sdata
);
goto
out
;
}
out_free:
while
(
i
>
0
)
kfree
(
local
->
sched_scan_ies
.
ie
[
--
i
]);
kfree
(
sched_scan_ies
.
ie
[
--
i
]);
out:
mutex_unlock
(
&
local
->
mtx
);
return
ret
;
...
...
@@ -970,7 +966,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
int
ieee80211_request_sched_scan_stop
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
int
ret
=
0
,
i
;
int
ret
=
0
;
mutex_lock
(
&
local
->
mtx
);
...
...
@@ -979,12 +975,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
goto
out
;
}
if
(
rcu_access_pointer
(
local
->
sched_scan_sdata
))
{
for
(
i
=
0
;
i
<
IEEE80211_NUM_BANDS
;
i
++
)
kfree
(
local
->
sched_scan_ies
.
ie
[
i
]);
if
(
rcu_access_pointer
(
local
->
sched_scan_sdata
))
drv_sched_scan_stop
(
local
,
sdata
);
}
out:
mutex_unlock
(
&
local
->
mtx
);
...
...
@@ -1006,7 +999,6 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
struct
ieee80211_local
*
local
=
container_of
(
work
,
struct
ieee80211_local
,
sched_scan_stopped_work
);
int
i
;
mutex_lock
(
&
local
->
mtx
);
...
...
@@ -1015,9 +1007,6 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
return
;
}
for
(
i
=
0
;
i
<
IEEE80211_NUM_BANDS
;
i
++
)
kfree
(
local
->
sched_scan_ies
.
ie
[
i
]);
rcu_assign_pointer
(
local
->
sched_scan_sdata
,
NULL
);
mutex_unlock
(
&
local
->
mtx
);
...
...
net/mac80211/sta_info.c
View file @
9b4e9e75
...
...
@@ -91,6 +91,70 @@ static int sta_info_hash_del(struct ieee80211_local *local,
return
-
ENOENT
;
}
static
void
free_sta_work
(
struct
work_struct
*
wk
)
{
struct
sta_info
*
sta
=
container_of
(
wk
,
struct
sta_info
,
free_sta_wk
);
int
ac
,
i
;
struct
tid_ampdu_tx
*
tid_tx
;
struct
ieee80211_sub_if_data
*
sdata
=
sta
->
sdata
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
/*
* At this point, when being called as call_rcu callback,
* neither mac80211 nor the driver can reference this
* sta struct any more except by still existing timers
* associated with this station that we clean up below.
*/
if
(
test_sta_flag
(
sta
,
WLAN_STA_PS_STA
))
{
BUG_ON
(
!
sdata
->
bss
);
clear_sta_flag
(
sta
,
WLAN_STA_PS_STA
);
atomic_dec
(
&
sdata
->
bss
->
num_sta_ps
);
sta_info_recalc_tim
(
sta
);
}
for
(
ac
=
0
;
ac
<
IEEE80211_NUM_ACS
;
ac
++
)
{
local
->
total_ps_buffered
-=
skb_queue_len
(
&
sta
->
ps_tx_buf
[
ac
]);
__skb_queue_purge
(
&
sta
->
ps_tx_buf
[
ac
]);
__skb_queue_purge
(
&
sta
->
tx_filtered
[
ac
]);
}
#ifdef CONFIG_MAC80211_MESH
if
(
ieee80211_vif_is_mesh
(
&
sdata
->
vif
))
{
mesh_accept_plinks_update
(
sdata
);
mesh_plink_deactivate
(
sta
);
del_timer_sync
(
&
sta
->
plink_timer
);
}
#endif
cancel_work_sync
(
&
sta
->
drv_unblock_wk
);
/*
* Destroy aggregation state here. It would be nice to wait for the
* driver to finish aggregation stop and then clean up, but for now
* drivers have to handle aggregation stop being requested, followed
* directly by station destruction.
*/
for
(
i
=
0
;
i
<
STA_TID_NUM
;
i
++
)
{
tid_tx
=
rcu_dereference_raw
(
sta
->
ampdu_mlme
.
tid_tx
[
i
]);
if
(
!
tid_tx
)
continue
;
__skb_queue_purge
(
&
tid_tx
->
pending
);
kfree
(
tid_tx
);
}
sta_info_free
(
local
,
sta
);
}
static
void
free_sta_rcu
(
struct
rcu_head
*
h
)
{
struct
sta_info
*
sta
=
container_of
(
h
,
struct
sta_info
,
rcu_head
);
ieee80211_queue_work
(
&
sta
->
local
->
hw
,
&
sta
->
free_sta_wk
);
}
/* protected by RCU */
struct
sta_info
*
sta_info_get
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
addr
)
...
...
@@ -241,6 +305,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
spin_lock_init
(
&
sta
->
lock
);
INIT_WORK
(
&
sta
->
drv_unblock_wk
,
sta_unblock
);
INIT_WORK
(
&
sta
->
free_sta_wk
,
free_sta_work
);
INIT_WORK
(
&
sta
->
ampdu_mlme
.
work
,
ieee80211_ba_session_work
);
mutex_init
(
&
sta
->
ampdu_mlme
.
mtx
);
...
...
@@ -654,8 +719,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
{
struct
ieee80211_local
*
local
;
struct
ieee80211_sub_if_data
*
sdata
;
int
ret
,
i
,
ac
;
struct
tid_ampdu_tx
*
tid_tx
;
int
ret
,
i
;
might_sleep
();
...
...
@@ -711,65 +775,14 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
WARN_ON_ONCE
(
ret
!=
0
);
}
/*
* At this point, after we wait for an RCU grace period,
* neither mac80211 nor the driver can reference this
* sta struct any more except by still existing timers
* associated with this station that we clean up below.
*/
synchronize_rcu
();
if
(
test_sta_flag
(
sta
,
WLAN_STA_PS_STA
))
{
BUG_ON
(
!
sdata
->
bss
);
clear_sta_flag
(
sta
,
WLAN_STA_PS_STA
);
atomic_dec
(
&
sdata
->
bss
->
num_sta_ps
);
sta_info_recalc_tim
(
sta
);
}
for
(
ac
=
0
;
ac
<
IEEE80211_NUM_ACS
;
ac
++
)
{
local
->
total_ps_buffered
-=
skb_queue_len
(
&
sta
->
ps_tx_buf
[
ac
]);
__skb_queue_purge
(
&
sta
->
ps_tx_buf
[
ac
]);
__skb_queue_purge
(
&
sta
->
tx_filtered
[
ac
]);
}
#ifdef CONFIG_MAC80211_MESH
if
(
ieee80211_vif_is_mesh
(
&
sdata
->
vif
))
mesh_accept_plinks_update
(
sdata
);
#endif
sta_dbg
(
sdata
,
"Removed STA %pM
\n
"
,
sta
->
sta
.
addr
);
cancel_work_sync
(
&
sta
->
drv_unblock_wk
);
cfg80211_del_sta
(
sdata
->
dev
,
sta
->
sta
.
addr
,
GFP_KERNEL
);
rate_control_remove_sta_debugfs
(
sta
);
ieee80211_sta_debugfs_remove
(
sta
);
#ifdef CONFIG_MAC80211_MESH
if
(
ieee80211_vif_is_mesh
(
&
sta
->
sdata
->
vif
))
{
mesh_plink_deactivate
(
sta
);
del_timer_sync
(
&
sta
->
plink_timer
);
}
#endif
/*
* Destroy aggregation state here. It would be nice to wait for the
* driver to finish aggregation stop and then clean up, but for now
* drivers have to handle aggregation stop being requested, followed
* directly by station destruction.
*/
for
(
i
=
0
;
i
<
STA_TID_NUM
;
i
++
)
{
tid_tx
=
rcu_dereference_raw
(
sta
->
ampdu_mlme
.
tid_tx
[
i
]);
if
(
!
tid_tx
)
continue
;
__skb_queue_purge
(
&
tid_tx
->
pending
);
kfree
(
tid_tx
);
}
sta_info_free
(
local
,
sta
);
call_rcu
(
&
sta
->
rcu_head
,
free_sta_rcu
);
return
0
;
}
...
...
net/mac80211/sta_info.h
View file @
9b4e9e75
...
...
@@ -287,6 +287,7 @@ struct sta_ampdu_mlme {
struct
sta_info
{
/* General information, mostly static */
struct
list_head
list
;
struct
rcu_head
rcu_head
;
struct
sta_info
__rcu
*
hnext
;
struct
ieee80211_local
*
local
;
struct
ieee80211_sub_if_data
*
sdata
;
...
...
@@ -297,6 +298,7 @@ struct sta_info {
spinlock_t
lock
;
struct
work_struct
drv_unblock_wk
;
struct
work_struct
free_sta_wk
;
u16
listen_interval
;
...
...
net/mac80211/status.c
View file @
9b4e9e75
...
...
@@ -517,29 +517,41 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
if
(
info
->
flags
&
IEEE80211_TX_INTFL_NL80211_FRAME_TX
)
{
u64
cookie
=
(
unsigned
long
)
skb
;
bool
found
=
false
;
acked
=
info
->
flags
&
IEEE80211_TX_STAT_ACK
;
if
(
ieee80211_is_nullfunc
(
hdr
->
frame_control
)
||
ieee80211_is_qos_nullfunc
(
hdr
->
frame_control
))
{
cfg80211_probe_status
(
skb
->
dev
,
hdr
->
addr1
,
cookie
,
acked
,
GFP_ATOMIC
);
}
else
if
(
skb
->
dev
)
{
cfg80211_mgmt_tx_status
(
skb
->
dev
->
ieee80211_ptr
,
cookie
,
skb
->
data
,
skb
->
len
,
acked
,
GFP_ATOMIC
);
}
else
{
struct
ieee80211_sub_if_data
*
p2p_sdata
;
rcu_read_lock
();
list_for_each_entry_rcu
(
sdata
,
&
local
->
interfaces
,
list
)
{
if
(
!
sdata
->
dev
)
continue
;
rcu_read_lock
();
if
(
skb
->
dev
!=
sdata
->
dev
)
continue
;
p2p_sdata
=
rcu_dereference
(
local
->
p2p_sdata
);
if
(
p2p_sdata
)
{
cfg80211_mgmt_tx_status
(
&
p2p_sdata
->
wdev
,
cookie
,
skb
->
data
,
skb
->
len
,
acked
,
GFP_ATOMIC
);
}
rcu_read_unlock
();
found
=
true
;
break
;
}
if
(
!
skb
->
dev
)
{
sdata
=
rcu_dereference
(
local
->
p2p_sdata
);
if
(
sdata
)
found
=
true
;
}
if
(
!
found
)
skb
->
dev
=
NULL
;
else
if
(
ieee80211_is_nullfunc
(
hdr
->
frame_control
)
||
ieee80211_is_qos_nullfunc
(
hdr
->
frame_control
))
{
cfg80211_probe_status
(
sdata
->
dev
,
hdr
->
addr1
,
cookie
,
acked
,
GFP_ATOMIC
);
}
else
{
cfg80211_mgmt_tx_status
(
&
sdata
->
wdev
,
cookie
,
skb
->
data
,
skb
->
len
,
acked
,
GFP_ATOMIC
);
}
rcu_read_unlock
();
}
if
(
unlikely
(
info
->
ack_frame_id
))
{
...
...
net/mac80211/tx.c
View file @
9b4e9e75
...
...
@@ -580,7 +580,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
tx
->
key
=
NULL
;
else
skip_hw
=
(
tx
->
key
->
conf
.
flags
&
IEEE80211_KEY_FLAG_SW_MGMT
)
&&
IEEE80211_KEY_FLAG_SW_MGMT
_TX
)
&&
ieee80211_is_mgmt
(
hdr
->
frame_control
);
break
;
case
WLAN_CIPHER_SUITE_AES_CMAC
:
...
...
net/mac80211/util.c
View file @
9b4e9e75
...
...
@@ -792,8 +792,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
elems
->
country_elem_len
=
elen
;
break
;
case
WLAN_EID_PWR_CONSTRAINT
:
if
(
elen
!=
1
)
{
elem_parse_failed
=
true
;
break
;
}
elems
->
pwr_constr_elem
=
pos
;
elems
->
pwr_constr_elem_len
=
elen
;
break
;
case
WLAN_EID_TIMEOUT_INTERVAL
:
elems
->
timeout_int
=
pos
;
...
...
@@ -1004,6 +1007,45 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
ieee80211_tx_skb
(
sdata
,
skb
);
}
void
ieee80211_send_deauth_disassoc
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
bssid
,
u16
stype
,
u16
reason
,
bool
send_frame
,
u8
*
frame_buf
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
sk_buff
*
skb
;
struct
ieee80211_mgmt
*
mgmt
=
(
void
*
)
frame_buf
;
/* build frame */
mgmt
->
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_MGMT
|
stype
);
mgmt
->
duration
=
0
;
/* initialize only */
mgmt
->
seq_ctrl
=
0
;
/* initialize only */
memcpy
(
mgmt
->
da
,
bssid
,
ETH_ALEN
);
memcpy
(
mgmt
->
sa
,
sdata
->
vif
.
addr
,
ETH_ALEN
);
memcpy
(
mgmt
->
bssid
,
bssid
,
ETH_ALEN
);
/* u.deauth.reason_code == u.disassoc.reason_code */
mgmt
->
u
.
deauth
.
reason_code
=
cpu_to_le16
(
reason
);
if
(
send_frame
)
{
skb
=
dev_alloc_skb
(
local
->
hw
.
extra_tx_headroom
+
IEEE80211_DEAUTH_FRAME_LEN
);
if
(
!
skb
)
return
;
skb_reserve
(
skb
,
local
->
hw
.
extra_tx_headroom
);
/* copy in frame */
memcpy
(
skb_put
(
skb
,
IEEE80211_DEAUTH_FRAME_LEN
),
mgmt
,
IEEE80211_DEAUTH_FRAME_LEN
);
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
||
!
(
sdata
->
u
.
mgd
.
flags
&
IEEE80211_STA_MFP_ENABLED
))
IEEE80211_SKB_CB
(
skb
)
->
flags
|=
IEEE80211_TX_INTFL_DONT_ENCRYPT
;
ieee80211_tx_skb
(
sdata
,
skb
);
}
}
int
ieee80211_build_preq_ies
(
struct
ieee80211_local
*
local
,
u8
*
buffer
,
const
u8
*
ie
,
size_t
ie_len
,
enum
ieee80211_band
band
,
u32
rate_mask
,
...
...
@@ -1564,14 +1606,13 @@ static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
return
0
;
}
/* must hold iflist_mtx */
void
ieee80211_recalc_smps
(
struct
ieee80211_local
*
local
)
{
struct
ieee80211_sub_if_data
*
sdata
;
enum
ieee80211_smps_mode
smps_mode
=
IEEE80211_SMPS_OFF
;
int
count
=
0
;
lockdep_assert_held
(
&
local
->
iflist_mtx
);
mutex_lock
(
&
local
->
iflist_mtx
);
/*
* This function could be improved to handle multiple
...
...
@@ -1600,12 +1641,14 @@ void ieee80211_recalc_smps(struct ieee80211_local *local)
}
if
(
smps_mode
==
local
->
smps_mode
)
return
;
goto
unlock
;
set:
local
->
smps_mode
=
smps_mode
;
/* changed flag is auto-detected for this */
ieee80211_hw_config
(
local
,
0
);
unlock:
mutex_unlock
(
&
local
->
iflist_mtx
);
}
static
bool
ieee80211_id_in_list
(
const
u8
*
ids
,
int
n_ids
,
u8
id
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment