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
nexedi
linux
Commits
e9517fec
Commit
e9517fec
authored
Oct 10, 2013
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
274dede8
7578d575
Changes
29
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1290 additions
and
544 deletions
+1290
-544
include/linux/ieee80211.h
include/linux/ieee80211.h
+2
-2
include/net/cfg80211.h
include/net/cfg80211.h
+9
-0
include/net/mac80211.h
include/net/mac80211.h
+42
-0
net/mac80211/cfg.c
net/mac80211/cfg.c
+69
-23
net/mac80211/chan.c
net/mac80211/chan.c
+0
-5
net/mac80211/debugfs.c
net/mac80211/debugfs.c
+29
-26
net/mac80211/driver-ops.h
net/mac80211/driver-ops.h
+27
-0
net/mac80211/ibss.c
net/mac80211/ibss.c
+520
-88
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+29
-1
net/mac80211/iface.c
net/mac80211/iface.c
+4
-0
net/mac80211/key.c
net/mac80211/key.c
+1
-1
net/mac80211/mlme.c
net/mac80211/mlme.c
+68
-266
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel.c
+14
-0
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rc80211_minstrel_ht.c
+13
-10
net/mac80211/rc80211_pid_debugfs.c
net/mac80211/rc80211_pid_debugfs.c
+13
-13
net/mac80211/rx.c
net/mac80211/rx.c
+28
-11
net/mac80211/scan.c
net/mac80211/scan.c
+1
-2
net/mac80211/spectmgmt.c
net/mac80211/spectmgmt.c
+162
-0
net/mac80211/trace.h
net/mac80211/trace.h
+35
-0
net/mac80211/tx.c
net/mac80211/tx.c
+34
-5
net/mac80211/util.c
net/mac80211/util.c
+110
-52
net/mac80211/vht.c
net/mac80211/vht.c
+2
-2
net/wireless/chan.c
net/wireless/chan.c
+1
-0
net/wireless/core.h
net/wireless/core.h
+0
-9
net/wireless/debugfs.c
net/wireless/debugfs.c
+13
-11
net/wireless/genregdb.awk
net/wireless/genregdb.awk
+6
-0
net/wireless/nl80211.c
net/wireless/nl80211.c
+37
-15
net/wireless/reg.c
net/wireless/reg.c
+12
-2
net/wireless/util.c
net/wireless/util.c
+9
-0
No files found.
include/linux/ieee80211.h
View file @
e9517fec
...
...
@@ -1391,8 +1391,8 @@ struct ieee80211_vht_operation {
#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700
#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
#define IEEE80211_VHT_CAP_BEAMFORME
R_ANTENNAS_MAX 0x00006
000
#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x000
3
0000
#define IEEE80211_VHT_CAP_BEAMFORME
E_STS_MAX 0x0000e
000
#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x000
7
0000
#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
...
...
include/net/cfg80211.h
View file @
e9517fec
...
...
@@ -436,6 +436,15 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
const
struct
cfg80211_chan_def
*
chandef
,
u32
prohibited_flags
);
/**
* cfg80211_chandef_dfs_required - checks if radar detection is required
* @wiphy: the wiphy to validate against
* @chandef: the channel definition to check
* Return: 1 if radar detection is required, 0 if it is not, < 0 on error
*/
int
cfg80211_chandef_dfs_required
(
struct
wiphy
*
wiphy
,
const
struct
cfg80211_chan_def
*
chandef
);
/**
* ieee80211_chandef_rate_flags - returns rate flags for a channel
*
...
...
include/net/mac80211.h
View file @
e9517fec
...
...
@@ -829,6 +829,15 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3
* @RX_FLAG_10MHZ: 10 MHz (half channel) was used
* @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used
* @RX_FLAG_AMSDU_MORE: Some drivers may prefer to report separate A-MSDU
* subframes instead of a one huge frame for performance reasons.
* All, but the last MSDU from an A-MSDU should have this flag set. E.g.
* if an A-MSDU has 3 frames, the first 2 must have the flag set, while
* the 3rd (last) one must not have this flag set. The flag is used to
* deal with retransmission/duplication recovery properly since A-MSDU
* subframes share the same sequence number. Reported subframes can be
* either regular MSDU or singly A-MSDUs. Subframes must not be
* interleaved with other frames.
*/
enum
mac80211_rx_flags
{
RX_FLAG_MMIC_ERROR
=
BIT
(
0
),
...
...
@@ -859,6 +868,7 @@ enum mac80211_rx_flags {
RX_FLAG_STBC_MASK
=
BIT
(
26
)
|
BIT
(
27
),
RX_FLAG_10MHZ
=
BIT
(
28
),
RX_FLAG_5MHZ
=
BIT
(
29
),
RX_FLAG_AMSDU_MORE
=
BIT
(
30
),
};
#define RX_FLAG_STBC_SHIFT 26
...
...
@@ -1492,6 +1502,11 @@ struct ieee80211_tx_control {
*
* @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames
* only, to allow getting TBTT of a DTIM beacon.
*
* @IEEE80211_HW_CHANCTX_STA_CSA: Support 802.11h based channel-switch (CSA)
* for a single active channel while using channel contexts. When support
* is not enabled the default action is to disconnect when getting the
* CSA frame.
*/
enum
ieee80211_hw_flags
{
IEEE80211_HW_HAS_RATE_CONTROL
=
1
<<
0
,
...
...
@@ -1522,6 +1537,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF
=
1
<<
25
,
IEEE80211_HW_TIMING_BEACON_ONLY
=
1
<<
26
,
IEEE80211_HW_SUPPORTS_HT_CCK_RATES
=
1
<<
27
,
IEEE80211_HW_CHANCTX_STA_CSA
=
1
<<
28
,
};
/**
...
...
@@ -2666,6 +2682,10 @@ enum ieee80211_roc_type {
* zero using ieee80211_csa_is_complete() after the beacon has been
* transmitted and then call ieee80211_csa_finish().
*
* @join_ibss: Join an IBSS (on an IBSS interface); this is called after all
* information in bss_conf is set up and the beacon can be retrieved. A
* channel context is bound before this is called.
* @leave_ibss: Leave the IBSS again.
*/
struct
ieee80211_ops
{
void
(
*
tx
)(
struct
ieee80211_hw
*
hw
,
...
...
@@ -2857,6 +2877,9 @@ struct ieee80211_ops {
void
(
*
channel_switch_beacon
)(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
cfg80211_chan_def
*
chandef
);
int
(
*
join_ibss
)(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
);
void
(
*
leave_ibss
)(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
);
};
/**
...
...
@@ -3919,6 +3942,25 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
struct
ieee80211_vif
*
vif
),
void
*
data
);
/**
* ieee80211_iterate_active_interfaces_rtnl - iterate active interfaces
*
* This function iterates over the interfaces associated with a given
* hardware that are currently active and calls the callback for them.
* This version can only be used while holding the RTNL.
*
* @hw: the hardware struct of which the interfaces should be iterated over
* @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
* @iterator: the iterator function to call, cannot sleep
* @data: first argument of the iterator function
*/
void
ieee80211_iterate_active_interfaces_rtnl
(
struct
ieee80211_hw
*
hw
,
u32
iter_flags
,
void
(
*
iterator
)(
void
*
data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
),
void
*
data
);
/**
* ieee80211_queue_work - add work onto the mac80211 workqueue
*
...
...
net/mac80211/cfg.c
View file @
e9517fec
...
...
@@ -2865,30 +2865,43 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
if
(
!
ieee80211_sdata_running
(
sdata
))
return
;
if
(
WARN_ON
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_AP
))
return
;
sdata
->
radar_required
=
sdata
->
csa_radar_required
;
err
=
ieee80211_vif_change_channel
(
sdata
,
&
local
->
csa_chandef
,
&
changed
);
if
(
WARN_ON
(
err
<
0
))
return
;
err
=
ieee80211_assign_beacon
(
sdata
,
sdata
->
u
.
ap
.
next_beacon
);
if
(
err
<
0
)
return
;
if
(
!
local
->
use_chanctx
)
{
local
->
_oper_chandef
=
local
->
csa_chandef
;
ieee80211_hw_config
(
local
,
0
);
}
changed
|=
err
;
kfree
(
sdata
->
u
.
ap
.
next_beacon
);
sdata
->
u
.
ap
.
next_beacon
=
NULL
;
ieee80211_bss_info_change_notify
(
sdata
,
changed
);
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_AP
:
err
=
ieee80211_assign_beacon
(
sdata
,
sdata
->
u
.
ap
.
next_beacon
);
if
(
err
<
0
)
return
;
changed
|=
err
;
kfree
(
sdata
->
u
.
ap
.
next_beacon
);
sdata
->
u
.
ap
.
next_beacon
=
NULL
;
ieee80211_bss_info_change_notify
(
sdata
,
err
);
break
;
case
NL80211_IFTYPE_ADHOC
:
ieee80211_ibss_finish_csa
(
sdata
);
break
;
default:
WARN_ON
(
1
);
return
;
}
sdata
->
vif
.
csa_active
=
false
;
ieee80211_wake_queues_by_reason
(
&
sdata
->
local
->
hw
,
IEEE80211_MAX_QUEUE_MAP
,
IEEE80211_QUEUE_STOP_REASON_CSA
);
ieee80211_bss_info_change_notify
(
sdata
,
changed
);
cfg80211_ch_switch_notify
(
sdata
->
dev
,
&
local
->
csa_chandef
);
}
...
...
@@ -2936,20 +2949,56 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
if
(
sdata
->
vif
.
csa_active
)
return
-
EBUSY
;
/* only handle AP for now. */
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_AP
:
sdata
->
csa_counter_offset_beacon
=
params
->
counter_offset_beacon
;
sdata
->
csa_counter_offset_presp
=
params
->
counter_offset_presp
;
sdata
->
u
.
ap
.
next_beacon
=
cfg80211_beacon_dup
(
&
params
->
beacon_after
);
if
(
!
sdata
->
u
.
ap
.
next_beacon
)
return
-
ENOMEM
;
err
=
ieee80211_assign_beacon
(
sdata
,
&
params
->
beacon_csa
);
if
(
err
<
0
)
{
kfree
(
sdata
->
u
.
ap
.
next_beacon
);
return
err
;
}
break
;
case
NL80211_IFTYPE_ADHOC
:
if
(
!
sdata
->
vif
.
bss_conf
.
ibss_joined
)
return
-
EINVAL
;
if
(
params
->
chandef
.
width
!=
sdata
->
u
.
ibss
.
chandef
.
width
)
return
-
EINVAL
;
switch
(
params
->
chandef
.
width
)
{
case
NL80211_CHAN_WIDTH_40
:
if
(
cfg80211_get_chandef_type
(
&
params
->
chandef
)
!=
cfg80211_get_chandef_type
(
&
sdata
->
u
.
ibss
.
chandef
))
return
-
EINVAL
;
case
NL80211_CHAN_WIDTH_5
:
case
NL80211_CHAN_WIDTH_10
:
case
NL80211_CHAN_WIDTH_20_NOHT
:
case
NL80211_CHAN_WIDTH_20
:
break
;
default:
return
-
EINVAL
;
}
/* changes into another band are not supported */
if
(
sdata
->
u
.
ibss
.
chandef
.
chan
->
band
!=
params
->
chandef
.
chan
->
band
)
return
-
EINVAL
;
err
=
ieee80211_ibss_csa_beacon
(
sdata
,
params
);
if
(
err
<
0
)
return
err
;
break
;
default:
return
-
EOPNOTSUPP
;
}
sdata
->
u
.
ap
.
next_beacon
=
cfg80211_beacon_dup
(
&
params
->
beacon_after
);
if
(
!
sdata
->
u
.
ap
.
next_beacon
)
return
-
ENOMEM
;
sdata
->
csa_counter_offset_beacon
=
params
->
counter_offset_beacon
;
sdata
->
csa_counter_offset_presp
=
params
->
counter_offset_presp
;
sdata
->
csa_radar_required
=
params
->
radar_required
;
if
(
params
->
block_tx
)
...
...
@@ -2957,10 +3006,6 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
IEEE80211_MAX_QUEUE_MAP
,
IEEE80211_QUEUE_STOP_REASON_CSA
);
err
=
ieee80211_assign_beacon
(
sdata
,
&
params
->
beacon_csa
);
if
(
err
<
0
)
return
err
;
local
->
csa_chandef
=
params
->
chandef
;
sdata
->
vif
.
csa_active
=
true
;
...
...
@@ -3014,7 +3059,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
need_offchan
=
true
;
if
(
!
ieee80211_is_action
(
mgmt
->
frame_control
)
||
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_PUBLIC
||
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_SELF_PROTECTED
)
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_SELF_PROTECTED
||
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_SPECTRUM_MGMT
)
break
;
rcu_read_lock
();
sta
=
sta_info_get
(
sdata
,
mgmt
->
da
);
...
...
net/mac80211/chan.c
View file @
e9517fec
...
...
@@ -453,11 +453,6 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
chanctx_changed
|=
IEEE80211_CHANCTX_CHANGE_CHANNEL
;
drv_change_chanctx
(
local
,
ctx
,
chanctx_changed
);
if
(
!
local
->
use_chanctx
)
{
local
->
_oper_chandef
=
*
chandef
;
ieee80211_hw_config
(
local
,
0
);
}
ieee80211_recalc_chanctx_chantype
(
local
,
ctx
);
ieee80211_recalc_smps_chanctx
(
local
,
ctx
);
ieee80211_recalc_radar_chanctx
(
local
,
ctx
);
...
...
net/mac80211/debugfs.c
View file @
e9517fec
...
...
@@ -103,54 +103,57 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
if
(
!
buf
)
return
0
;
sf
+=
snprintf
(
buf
,
mxln
-
sf
,
"0x%x
\n
"
,
local
->
hw
.
flags
);
sf
+=
s
c
nprintf
(
buf
,
mxln
-
sf
,
"0x%x
\n
"
,
local
->
hw
.
flags
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_HAS_RATE_CONTROL
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"HAS_RATE_CONTROL
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"HAS_RATE_CONTROL
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_RX_INCLUDES_FCS
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"RX_INCLUDES_FCS
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"RX_INCLUDES_FCS
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"HOST_BCAST_PS_BUFFERING
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"HOST_BCAST_PS_BUFFERING
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"2GHZ_SHORT_SLOT_INCAPABLE
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"2GHZ_SHORT_SLOT_INCAPABLE
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"2GHZ_SHORT_PREAMBLE_INCAPABLE
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"2GHZ_SHORT_PREAMBLE_INCAPABLE
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_SIGNAL_UNSPEC
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"SIGNAL_UNSPEC
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"SIGNAL_UNSPEC
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_SIGNAL_DBM
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"SIGNAL_DBM
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"SIGNAL_DBM
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"NEED_DTIM_BEFORE_ASSOC
\n
"
);
sf
+=
scnprintf
(
buf
+
sf
,
mxln
-
sf
,
"NEED_DTIM_BEFORE_ASSOC
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_SPECTRUM_MGMT
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"SPECTRUM_MGMT
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"SPECTRUM_MGMT
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_AMPDU_AGGREGATION
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"AMPDU_AGGREGATION
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"AMPDU_AGGREGATION
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_SUPPORTS_PS
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_PS
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_PS
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_PS_NULLFUNC_STACK
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"PS_NULLFUNC_STACK
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"PS_NULLFUNC_STACK
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_SUPPORTS_DYNAMIC_PS
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_DYNAMIC_PS
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_DYNAMIC_PS
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_MFP_CAPABLE
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"MFP_CAPABLE
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"MFP_CAPABLE
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_SUPPORTS_STATIC_SMPS
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_STATIC_SMPS
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_STATIC_SMPS
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_DYNAMIC_SMPS
\n
"
);
sf
+=
scnprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_DYNAMIC_SMPS
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_SUPPORTS_UAPSD
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_UAPSD
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_UAPSD
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_REPORTS_TX_ACK_STATUS
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"REPORTS_TX_ACK_STATUS
\n
"
);
sf
+=
scnprintf
(
buf
+
sf
,
mxln
-
sf
,
"REPORTS_TX_ACK_STATUS
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_CONNECTION_MONITOR
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"CONNECTION_MONITOR
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"CONNECTION_MONITOR
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_SUPPORTS_PER_STA_GTK
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_PER_STA_GTK
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"SUPPORTS_PER_STA_GTK
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_AP_LINK_PS
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"AP_LINK_PS
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"AP_LINK_PS
\n
"
);
if
(
local
->
hw
.
flags
&
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW
)
sf
+=
snprintf
(
buf
+
sf
,
mxln
-
sf
,
"TX_AMPDU_SETUP_IN_HW
\n
"
);
sf
+=
s
c
nprintf
(
buf
+
sf
,
mxln
-
sf
,
"TX_AMPDU_SETUP_IN_HW
\n
"
);
rv
=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
strlen
(
buf
));
kfree
(
buf
);
...
...
net/mac80211/driver-ops.h
View file @
e9517fec
...
...
@@ -1085,4 +1085,31 @@ drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata,
}
}
static
inline
int
drv_join_ibss
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
)
{
int
ret
=
0
;
might_sleep
();
check_sdata_in_driver
(
sdata
);
trace_drv_join_ibss
(
local
,
sdata
,
&
sdata
->
vif
.
bss_conf
);
if
(
local
->
ops
->
join_ibss
)
ret
=
local
->
ops
->
join_ibss
(
&
local
->
hw
,
&
sdata
->
vif
);
trace_drv_return_int
(
local
,
ret
);
return
ret
;
}
static
inline
void
drv_leave_ibss
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
)
{
might_sleep
();
check_sdata_in_driver
(
sdata
);
trace_drv_leave_ibss
(
local
,
sdata
);
if
(
local
->
ops
->
leave_ibss
)
local
->
ops
->
leave_ibss
(
&
local
->
hw
,
&
sdata
->
vif
);
trace_drv_return_void
(
local
);
}
#endif
/* __MAC80211_DRIVER_OPS */
net/mac80211/ibss.c
View file @
e9517fec
This diff is collapsed.
Click to expand it.
net/mac80211/ieee80211_i.h
View file @
e9517fec
...
...
@@ -322,7 +322,6 @@ struct ieee80211_roc_work {
/* flags used in struct ieee80211_if_managed.flags */
enum
ieee80211_sta_flags
{
IEEE80211_STA_BEACON_POLL
=
BIT
(
0
),
IEEE80211_STA_CONNECTION_POLL
=
BIT
(
1
),
IEEE80211_STA_CONTROL_PORT
=
BIT
(
2
),
IEEE80211_STA_DISABLE_HT
=
BIT
(
4
),
...
...
@@ -487,6 +486,7 @@ struct ieee80211_if_managed {
struct
ieee80211_if_ibss
{
struct
timer_list
timer
;
struct
work_struct
csa_connection_drop_work
;
unsigned
long
last_scan_completed
;
...
...
@@ -1330,6 +1330,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
void
ieee80211_ibss_work
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_ibss_rx_queued_mgmt
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
sk_buff
*
skb
);
int
ieee80211_ibss_csa_beacon
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
cfg80211_csa_settings
*
csa_settings
);
int
ieee80211_ibss_finish_csa
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_ibss_stop
(
struct
ieee80211_sub_if_data
*
sdata
);
/* mesh code */
void
ieee80211_mesh_work
(
struct
ieee80211_sub_if_data
*
sdata
);
...
...
@@ -1481,6 +1485,29 @@ void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
void
ieee80211_process_measurement_req
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_mgmt
*
mgmt
,
size_t
len
);
/**
* ieee80211_parse_ch_switch_ie - parses channel switch IEs
* @sdata: the sdata of the interface which has received the frame
* @elems: parsed 802.11 elements received with the frame
* @beacon: indicates if the frame was a beacon or probe response
* @current_band: indicates the current band
* @sta_flags: contains information about own capabilities and restrictions
* to decide which channel switch announcements can be accepted. Only the
* following subset of &enum ieee80211_sta_flags are evaluated:
* %IEEE80211_STA_DISABLE_HT, %IEEE80211_STA_DISABLE_VHT,
* %IEEE80211_STA_DISABLE_40MHZ, %IEEE80211_STA_DISABLE_80P80MHZ,
* %IEEE80211_STA_DISABLE_160MHZ.
* @count: to be filled with the counter until the switch (on success only)
* @bssid: the currently connected bssid (for reporting)
* @mode: to be filled with CSA mode (on success only)
* @new_chandef: to be filled with destination chandef (on success only)
* Return: 0 on success, <0 on error and >0 if there is nothing to parse.
*/
int
ieee80211_parse_ch_switch_ie
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee802_11_elems
*
elems
,
bool
beacon
,
enum
ieee80211_band
current_band
,
u32
sta_flags
,
u8
*
bssid
,
u8
*
count
,
u8
*
mode
,
struct
cfg80211_chan_def
*
new_chandef
);
/* Suspend/resume and hw reconfiguration */
int
ieee80211_reconfig
(
struct
ieee80211_local
*
local
);
...
...
@@ -1654,6 +1681,7 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
void
ieee80211_ht_oper_to_chandef
(
struct
ieee80211_channel
*
control_chan
,
const
struct
ieee80211_ht_operation
*
ht_oper
,
struct
cfg80211_chan_def
*
chandef
);
u32
ieee80211_chandef_downgrade
(
struct
cfg80211_chan_def
*
c
);
int
__must_check
ieee80211_vif_use_channel
(
struct
ieee80211_sub_if_data
*
sdata
,
...
...
net/mac80211/iface.c
View file @
e9517fec
...
...
@@ -766,6 +766,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_STATION
)
ieee80211_mgd_stop
(
sdata
);
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_ADHOC
)
ieee80211_ibss_stop
(
sdata
);
/*
* Remove all stations associated with this interface.
*
...
...
net/mac80211/key.c
View file @
e9517fec
...
...
@@ -879,7 +879,7 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
keyconf
->
keylen
,
keyconf
->
key
,
0
,
NULL
);
if
(
IS_ERR
(
key
))
return
ERR_
PTR
(
PTR_ERR
(
key
)
);
return
ERR_
CAST
(
key
);
if
(
sdata
->
u
.
mgd
.
mfp
!=
IEEE80211_MFP_DISABLED
)
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_RX_MGMT
;
...
...
net/mac80211/mlme.c
View file @
e9517fec
This diff is collapsed.
Click to expand it.
net/mac80211/rc80211_minstrel.c
View file @
e9517fec
...
...
@@ -203,6 +203,15 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
memcpy
(
mi
->
max_tp_rate
,
tmp_tp_rate
,
sizeof
(
mi
->
max_tp_rate
));
mi
->
max_prob_rate
=
tmp_prob_rate
;
#ifdef CONFIG_MAC80211_DEBUGFS
/* use fixed index if set */
if
(
mp
->
fixed_rate_idx
!=
-
1
)
{
mi
->
max_tp_rate
[
0
]
=
mp
->
fixed_rate_idx
;
mi
->
max_tp_rate
[
1
]
=
mp
->
fixed_rate_idx
;
mi
->
max_prob_rate
=
mp
->
fixed_rate_idx
;
}
#endif
/* Reset update timer */
mi
->
stats_update
=
jiffies
;
...
...
@@ -310,6 +319,11 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
/* increase sum packet counter */
mi
->
packet_count
++
;
#ifdef CONFIG_MAC80211_DEBUGFS
if
(
mp
->
fixed_rate_idx
!=
-
1
)
return
;
#endif
delta
=
(
mi
->
packet_count
*
sampling_ratio
/
100
)
-
(
mi
->
sample_count
+
mi
->
sample_deferred
/
2
);
...
...
net/mac80211/rc80211_minstrel_ht.c
View file @
e9517fec
...
...
@@ -365,6 +365,14 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
}
}
#ifdef CONFIG_MAC80211_DEBUGFS
/* use fixed index if set */
if
(
mp
->
fixed_rate_idx
!=
-
1
)
{
mi
->
max_tp_rate
=
mp
->
fixed_rate_idx
;
mi
->
max_tp_rate2
=
mp
->
fixed_rate_idx
;
mi
->
max_prob_rate
=
mp
->
fixed_rate_idx
;
}
#endif
mi
->
stats_update
=
jiffies
;
}
...
...
@@ -774,6 +782,11 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
info
->
flags
|=
mi
->
tx_flags
;
minstrel_ht_check_cck_shortpreamble
(
mp
,
mi
,
txrc
->
short_preamble
);
#ifdef CONFIG_MAC80211_DEBUGFS
if
(
mp
->
fixed_rate_idx
!=
-
1
)
return
;
#endif
/* Don't use EAPOL frames for sampling on non-mrr hw */
if
(
mp
->
hw
->
max_rates
==
1
&&
(
info
->
control
.
flags
&
IEEE80211_TX_CTRL_PORT_CTRL_PROTO
))
...
...
@@ -781,16 +794,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
else
sample_idx
=
minstrel_get_sample_rate
(
mp
,
mi
);
#ifdef CONFIG_MAC80211_DEBUGFS
/* use fixed index if set */
if
(
mp
->
fixed_rate_idx
!=
-
1
)
{
mi
->
max_tp_rate
=
mp
->
fixed_rate_idx
;
mi
->
max_tp_rate2
=
mp
->
fixed_rate_idx
;
mi
->
max_prob_rate
=
mp
->
fixed_rate_idx
;
sample_idx
=
-
1
;
}
#endif
mi
->
total_packets
++
;
/* wraparound */
...
...
net/mac80211/rc80211_pid_debugfs.c
View file @
e9517fec
...
...
@@ -167,29 +167,29 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf,
* provide large enough buffers. */
length
=
length
<
RC_PID_PRINT_BUF_SIZE
?
length
:
RC_PID_PRINT_BUF_SIZE
;
p
=
snprintf
(
pb
,
length
,
"%u %lu "
,
ev
->
id
,
ev
->
timestamp
);
p
=
s
c
nprintf
(
pb
,
length
,
"%u %lu "
,
ev
->
id
,
ev
->
timestamp
);
switch
(
ev
->
type
)
{
case
RC_PID_EVENT_TYPE_TX_STATUS
:
p
+=
snprintf
(
pb
+
p
,
length
-
p
,
"tx_status %u %u"
,
!
(
ev
->
data
.
flags
&
IEEE80211_TX_STAT_ACK
),
ev
->
data
.
tx_status
.
status
.
rates
[
0
].
idx
);
p
+=
s
c
nprintf
(
pb
+
p
,
length
-
p
,
"tx_status %u %u"
,
!
(
ev
->
data
.
flags
&
IEEE80211_TX_STAT_ACK
),
ev
->
data
.
tx_status
.
status
.
rates
[
0
].
idx
);
break
;
case
RC_PID_EVENT_TYPE_RATE_CHANGE
:
p
+=
snprintf
(
pb
+
p
,
length
-
p
,
"rate_change %d %d"
,
ev
->
data
.
index
,
ev
->
data
.
rate
);
p
+=
s
c
nprintf
(
pb
+
p
,
length
-
p
,
"rate_change %d %d"
,
ev
->
data
.
index
,
ev
->
data
.
rate
);
break
;
case
RC_PID_EVENT_TYPE_TX_RATE
:
p
+=
snprintf
(
pb
+
p
,
length
-
p
,
"tx_rate %d %d"
,
ev
->
data
.
index
,
ev
->
data
.
rate
);
p
+=
s
c
nprintf
(
pb
+
p
,
length
-
p
,
"tx_rate %d %d"
,
ev
->
data
.
index
,
ev
->
data
.
rate
);
break
;
case
RC_PID_EVENT_TYPE_PF_SAMPLE
:
p
+=
snprintf
(
pb
+
p
,
length
-
p
,
"pf_sample %d %d %d %d"
,
ev
->
data
.
pf_sample
,
ev
->
data
.
prop_err
,
ev
->
data
.
int_err
,
ev
->
data
.
der_err
);
p
+=
s
c
nprintf
(
pb
+
p
,
length
-
p
,
"pf_sample %d %d %d %d"
,
ev
->
data
.
pf_sample
,
ev
->
data
.
prop_err
,
ev
->
data
.
int_err
,
ev
->
data
.
der_err
);
break
;
}
p
+=
snprintf
(
pb
+
p
,
length
-
p
,
"
\n
"
);
p
+=
s
c
nprintf
(
pb
+
p
,
length
-
p
,
"
\n
"
);
spin_unlock_irqrestore
(
&
events
->
lock
,
status
);
...
...
net/mac80211/rx.c
View file @
e9517fec
...
...
@@ -995,8 +995,9 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
rx
->
sta
->
num_duplicates
++
;
}
return
RX_DROP_UNUSABLE
;
}
else
}
else
if
(
!
(
status
->
flag
&
RX_FLAG_AMSDU_MORE
))
{
rx
->
sta
->
last_seq_ctrl
[
rx
->
seqno_idx
]
=
hdr
->
seq_ctrl
;
}
}
if
(
unlikely
(
rx
->
skb
->
len
<
16
))
{
...
...
@@ -2402,7 +2403,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
return
RX_DROP_UNUSABLE
;
if
(
!
rx
->
sta
&&
mgmt
->
u
.
action
.
category
!=
WLAN_CATEGORY_PUBLIC
&&
mgmt
->
u
.
action
.
category
!=
WLAN_CATEGORY_SELF_PROTECTED
)
mgmt
->
u
.
action
.
category
!=
WLAN_CATEGORY_SELF_PROTECTED
&&
mgmt
->
u
.
action
.
category
!=
WLAN_CATEGORY_SPECTRUM_MGMT
)
return
RX_DROP_UNUSABLE
;
if
(
!
(
status
->
rx_flags
&
IEEE80211_RX_RA_MATCH
))
...
...
@@ -2566,31 +2568,46 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
goto
queue
;
case
WLAN_CATEGORY_SPECTRUM_MGMT
:
if
(
status
->
band
!=
IEEE80211_BAND_5GHZ
)
break
;
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
)
break
;
/* verify action_code is present */
if
(
len
<
IEEE80211_MIN_ACTION_SIZE
+
1
)
break
;
switch
(
mgmt
->
u
.
action
.
u
.
measurement
.
action_code
)
{
case
WLAN_ACTION_SPCT_MSR_REQ
:
if
(
status
->
band
!=
IEEE80211_BAND_5GHZ
)
break
;
if
(
len
<
(
IEEE80211_MIN_ACTION_SIZE
+
sizeof
(
mgmt
->
u
.
action
.
u
.
measurement
)))
break
;
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
)
break
;
ieee80211_process_measurement_req
(
sdata
,
mgmt
,
len
);
goto
handled
;
case
WLAN_ACTION_SPCT_CHL_SWITCH
:
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
)
case
WLAN_ACTION_SPCT_CHL_SWITCH
:
{
u8
*
bssid
;
if
(
len
<
(
IEEE80211_MIN_ACTION_SIZE
+
sizeof
(
mgmt
->
u
.
action
.
u
.
chan_switch
)))
break
;
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
&&
sdata
->
vif
.
type
!=
NL80211_IFTYPE_ADHOC
)
break
;
if
(
!
ether_addr_equal
(
mgmt
->
bssid
,
sdata
->
u
.
mgd
.
bssid
))
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_STATION
)
bssid
=
sdata
->
u
.
mgd
.
bssid
;
else
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_ADHOC
)
bssid
=
sdata
->
u
.
ibss
.
bssid
;
else
break
;
if
(
!
ether_addr_equal
(
mgmt
->
bssid
,
bssid
))
break
;
goto
queue
;
}
}
break
;
case
WLAN_CATEGORY_SA_QUERY
:
...
...
net/mac80211/scan.c
View file @
e9517fec
...
...
@@ -391,8 +391,7 @@ static bool ieee80211_can_scan(struct ieee80211_local *local,
return
false
;
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_STATION
&&
sdata
->
u
.
mgd
.
flags
&
(
IEEE80211_STA_BEACON_POLL
|
IEEE80211_STA_CONNECTION_POLL
))
sdata
->
u
.
mgd
.
flags
&
IEEE80211_STA_CONNECTION_POLL
)
return
false
;
return
true
;
...
...
net/mac80211/spectmgmt.c
View file @
e9517fec
...
...
@@ -21,6 +21,168 @@
#include "sta_info.h"
#include "wme.h"
int
ieee80211_parse_ch_switch_ie
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee802_11_elems
*
elems
,
bool
beacon
,
enum
ieee80211_band
current_band
,
u32
sta_flags
,
u8
*
bssid
,
u8
*
count
,
u8
*
mode
,
struct
cfg80211_chan_def
*
new_chandef
)
{
enum
ieee80211_band
new_band
;
int
new_freq
;
u8
new_chan_no
;
struct
ieee80211_channel
*
new_chan
;
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
;
const
struct
ieee80211_ht_operation
*
ht_oper
;
int
secondary_channel_offset
=
-
1
;
sec_chan_offs
=
elems
->
sec_chan_offs
;
wide_bw_chansw_ie
=
elems
->
wide_bw_chansw_ie
;
ht_oper
=
elems
->
ht_operation
;
if
(
sta_flags
&
(
IEEE80211_STA_DISABLE_HT
|
IEEE80211_STA_DISABLE_40MHZ
))
{
sec_chan_offs
=
NULL
;
wide_bw_chansw_ie
=
NULL
;
/* only used for bandwidth here */
ht_oper
=
NULL
;
}
if
(
sta_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
);
return
-
EINVAL
;
}
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
=
current_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
1
;
}
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
,
"BSS %pM switches to unsupported channel (%d MHz), disconnecting
\n
"
,
bssid
,
new_freq
);
return
-
EINVAL
;
}
if
(
!
beacon
&&
sec_chan_offs
)
{
secondary_channel_offset
=
sec_chan_offs
->
sec_chan_offs
;
}
else
if
(
beacon
&&
ht_oper
)
{
secondary_channel_offset
=
ht_oper
->
ht_param
&
IEEE80211_HT_PARAM_CHA_SEC_OFFSET
;
}
else
if
(
!
(
sta_flags
&
IEEE80211_STA_DISABLE_HT
))
{
/* If it's not a beacon, HT is enabled and the IE not present,
* it's 20 MHz, 802.11-2012 8.5.2.6:
* This element [the Secondary Channel Offset Element] is
* present when switching to a 40 MHz channel. It may be
* present when switching to a 20 MHz channel (in which
* case the secondary channel offset is set to SCN).
*/
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
);
/* 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
;
}
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
(
sta_flags
&
IEEE80211_STA_DISABLE_80P80MHZ
&&
new_vht_chandef
.
width
==
NL80211_CHAN_WIDTH_80P80
)
ieee80211_chandef_downgrade
(
&
new_vht_chandef
);
if
(
sta_flags
&
IEEE80211_STA_DISABLE_160MHZ
&&
new_vht_chandef
.
width
==
NL80211_CHAN_WIDTH_160
)
ieee80211_chandef_downgrade
(
&
new_vht_chandef
);
if
(
sta_flags
&
IEEE80211_STA_DISABLE_40MHZ
&&
new_vht_chandef
.
width
>
NL80211_CHAN_WIDTH_20
)
ieee80211_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
,
"BSS %pM: CSA has inconsistent channel data, disconnecting
\n
"
,
bssid
);
return
-
EINVAL
;
}
*
new_chandef
=
new_vht_chandef
;
}
return
0
;
}
static
void
ieee80211_send_refuse_measurement_request
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_msrment_ie
*
request_ie
,
const
u8
*
da
,
const
u8
*
bssid
,
...
...
net/mac80211/trace.h
View file @
e9517fec
...
...
@@ -1475,6 +1475,41 @@ DEFINE_EVENT(local_sdata_evt, drv_ipv6_addr_change,
);
#endif
TRACE_EVENT
(
drv_join_ibss
,
TP_PROTO
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_bss_conf
*
info
),
TP_ARGS
(
local
,
sdata
,
info
),
TP_STRUCT__entry
(
LOCAL_ENTRY
VIF_ENTRY
__field
(
u8
,
dtimper
)
__field
(
u16
,
bcnint
)
__dynamic_array
(
u8
,
ssid
,
info
->
ssid_len
);
),
TP_fast_assign
(
LOCAL_ASSIGN
;
VIF_ASSIGN
;
__entry
->
dtimper
=
info
->
dtim_period
;
__entry
->
bcnint
=
info
->
beacon_int
;
memcpy
(
__get_dynamic_array
(
ssid
),
info
->
ssid
,
info
->
ssid_len
);
),
TP_printk
(
LOCAL_PR_FMT
VIF_PR_FMT
,
LOCAL_PR_ARG
,
VIF_PR_ARG
)
);
DEFINE_EVENT
(
local_sdata_evt
,
drv_leave_ibss
,
TP_PROTO
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
),
TP_ARGS
(
local
,
sdata
)
);
/*
* Tracing for API calls that drivers call.
*/
...
...
net/mac80211/tx.c
View file @
e9517fec
...
...
@@ -1981,7 +1981,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
* EAPOL frames from the local station.
*/
if
(
unlikely
(
!
ieee80211_vif_is_mesh
(
&
sdata
->
vif
)
&&
!
is_multicast_ether_addr
(
hdr
.
addr1
)
&&
!
authorized
&&
!
multicast
&&
!
authorized
&&
(
cpu_to_be16
(
ethertype
)
!=
sdata
->
control_port_protocol
||
!
ether_addr_equal
(
sdata
->
vif
.
addr
,
skb
->
data
+
ETH_ALEN
))))
{
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
...
...
@@ -2357,15 +2357,31 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
struct
probe_resp
*
resp
;
int
counter_offset_beacon
=
sdata
->
csa_counter_offset_beacon
;
int
counter_offset_presp
=
sdata
->
csa_counter_offset_presp
;
u8
*
beacon_data
;
size_t
beacon_data_len
;
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_AP
:
beacon_data
=
beacon
->
tail
;
beacon_data_len
=
beacon
->
tail_len
;
break
;
case
NL80211_IFTYPE_ADHOC
:
beacon_data
=
beacon
->
head
;
beacon_data_len
=
beacon
->
head_len
;
break
;
default:
return
;
}
if
(
WARN_ON
(
counter_offset_beacon
>=
beacon_data_len
))
return
;
/* warn if the driver did not check for/react to csa completeness */
if
(
WARN_ON
(
((
u8
*
)
beacon
->
tail
)
[
counter_offset_beacon
]
==
0
))
if
(
WARN_ON
(
beacon_data
[
counter_offset_beacon
]
==
0
))
return
;
((
u8
*
)
beacon
->
tail
)
[
counter_offset_beacon
]
--
;
beacon_data
[
counter_offset_beacon
]
--
;
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_AP
&&
counter_offset_presp
)
{
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_AP
&&
counter_offset_presp
)
{
rcu_read_lock
();
resp
=
rcu_dereference
(
sdata
->
u
.
ap
.
probe_resp
);
...
...
@@ -2400,6 +2416,15 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
goto
out
;
beacon_data
=
beacon
->
tail
;
beacon_data_len
=
beacon
->
tail_len
;
}
else
if
(
vif
->
type
==
NL80211_IFTYPE_ADHOC
)
{
struct
ieee80211_if_ibss
*
ifibss
=
&
sdata
->
u
.
ibss
;
beacon
=
rcu_dereference
(
ifibss
->
presp
);
if
(
!
beacon
)
goto
out
;
beacon_data
=
beacon
->
head
;
beacon_data_len
=
beacon
->
head_len
;
}
else
{
WARN_ON
(
1
);
goto
out
;
...
...
@@ -2484,6 +2509,10 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
if
(
!
presp
)
goto
out
;
if
(
sdata
->
vif
.
csa_active
)
ieee80211_update_csa
(
sdata
,
presp
);
skb
=
dev_alloc_skb
(
local
->
tx_headroom
+
presp
->
head_len
);
if
(
!
skb
)
goto
out
;
...
...
net/mac80211/util.c
View file @
e9517fec
...
...
@@ -567,18 +567,15 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
IEEE80211_QUEUE_STOP_REASON_FLUSH
);
}
void
ieee80211_iterate_active_interfaces
(
struct
ieee80211_hw
*
hw
,
u32
iter_flags
,
void
(
*
iterator
)(
void
*
data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
),
void
*
data
)
static
void
__iterate_active_interfaces
(
struct
ieee80211_local
*
local
,
u32
iter_flags
,
void
(
*
iterator
)(
void
*
data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
),
void
*
data
)
{
struct
ieee80211_local
*
local
=
hw_to_local
(
hw
);
struct
ieee80211_sub_if_data
*
sdata
;
mutex_lock
(
&
local
->
iflist_mtx
);
list_for_each_entry
(
sdata
,
&
local
->
interfaces
,
list
)
{
list_for_each_entry_rcu
(
sdata
,
&
local
->
interfaces
,
list
)
{
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_MONITOR
:
if
(
!
(
sdata
->
u
.
mntr_flags
&
MONITOR_FLAG_ACTIVE
))
...
...
@@ -597,13 +594,25 @@ void ieee80211_iterate_active_interfaces(
&
sdata
->
vif
);
}
sdata
=
rcu_dereference_protected
(
local
->
monitor_sdata
,
lockdep_is_held
(
&
local
->
iflist_mtx
));
sdata
=
rcu_dereference_check
(
local
->
monitor_sdata
,
lockdep_is_held
(
&
local
->
iflist_mtx
)
||
lockdep_rtnl_is_held
());
if
(
sdata
&&
(
iter_flags
&
IEEE80211_IFACE_ITER_RESUME_ALL
||
sdata
->
flags
&
IEEE80211_SDATA_IN_DRIVER
))
iterator
(
data
,
sdata
->
vif
.
addr
,
&
sdata
->
vif
);
}
void
ieee80211_iterate_active_interfaces
(
struct
ieee80211_hw
*
hw
,
u32
iter_flags
,
void
(
*
iterator
)(
void
*
data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
),
void
*
data
)
{
struct
ieee80211_local
*
local
=
hw_to_local
(
hw
);
mutex_lock
(
&
local
->
iflist_mtx
);
__iterate_active_interfaces
(
local
,
iter_flags
,
iterator
,
data
);
mutex_unlock
(
&
local
->
iflist_mtx
);
}
EXPORT_SYMBOL_GPL
(
ieee80211_iterate_active_interfaces
);
...
...
@@ -615,38 +624,26 @@ void ieee80211_iterate_active_interfaces_atomic(
void
*
data
)
{
struct
ieee80211_local
*
local
=
hw_to_local
(
hw
);
struct
ieee80211_sub_if_data
*
sdata
;
rcu_read_lock
();
__iterate_active_interfaces
(
local
,
iter_flags
,
iterator
,
data
);
rcu_read_unlock
();
}
EXPORT_SYMBOL_GPL
(
ieee80211_iterate_active_interfaces_atomic
);
list_for_each_entry_rcu
(
sdata
,
&
local
->
interfaces
,
list
)
{
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_MONITOR
:
if
(
!
(
sdata
->
u
.
mntr_flags
&
MONITOR_FLAG_ACTIVE
))
continue
;
break
;
case
NL80211_IFTYPE_AP_VLAN
:
continue
;
default:
break
;
}
if
(
!
(
iter_flags
&
IEEE80211_IFACE_ITER_RESUME_ALL
)
&&
!
(
sdata
->
flags
&
IEEE80211_SDATA_IN_DRIVER
))
continue
;
if
(
ieee80211_sdata_running
(
sdata
))
iterator
(
data
,
sdata
->
vif
.
addr
,
&
sdata
->
vif
);
}
void
ieee80211_iterate_active_interfaces_rtnl
(
struct
ieee80211_hw
*
hw
,
u32
iter_flags
,
void
(
*
iterator
)(
void
*
data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
),
void
*
data
)
{
struct
ieee80211_local
*
local
=
hw_to_local
(
hw
);
sdata
=
rcu_dereference
(
local
->
monitor_sdata
);
if
(
sdata
&&
(
iter_flags
&
IEEE80211_IFACE_ITER_RESUME_ALL
||
sdata
->
flags
&
IEEE80211_SDATA_IN_DRIVER
))
iterator
(
data
,
sdata
->
vif
.
addr
,
&
sdata
->
vif
);
ASSERT_RTNL
();
rcu_read_unlock
(
);
__iterate_active_interfaces
(
local
,
iter_flags
,
iterator
,
data
);
}
EXPORT_SYMBOL_GPL
(
ieee80211_iterate_active_interfaces_
atomic
);
EXPORT_SYMBOL_GPL
(
ieee80211_iterate_active_interfaces_
rtnl
);
/*
* Nothing should have been stuffed into the workqueue during
...
...
@@ -1007,14 +1004,21 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
*/
enable_qos
=
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
);
for
(
ac
=
0
;
ac
<
IEEE80211_NUM_ACS
;
ac
++
)
{
/* Set defaults according to 802.11-2007 Table 7-37 */
aCWmax
=
1023
;
if
(
use_11b
)
aCWmin
=
31
;
else
aCWmin
=
15
;
/* Set defaults according to 802.11-2007 Table 7-37 */
aCWmax
=
1023
;
if
(
use_11b
)
aCWmin
=
31
;
else
aCWmin
=
15
;
/* Confiure old 802.11b/g medium access rules. */
qparam
.
cw_max
=
aCWmax
;
qparam
.
cw_min
=
aCWmin
;
qparam
.
txop
=
0
;
qparam
.
aifs
=
2
;
for
(
ac
=
0
;
ac
<
IEEE80211_NUM_ACS
;
ac
++
)
{
/* Update if QoS is enabled. */
if
(
enable_qos
)
{
switch
(
ac
)
{
case
IEEE80211_AC_BK
:
...
...
@@ -1050,12 +1054,6 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
qparam
.
aifs
=
2
;
break
;
}
}
else
{
/* Confiure old 802.11b/g medium access rules. */
qparam
.
cw_max
=
aCWmax
;
qparam
.
cw_min
=
aCWmin
;
qparam
.
txop
=
0
;
qparam
.
aifs
=
2
;
}
qparam
.
uapsd
=
false
;
...
...
@@ -1084,8 +1082,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
struct
ieee80211_mgmt
*
mgmt
;
int
err
;
skb
=
dev_alloc_skb
(
local
->
hw
.
extra_tx_headroom
+
sizeof
(
*
mgmt
)
+
6
+
extra_len
);
/* 24 + 6 = header + auth_algo + auth_transaction + status_code */
skb
=
dev_alloc_skb
(
local
->
hw
.
extra_tx_headroom
+
24
+
6
+
extra_len
);
if
(
!
skb
)
return
;
...
...
@@ -2295,3 +2293,63 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw)
ieee80211_queue_work
(
hw
,
&
local
->
radar_detected_work
);
}
EXPORT_SYMBOL
(
ieee80211_radar_detected
);
u32
ieee80211_chandef_downgrade
(
struct
cfg80211_chan_def
*
c
)
{
u32
ret
;
int
tmp
;
switch
(
c
->
width
)
{
case
NL80211_CHAN_WIDTH_20
:
c
->
width
=
NL80211_CHAN_WIDTH_20_NOHT
;
ret
=
IEEE80211_STA_DISABLE_HT
|
IEEE80211_STA_DISABLE_VHT
;
break
;
case
NL80211_CHAN_WIDTH_40
:
c
->
width
=
NL80211_CHAN_WIDTH_20
;
c
->
center_freq1
=
c
->
chan
->
center_freq
;
ret
=
IEEE80211_STA_DISABLE_40MHZ
|
IEEE80211_STA_DISABLE_VHT
;
break
;
case
NL80211_CHAN_WIDTH_80
:
tmp
=
(
30
+
c
->
chan
->
center_freq
-
c
->
center_freq1
)
/
20
;
/* n_P40 */
tmp
/=
2
;
/* freq_P40 */
c
->
center_freq1
=
c
->
center_freq1
-
20
+
40
*
tmp
;
c
->
width
=
NL80211_CHAN_WIDTH_40
;
ret
=
IEEE80211_STA_DISABLE_VHT
;
break
;
case
NL80211_CHAN_WIDTH_80P80
:
c
->
center_freq2
=
0
;
c
->
width
=
NL80211_CHAN_WIDTH_80
;
ret
=
IEEE80211_STA_DISABLE_80P80MHZ
|
IEEE80211_STA_DISABLE_160MHZ
;
break
;
case
NL80211_CHAN_WIDTH_160
:
/* n_P20 */
tmp
=
(
70
+
c
->
chan
->
center_freq
-
c
->
center_freq1
)
/
20
;
/* n_P80 */
tmp
/=
4
;
c
->
center_freq1
=
c
->
center_freq1
-
40
+
80
*
tmp
;
c
->
width
=
NL80211_CHAN_WIDTH_80
;
ret
=
IEEE80211_STA_DISABLE_80P80MHZ
|
IEEE80211_STA_DISABLE_160MHZ
;
break
;
default:
case
NL80211_CHAN_WIDTH_20_NOHT
:
WARN_ON_ONCE
(
1
);
c
->
width
=
NL80211_CHAN_WIDTH_20_NOHT
;
ret
=
IEEE80211_STA_DISABLE_HT
|
IEEE80211_STA_DISABLE_VHT
;
break
;
case
NL80211_CHAN_WIDTH_5
:
case
NL80211_CHAN_WIDTH_10
:
WARN_ON_ONCE
(
1
);
/* keep c->width */
ret
=
IEEE80211_STA_DISABLE_HT
|
IEEE80211_STA_DISABLE_VHT
;
break
;
}
WARN_ON_ONCE
(
!
cfg80211_chandef_valid
(
c
));
return
ret
;
}
net/mac80211/vht.c
View file @
e9517fec
...
...
@@ -185,13 +185,13 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
if
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
)
{
vht_cap
->
cap
|=
cap_info
&
(
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
|
IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX
|
IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX
);
}
if
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
)
vht_cap
->
cap
|=
cap_info
&
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
;
(
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
|
IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX
);
if
(
own_cap
.
cap
&
IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE
)
vht_cap
->
cap
|=
cap_info
&
...
...
net/wireless/chan.c
View file @
e9517fec
...
...
@@ -328,6 +328,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
return
cfg80211_get_chans_dfs_required
(
wiphy
,
chandef
->
center_freq2
,
width
);
}
EXPORT_SYMBOL
(
cfg80211_chandef_dfs_required
);
static
bool
cfg80211_secondary_chans_ok
(
struct
wiphy
*
wiphy
,
u32
center_freq
,
u32
bandwidth
,
...
...
net/wireless/core.h
View file @
e9517fec
...
...
@@ -382,15 +382,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
enum
cfg80211_chan_mode
chanmode
,
u8
radar_detect
);
/**
* cfg80211_chandef_dfs_required - checks if radar detection is required
* @wiphy: the wiphy to validate against
* @chandef: the channel definition to check
* Return: 1 if radar detection is required, 0 if it is not, < 0 on error
*/
int
cfg80211_chandef_dfs_required
(
struct
wiphy
*
wiphy
,
const
struct
cfg80211_chan_def
*
c
);
void
cfg80211_set_dfs_state
(
struct
wiphy
*
wiphy
,
const
struct
cfg80211_chan_def
*
chandef
,
enum
nl80211_dfs_state
dfs_state
);
...
...
net/wireless/debugfs.c
View file @
e9517fec
...
...
@@ -47,17 +47,19 @@ static int ht_print_chan(struct ieee80211_channel *chan,
return
0
;
if
(
chan
->
flags
&
IEEE80211_CHAN_DISABLED
)
return
snprintf
(
buf
+
offset
,
buf_size
-
offset
,
"%d Disabled
\n
"
,
chan
->
center_freq
);
return
snprintf
(
buf
+
offset
,
buf_size
-
offset
,
"%d HT40 %c%c
\n
"
,
chan
->
center_freq
,
(
chan
->
flags
&
IEEE80211_CHAN_NO_HT40MINUS
)
?
' '
:
'-'
,
(
chan
->
flags
&
IEEE80211_CHAN_NO_HT40PLUS
)
?
' '
:
'+'
);
return
scnprintf
(
buf
+
offset
,
buf_size
-
offset
,
"%d Disabled
\n
"
,
chan
->
center_freq
);
return
scnprintf
(
buf
+
offset
,
buf_size
-
offset
,
"%d HT40 %c%c
\n
"
,
chan
->
center_freq
,
(
chan
->
flags
&
IEEE80211_CHAN_NO_HT40MINUS
)
?
' '
:
'-'
,
(
chan
->
flags
&
IEEE80211_CHAN_NO_HT40PLUS
)
?
' '
:
'+'
);
}
static
ssize_t
ht40allow_map_read
(
struct
file
*
file
,
...
...
net/wireless/genregdb.awk
View file @
e9517fec
...
...
@@ -46,6 +46,12 @@ BEGIN {
sub
(
/:/
,
""
,
country
)
printf
"static const struct ieee80211_regdomain regdom_%s = {\n"
,
country
printf
"\t.alpha2 = \"%s\",\n"
,
country
if
(
$NF
~
/DFS-ETSI/
)
printf
"\t.dfs_region = NL80211_DFS_ETSI,\n"
else
if
(
$NF
~
/DFS-FCC/
)
printf
"\t.dfs_region = NL80211_DFS_FCC,\n"
else
if
(
$NF
~
/DFS-JP/
)
printf
"\t.dfs_region = NL80211_DFS_JP,\n"
printf
"\t.reg_rules = {\n"
active
=
1
regdb
=
regdb
"\t®dom_"
country
",\n"
...
...
net/wireless/nl80211.c
View file @
e9517fec
...
...
@@ -5591,6 +5591,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if
(
err
)
return
err
;
if
(
netif_carrier_ok
(
dev
))
return
-
EBUSY
;
if
(
wdev
->
cac_started
)
return
-
EBUSY
;
...
...
@@ -5634,15 +5637,26 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
static
struct
nlattr
*
csa_attrs
[
NL80211_ATTR_MAX
+
1
];
u8
radar_detect_width
=
0
;
int
err
;
bool
need_new_beacon
=
false
;
if
(
!
rdev
->
ops
->
channel_switch
||
!
(
rdev
->
wiphy
.
flags
&
WIPHY_FLAG_HAS_CHANNEL_SWITCH
))
return
-
EOPNOTSUPP
;
/* may add IBSS support later */
if
(
dev
->
ieee80211_ptr
->
iftype
!=
NL80211_IFTYPE_AP
&&
dev
->
ieee80211_ptr
->
iftype
!=
NL80211_IFTYPE_P2P_GO
)
switch
(
dev
->
ieee80211_ptr
->
iftype
)
{
case
NL80211_IFTYPE_AP
:
case
NL80211_IFTYPE_P2P_GO
:
need_new_beacon
=
true
;
/* useless if AP is not running */
if
(
!
wdev
->
beacon_interval
)
return
-
EINVAL
;
break
;
case
NL80211_IFTYPE_ADHOC
:
break
;
default:
return
-
EOPNOTSUPP
;
}
memset
(
&
params
,
0
,
sizeof
(
params
));
...
...
@@ -5651,15 +5665,16 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return
-
EINVAL
;
/* only important for AP, IBSS and mesh create IEs internally */
if
(
!
info
->
attrs
[
NL80211_ATTR_CSA_IES
])
return
-
EINVAL
;
/* useless if AP is not running */
if
(
!
wdev
->
beacon_interval
)
if
(
need_new_beacon
&&
(
!
info
->
attrs
[
NL80211_ATTR_CSA_IES
]
||
!
info
->
attrs
[
NL80211_ATTR_CSA_C_OFF_BEACON
]))
return
-
EINVAL
;
params
.
count
=
nla_get_u32
(
info
->
attrs
[
NL80211_ATTR_CH_SWITCH_COUNT
]);
if
(
!
need_new_beacon
)
goto
skip_beacons
;
err
=
nl80211_parse_beacon
(
info
->
attrs
,
&
params
.
beacon_after
);
if
(
err
)
return
err
;
...
...
@@ -5699,6 +5714,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return
-
EINVAL
;
}
skip_beacons:
err
=
nl80211_parse_chandef
(
rdev
,
info
,
&
params
.
chandef
);
if
(
err
)
return
err
;
...
...
@@ -5706,12 +5722,17 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
if
(
!
cfg80211_reg_can_beacon
(
&
rdev
->
wiphy
,
&
params
.
chandef
))
return
-
EINVAL
;
err
=
cfg80211_chandef_dfs_required
(
wdev
->
wiphy
,
&
params
.
chandef
);
if
(
err
<
0
)
{
return
err
;
}
else
if
(
err
)
{
radar_detect_width
=
BIT
(
params
.
chandef
.
width
);
params
.
radar_required
=
true
;
/* DFS channels are only supported for AP/P2P GO ... for now. */
if
(
dev
->
ieee80211_ptr
->
iftype
==
NL80211_IFTYPE_AP
||
dev
->
ieee80211_ptr
->
iftype
==
NL80211_IFTYPE_P2P_GO
)
{
err
=
cfg80211_chandef_dfs_required
(
wdev
->
wiphy
,
&
params
.
chandef
);
if
(
err
<
0
)
{
return
err
;
}
else
if
(
err
)
{
radar_detect_width
=
BIT
(
params
.
chandef
.
width
);
params
.
radar_required
=
true
;
}
}
err
=
cfg80211_can_use_iftype_chan
(
rdev
,
wdev
,
wdev
->
iftype
,
...
...
@@ -10740,7 +10761,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
wdev_lock
(
wdev
);
if
(
WARN_ON
(
wdev
->
iftype
!=
NL80211_IFTYPE_AP
&&
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_GO
))
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_GO
&&
wdev
->
iftype
!=
NL80211_IFTYPE_ADHOC
))
goto
out
;
wdev
->
channel
=
chandef
->
chan
;
...
...
net/wireless/reg.c
View file @
e9517fec
...
...
@@ -172,11 +172,21 @@ static const struct ieee80211_regdomain world_regdom = {
NL80211_RRF_NO_IBSS
|
NL80211_RRF_NO_OFDM
),
/* IEEE 802.11a, channel 36..48 */
REG_RULE
(
5180
-
10
,
5240
+
10
,
8
0
,
6
,
20
,
REG_RULE
(
5180
-
10
,
5240
+
10
,
16
0
,
6
,
20
,
NL80211_RRF_PASSIVE_SCAN
|
NL80211_RRF_NO_IBSS
),
/* NB: 5260 MHz - 5700 MHz requires DFS */
/* IEEE 802.11a, channel 52..64 - DFS required */
REG_RULE
(
5260
-
10
,
5320
+
10
,
160
,
6
,
20
,
NL80211_RRF_PASSIVE_SCAN
|
NL80211_RRF_NO_IBSS
|
NL80211_RRF_DFS
),
/* IEEE 802.11a, channel 100..144 - DFS required */
REG_RULE
(
5500
-
10
,
5720
+
10
,
160
,
6
,
20
,
NL80211_RRF_PASSIVE_SCAN
|
NL80211_RRF_NO_IBSS
|
NL80211_RRF_DFS
),
/* IEEE 802.11a, channel 149..165 */
REG_RULE
(
5745
-
10
,
5825
+
10
,
80
,
6
,
20
,
...
...
net/wireless/util.c
View file @
e9517fec
...
...
@@ -10,6 +10,7 @@
#include <net/cfg80211.h>
#include <net/ip.h>
#include <net/dsfield.h>
#include <linux/if_vlan.h>
#include "core.h"
#include "rdev-ops.h"
...
...
@@ -691,6 +692,7 @@ EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
unsigned
int
cfg80211_classify8021d
(
struct
sk_buff
*
skb
)
{
unsigned
int
dscp
;
unsigned
char
vlan_priority
;
/* skb->priority values from 256->263 are magic values to
* directly indicate a specific 802.1d priority. This is used
...
...
@@ -700,6 +702,13 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb)
if
(
skb
->
priority
>=
256
&&
skb
->
priority
<=
263
)
return
skb
->
priority
-
256
;
if
(
vlan_tx_tag_present
(
skb
))
{
vlan_priority
=
(
vlan_tx_tag_get
(
skb
)
&
VLAN_PRIO_MASK
)
>>
VLAN_PRIO_SHIFT
;
if
(
vlan_priority
>
0
)
return
vlan_priority
;
}
switch
(
skb
->
protocol
)
{
case
htons
(
ETH_P_IP
):
dscp
=
ipv4_get_dsfield
(
ip_hdr
(
skb
))
&
0xfc
;
...
...
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