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
fa597844
Commit
fa597844
authored
Aug 09, 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
2437f3c5
73da7d5b
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
772 additions
and
34 deletions
+772
-34
include/linux/ieee80211.h
include/linux/ieee80211.h
+9
-0
include/net/cfg80211.h
include/net/cfg80211.h
+33
-0
include/net/mac80211.h
include/net/mac80211.h
+37
-0
include/uapi/linux/nl80211.h
include/uapi/linux/nl80211.h
+30
-0
net/mac80211/cfg.c
net/mac80211/cfg.c
+185
-2
net/mac80211/chan.c
net/mac80211/chan.c
+58
-0
net/mac80211/debugfs_sta.c
net/mac80211/debugfs_sta.c
+9
-0
net/mac80211/driver-ops.h
net/mac80211/driver-ops.h
+13
-0
net/mac80211/ibss.c
net/mac80211/ibss.c
+29
-1
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+17
-1
net/mac80211/iface.c
net/mac80211/iface.c
+9
-0
net/mac80211/led.c
net/mac80211/led.c
+7
-12
net/mac80211/led.h
net/mac80211/led.h
+2
-2
net/mac80211/status.c
net/mac80211/status.c
+64
-14
net/mac80211/trace.h
net/mac80211/trace.h
+26
-0
net/mac80211/tx.c
net/mac80211/tx.c
+78
-1
net/wireless/nl80211.c
net/wireless/nl80211.c
+121
-1
net/wireless/rdev-ops.h
net/wireless/rdev-ops.h
+12
-0
net/wireless/trace.h
net/wireless/trace.h
+33
-0
No files found.
include/linux/ieee80211.h
View file @
fa597844
...
@@ -1709,6 +1709,10 @@ enum ieee80211_eid {
...
@@ -1709,6 +1709,10 @@ enum ieee80211_eid {
WLAN_EID_OPMODE_NOTIF
=
199
,
WLAN_EID_OPMODE_NOTIF
=
199
,
WLAN_EID_WIDE_BW_CHANNEL_SWITCH
=
194
,
WLAN_EID_WIDE_BW_CHANNEL_SWITCH
=
194
,
WLAN_EID_CHANNEL_SWITCH_WRAPPER
=
196
,
WLAN_EID_CHANNEL_SWITCH_WRAPPER
=
196
,
WLAN_EID_EXTENDED_BSS_LOAD
=
193
,
WLAN_EID_VHT_TX_POWER_ENVELOPE
=
195
,
WLAN_EID_AID
=
197
,
WLAN_EID_QUIET_CHANNEL
=
198
,
/* 802.11ad */
/* 802.11ad */
WLAN_EID_NON_TX_BSSID_CAP
=
83
,
WLAN_EID_NON_TX_BSSID_CAP
=
83
,
...
@@ -1860,6 +1864,11 @@ enum ieee80211_tdls_actioncode {
...
@@ -1860,6 +1864,11 @@ enum ieee80211_tdls_actioncode {
WLAN_TDLS_DISCOVERY_REQUEST
=
10
,
WLAN_TDLS_DISCOVERY_REQUEST
=
10
,
};
};
/* Interworking capabilities are set in 7th bit of 4th byte of the
* @WLAN_EID_EXT_CAPABILITY information element
*/
#define WLAN_EXT_CAPA4_INTERWORKING_ENABLED BIT(7)
/*
/*
* TDLS capabililites to be enabled in the 5th byte of the
* TDLS capabililites to be enabled in the 5th byte of the
* @WLAN_EID_EXT_CAPABILITY information element
* @WLAN_EID_EXT_CAPABILITY information element
...
...
include/net/cfg80211.h
View file @
fa597844
...
@@ -665,6 +665,30 @@ struct cfg80211_ap_settings {
...
@@ -665,6 +665,30 @@ struct cfg80211_ap_settings {
bool
radar_required
;
bool
radar_required
;
};
};
/**
* struct cfg80211_csa_settings - channel switch settings
*
* Used for channel switch
*
* @chandef: defines the channel to use after the switch
* @beacon_csa: beacon data while performing the switch
* @counter_offset_beacon: offset for the counter within the beacon (tail)
* @counter_offset_presp: offset for the counter within the probe response
* @beacon_after: beacon data to be used on the new channel
* @radar_required: whether radar detection is required on the new channel
* @block_tx: whether transmissions should be blocked while changing
* @count: number of beacons until switch
*/
struct
cfg80211_csa_settings
{
struct
cfg80211_chan_def
chandef
;
struct
cfg80211_beacon_data
beacon_csa
;
u16
counter_offset_beacon
,
counter_offset_presp
;
struct
cfg80211_beacon_data
beacon_after
;
bool
radar_required
;
bool
block_tx
;
u8
count
;
};
/**
/**
* enum station_parameters_apply_mask - station parameter values to apply
* enum station_parameters_apply_mask - station parameter values to apply
* @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
* @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
...
@@ -2139,6 +2163,8 @@ struct cfg80211_update_ft_ies_params {
...
@@ -2139,6 +2163,8 @@ struct cfg80211_update_ft_ies_params {
* @crit_proto_stop: Indicates critical protocol no longer needs increased link
* @crit_proto_stop: Indicates critical protocol no longer needs increased link
* reliability. This operation can not fail.
* reliability. This operation can not fail.
* @set_coalesce: Set coalesce parameters.
* @set_coalesce: Set coalesce parameters.
*
* @channel_switch: initiate channel-switch procedure (with CSA)
*/
*/
struct
cfg80211_ops
{
struct
cfg80211_ops
{
int
(
*
suspend
)(
struct
wiphy
*
wiphy
,
struct
cfg80211_wowlan
*
wow
);
int
(
*
suspend
)(
struct
wiphy
*
wiphy
,
struct
cfg80211_wowlan
*
wow
);
...
@@ -2376,6 +2402,10 @@ struct cfg80211_ops {
...
@@ -2376,6 +2402,10 @@ struct cfg80211_ops {
struct
wireless_dev
*
wdev
);
struct
wireless_dev
*
wdev
);
int
(
*
set_coalesce
)(
struct
wiphy
*
wiphy
,
int
(
*
set_coalesce
)(
struct
wiphy
*
wiphy
,
struct
cfg80211_coalesce
*
coalesce
);
struct
cfg80211_coalesce
*
coalesce
);
int
(
*
channel_switch
)(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
cfg80211_csa_settings
*
params
);
};
};
/*
/*
...
@@ -2441,6 +2471,8 @@ struct cfg80211_ops {
...
@@ -2441,6 +2471,8 @@ struct cfg80211_ops {
* @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX.
* @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX.
* @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call.
* @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call.
* @WIPHY_FLAG_SUPPORTS_5_10_MHZ: Device supports 5 MHz and 10 MHz channels.
* @WIPHY_FLAG_SUPPORTS_5_10_MHZ: Device supports 5 MHz and 10 MHz channels.
* @WIPHY_FLAG_HAS_CHANNEL_SWITCH: Device supports channel switch in
* beaconing mode (AP, IBSS, Mesh, ...).
*/
*/
enum
wiphy_flags
{
enum
wiphy_flags
{
WIPHY_FLAG_CUSTOM_REGULATORY
=
BIT
(
0
),
WIPHY_FLAG_CUSTOM_REGULATORY
=
BIT
(
0
),
...
@@ -2465,6 +2497,7 @@ enum wiphy_flags {
...
@@ -2465,6 +2497,7 @@ enum wiphy_flags {
WIPHY_FLAG_OFFCHAN_TX
=
BIT
(
20
),
WIPHY_FLAG_OFFCHAN_TX
=
BIT
(
20
),
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
=
BIT
(
21
),
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
=
BIT
(
21
),
WIPHY_FLAG_SUPPORTS_5_10_MHZ
=
BIT
(
22
),
WIPHY_FLAG_SUPPORTS_5_10_MHZ
=
BIT
(
22
),
WIPHY_FLAG_HAS_CHANNEL_SWITCH
=
BIT
(
23
),
};
};
/**
/**
...
...
include/net/mac80211.h
View file @
fa597844
...
@@ -152,11 +152,14 @@ struct ieee80211_low_level_stats {
...
@@ -152,11 +152,14 @@ struct ieee80211_low_level_stats {
* @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed
* @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed
* @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
* @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
* @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed
* @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed
* @IEEE80211_CHANCTX_CHANGE_CHANNEL: switched to another operating channel,
* this is used only with channel switching with CSA
*/
*/
enum
ieee80211_chanctx_change
{
enum
ieee80211_chanctx_change
{
IEEE80211_CHANCTX_CHANGE_WIDTH
=
BIT
(
0
),
IEEE80211_CHANCTX_CHANGE_WIDTH
=
BIT
(
0
),
IEEE80211_CHANCTX_CHANGE_RX_CHAINS
=
BIT
(
1
),
IEEE80211_CHANCTX_CHANGE_RX_CHAINS
=
BIT
(
1
),
IEEE80211_CHANCTX_CHANGE_RADAR
=
BIT
(
2
),
IEEE80211_CHANCTX_CHANGE_RADAR
=
BIT
(
2
),
IEEE80211_CHANCTX_CHANGE_CHANNEL
=
BIT
(
3
),
};
};
/**
/**
...
@@ -1084,6 +1087,7 @@ enum ieee80211_vif_flags {
...
@@ -1084,6 +1087,7 @@ enum ieee80211_vif_flags {
* @addr: address of this interface
* @addr: address of this interface
* @p2p: indicates whether this AP or STA interface is a p2p
* @p2p: indicates whether this AP or STA interface is a p2p
* interface, i.e. a GO or p2p-sta respectively
* interface, i.e. a GO or p2p-sta respectively
* @csa_active: marks whether a channel switch is going on
* @driver_flags: flags/capabilities the driver has for this interface,
* @driver_flags: flags/capabilities the driver has for this interface,
* these need to be set (or cleared) when the interface is added
* these need to be set (or cleared) when the interface is added
* or, if supported by the driver, the interface type is changed
* or, if supported by the driver, the interface type is changed
...
@@ -1106,6 +1110,7 @@ struct ieee80211_vif {
...
@@ -1106,6 +1110,7 @@ struct ieee80211_vif {
struct
ieee80211_bss_conf
bss_conf
;
struct
ieee80211_bss_conf
bss_conf
;
u8
addr
[
ETH_ALEN
];
u8
addr
[
ETH_ALEN
];
bool
p2p
;
bool
p2p
;
bool
csa_active
;
u8
cab_queue
;
u8
cab_queue
;
u8
hw_queue
[
IEEE80211_NUM_ACS
];
u8
hw_queue
[
IEEE80211_NUM_ACS
];
...
@@ -2637,6 +2642,16 @@ enum ieee80211_roc_type {
...
@@ -2637,6 +2642,16 @@ enum ieee80211_roc_type {
* @ipv6_addr_change: IPv6 address assignment on the given interface changed.
* @ipv6_addr_change: IPv6 address assignment on the given interface changed.
* Currently, this is only called for managed or P2P client interfaces.
* Currently, this is only called for managed or P2P client interfaces.
* This callback is optional; it must not sleep.
* This callback is optional; it must not sleep.
*
* @channel_switch_beacon: Starts a channel switch to a new channel.
* Beacons are modified to include CSA or ECSA IEs before calling this
* function. The corresponding count fields in these IEs must be
* decremented, and when they reach zero the driver must call
* ieee80211_csa_finish(). Drivers which use ieee80211_beacon_get()
* get the csa counter decremented by mac80211, but must check if it is
* zero using ieee80211_csa_is_complete() after the beacon has been
* transmitted and then call ieee80211_csa_finish().
*
*/
*/
struct
ieee80211_ops
{
struct
ieee80211_ops
{
void
(
*
tx
)(
struct
ieee80211_hw
*
hw
,
void
(
*
tx
)(
struct
ieee80211_hw
*
hw
,
...
@@ -2824,6 +2839,9 @@ struct ieee80211_ops {
...
@@ -2824,6 +2839,9 @@ struct ieee80211_ops {
struct
ieee80211_vif
*
vif
,
struct
ieee80211_vif
*
vif
,
struct
inet6_dev
*
idev
);
struct
inet6_dev
*
idev
);
#endif
#endif
void
(
*
channel_switch_beacon
)(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
cfg80211_chan_def
*
chandef
);
};
};
/**
/**
...
@@ -3318,6 +3336,25 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
...
@@ -3318,6 +3336,25 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
return
ieee80211_beacon_get_tim
(
hw
,
vif
,
NULL
,
NULL
);
return
ieee80211_beacon_get_tim
(
hw
,
vif
,
NULL
,
NULL
);
}
}
/**
* ieee80211_csa_finish - notify mac80211 about channel switch
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
*
* After a channel switch announcement was scheduled and the counter in this
* announcement hit zero, this function must be called by the driver to
* notify mac80211 that the channel can be changed.
*/
void
ieee80211_csa_finish
(
struct
ieee80211_vif
*
vif
);
/**
* ieee80211_csa_is_complete - find out if counters reached zero
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
*
* This function returns whether the channel switch counters reached zero.
*/
bool
ieee80211_csa_is_complete
(
struct
ieee80211_vif
*
vif
);
/**
/**
* ieee80211_proberesp_get - retrieve a Probe Response template
* ieee80211_proberesp_get - retrieve a Probe Response template
* @hw: pointer obtained from ieee80211_alloc_hw().
* @hw: pointer obtained from ieee80211_alloc_hw().
...
...
include/uapi/linux/nl80211.h
View file @
fa597844
...
@@ -676,6 +676,16 @@
...
@@ -676,6 +676,16 @@
* @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules.
* @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules.
* @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules.
* @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules.
*
*
* @NL80211_CMD_CHANNEL_SWITCH: Perform a channel switch by announcing the
* the new channel information (Channel Switch Announcement - CSA)
* in the beacon for some time (as defined in the
* %NL80211_ATTR_CH_SWITCH_COUNT parameter) and then change to the
* new channel. Userspace provides the new channel information (using
* %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel
* width). %NL80211_ATTR_CH_SWITCH_BLOCK_TX may be supplied to inform
* other station that transmission must be blocked until the channel
* switch is complete.
*
* @NL80211_CMD_MAX: highest used command number
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
* @__NL80211_CMD_AFTER_LAST: internal use
*/
*/
...
@@ -841,6 +851,8 @@ enum nl80211_commands {
...
@@ -841,6 +851,8 @@ enum nl80211_commands {
NL80211_CMD_GET_COALESCE
,
NL80211_CMD_GET_COALESCE
,
NL80211_CMD_SET_COALESCE
,
NL80211_CMD_SET_COALESCE
,
NL80211_CMD_CHANNEL_SWITCH
,
/* add new commands above here */
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
/* used to define NL80211_CMD_MAX below */
...
@@ -1469,6 +1481,18 @@ enum nl80211_commands {
...
@@ -1469,6 +1481,18 @@ enum nl80211_commands {
*
*
* @NL80211_ATTR_COALESCE_RULE: Coalesce rule information.
* @NL80211_ATTR_COALESCE_RULE: Coalesce rule information.
*
*
* @NL80211_ATTR_CH_SWITCH_COUNT: u32 attribute specifying the number of TBTT's
* until the channel switch event.
* @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission
* must be blocked on the current channel (before the channel switch
* operation).
* @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information
* for the time while performing a channel switch.
* @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter
* field in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
* @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter
* field in the probe response (%NL80211_ATTR_PROBE_RESP).
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
*/
...
@@ -1771,6 +1795,12 @@ enum nl80211_attrs {
...
@@ -1771,6 +1795,12 @@ enum nl80211_attrs {
NL80211_ATTR_COALESCE_RULE
,
NL80211_ATTR_COALESCE_RULE
,
NL80211_ATTR_CH_SWITCH_COUNT
,
NL80211_ATTR_CH_SWITCH_BLOCK_TX
,
NL80211_ATTR_CSA_IES
,
NL80211_ATTR_CSA_C_OFF_BEACON
,
NL80211_ATTR_CSA_C_OFF_PRESP
,
/* add attributes here, update the policy in nl80211.c */
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST
,
__NL80211_ATTR_AFTER_LAST
,
...
...
net/mac80211/cfg.c
View file @
fa597844
...
@@ -862,8 +862,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
...
@@ -862,8 +862,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
return
0
;
return
0
;
}
}
static
int
ieee80211_assign_beacon
(
struct
ieee80211_sub_if_data
*
sdata
,
int
ieee80211_assign_beacon
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
cfg80211_beacon_data
*
params
)
struct
cfg80211_beacon_data
*
params
)
{
{
struct
beacon_data
*
new
,
*
old
;
struct
beacon_data
*
new
,
*
old
;
int
new_head_len
,
new_tail_len
;
int
new_head_len
,
new_tail_len
;
...
@@ -1026,6 +1026,12 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
...
@@ -1026,6 +1026,12 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
dev
);
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
dev
);
/* don't allow changing the beacon while CSA is in place - offset
* of channel switch counter may change
*/
if
(
sdata
->
vif
.
csa_active
)
return
-
EBUSY
;
old
=
rtnl_dereference
(
sdata
->
u
.
ap
.
beacon
);
old
=
rtnl_dereference
(
sdata
->
u
.
ap
.
beacon
);
if
(
!
old
)
if
(
!
old
)
return
-
ENOENT
;
return
-
ENOENT
;
...
@@ -1050,6 +1056,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
...
@@ -1050,6 +1056,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
return
-
ENOENT
;
return
-
ENOENT
;
old_probe_resp
=
rtnl_dereference
(
sdata
->
u
.
ap
.
probe_resp
);
old_probe_resp
=
rtnl_dereference
(
sdata
->
u
.
ap
.
probe_resp
);
/* abort any running channel switch */
sdata
->
vif
.
csa_active
=
false
;
cancel_work_sync
(
&
sdata
->
csa_finalize_work
);
/* turn off carrier for this interface and dependent VLANs */
/* turn off carrier for this interface and dependent VLANs */
list_for_each_entry
(
vlan
,
&
sdata
->
u
.
ap
.
vlans
,
u
.
vlan
.
list
)
list_for_each_entry
(
vlan
,
&
sdata
->
u
.
ap
.
vlans
,
u
.
vlan
.
list
)
netif_carrier_off
(
vlan
->
dev
);
netif_carrier_off
(
vlan
->
dev
);
...
@@ -2777,6 +2787,178 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
...
@@ -2777,6 +2787,178 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
return
0
;
return
0
;
}
}
static
struct
cfg80211_beacon_data
*
cfg80211_beacon_dup
(
struct
cfg80211_beacon_data
*
beacon
)
{
struct
cfg80211_beacon_data
*
new_beacon
;
u8
*
pos
;
int
len
;
len
=
beacon
->
head_len
+
beacon
->
tail_len
+
beacon
->
beacon_ies_len
+
beacon
->
proberesp_ies_len
+
beacon
->
assocresp_ies_len
+
beacon
->
probe_resp_len
;
new_beacon
=
kzalloc
(
sizeof
(
*
new_beacon
)
+
len
,
GFP_KERNEL
);
if
(
!
new_beacon
)
return
NULL
;
pos
=
(
u8
*
)(
new_beacon
+
1
);
if
(
beacon
->
head_len
)
{
new_beacon
->
head_len
=
beacon
->
head_len
;
new_beacon
->
head
=
pos
;
memcpy
(
pos
,
beacon
->
head
,
beacon
->
head_len
);
pos
+=
beacon
->
head_len
;
}
if
(
beacon
->
tail_len
)
{
new_beacon
->
tail_len
=
beacon
->
tail_len
;
new_beacon
->
tail
=
pos
;
memcpy
(
pos
,
beacon
->
tail
,
beacon
->
tail_len
);
pos
+=
beacon
->
tail_len
;
}
if
(
beacon
->
beacon_ies_len
)
{
new_beacon
->
beacon_ies_len
=
beacon
->
beacon_ies_len
;
new_beacon
->
beacon_ies
=
pos
;
memcpy
(
pos
,
beacon
->
beacon_ies
,
beacon
->
beacon_ies_len
);
pos
+=
beacon
->
beacon_ies_len
;
}
if
(
beacon
->
proberesp_ies_len
)
{
new_beacon
->
proberesp_ies_len
=
beacon
->
proberesp_ies_len
;
new_beacon
->
proberesp_ies
=
pos
;
memcpy
(
pos
,
beacon
->
proberesp_ies
,
beacon
->
proberesp_ies_len
);
pos
+=
beacon
->
proberesp_ies_len
;
}
if
(
beacon
->
assocresp_ies_len
)
{
new_beacon
->
assocresp_ies_len
=
beacon
->
assocresp_ies_len
;
new_beacon
->
assocresp_ies
=
pos
;
memcpy
(
pos
,
beacon
->
assocresp_ies
,
beacon
->
assocresp_ies_len
);
pos
+=
beacon
->
assocresp_ies_len
;
}
if
(
beacon
->
probe_resp_len
)
{
new_beacon
->
probe_resp_len
=
beacon
->
probe_resp_len
;
beacon
->
probe_resp
=
pos
;
memcpy
(
pos
,
beacon
->
probe_resp
,
beacon
->
probe_resp_len
);
pos
+=
beacon
->
probe_resp_len
;
}
return
new_beacon
;
}
void
ieee80211_csa_finalize_work
(
struct
work_struct
*
work
)
{
struct
ieee80211_sub_if_data
*
sdata
=
container_of
(
work
,
struct
ieee80211_sub_if_data
,
csa_finalize_work
);
struct
ieee80211_local
*
local
=
sdata
->
local
;
int
err
,
changed
;
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
;
changed
|=
err
;
kfree
(
sdata
->
u
.
ap
.
next_beacon
);
sdata
->
u
.
ap
.
next_beacon
=
NULL
;
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
);
}
static
int
ieee80211_channel_switch
(
struct
wiphy
*
wiphy
,
struct
net_device
*
dev
,
struct
cfg80211_csa_settings
*
params
)
{
struct
ieee80211_sub_if_data
*
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
dev
);
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_chanctx_conf
*
chanctx_conf
;
struct
ieee80211_chanctx
*
chanctx
;
int
err
,
num_chanctx
;
if
(
!
list_empty
(
&
local
->
roc_list
)
||
local
->
scanning
)
return
-
EBUSY
;
if
(
sdata
->
wdev
.
cac_started
)
return
-
EBUSY
;
if
(
cfg80211_chandef_identical
(
&
params
->
chandef
,
&
sdata
->
vif
.
bss_conf
.
chandef
))
return
-
EINVAL
;
rcu_read_lock
();
chanctx_conf
=
rcu_dereference
(
sdata
->
vif
.
chanctx_conf
);
if
(
!
chanctx_conf
)
{
rcu_read_unlock
();
return
-
EBUSY
;
}
/* don't handle for multi-VIF cases */
chanctx
=
container_of
(
chanctx_conf
,
struct
ieee80211_chanctx
,
conf
);
if
(
chanctx
->
refcount
>
1
)
{
rcu_read_unlock
();
return
-
EBUSY
;
}
num_chanctx
=
0
;
list_for_each_entry_rcu
(
chanctx
,
&
local
->
chanctx_list
,
list
)
num_chanctx
++
;
rcu_read_unlock
();
if
(
num_chanctx
>
1
)
return
-
EBUSY
;
/* don't allow another channel switch if one is already active. */
if
(
sdata
->
vif
.
csa_active
)
return
-
EBUSY
;
/* only handle AP for now. */
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_AP
:
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
)
ieee80211_stop_queues_by_reason
(
&
local
->
hw
,
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
;
ieee80211_bss_info_change_notify
(
sdata
,
err
);
drv_channel_switch_beacon
(
sdata
,
&
params
->
chandef
);
return
0
;
}
static
int
ieee80211_mgmt_tx
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
static
int
ieee80211_mgmt_tx
(
struct
wiphy
*
wiphy
,
struct
wireless_dev
*
wdev
,
struct
ieee80211_channel
*
chan
,
bool
offchan
,
struct
ieee80211_channel
*
chan
,
bool
offchan
,
unsigned
int
wait
,
const
u8
*
buf
,
size_t
len
,
unsigned
int
wait
,
const
u8
*
buf
,
size_t
len
,
...
@@ -3494,4 +3676,5 @@ struct cfg80211_ops mac80211_config_ops = {
...
@@ -3494,4 +3676,5 @@ struct cfg80211_ops mac80211_config_ops = {
.
get_et_strings
=
ieee80211_get_et_strings
,
.
get_et_strings
=
ieee80211_get_et_strings
,
.
get_channel
=
ieee80211_cfg_get_channel
,
.
get_channel
=
ieee80211_cfg_get_channel
,
.
start_radar_detection
=
ieee80211_start_radar_detection
,
.
start_radar_detection
=
ieee80211_start_radar_detection
,
.
channel_switch
=
ieee80211_channel_switch
,
};
};
net/mac80211/chan.c
View file @
fa597844
...
@@ -410,6 +410,64 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
...
@@ -410,6 +410,64 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
return
ret
;
return
ret
;
}
}
int
ieee80211_vif_change_channel
(
struct
ieee80211_sub_if_data
*
sdata
,
const
struct
cfg80211_chan_def
*
chandef
,
u32
*
changed
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_chanctx_conf
*
conf
;
struct
ieee80211_chanctx
*
ctx
;
int
ret
;
u32
chanctx_changed
=
0
;
/* should never be called if not performing a channel switch. */
if
(
WARN_ON
(
!
sdata
->
vif
.
csa_active
))
return
-
EINVAL
;
if
(
!
cfg80211_chandef_usable
(
sdata
->
local
->
hw
.
wiphy
,
chandef
,
IEEE80211_CHAN_DISABLED
))
return
-
EINVAL
;
mutex_lock
(
&
local
->
chanctx_mtx
);
conf
=
rcu_dereference_protected
(
sdata
->
vif
.
chanctx_conf
,
lockdep_is_held
(
&
local
->
chanctx_mtx
));
if
(
!
conf
)
{
ret
=
-
EINVAL
;
goto
out
;
}
ctx
=
container_of
(
conf
,
struct
ieee80211_chanctx
,
conf
);
if
(
ctx
->
refcount
!=
1
)
{
ret
=
-
EINVAL
;
goto
out
;
}
if
(
sdata
->
vif
.
bss_conf
.
chandef
.
width
!=
chandef
->
width
)
{
chanctx_changed
=
IEEE80211_CHANCTX_CHANGE_WIDTH
;
*
changed
|=
BSS_CHANGED_BANDWIDTH
;
}
sdata
->
vif
.
bss_conf
.
chandef
=
*
chandef
;
ctx
->
conf
.
def
=
*
chandef
;
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
);
ret
=
0
;
out:
mutex_unlock
(
&
local
->
chanctx_mtx
);
return
ret
;
}
int
ieee80211_vif_change_bandwidth
(
struct
ieee80211_sub_if_data
*
sdata
,
int
ieee80211_vif_change_bandwidth
(
struct
ieee80211_sub_if_data
*
sdata
,
const
struct
cfg80211_chan_def
*
chandef
,
const
struct
cfg80211_chan_def
*
chandef
,
u32
*
changed
)
u32
*
changed
)
...
...
net/mac80211/debugfs_sta.c
View file @
fa597844
...
@@ -455,6 +455,15 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
...
@@ -455,6 +455,15 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD_COUNTER
(
tx_retry_count
,
tx_retry_count
);
DEBUGFS_ADD_COUNTER
(
tx_retry_count
,
tx_retry_count
);
DEBUGFS_ADD_COUNTER
(
wep_weak_iv_count
,
wep_weak_iv_count
);
DEBUGFS_ADD_COUNTER
(
wep_weak_iv_count
,
wep_weak_iv_count
);
if
(
sizeof
(
sta
->
driver_buffered_tids
)
==
sizeof
(
u32
))
debugfs_create_x32
(
"driver_buffered_tids"
,
0400
,
sta
->
debugfs
.
dir
,
(
u32
*
)
&
sta
->
driver_buffered_tids
);
else
debugfs_create_x64
(
"driver_buffered_tids"
,
0400
,
sta
->
debugfs
.
dir
,
(
u64
*
)
&
sta
->
driver_buffered_tids
);
drv_sta_add_debugfs
(
local
,
sdata
,
&
sta
->
sta
,
sta
->
debugfs
.
dir
);
drv_sta_add_debugfs
(
local
,
sdata
,
&
sta
->
sta
,
sta
->
debugfs
.
dir
);
}
}
...
...
net/mac80211/driver-ops.h
View file @
fa597844
...
@@ -1072,4 +1072,17 @@ static inline void drv_ipv6_addr_change(struct ieee80211_local *local,
...
@@ -1072,4 +1072,17 @@ static inline void drv_ipv6_addr_change(struct ieee80211_local *local,
}
}
#endif
#endif
static
inline
void
drv_channel_switch_beacon
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
cfg80211_chan_def
*
chandef
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
if
(
local
->
ops
->
channel_switch_beacon
)
{
trace_drv_channel_switch_beacon
(
local
,
sdata
,
chandef
);
local
->
ops
->
channel_switch_beacon
(
&
local
->
hw
,
&
sdata
->
vif
,
chandef
);
}
}
#endif
/* __MAC80211_DRIVER_OPS */
#endif
/* __MAC80211_DRIVER_OPS */
net/mac80211/ibss.c
View file @
fa597844
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
#define IEEE80211_IBSS_RSN_INACTIVITY_LIMIT (10 * HZ)
#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
...
@@ -740,6 +741,33 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
...
@@ -740,6 +741,33 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
return
active
;
return
active
;
}
}
static
void
ieee80211_ibss_sta_expire
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
sta_info
*
sta
,
*
tmp
;
unsigned
long
exp_time
=
IEEE80211_IBSS_INACTIVITY_LIMIT
;
unsigned
long
exp_rsn_time
=
IEEE80211_IBSS_RSN_INACTIVITY_LIMIT
;
mutex_lock
(
&
local
->
sta_mtx
);
list_for_each_entry_safe
(
sta
,
tmp
,
&
local
->
sta_list
,
list
)
{
if
(
sdata
!=
sta
->
sdata
)
continue
;
if
(
time_after
(
jiffies
,
sta
->
last_rx
+
exp_time
)
||
(
time_after
(
jiffies
,
sta
->
last_rx
+
exp_rsn_time
)
&&
sta
->
sta_state
!=
IEEE80211_STA_AUTHORIZED
))
{
sta_dbg
(
sta
->
sdata
,
"expiring inactive %sSTA %pM
\n
"
,
sta
->
sta_state
!=
IEEE80211_STA_AUTHORIZED
?
"not authorized "
:
""
,
sta
->
sta
.
addr
);
WARN_ON
(
__sta_info_destroy
(
sta
));
}
}
mutex_unlock
(
&
local
->
sta_mtx
);
}
/*
/*
* This function is called with state == IEEE80211_IBSS_MLME_JOINED
* This function is called with state == IEEE80211_IBSS_MLME_JOINED
*/
*/
...
@@ -754,7 +782,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
...
@@ -754,7 +782,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
mod_timer
(
&
ifibss
->
timer
,
mod_timer
(
&
ifibss
->
timer
,
round_jiffies
(
jiffies
+
IEEE80211_IBSS_MERGE_INTERVAL
));
round_jiffies
(
jiffies
+
IEEE80211_IBSS_MERGE_INTERVAL
));
ieee80211_
sta_expire
(
sdata
,
IEEE80211_IBSS_INACTIVITY_LIMIT
);
ieee80211_
ibss_sta_expire
(
sdata
);
if
(
time_before
(
jiffies
,
ifibss
->
last_scan_completed
+
if
(
time_before
(
jiffies
,
ifibss
->
last_scan_completed
+
IEEE80211_IBSS_MERGE_INTERVAL
))
IEEE80211_IBSS_MERGE_INTERVAL
))
...
...
net/mac80211/ieee80211_i.h
View file @
fa597844
...
@@ -259,6 +259,8 @@ struct ieee80211_if_ap {
...
@@ -259,6 +259,8 @@ struct ieee80211_if_ap {
struct
beacon_data
__rcu
*
beacon
;
struct
beacon_data
__rcu
*
beacon
;
struct
probe_resp
__rcu
*
probe_resp
;
struct
probe_resp
__rcu
*
probe_resp
;
/* to be used after channel switch. */
struct
cfg80211_beacon_data
*
next_beacon
;
struct
list_head
vlans
;
struct
list_head
vlans
;
struct
ps_data
ps
;
struct
ps_data
ps
;
...
@@ -716,6 +718,11 @@ struct ieee80211_sub_if_data {
...
@@ -716,6 +718,11 @@ struct ieee80211_sub_if_data {
struct
ieee80211_tx_queue_params
tx_conf
[
IEEE80211_NUM_ACS
];
struct
ieee80211_tx_queue_params
tx_conf
[
IEEE80211_NUM_ACS
];
struct
work_struct
csa_finalize_work
;
int
csa_counter_offset_beacon
;
int
csa_counter_offset_presp
;
bool
csa_radar_required
;
/* used to reconfigure hardware SM PS */
/* used to reconfigure hardware SM PS */
struct
work_struct
recalc_smps
;
struct
work_struct
recalc_smps
;
...
@@ -1094,7 +1101,6 @@ struct ieee80211_local {
...
@@ -1094,7 +1101,6 @@ struct ieee80211_local {
u32
dot11TransmittedFrameCount
;
u32
dot11TransmittedFrameCount
;
#ifdef CONFIG_MAC80211_LEDS
#ifdef CONFIG_MAC80211_LEDS
int
tx_led_counter
,
rx_led_counter
;
struct
led_trigger
*
tx_led
,
*
rx_led
,
*
assoc_led
,
*
radio_led
;
struct
led_trigger
*
tx_led
,
*
rx_led
,
*
assoc_led
,
*
radio_led
;
struct
tpt_led_trigger
*
tpt_led_trigger
;
struct
tpt_led_trigger
*
tpt_led_trigger
;
char
tx_led_name
[
32
],
rx_led_name
[
32
],
char
tx_led_name
[
32
],
rx_led_name
[
32
],
...
@@ -1373,6 +1379,9 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
...
@@ -1373,6 +1379,9 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
void
ieee80211_sw_roc_work
(
struct
work_struct
*
work
);
void
ieee80211_sw_roc_work
(
struct
work_struct
*
work
);
void
ieee80211_handle_roc_started
(
struct
ieee80211_roc_work
*
roc
);
void
ieee80211_handle_roc_started
(
struct
ieee80211_roc_work
*
roc
);
/* channel switch handling */
void
ieee80211_csa_finalize_work
(
struct
work_struct
*
work
);
/* interface handling */
/* interface handling */
int
ieee80211_iface_init
(
void
);
int
ieee80211_iface_init
(
void
);
void
ieee80211_iface_exit
(
void
);
void
ieee80211_iface_exit
(
void
);
...
@@ -1394,6 +1403,8 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
...
@@ -1394,6 +1403,8 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
bool
__ieee80211_recalc_txpower
(
struct
ieee80211_sub_if_data
*
sdata
);
bool
__ieee80211_recalc_txpower
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_recalc_txpower
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_recalc_txpower
(
struct
ieee80211_sub_if_data
*
sdata
);
int
ieee80211_assign_beacon
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
cfg80211_beacon_data
*
params
);
static
inline
bool
ieee80211_sdata_running
(
struct
ieee80211_sub_if_data
*
sdata
)
static
inline
bool
ieee80211_sdata_running
(
struct
ieee80211_sub_if_data
*
sdata
)
{
{
...
@@ -1655,6 +1666,11 @@ int __must_check
...
@@ -1655,6 +1666,11 @@ int __must_check
ieee80211_vif_change_bandwidth
(
struct
ieee80211_sub_if_data
*
sdata
,
ieee80211_vif_change_bandwidth
(
struct
ieee80211_sub_if_data
*
sdata
,
const
struct
cfg80211_chan_def
*
chandef
,
const
struct
cfg80211_chan_def
*
chandef
,
u32
*
changed
);
u32
*
changed
);
/* NOTE: only use ieee80211_vif_change_channel() for channel switch */
int
__must_check
ieee80211_vif_change_channel
(
struct
ieee80211_sub_if_data
*
sdata
,
const
struct
cfg80211_chan_def
*
chandef
,
u32
*
changed
);
void
ieee80211_vif_release_channel
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_vif_release_channel
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_vif_vlan_copy_chanctx
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_vif_vlan_copy_chanctx
(
struct
ieee80211_sub_if_data
*
sdata
);
void
ieee80211_vif_copy_chanctx_to_vlans
(
struct
ieee80211_sub_if_data
*
sdata
,
void
ieee80211_vif_copy_chanctx_to_vlans
(
struct
ieee80211_sub_if_data
*
sdata
,
...
...
net/mac80211/iface.c
View file @
fa597844
...
@@ -274,6 +274,12 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
...
@@ -274,6 +274,12 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
if
(
iftype
==
NL80211_IFTYPE_ADHOC
&&
if
(
iftype
==
NL80211_IFTYPE_ADHOC
&&
nsdata
->
vif
.
type
==
NL80211_IFTYPE_ADHOC
)
nsdata
->
vif
.
type
==
NL80211_IFTYPE_ADHOC
)
return
-
EBUSY
;
return
-
EBUSY
;
/*
* will not add another interface while any channel
* switch is active.
*/
if
(
nsdata
->
vif
.
csa_active
)
return
-
EBUSY
;
/*
/*
* The remaining checks are only performed for interfaces
* The remaining checks are only performed for interfaces
...
@@ -804,6 +810,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
...
@@ -804,6 +810,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
cancel_work_sync
(
&
local
->
dynamic_ps_enable_work
);
cancel_work_sync
(
&
local
->
dynamic_ps_enable_work
);
cancel_work_sync
(
&
sdata
->
recalc_smps
);
cancel_work_sync
(
&
sdata
->
recalc_smps
);
sdata
->
vif
.
csa_active
=
false
;
cancel_work_sync
(
&
sdata
->
csa_finalize_work
);
cancel_delayed_work_sync
(
&
sdata
->
dfs_cac_timer_work
);
cancel_delayed_work_sync
(
&
sdata
->
dfs_cac_timer_work
);
...
@@ -1267,6 +1275,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
...
@@ -1267,6 +1275,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
skb_queue_head_init
(
&
sdata
->
skb_queue
);
skb_queue_head_init
(
&
sdata
->
skb_queue
);
INIT_WORK
(
&
sdata
->
work
,
ieee80211_iface_work
);
INIT_WORK
(
&
sdata
->
work
,
ieee80211_iface_work
);
INIT_WORK
(
&
sdata
->
recalc_smps
,
ieee80211_recalc_smps_work
);
INIT_WORK
(
&
sdata
->
recalc_smps
,
ieee80211_recalc_smps_work
);
INIT_WORK
(
&
sdata
->
csa_finalize_work
,
ieee80211_csa_finalize_work
);
switch
(
type
)
{
switch
(
type
)
{
case
NL80211_IFTYPE_P2P_GO
:
case
NL80211_IFTYPE_P2P_GO
:
...
...
net/mac80211/led.c
View file @
fa597844
...
@@ -12,27 +12,22 @@
...
@@ -12,27 +12,22 @@
#include <linux/export.h>
#include <linux/export.h>
#include "led.h"
#include "led.h"
#define MAC80211_BLINK_DELAY 50
/* ms */
void
ieee80211_led_rx
(
struct
ieee80211_local
*
local
)
void
ieee80211_led_rx
(
struct
ieee80211_local
*
local
)
{
{
unsigned
long
led_delay
=
MAC80211_BLINK_DELAY
;
if
(
unlikely
(
!
local
->
rx_led
))
if
(
unlikely
(
!
local
->
rx_led
))
return
;
return
;
if
(
local
->
rx_led_counter
++
%
2
==
0
)
led_trigger_blink_oneshot
(
local
->
rx_led
,
&
led_delay
,
&
led_delay
,
0
);
led_trigger_event
(
local
->
rx_led
,
LED_OFF
);
else
led_trigger_event
(
local
->
rx_led
,
LED_FULL
);
}
}
/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
void
ieee80211_led_tx
(
struct
ieee80211_local
*
local
)
void
ieee80211_led_tx
(
struct
ieee80211_local
*
local
,
int
q
)
{
{
unsigned
long
led_delay
=
MAC80211_BLINK_DELAY
;
if
(
unlikely
(
!
local
->
tx_led
))
if
(
unlikely
(
!
local
->
tx_led
))
return
;
return
;
/* not sure how this is supposed to work ... */
led_trigger_blink_oneshot
(
local
->
tx_led
,
&
led_delay
,
&
led_delay
,
0
);
local
->
tx_led_counter
+=
2
*
q
-
1
;
if
(
local
->
tx_led_counter
%
2
==
0
)
led_trigger_event
(
local
->
tx_led
,
LED_OFF
);
else
led_trigger_event
(
local
->
tx_led
,
LED_FULL
);
}
}
void
ieee80211_led_assoc
(
struct
ieee80211_local
*
local
,
bool
associated
)
void
ieee80211_led_assoc
(
struct
ieee80211_local
*
local
,
bool
associated
)
...
...
net/mac80211/led.h
View file @
fa597844
...
@@ -13,7 +13,7 @@
...
@@ -13,7 +13,7 @@
#ifdef CONFIG_MAC80211_LEDS
#ifdef CONFIG_MAC80211_LEDS
void
ieee80211_led_rx
(
struct
ieee80211_local
*
local
);
void
ieee80211_led_rx
(
struct
ieee80211_local
*
local
);
void
ieee80211_led_tx
(
struct
ieee80211_local
*
local
,
int
q
);
void
ieee80211_led_tx
(
struct
ieee80211_local
*
local
);
void
ieee80211_led_assoc
(
struct
ieee80211_local
*
local
,
void
ieee80211_led_assoc
(
struct
ieee80211_local
*
local
,
bool
associated
);
bool
associated
);
void
ieee80211_led_radio
(
struct
ieee80211_local
*
local
,
void
ieee80211_led_radio
(
struct
ieee80211_local
*
local
,
...
@@ -27,7 +27,7 @@ void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
...
@@ -27,7 +27,7 @@ void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
static
inline
void
ieee80211_led_rx
(
struct
ieee80211_local
*
local
)
static
inline
void
ieee80211_led_rx
(
struct
ieee80211_local
*
local
)
{
{
}
}
static
inline
void
ieee80211_led_tx
(
struct
ieee80211_local
*
local
,
int
q
)
static
inline
void
ieee80211_led_tx
(
struct
ieee80211_local
*
local
)
{
{
}
}
static
inline
void
ieee80211_led_assoc
(
struct
ieee80211_local
*
local
,
static
inline
void
ieee80211_led_assoc
(
struct
ieee80211_local
*
local
,
...
...
net/mac80211/status.c
View file @
fa597844
...
@@ -235,7 +235,8 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
...
@@ -235,7 +235,8 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
/* IEEE80211_RADIOTAP_RATE rate */
/* IEEE80211_RADIOTAP_RATE rate */
if
(
info
->
status
.
rates
[
0
].
idx
>=
0
&&
if
(
info
->
status
.
rates
[
0
].
idx
>=
0
&&
!
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
))
!
(
info
->
status
.
rates
[
0
].
flags
&
(
IEEE80211_TX_RC_MCS
|
IEEE80211_TX_RC_VHT_MCS
)))
len
+=
2
;
len
+=
2
;
/* IEEE80211_RADIOTAP_TX_FLAGS */
/* IEEE80211_RADIOTAP_TX_FLAGS */
...
@@ -244,16 +245,21 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
...
@@ -244,16 +245,21 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
/* IEEE80211_RADIOTAP_DATA_RETRIES */
/* IEEE80211_RADIOTAP_DATA_RETRIES */
len
+=
1
;
len
+=
1
;
/* IEEE80211_TX_RC_MCS */
/* IEEE80211_RADIOTAP_MCS
if
(
info
->
status
.
rates
[
0
].
idx
>=
0
&&
* IEEE80211_RADIOTAP_VHT */
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
)
if
(
info
->
status
.
rates
[
0
].
idx
>=
0
)
{
len
+=
3
;
if
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
)
len
+=
3
;
else
if
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_VHT_MCS
)
len
=
ALIGN
(
len
,
2
)
+
12
;
}
return
len
;
return
len
;
}
}
static
void
static
void
ieee80211_add_tx_radiotap_header
(
struct
ieee80211_supported_band
*
sband
,
ieee80211_add_tx_radiotap_header
(
struct
ieee80211_local
*
local
,
struct
ieee80211_supported_band
*
sband
,
struct
sk_buff
*
skb
,
int
retry_count
,
struct
sk_buff
*
skb
,
int
retry_count
,
int
rtap_len
,
int
shift
)
int
rtap_len
,
int
shift
)
{
{
...
@@ -280,7 +286,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
...
@@ -280,7 +286,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
/* IEEE80211_RADIOTAP_RATE */
/* IEEE80211_RADIOTAP_RATE */
if
(
info
->
status
.
rates
[
0
].
idx
>=
0
&&
if
(
info
->
status
.
rates
[
0
].
idx
>=
0
&&
!
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
))
{
!
(
info
->
status
.
rates
[
0
].
flags
&
(
IEEE80211_TX_RC_MCS
|
IEEE80211_TX_RC_VHT_MCS
)))
{
u16
rate
;
u16
rate
;
rthdr
->
it_present
|=
cpu_to_le32
(
1
<<
IEEE80211_RADIOTAP_RATE
);
rthdr
->
it_present
|=
cpu_to_le32
(
1
<<
IEEE80211_RADIOTAP_RATE
);
...
@@ -310,9 +317,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
...
@@ -310,9 +317,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
*
pos
=
retry_count
;
*
pos
=
retry_count
;
pos
++
;
pos
++
;
/* IEEE80211_TX_RC_MCS */
if
(
info
->
status
.
rates
[
0
].
idx
<
0
)
if
(
info
->
status
.
rates
[
0
].
idx
>=
0
&&
return
;
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
)
{
/* IEEE80211_RADIOTAP_MCS
* IEEE80211_RADIOTAP_VHT */
if
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_MCS
)
{
rthdr
->
it_present
|=
cpu_to_le32
(
1
<<
IEEE80211_RADIOTAP_MCS
);
rthdr
->
it_present
|=
cpu_to_le32
(
1
<<
IEEE80211_RADIOTAP_MCS
);
pos
[
0
]
=
IEEE80211_RADIOTAP_MCS_HAVE_MCS
|
pos
[
0
]
=
IEEE80211_RADIOTAP_MCS_HAVE_MCS
|
IEEE80211_RADIOTAP_MCS_HAVE_GI
|
IEEE80211_RADIOTAP_MCS_HAVE_GI
|
...
@@ -325,8 +335,48 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
...
@@ -325,8 +335,48 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
pos
[
1
]
|=
IEEE80211_RADIOTAP_MCS_FMT_GF
;
pos
[
1
]
|=
IEEE80211_RADIOTAP_MCS_FMT_GF
;
pos
[
2
]
=
info
->
status
.
rates
[
0
].
idx
;
pos
[
2
]
=
info
->
status
.
rates
[
0
].
idx
;
pos
+=
3
;
pos
+=
3
;
}
}
else
if
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_VHT_MCS
)
{
u16
known
=
local
->
hw
.
radiotap_vht_details
&
(
IEEE80211_RADIOTAP_VHT_KNOWN_GI
|
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH
);
rthdr
->
it_present
|=
cpu_to_le32
(
1
<<
IEEE80211_RADIOTAP_VHT
);
/* required alignment from rthdr */
pos
=
(
u8
*
)
rthdr
+
ALIGN
(
pos
-
(
u8
*
)
rthdr
,
2
);
/* u16 known - IEEE80211_RADIOTAP_VHT_KNOWN_* */
put_unaligned_le16
(
known
,
pos
);
pos
+=
2
;
/* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */
if
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_SHORT_GI
)
*
pos
|=
IEEE80211_RADIOTAP_VHT_FLAG_SGI
;
pos
++
;
/* u8 bandwidth */
if
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_40_MHZ_WIDTH
)
*
pos
=
1
;
else
if
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_80_MHZ_WIDTH
)
*
pos
=
4
;
else
if
(
info
->
status
.
rates
[
0
].
flags
&
IEEE80211_TX_RC_160_MHZ_WIDTH
)
*
pos
=
11
;
else
/* IEEE80211_TX_RC_{20_MHZ_WIDTH,FIXME:DUP_DATA} */
*
pos
=
0
;
pos
++
;
/* u8 mcs_nss[4] */
*
pos
=
(
ieee80211_rate_get_vht_mcs
(
&
info
->
status
.
rates
[
0
])
<<
4
)
|
ieee80211_rate_get_vht_nss
(
&
info
->
status
.
rates
[
0
]);
pos
+=
4
;
/* u8 coding */
pos
++
;
/* u8 group_id */
pos
++
;
/* u16 partial_aid */
pos
+=
2
;
}
}
}
static
void
ieee80211_report_used_skb
(
struct
ieee80211_local
*
local
,
static
void
ieee80211_report_used_skb
(
struct
ieee80211_local
*
local
,
...
@@ -564,7 +614,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
...
@@ -564,7 +614,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
rcu_read_unlock
();
rcu_read_unlock
();
ieee80211_led_tx
(
local
,
0
);
ieee80211_led_tx
(
local
);
/* SNMP counters
/* SNMP counters
* Fragments are passed to low-level drivers as separate skbs, so these
* Fragments are passed to low-level drivers as separate skbs, so these
...
@@ -631,8 +681,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
...
@@ -631,8 +681,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
return
;
return
;
}
}
ieee80211_add_tx_radiotap_header
(
sband
,
skb
,
retry_count
,
rtap_len
,
ieee80211_add_tx_radiotap_header
(
local
,
sband
,
skb
,
retry_count
,
shift
);
rtap_len
,
shift
);
/* XXX: is this sufficient for BPF? */
/* XXX: is this sufficient for BPF? */
skb_set_mac_header
(
skb
,
0
);
skb_set_mac_header
(
skb
,
0
);
...
...
net/mac80211/trace.h
View file @
fa597844
...
@@ -1906,6 +1906,32 @@ TRACE_EVENT(api_radar_detected,
...
@@ -1906,6 +1906,32 @@ TRACE_EVENT(api_radar_detected,
)
)
);
);
TRACE_EVENT
(
drv_channel_switch_beacon
,
TP_PROTO
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
,
struct
cfg80211_chan_def
*
chandef
),
TP_ARGS
(
local
,
sdata
,
chandef
),
TP_STRUCT__entry
(
LOCAL_ENTRY
VIF_ENTRY
CHANDEF_ENTRY
),
TP_fast_assign
(
LOCAL_ASSIGN
;
VIF_ASSIGN
;
CHANDEF_ASSIGN
(
chandef
);
),
TP_printk
(
LOCAL_PR_FMT
VIF_PR_FMT
" channel switch to "
CHANDEF_PR_FMT
,
LOCAL_PR_ARG
,
VIF_PR_ARG
,
CHANDEF_PR_ARG
)
);
#ifdef CONFIG_MAC80211_MESSAGE_TRACING
#ifdef CONFIG_MAC80211_MESSAGE_TRACING
#undef TRACE_SYSTEM
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mac80211_msg
#define TRACE_SYSTEM mac80211_msg
...
...
net/mac80211/tx.c
View file @
fa597844
...
@@ -1300,7 +1300,6 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
...
@@ -1300,7 +1300,6 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
txpending
);
txpending
);
ieee80211_tpt_led_trig_tx
(
local
,
fc
,
led_len
);
ieee80211_tpt_led_trig_tx
(
local
,
fc
,
led_len
);
ieee80211_led_tx
(
local
,
1
);
WARN_ON_ONCE
(
!
skb_queue_empty
(
skbs
));
WARN_ON_ONCE
(
!
skb_queue_empty
(
skbs
));
...
@@ -2339,6 +2338,81 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
...
@@ -2339,6 +2338,81 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
return
0
;
return
0
;
}
}
void
ieee80211_csa_finish
(
struct
ieee80211_vif
*
vif
)
{
struct
ieee80211_sub_if_data
*
sdata
=
vif_to_sdata
(
vif
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
csa_finalize_work
);
}
EXPORT_SYMBOL
(
ieee80211_csa_finish
);
static
void
ieee80211_update_csa
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
beacon_data
*
beacon
)
{
struct
probe_resp
*
resp
;
int
counter_offset_beacon
=
sdata
->
csa_counter_offset_beacon
;
int
counter_offset_presp
=
sdata
->
csa_counter_offset_presp
;
/* warn if the driver did not check for/react to csa completeness */
if
(
WARN_ON
(((
u8
*
)
beacon
->
tail
)[
counter_offset_beacon
]
==
0
))
return
;
((
u8
*
)
beacon
->
tail
)[
counter_offset_beacon
]
--
;
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_AP
&&
counter_offset_presp
)
{
rcu_read_lock
();
resp
=
rcu_dereference
(
sdata
->
u
.
ap
.
probe_resp
);
/* if nl80211 accepted the offset, this should not happen. */
if
(
WARN_ON
(
!
resp
))
{
rcu_read_unlock
();
return
;
}
resp
->
data
[
counter_offset_presp
]
--
;
rcu_read_unlock
();
}
}
bool
ieee80211_csa_is_complete
(
struct
ieee80211_vif
*
vif
)
{
struct
ieee80211_sub_if_data
*
sdata
=
vif_to_sdata
(
vif
);
struct
beacon_data
*
beacon
=
NULL
;
u8
*
beacon_data
;
size_t
beacon_data_len
;
int
counter_beacon
=
sdata
->
csa_counter_offset_beacon
;
int
ret
=
false
;
if
(
!
ieee80211_sdata_running
(
sdata
))
return
false
;
rcu_read_lock
();
if
(
vif
->
type
==
NL80211_IFTYPE_AP
)
{
struct
ieee80211_if_ap
*
ap
=
&
sdata
->
u
.
ap
;
beacon
=
rcu_dereference
(
ap
->
beacon
);
if
(
WARN_ON
(
!
beacon
||
!
beacon
->
tail
))
goto
out
;
beacon_data
=
beacon
->
tail
;
beacon_data_len
=
beacon
->
tail_len
;
}
else
{
WARN_ON
(
1
);
goto
out
;
}
if
(
WARN_ON
(
counter_beacon
>
beacon_data_len
))
goto
out
;
if
(
beacon_data
[
counter_beacon
]
==
0
)
ret
=
true
;
out:
rcu_read_unlock
();
return
ret
;
}
EXPORT_SYMBOL
(
ieee80211_csa_is_complete
);
struct
sk_buff
*
ieee80211_beacon_get_tim
(
struct
ieee80211_hw
*
hw
,
struct
sk_buff
*
ieee80211_beacon_get_tim
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_vif
*
vif
,
u16
*
tim_offset
,
u16
*
tim_length
)
u16
*
tim_offset
,
u16
*
tim_length
)
...
@@ -2369,6 +2443,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
...
@@ -2369,6 +2443,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
struct
beacon_data
*
beacon
=
rcu_dereference
(
ap
->
beacon
);
struct
beacon_data
*
beacon
=
rcu_dereference
(
ap
->
beacon
);
if
(
beacon
)
{
if
(
beacon
)
{
if
(
sdata
->
vif
.
csa_active
)
ieee80211_update_csa
(
sdata
,
beacon
);
/*
/*
* headroom, head length,
* headroom, head length,
* tail length and maximum TIM length
* tail length and maximum TIM length
...
...
net/wireless/nl80211.c
View file @
fa597844
...
@@ -349,6 +349,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
...
@@ -349,6 +349,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[
NL80211_ATTR_IE_RIC
]
=
{
.
type
=
NLA_BINARY
,
[
NL80211_ATTR_IE_RIC
]
=
{
.
type
=
NLA_BINARY
,
.
len
=
IEEE80211_MAX_DATA_LEN
},
.
len
=
IEEE80211_MAX_DATA_LEN
},
[
NL80211_ATTR_PEER_AID
]
=
{
.
type
=
NLA_U16
},
[
NL80211_ATTR_PEER_AID
]
=
{
.
type
=
NLA_U16
},
[
NL80211_ATTR_CH_SWITCH_COUNT
]
=
{
.
type
=
NLA_U32
},
[
NL80211_ATTR_CH_SWITCH_BLOCK_TX
]
=
{
.
type
=
NLA_FLAG
},
[
NL80211_ATTR_CSA_IES
]
=
{
.
type
=
NLA_NESTED
},
[
NL80211_ATTR_CSA_C_OFF_BEACON
]
=
{
.
type
=
NLA_U16
},
[
NL80211_ATTR_CSA_C_OFF_PRESP
]
=
{
.
type
=
NLA_U16
},
};
};
/* policy for the key attributes */
/* policy for the key attributes */
...
@@ -1424,6 +1429,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
...
@@ -1424,6 +1429,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
if
(
state
->
split
)
{
if
(
state
->
split
)
{
CMD
(
crit_proto_start
,
CRIT_PROTOCOL_START
);
CMD
(
crit_proto_start
,
CRIT_PROTOCOL_START
);
CMD
(
crit_proto_stop
,
CRIT_PROTOCOL_STOP
);
CMD
(
crit_proto_stop
,
CRIT_PROTOCOL_STOP
);
if
(
dev
->
wiphy
.
flags
&
WIPHY_FLAG_HAS_CHANNEL_SWITCH
)
CMD
(
channel_switch
,
CHANNEL_SWITCH
);
}
}
#ifdef CONFIG_NL80211_TESTMODE
#ifdef CONFIG_NL80211_TESTMODE
...
@@ -5615,6 +5622,111 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
...
@@ -5615,6 +5622,111 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
return
err
;
return
err
;
}
}
static
int
nl80211_channel_switch
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
struct
cfg80211_registered_device
*
rdev
=
info
->
user_ptr
[
0
];
struct
net_device
*
dev
=
info
->
user_ptr
[
1
];
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
cfg80211_csa_settings
params
;
/* csa_attrs is defined static to avoid waste of stack size - this
* function is called under RTNL lock, so this should not be a problem.
*/
static
struct
nlattr
*
csa_attrs
[
NL80211_ATTR_MAX
+
1
];
u8
radar_detect_width
=
0
;
int
err
;
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
)
return
-
EOPNOTSUPP
;
memset
(
&
params
,
0
,
sizeof
(
params
));
if
(
!
info
->
attrs
[
NL80211_ATTR_WIPHY_FREQ
]
||
!
info
->
attrs
[
NL80211_ATTR_CH_SWITCH_COUNT
])
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
)
return
-
EINVAL
;
params
.
count
=
nla_get_u32
(
info
->
attrs
[
NL80211_ATTR_CH_SWITCH_COUNT
]);
err
=
nl80211_parse_beacon
(
info
->
attrs
,
&
params
.
beacon_after
);
if
(
err
)
return
err
;
err
=
nla_parse_nested
(
csa_attrs
,
NL80211_ATTR_MAX
,
info
->
attrs
[
NL80211_ATTR_CSA_IES
],
nl80211_policy
);
if
(
err
)
return
err
;
err
=
nl80211_parse_beacon
(
csa_attrs
,
&
params
.
beacon_csa
);
if
(
err
)
return
err
;
if
(
!
csa_attrs
[
NL80211_ATTR_CSA_C_OFF_BEACON
])
return
-
EINVAL
;
params
.
counter_offset_beacon
=
nla_get_u16
(
csa_attrs
[
NL80211_ATTR_CSA_C_OFF_BEACON
]);
if
(
params
.
counter_offset_beacon
>=
params
.
beacon_csa
.
tail_len
)
return
-
EINVAL
;
/* sanity check - counters should be the same */
if
(
params
.
beacon_csa
.
tail
[
params
.
counter_offset_beacon
]
!=
params
.
count
)
return
-
EINVAL
;
if
(
csa_attrs
[
NL80211_ATTR_CSA_C_OFF_PRESP
])
{
params
.
counter_offset_presp
=
nla_get_u16
(
csa_attrs
[
NL80211_ATTR_CSA_C_OFF_PRESP
]);
if
(
params
.
counter_offset_presp
>=
params
.
beacon_csa
.
probe_resp_len
)
return
-
EINVAL
;
if
(
params
.
beacon_csa
.
probe_resp
[
params
.
counter_offset_presp
]
!=
params
.
count
)
return
-
EINVAL
;
}
err
=
nl80211_parse_chandef
(
rdev
,
info
,
&
params
.
chandef
);
if
(
err
)
return
err
;
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
;
}
err
=
cfg80211_can_use_iftype_chan
(
rdev
,
wdev
,
wdev
->
iftype
,
params
.
chandef
.
chan
,
CHAN_MODE_SHARED
,
radar_detect_width
);
if
(
err
)
return
err
;
if
(
info
->
attrs
[
NL80211_ATTR_CH_SWITCH_BLOCK_TX
])
params
.
block_tx
=
true
;
return
rdev_channel_switch
(
rdev
,
dev
,
&
params
);
}
static
int
nl80211_send_bss
(
struct
sk_buff
*
msg
,
struct
netlink_callback
*
cb
,
static
int
nl80211_send_bss
(
struct
sk_buff
*
msg
,
struct
netlink_callback
*
cb
,
u32
seq
,
int
flags
,
u32
seq
,
int
flags
,
struct
cfg80211_registered_device
*
rdev
,
struct
cfg80211_registered_device
*
rdev
,
...
@@ -9365,7 +9477,15 @@ static struct genl_ops nl80211_ops[] = {
...
@@ -9365,7 +9477,15 @@ static struct genl_ops nl80211_ops[] = {
.
flags
=
GENL_ADMIN_PERM
,
.
flags
=
GENL_ADMIN_PERM
,
.
internal_flags
=
NL80211_FLAG_NEED_WIPHY
|
.
internal_flags
=
NL80211_FLAG_NEED_WIPHY
|
NL80211_FLAG_NEED_RTNL
,
NL80211_FLAG_NEED_RTNL
,
}
},
{
.
cmd
=
NL80211_CMD_CHANNEL_SWITCH
,
.
doit
=
nl80211_channel_switch
,
.
policy
=
nl80211_policy
,
.
flags
=
GENL_ADMIN_PERM
,
.
internal_flags
=
NL80211_FLAG_NEED_NETDEV_UP
|
NL80211_FLAG_NEED_RTNL
,
},
};
};
static
struct
genl_multicast_group
nl80211_mlme_mcgrp
=
{
static
struct
genl_multicast_group
nl80211_mlme_mcgrp
=
{
...
...
net/wireless/rdev-ops.h
View file @
fa597844
...
@@ -923,4 +923,16 @@ static inline void rdev_crit_proto_stop(struct cfg80211_registered_device *rdev,
...
@@ -923,4 +923,16 @@ static inline void rdev_crit_proto_stop(struct cfg80211_registered_device *rdev,
trace_rdev_return_void
(
&
rdev
->
wiphy
);
trace_rdev_return_void
(
&
rdev
->
wiphy
);
}
}
static
inline
int
rdev_channel_switch
(
struct
cfg80211_registered_device
*
rdev
,
struct
net_device
*
dev
,
struct
cfg80211_csa_settings
*
params
)
{
int
ret
;
trace_rdev_channel_switch
(
&
rdev
->
wiphy
,
dev
,
params
);
ret
=
rdev
->
ops
->
channel_switch
(
&
rdev
->
wiphy
,
dev
,
params
);
trace_rdev_return_int
(
&
rdev
->
wiphy
,
ret
);
return
ret
;
}
#endif
/* __CFG80211_RDEV_OPS */
#endif
/* __CFG80211_RDEV_OPS */
net/wireless/trace.h
View file @
fa597844
...
@@ -1841,6 +1841,39 @@ TRACE_EVENT(rdev_crit_proto_stop,
...
@@ -1841,6 +1841,39 @@ TRACE_EVENT(rdev_crit_proto_stop,
WIPHY_PR_ARG
,
WDEV_PR_ARG
)
WIPHY_PR_ARG
,
WDEV_PR_ARG
)
);
);
TRACE_EVENT
(
rdev_channel_switch
,
TP_PROTO
(
struct
wiphy
*
wiphy
,
struct
net_device
*
netdev
,
struct
cfg80211_csa_settings
*
params
),
TP_ARGS
(
wiphy
,
netdev
,
params
),
TP_STRUCT__entry
(
WIPHY_ENTRY
NETDEV_ENTRY
CHAN_DEF_ENTRY
__field
(
u16
,
counter_offset_beacon
)
__field
(
u16
,
counter_offset_presp
)
__field
(
bool
,
radar_required
)
__field
(
bool
,
block_tx
)
__field
(
u8
,
count
)
),
TP_fast_assign
(
WIPHY_ASSIGN
;
NETDEV_ASSIGN
;
CHAN_DEF_ASSIGN
(
&
params
->
chandef
);
__entry
->
counter_offset_beacon
=
params
->
counter_offset_beacon
;
__entry
->
counter_offset_presp
=
params
->
counter_offset_presp
;
__entry
->
radar_required
=
params
->
radar_required
;
__entry
->
block_tx
=
params
->
block_tx
;
__entry
->
count
=
params
->
count
;
),
TP_printk
(
WIPHY_PR_FMT
", "
NETDEV_PR_FMT
", "
CHAN_DEF_PR_FMT
", block_tx: %d, count: %u, radar_required: %d"
", counter offsets (beacon/presp): %u/%u"
,
WIPHY_PR_ARG
,
NETDEV_PR_ARG
,
CHAN_DEF_PR_ARG
,
__entry
->
block_tx
,
__entry
->
count
,
__entry
->
radar_required
,
__entry
->
counter_offset_beacon
,
__entry
->
counter_offset_presp
)
);
/*************************************************************
/*************************************************************
* cfg80211 exported functions traces *
* cfg80211 exported functions traces *
*************************************************************/
*************************************************************/
...
...
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