Minor updates:
* BSS coloring support * MEI commands for Intel platforms * various fixes/cleanups -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAmEfiUEACgkQB8qZga/f l8QnDRAAiLKYLSfxTCf73KT/cUFOXPAAPG8r23tpgb1h/GgXcTVSTccnBfDWZWnv cX2YknF2hP3JU4SCjV28io+IvftlYp7gMua8yN6ekMQ31Dzw3kkVQbrNdF7sWglQ XhLws8KrZ6UwFSxqjSg1cX2oAYb6AwkDy5z+1lX+PxBoH5duVlWzCYe3ohXnuZgR 8Y9iz1eIxCprt1aXSIHyyT96a7TTG552T+FjenZM2+wHDu4sXGJLWSSUkM6rXUQI bXV1gon50VaqfmbAfusgmhSmmCfHqlx7P0sBKxdJ17WuuBf3FtGLQX07EzBU/0vD t3jSv4x4tXWhnA+Lyxx89WT13pz89iPnI4OjpxaxE+4wTOeiGrTZcHNMMHrgyEcQ f1PiEwwsTt5PM4y/e1rhdpm2Mrw3VxDOQ+A/vHPUzoLv7ewehGw8IGw6spocA+QL 1YB3g6tiVPEIbfczTY+qJy8E4MRh93toO3O2DywE+UXxC3OR8Eo/tFB+yREzCnnN 6jAMGrYYDONKSiU3x9NRlV5luqPmUa1Rwjv+dkg+g7jES1hAjZa+oKtPffDzzGOn C8bsN8TEiMyHtmtgi5IZQTIS0/rqKVV+rgA0DHoTqRVzuInA1Pmrx0k4H6Vy7zGA HahTJVPoO4VHWTtmztwkbONfEe0hR0OE/MGHgEqzdkbpIqVkMBw= =q8bL -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-net-next-2021-08-20' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== Minor updates: * BSS coloring support * MEI commands for Intel platforms * various fixes/cleanups * tag 'mac80211-next-for-net-next-2021-08-20' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next: cfg80211: fix BSS color notify trace enum confusion mac80211: Fix insufficient headroom issue for AMSDU mac80211: add support for BSS color change nl80211: add support for BSS coloring mac80211: Use flex-array for radiotap header bitmap mac80211: radiotap: Use BIT() instead of shifts mac80211: Remove unnecessary variable and label mac80211: include <linux/rbtree.h> mac80211: Fix monitor MTU limit so that A-MSDUs get through mac80211: remove unnecessary NULL check in ieee80211_register_hw() mac80211: Reject zero MAC address in sta_info_insert_check() nl80211: vendor-cmd: add Intel vendor commands for iwlmei usage ==================== Link: https://lore.kernel.org/r/20210820105329.48674-1-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Коммит
4af14dbaea
|
@ -1252,6 +1252,27 @@ struct cfg80211_csa_settings {
|
||||||
u8 count;
|
u8 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cfg80211_color_change_settings - color change settings
|
||||||
|
*
|
||||||
|
* Used for bss color change
|
||||||
|
*
|
||||||
|
* @beacon_color_change: beacon data while performing the color countdown
|
||||||
|
* @counter_offsets_beacon: offsets of the counters within the beacon (tail)
|
||||||
|
* @counter_offsets_presp: offsets of the counters within the probe response
|
||||||
|
* @beacon_next: beacon data to be used after the color change
|
||||||
|
* @count: number of beacons until the color change
|
||||||
|
* @color: the color used after the change
|
||||||
|
*/
|
||||||
|
struct cfg80211_color_change_settings {
|
||||||
|
struct cfg80211_beacon_data beacon_color_change;
|
||||||
|
u16 counter_offset_beacon;
|
||||||
|
u16 counter_offset_presp;
|
||||||
|
struct cfg80211_beacon_data beacon_next;
|
||||||
|
u8 count;
|
||||||
|
u8 color;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iface_combination_params - input parameters for interface combinations
|
* struct iface_combination_params - input parameters for interface combinations
|
||||||
*
|
*
|
||||||
|
@ -3995,6 +4016,8 @@ struct mgmt_frame_regs {
|
||||||
* given TIDs. This callback may sleep.
|
* given TIDs. This callback may sleep.
|
||||||
*
|
*
|
||||||
* @set_sar_specs: Update the SAR (TX power) settings.
|
* @set_sar_specs: Update the SAR (TX power) settings.
|
||||||
|
*
|
||||||
|
* @color_change: Initiate a color change.
|
||||||
*/
|
*/
|
||||||
struct cfg80211_ops {
|
struct cfg80211_ops {
|
||||||
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
||||||
|
@ -4322,6 +4345,9 @@ struct cfg80211_ops {
|
||||||
const u8 *peer, u8 tids);
|
const u8 *peer, u8 tids);
|
||||||
int (*set_sar_specs)(struct wiphy *wiphy,
|
int (*set_sar_specs)(struct wiphy *wiphy,
|
||||||
struct cfg80211_sar_specs *sar);
|
struct cfg80211_sar_specs *sar);
|
||||||
|
int (*color_change)(struct wiphy *wiphy,
|
||||||
|
struct net_device *dev,
|
||||||
|
struct cfg80211_color_change_settings *params);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8218,4 +8244,70 @@ void cfg80211_update_owe_info_event(struct net_device *netdev,
|
||||||
*/
|
*/
|
||||||
void cfg80211_bss_flush(struct wiphy *wiphy);
|
void cfg80211_bss_flush(struct wiphy *wiphy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_bss_color_notify - notify about bss color event
|
||||||
|
* @dev: network device
|
||||||
|
* @gfp: allocation flags
|
||||||
|
* @cmd: the actual event we want to notify
|
||||||
|
* @count: the number of TBTTs until the color change happens
|
||||||
|
* @color_bitmap: representations of the colors that the local BSS is aware of
|
||||||
|
*/
|
||||||
|
int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
|
||||||
|
enum nl80211_commands cmd, u8 count,
|
||||||
|
u64 color_bitmap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_obss_color_collision_notify - notify about bss color collision
|
||||||
|
* @dev: network device
|
||||||
|
* @color_bitmap: representations of the colors that the local BSS is aware of
|
||||||
|
*/
|
||||||
|
static inline int cfg80211_obss_color_collision_notify(struct net_device *dev,
|
||||||
|
u64 color_bitmap)
|
||||||
|
{
|
||||||
|
return cfg80211_bss_color_notify(dev, GFP_KERNEL,
|
||||||
|
NL80211_CMD_OBSS_COLOR_COLLISION,
|
||||||
|
0, color_bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_color_change_started_notify - notify color change start
|
||||||
|
* @dev: the device on which the color is switched
|
||||||
|
* @count: the number of TBTTs until the color change happens
|
||||||
|
*
|
||||||
|
* Inform the userspace about the color change that has started.
|
||||||
|
*/
|
||||||
|
static inline int cfg80211_color_change_started_notify(struct net_device *dev,
|
||||||
|
u8 count)
|
||||||
|
{
|
||||||
|
return cfg80211_bss_color_notify(dev, GFP_KERNEL,
|
||||||
|
NL80211_CMD_COLOR_CHANGE_STARTED,
|
||||||
|
count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_color_change_aborted_notify - notify color change abort
|
||||||
|
* @dev: the device on which the color is switched
|
||||||
|
*
|
||||||
|
* Inform the userspace about the color change that has aborted.
|
||||||
|
*/
|
||||||
|
static inline int cfg80211_color_change_aborted_notify(struct net_device *dev)
|
||||||
|
{
|
||||||
|
return cfg80211_bss_color_notify(dev, GFP_KERNEL,
|
||||||
|
NL80211_CMD_COLOR_CHANGE_ABORTED,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_color_change_notify - notify color change completion
|
||||||
|
* @dev: the device on which the color was switched
|
||||||
|
*
|
||||||
|
* Inform the userspace about the color change that has completed.
|
||||||
|
*/
|
||||||
|
static inline int cfg80211_color_change_notify(struct net_device *dev)
|
||||||
|
{
|
||||||
|
return cfg80211_bss_color_notify(dev, GFP_KERNEL,
|
||||||
|
NL80211_CMD_COLOR_CHANGE_COMPLETED,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __NET_CFG80211_H */
|
#endif /* __NET_CFG80211_H */
|
||||||
|
|
|
@ -43,6 +43,11 @@ struct ieee80211_radiotap_header {
|
||||||
* @it_present: (first) present word
|
* @it_present: (first) present word
|
||||||
*/
|
*/
|
||||||
__le32 it_present;
|
__le32 it_present;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it_optional: all remaining presence bitmaps
|
||||||
|
*/
|
||||||
|
__le32 it_optional[];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/* version is always 0 */
|
/* version is always 0 */
|
||||||
|
|
|
@ -1711,6 +1711,10 @@ enum ieee80211_offload_flags {
|
||||||
* protected by fq->lock.
|
* protected by fq->lock.
|
||||||
* @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
|
* @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
|
||||||
* &enum ieee80211_offload_flags.
|
* &enum ieee80211_offload_flags.
|
||||||
|
* @color_change_active: marks whether a color change is ongoing. Internally it is
|
||||||
|
* write-protected by sdata_lock and local->mtx so holding either is fine
|
||||||
|
* for read access.
|
||||||
|
* @color_change_color: the bss color that will be used after the change.
|
||||||
*/
|
*/
|
||||||
struct ieee80211_vif {
|
struct ieee80211_vif {
|
||||||
enum nl80211_iftype type;
|
enum nl80211_iftype type;
|
||||||
|
@ -1739,6 +1743,9 @@ struct ieee80211_vif {
|
||||||
|
|
||||||
bool txqs_stopped[IEEE80211_NUM_ACS];
|
bool txqs_stopped[IEEE80211_NUM_ACS];
|
||||||
|
|
||||||
|
bool color_change_active;
|
||||||
|
u8 color_change_color;
|
||||||
|
|
||||||
/* must be last */
|
/* must be last */
|
||||||
u8 drv_priv[] __aligned(sizeof(void *));
|
u8 drv_priv[] __aligned(sizeof(void *));
|
||||||
};
|
};
|
||||||
|
@ -5007,6 +5014,16 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif);
|
||||||
*/
|
*/
|
||||||
bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif);
|
bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_color_change_finish - notify mac80211 about color change
|
||||||
|
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||||
|
*
|
||||||
|
* After a color change announcement was scheduled and the counter in this
|
||||||
|
* announcement hits 1, this function must be called by the driver to
|
||||||
|
* notify mac80211 that the color can be changed
|
||||||
|
*/
|
||||||
|
void ieee80211_color_change_finish(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().
|
||||||
|
@ -6771,6 +6788,18 @@ struct sk_buff *
|
||||||
ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw,
|
ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif);
|
struct ieee80211_vif *vif);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieeee80211_obss_color_collision_notify - notify userland about a BSS color
|
||||||
|
* collision.
|
||||||
|
*
|
||||||
|
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||||
|
* @color_bitmap: a 64 bit bitmap representing the colors that the local BSS is
|
||||||
|
* aware of.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ieeee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
|
||||||
|
u64 color_bitmap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_is_tx_data - check if frame is a data frame
|
* ieee80211_is_tx_data - check if frame is a data frame
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||||
|
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||||
|
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||||
|
*/
|
||||||
|
#ifndef __VENDOR_CMD_INTEL_H__
|
||||||
|
#define __VENDOR_CMD_INTEL_H__
|
||||||
|
|
||||||
|
#define INTEL_OUI 0x001735
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum iwl_mvm_vendor_cmd - supported vendor commands
|
||||||
|
* @IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO: reports CSME connection info.
|
||||||
|
* @IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP: asks for ownership on the device.
|
||||||
|
* @IWL_MVM_VENDOR_CMD_ROAMING_FORBIDDEN_EVENT: notifies if roaming is allowed.
|
||||||
|
* It contains a &IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN and a
|
||||||
|
* &IWL_MVM_VENDOR_ATTR_VIF_ADDR attributes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum iwl_mvm_vendor_cmd {
|
||||||
|
IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO = 0x2d,
|
||||||
|
IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP = 0x30,
|
||||||
|
IWL_MVM_VENDOR_CMD_ROAMING_FORBIDDEN_EVENT = 0x32,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum iwl_vendor_auth_akm_mode {
|
||||||
|
IWL_VENDOR_AUTH_OPEN,
|
||||||
|
IWL_VENDOR_AUTH_RSNA = 0x6,
|
||||||
|
IWL_VENDOR_AUTH_RSNA_PSK,
|
||||||
|
IWL_VENDOR_AUTH_SAE = 0x9,
|
||||||
|
IWL_VENDOR_AUTH_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum iwl_mvm_vendor_attr - attributes used in vendor commands
|
||||||
|
* @__IWL_MVM_VENDOR_ATTR_INVALID: attribute 0 is invalid
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_VIF_ADDR: interface MAC address
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_ADDR: MAC address
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_SSID: SSID (binary attribute, 0..32 octets)
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_STA_CIPHER: the cipher to use for the station with the
|
||||||
|
* mac address specified in &IWL_MVM_VENDOR_ATTR_ADDR.
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN: u8 attribute. Indicates whether
|
||||||
|
* roaming is forbidden or not. Value 1 means roaming is forbidden,
|
||||||
|
* 0 mean roaming is allowed.
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_AUTH_MODE: u32 attribute. Authentication mode type
|
||||||
|
* as specified in &enum iwl_vendor_auth_akm_mode.
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_CHANNEL_NUM: u8 attribute. Contains channel number.
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_BAND: u8 attribute.
|
||||||
|
* 0 for 2.4 GHz band, 1 for 5.2GHz band and 2 for 6GHz band.
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_COLLOC_CHANNEL: u32 attribute. Channel number of
|
||||||
|
* collocated AP. Relevant for 6GHz AP info.
|
||||||
|
* @IWL_MVM_VENDOR_ATTR_COLLOC_ADDR: MAC address of a collocated AP.
|
||||||
|
* Relevant for 6GHz AP info.
|
||||||
|
*
|
||||||
|
* @NUM_IWL_MVM_VENDOR_ATTR: number of vendor attributes
|
||||||
|
* @MAX_IWL_MVM_VENDOR_ATTR: highest vendor attribute number
|
||||||
|
|
||||||
|
*/
|
||||||
|
enum iwl_mvm_vendor_attr {
|
||||||
|
__IWL_MVM_VENDOR_ATTR_INVALID = 0x00,
|
||||||
|
IWL_MVM_VENDOR_ATTR_VIF_ADDR = 0x02,
|
||||||
|
IWL_MVM_VENDOR_ATTR_ADDR = 0x0a,
|
||||||
|
IWL_MVM_VENDOR_ATTR_SSID = 0x3d,
|
||||||
|
IWL_MVM_VENDOR_ATTR_STA_CIPHER = 0x51,
|
||||||
|
IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN = 0x64,
|
||||||
|
IWL_MVM_VENDOR_ATTR_AUTH_MODE = 0x65,
|
||||||
|
IWL_MVM_VENDOR_ATTR_CHANNEL_NUM = 0x66,
|
||||||
|
IWL_MVM_VENDOR_ATTR_BAND = 0x69,
|
||||||
|
IWL_MVM_VENDOR_ATTR_COLLOC_CHANNEL = 0x70,
|
||||||
|
IWL_MVM_VENDOR_ATTR_COLLOC_ADDR = 0x71,
|
||||||
|
|
||||||
|
NUM_IWL_MVM_VENDOR_ATTR,
|
||||||
|
MAX_IWL_MVM_VENDOR_ATTR = NUM_IWL_MVM_VENDOR_ATTR - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __VENDOR_CMD_INTEL_H__ */
|
|
@ -1185,6 +1185,21 @@
|
||||||
* passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to
|
* passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to
|
||||||
* specify the wiphy index to be applied to.
|
* specify the wiphy index to be applied to.
|
||||||
*
|
*
|
||||||
|
* @NL80211_CMD_OBSS_COLOR_COLLISION: This notification is sent out whenever
|
||||||
|
* mac80211/drv detects a bss color collision.
|
||||||
|
*
|
||||||
|
* @NL80211_CMD_COLOR_CHANGE_REQUEST: This command is used to indicate that
|
||||||
|
* userspace wants to change the BSS color.
|
||||||
|
*
|
||||||
|
* @NL80211_CMD_COLOR_CHANGE_STARTED: Notify userland, that a color change has
|
||||||
|
* started
|
||||||
|
*
|
||||||
|
* @NL80211_CMD_COLOR_CHANGE_ABORTED: Notify userland, that the color change has
|
||||||
|
* been aborted
|
||||||
|
*
|
||||||
|
* @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change
|
||||||
|
* has completed
|
||||||
|
*
|
||||||
* @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
|
||||||
*/
|
*/
|
||||||
|
@ -1417,6 +1432,14 @@ enum nl80211_commands {
|
||||||
|
|
||||||
NL80211_CMD_SET_SAR_SPECS,
|
NL80211_CMD_SET_SAR_SPECS,
|
||||||
|
|
||||||
|
NL80211_CMD_OBSS_COLOR_COLLISION,
|
||||||
|
|
||||||
|
NL80211_CMD_COLOR_CHANGE_REQUEST,
|
||||||
|
|
||||||
|
NL80211_CMD_COLOR_CHANGE_STARTED,
|
||||||
|
NL80211_CMD_COLOR_CHANGE_ABORTED,
|
||||||
|
NL80211_CMD_COLOR_CHANGE_COMPLETED,
|
||||||
|
|
||||||
/* add new commands above here */
|
/* add new commands above here */
|
||||||
|
|
||||||
/* used to define NL80211_CMD_MAX below */
|
/* used to define NL80211_CMD_MAX below */
|
||||||
|
@ -2560,6 +2583,16 @@ enum nl80211_commands {
|
||||||
* disassoc events to indicate that an immediate reconnect to the AP
|
* disassoc events to indicate that an immediate reconnect to the AP
|
||||||
* is desired.
|
* is desired.
|
||||||
*
|
*
|
||||||
|
* @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the
|
||||||
|
* %NL80211_CMD_OBSS_COLOR_COLLISION event.
|
||||||
|
*
|
||||||
|
* @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's
|
||||||
|
* until the color switch event.
|
||||||
|
* @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are
|
||||||
|
* switching to
|
||||||
|
* @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
|
||||||
|
* information for the time while performing a color switch.
|
||||||
|
*
|
||||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||||
* @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
|
||||||
|
@ -3057,6 +3090,12 @@ enum nl80211_attrs {
|
||||||
|
|
||||||
NL80211_ATTR_DISABLE_HE,
|
NL80211_ATTR_DISABLE_HE,
|
||||||
|
|
||||||
|
NL80211_ATTR_OBSS_COLOR_BITMAP,
|
||||||
|
|
||||||
|
NL80211_ATTR_COLOR_CHANGE_COUNT,
|
||||||
|
NL80211_ATTR_COLOR_CHANGE_COLOR,
|
||||||
|
NL80211_ATTR_COLOR_CHANGE_ELEMS,
|
||||||
|
|
||||||
/* 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,
|
||||||
|
@ -5953,6 +5992,9 @@ enum nl80211_feature_flags {
|
||||||
* frame protection for all management frames exchanged during the
|
* frame protection for all management frames exchanged during the
|
||||||
* negotiation and range measurement procedure.
|
* negotiation and range measurement procedure.
|
||||||
*
|
*
|
||||||
|
* @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
|
||||||
|
* detection and change announcemnts.
|
||||||
|
*
|
||||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||||
*/
|
*/
|
||||||
|
@ -6017,6 +6059,7 @@ enum nl80211_ext_feature_index {
|
||||||
NL80211_EXT_FEATURE_SECURE_LTF,
|
NL80211_EXT_FEATURE_SECURE_LTF,
|
||||||
NL80211_EXT_FEATURE_SECURE_RTT,
|
NL80211_EXT_FEATURE_SECURE_RTT,
|
||||||
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
|
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
|
||||||
|
NL80211_EXT_FEATURE_BSS_COLOR,
|
||||||
|
|
||||||
/* add new features before the definition below */
|
/* add new features before the definition below */
|
||||||
NUM_NL80211_EXT_FEATURES,
|
NUM_NL80211_EXT_FEATURES,
|
||||||
|
|
|
@ -828,9 +828,11 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
static int
|
||||||
|
ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
||||||
const u8 *resp, size_t resp_len,
|
const u8 *resp, size_t resp_len,
|
||||||
const struct ieee80211_csa_settings *csa)
|
const struct ieee80211_csa_settings *csa,
|
||||||
|
const struct ieee80211_color_change_settings *cca)
|
||||||
{
|
{
|
||||||
struct probe_resp *new, *old;
|
struct probe_resp *new, *old;
|
||||||
|
|
||||||
|
@ -850,6 +852,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
||||||
memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_presp,
|
memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_presp,
|
||||||
csa->n_counter_offsets_presp *
|
csa->n_counter_offsets_presp *
|
||||||
sizeof(new->cntdwn_counter_offsets[0]));
|
sizeof(new->cntdwn_counter_offsets[0]));
|
||||||
|
else if (cca)
|
||||||
|
new->cntdwn_counter_offsets[0] = cca->counter_offset_presp;
|
||||||
|
|
||||||
rcu_assign_pointer(sdata->u.ap.probe_resp, new);
|
rcu_assign_pointer(sdata->u.ap.probe_resp, new);
|
||||||
if (old)
|
if (old)
|
||||||
|
@ -955,7 +959,8 @@ static int ieee80211_set_ftm_responder_params(
|
||||||
|
|
||||||
static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
struct cfg80211_beacon_data *params,
|
struct cfg80211_beacon_data *params,
|
||||||
const struct ieee80211_csa_settings *csa)
|
const struct ieee80211_csa_settings *csa,
|
||||||
|
const struct ieee80211_color_change_settings *cca)
|
||||||
{
|
{
|
||||||
struct beacon_data *new, *old;
|
struct beacon_data *new, *old;
|
||||||
int new_head_len, new_tail_len;
|
int new_head_len, new_tail_len;
|
||||||
|
@ -1004,6 +1009,9 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon,
|
memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon,
|
||||||
csa->n_counter_offsets_beacon *
|
csa->n_counter_offsets_beacon *
|
||||||
sizeof(new->cntdwn_counter_offsets[0]));
|
sizeof(new->cntdwn_counter_offsets[0]));
|
||||||
|
} else if (cca) {
|
||||||
|
new->cntdwn_current_counter = cca->count;
|
||||||
|
new->cntdwn_counter_offsets[0] = cca->counter_offset_beacon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy in head */
|
/* copy in head */
|
||||||
|
@ -1020,7 +1028,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
memcpy(new->tail, old->tail, new_tail_len);
|
memcpy(new->tail, old->tail, new_tail_len);
|
||||||
|
|
||||||
err = ieee80211_set_probe_resp(sdata, params->probe_resp,
|
err = ieee80211_set_probe_resp(sdata, params->probe_resp,
|
||||||
params->probe_resp_len, csa);
|
params->probe_resp_len, csa, cca);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
kfree(new);
|
kfree(new);
|
||||||
return err;
|
return err;
|
||||||
|
@ -1175,7 +1183,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||||
if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL))
|
if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL))
|
||||||
sdata->vif.bss_conf.beacon_tx_rate = params->beacon_rate;
|
sdata->vif.bss_conf.beacon_tx_rate = params->beacon_rate;
|
||||||
|
|
||||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL);
|
err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto error;
|
goto error;
|
||||||
changed |= err;
|
changed |= err;
|
||||||
|
@ -1230,17 +1238,17 @@ 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);
|
||||||
sdata_assert_lock(sdata);
|
sdata_assert_lock(sdata);
|
||||||
|
|
||||||
/* don't allow changing the beacon while CSA is in place - offset
|
/* don't allow changing the beacon while a countdown is in place - offset
|
||||||
* of channel switch counter may change
|
* of channel switch counter may change
|
||||||
*/
|
*/
|
||||||
if (sdata->vif.csa_active)
|
if (sdata->vif.csa_active || sdata->vif.color_change_active)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||||
if (!old)
|
if (!old)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
err = ieee80211_assign_beacon(sdata, params, NULL);
|
err = ieee80211_assign_beacon(sdata, params, NULL, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
ieee80211_bss_info_change_notify(sdata, err);
|
ieee80211_bss_info_change_notify(sdata, err);
|
||||||
|
@ -3156,7 +3164,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
||||||
NULL);
|
NULL, NULL);
|
||||||
kfree(sdata->u.ap.next_beacon);
|
kfree(sdata->u.ap.next_beacon);
|
||||||
sdata->u.ap.next_beacon = NULL;
|
sdata->u.ap.next_beacon = NULL;
|
||||||
|
|
||||||
|
@ -3322,7 +3330,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
|
csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
|
||||||
csa.count = params->count;
|
csa.count = params->count;
|
||||||
|
|
||||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa);
|
err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
kfree(sdata->u.ap.next_beacon);
|
kfree(sdata->u.ap.next_beacon);
|
||||||
return err;
|
return err;
|
||||||
|
@ -3411,6 +3419,15 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata)
|
||||||
|
{
|
||||||
|
sdata->vif.color_change_active = false;
|
||||||
|
kfree(sdata->u.ap.next_beacon);
|
||||||
|
sdata->u.ap.next_beacon = NULL;
|
||||||
|
|
||||||
|
cfg80211_color_change_aborted_notify(sdata->dev);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
__ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
__ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||||
struct cfg80211_csa_settings *params)
|
struct cfg80211_csa_settings *params)
|
||||||
|
@ -3479,6 +3496,10 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if there is a color change in progress, abort it */
|
||||||
|
if (sdata->vif.color_change_active)
|
||||||
|
ieee80211_color_change_abort(sdata);
|
||||||
|
|
||||||
err = ieee80211_set_csa_beacon(sdata, params, &changed);
|
err = ieee80211_set_csa_beacon(sdata, params, &changed);
|
||||||
if (err) {
|
if (err) {
|
||||||
ieee80211_vif_unreserve_chanctx(sdata);
|
ieee80211_vif_unreserve_chanctx(sdata);
|
||||||
|
@ -4130,6 +4151,196 @@ static int ieee80211_set_sar_specs(struct wiphy *wiphy,
|
||||||
return local->ops->set_sar_specs(&local->hw, sar);
|
return local->ops->set_sar_specs(&local->hw, sar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
|
u32 *changed)
|
||||||
|
{
|
||||||
|
switch (sdata->vif.type) {
|
||||||
|
case NL80211_IFTYPE_AP: {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
||||||
|
NULL, NULL);
|
||||||
|
kfree(sdata->u.ap.next_beacon);
|
||||||
|
sdata->u.ap.next_beacon = NULL;
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*changed |= ret;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct cfg80211_color_change_settings *params,
|
||||||
|
u32 *changed)
|
||||||
|
{
|
||||||
|
struct ieee80211_color_change_settings color_change = {};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
switch (sdata->vif.type) {
|
||||||
|
case NL80211_IFTYPE_AP:
|
||||||
|
sdata->u.ap.next_beacon =
|
||||||
|
cfg80211_beacon_dup(¶ms->beacon_next);
|
||||||
|
if (!sdata->u.ap.next_beacon)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (params->count <= 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
color_change.counter_offset_beacon =
|
||||||
|
params->counter_offset_beacon;
|
||||||
|
color_change.counter_offset_presp =
|
||||||
|
params->counter_offset_presp;
|
||||||
|
color_change.count = params->count;
|
||||||
|
|
||||||
|
err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change,
|
||||||
|
NULL, &color_change);
|
||||||
|
if (err < 0) {
|
||||||
|
kfree(sdata->u.ap.next_beacon);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
*changed |= err;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
|
||||||
|
u8 color, int enable, u32 changed)
|
||||||
|
{
|
||||||
|
sdata->vif.bss_conf.he_bss_color.color = color;
|
||||||
|
sdata->vif.bss_conf.he_bss_color.enabled = enable;
|
||||||
|
changed |= BSS_CHANGED_HE_BSS_COLOR;
|
||||||
|
|
||||||
|
ieee80211_bss_info_change_notify(sdata, changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
u32 changed = 0;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
sdata_assert_lock(sdata);
|
||||||
|
lockdep_assert_held(&local->mtx);
|
||||||
|
|
||||||
|
sdata->vif.color_change_active = false;
|
||||||
|
|
||||||
|
err = ieee80211_set_after_color_change_beacon(sdata, &changed);
|
||||||
|
if (err) {
|
||||||
|
cfg80211_color_change_aborted_notify(sdata->dev);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ieee80211_color_change_bss_config_notify(sdata,
|
||||||
|
sdata->vif.color_change_color,
|
||||||
|
1, changed);
|
||||||
|
cfg80211_color_change_notify(sdata->dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ieee80211_color_change_finalize_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata =
|
||||||
|
container_of(work, struct ieee80211_sub_if_data,
|
||||||
|
color_change_finalize_work);
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
|
||||||
|
sdata_lock(sdata);
|
||||||
|
mutex_lock(&local->mtx);
|
||||||
|
|
||||||
|
/* AP might have been stopped while waiting for the lock. */
|
||||||
|
if (!sdata->vif.color_change_active)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
if (!ieee80211_sdata_running(sdata))
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
ieee80211_color_change_finalize(sdata);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&local->mtx);
|
||||||
|
sdata_unlock(sdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ieee80211_color_change_finish(struct ieee80211_vif *vif)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||||
|
|
||||||
|
ieee80211_queue_work(&sdata->local->hw,
|
||||||
|
&sdata->color_change_finalize_work);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(ieee80211_color_change_finish);
|
||||||
|
|
||||||
|
void
|
||||||
|
ieeee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
|
||||||
|
u64 color_bitmap)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||||
|
|
||||||
|
if (sdata->vif.color_change_active || sdata->vif.csa_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cfg80211_obss_color_collision_notify(sdata->dev, color_bitmap);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(ieeee80211_obss_color_collision_notify);
|
||||||
|
|
||||||
|
static int
|
||||||
|
ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
|
||||||
|
struct cfg80211_color_change_settings *params)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
u32 changed = 0;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
sdata_assert_lock(sdata);
|
||||||
|
|
||||||
|
mutex_lock(&local->mtx);
|
||||||
|
|
||||||
|
/* don't allow another color change if one is already active or if csa
|
||||||
|
* is active
|
||||||
|
*/
|
||||||
|
if (sdata->vif.color_change_active || sdata->vif.csa_active) {
|
||||||
|
err = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ieee80211_set_color_change_beacon(sdata, params, &changed);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
sdata->vif.color_change_active = true;
|
||||||
|
sdata->vif.color_change_color = params->color;
|
||||||
|
|
||||||
|
cfg80211_color_change_started_notify(sdata->dev, params->count);
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
ieee80211_color_change_bss_config_notify(sdata, 0, 0, changed);
|
||||||
|
else
|
||||||
|
/* if the beacon didn't change, we can finalize immediately */
|
||||||
|
ieee80211_color_change_finalize(sdata);
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&local->mtx);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
const struct cfg80211_ops mac80211_config_ops = {
|
const struct cfg80211_ops mac80211_config_ops = {
|
||||||
.add_virtual_intf = ieee80211_add_iface,
|
.add_virtual_intf = ieee80211_add_iface,
|
||||||
.del_virtual_intf = ieee80211_del_iface,
|
.del_virtual_intf = ieee80211_del_iface,
|
||||||
|
@ -4233,4 +4444,5 @@ const struct cfg80211_ops mac80211_config_ops = {
|
||||||
.set_tid_config = ieee80211_set_tid_config,
|
.set_tid_config = ieee80211_set_tid_config,
|
||||||
.reset_tid_config = ieee80211_reset_tid_config,
|
.reset_tid_config = ieee80211_reset_tid_config,
|
||||||
.set_sar_specs = ieee80211_set_sar_specs,
|
.set_sar_specs = ieee80211_set_sar_specs,
|
||||||
|
.color_change = ieee80211_color_change,
|
||||||
};
|
};
|
||||||
|
|
|
@ -489,7 +489,6 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
const struct cfg80211_bss_ies *ies;
|
const struct cfg80211_bss_ies *ies;
|
||||||
u16 capability = WLAN_CAPABILITY_IBSS;
|
u16 capability = WLAN_CAPABILITY_IBSS;
|
||||||
u64 tsf;
|
u64 tsf;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
sdata_assert_lock(sdata);
|
sdata_assert_lock(sdata);
|
||||||
|
|
||||||
|
@ -501,10 +500,8 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
ifibss->ssid_len, IEEE80211_BSS_TYPE_IBSS,
|
ifibss->ssid_len, IEEE80211_BSS_TYPE_IBSS,
|
||||||
IEEE80211_PRIVACY(ifibss->privacy));
|
IEEE80211_PRIVACY(ifibss->privacy));
|
||||||
|
|
||||||
if (WARN_ON(!cbss)) {
|
if (WARN_ON(!cbss))
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
ies = rcu_dereference(cbss->ies);
|
ies = rcu_dereference(cbss->ies);
|
||||||
|
@ -520,18 +517,14 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
sdata->vif.bss_conf.basic_rates,
|
sdata->vif.bss_conf.basic_rates,
|
||||||
capability, tsf, &ifibss->chandef,
|
capability, tsf, &ifibss->chandef,
|
||||||
NULL, csa_settings);
|
NULL, csa_settings);
|
||||||
if (!presp) {
|
if (!presp)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
rcu_assign_pointer(ifibss->presp, presp);
|
rcu_assign_pointer(ifibss->presp, presp);
|
||||||
if (old_presp)
|
if (old_presp)
|
||||||
kfree_rcu(old_presp, rcu_head);
|
kfree_rcu(old_presp, rcu_head);
|
||||||
|
|
||||||
return BSS_CHANGED_BEACON;
|
return BSS_CHANGED_BEACON;
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
|
int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
#include <linux/idr.h>
|
#include <linux/idr.h>
|
||||||
#include <linux/rhashtable.h>
|
#include <linux/rhashtable.h>
|
||||||
|
#include <linux/rbtree.h>
|
||||||
#include <net/ieee80211_radiotap.h>
|
#include <net/ieee80211_radiotap.h>
|
||||||
#include <net/cfg80211.h>
|
#include <net/cfg80211.h>
|
||||||
#include <net/mac80211.h>
|
#include <net/mac80211.h>
|
||||||
|
@ -244,6 +245,12 @@ struct ieee80211_csa_settings {
|
||||||
u8 count;
|
u8 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ieee80211_color_change_settings {
|
||||||
|
u16 counter_offset_beacon;
|
||||||
|
u16 counter_offset_presp;
|
||||||
|
u8 count;
|
||||||
|
};
|
||||||
|
|
||||||
struct beacon_data {
|
struct beacon_data {
|
||||||
u8 *head, *tail;
|
u8 *head, *tail;
|
||||||
int head_len, tail_len;
|
int head_len, tail_len;
|
||||||
|
@ -923,6 +930,8 @@ struct ieee80211_sub_if_data {
|
||||||
bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
|
bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
|
||||||
struct cfg80211_chan_def csa_chandef;
|
struct cfg80211_chan_def csa_chandef;
|
||||||
|
|
||||||
|
struct work_struct color_change_finalize_work;
|
||||||
|
|
||||||
struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */
|
struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */
|
||||||
struct list_head reserved_chanctx_list; /* protected by chanctx_mtx */
|
struct list_head reserved_chanctx_list; /* protected by chanctx_mtx */
|
||||||
|
|
||||||
|
@ -1887,6 +1896,9 @@ void ieee80211_csa_finalize_work(struct work_struct *work);
|
||||||
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||||
struct cfg80211_csa_settings *params);
|
struct cfg80211_csa_settings *params);
|
||||||
|
|
||||||
|
/* color change handling */
|
||||||
|
void ieee80211_color_change_finalize_work(struct work_struct *work);
|
||||||
|
|
||||||
/* interface handling */
|
/* interface handling */
|
||||||
#define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
|
#define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
|
||||||
NETIF_F_HW_CSUM | NETIF_F_SG | \
|
NETIF_F_HW_CSUM | NETIF_F_SG | \
|
||||||
|
|
|
@ -462,6 +462,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
|
||||||
sdata_unlock(sdata);
|
sdata_unlock(sdata);
|
||||||
|
|
||||||
cancel_work_sync(&sdata->csa_finalize_work);
|
cancel_work_sync(&sdata->csa_finalize_work);
|
||||||
|
cancel_work_sync(&sdata->color_change_finalize_work);
|
||||||
|
|
||||||
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
||||||
|
|
||||||
|
@ -1531,6 +1532,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
|
||||||
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);
|
INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work);
|
||||||
|
INIT_WORK(&sdata->color_change_finalize_work, ieee80211_color_change_finalize_work);
|
||||||
INIT_LIST_HEAD(&sdata->assigned_chanctx_list);
|
INIT_LIST_HEAD(&sdata->assigned_chanctx_list);
|
||||||
INIT_LIST_HEAD(&sdata->reserved_chanctx_list);
|
INIT_LIST_HEAD(&sdata->reserved_chanctx_list);
|
||||||
|
|
||||||
|
@ -2001,8 +2003,15 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
||||||
|
|
||||||
netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
|
netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
|
||||||
|
|
||||||
/* MTU range: 256 - 2304 */
|
/* MTU range is normally 256 - 2304, where the upper limit is
|
||||||
|
* the maximum MSDU size. Monitor interfaces send and receive
|
||||||
|
* MPDU and A-MSDU frames which may be much larger so we do
|
||||||
|
* not impose an upper limit in that case.
|
||||||
|
*/
|
||||||
ndev->min_mtu = 256;
|
ndev->min_mtu = 256;
|
||||||
|
if (type == NL80211_IFTYPE_MONITOR)
|
||||||
|
ndev->max_mtu = 0;
|
||||||
|
else
|
||||||
ndev->max_mtu = local->hw.max_mtu;
|
ndev->max_mtu = local->hw.max_mtu;
|
||||||
|
|
||||||
ret = cfg80211_register_netdevice(ndev);
|
ret = cfg80211_register_netdevice(ndev);
|
||||||
|
|
|
@ -1020,7 +1020,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||||
|
|
||||||
iftd = &sband->iftype_data[i];
|
iftd = &sband->iftype_data[i];
|
||||||
|
|
||||||
supp_he = supp_he || (iftd && iftd->he_cap.has_he);
|
supp_he = supp_he || iftd->he_cap.has_he;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HT, VHT, HE require QoS, thus >= 4 queues */
|
/* HT, VHT, HE require QoS, thus >= 4 queues */
|
||||||
|
|
|
@ -359,7 +359,12 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
|
|
||||||
put_unaligned_le32(it_present_val, it_present);
|
put_unaligned_le32(it_present_val, it_present);
|
||||||
|
|
||||||
pos = (void *)(it_present + 1);
|
/* This references through an offset into it_optional[] rather
|
||||||
|
* than via it_present otherwise later uses of pos will cause
|
||||||
|
* the compiler to think we have walked past the end of the
|
||||||
|
* struct member.
|
||||||
|
*/
|
||||||
|
pos = (void *)&rthdr->it_optional[it_present - rthdr->it_optional];
|
||||||
|
|
||||||
/* the order of the following fields is important */
|
/* the order of the following fields is important */
|
||||||
|
|
||||||
|
@ -372,7 +377,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
ieee80211_calculate_rx_timestamp(local, status,
|
ieee80211_calculate_rx_timestamp(local, status,
|
||||||
mpdulen, 0),
|
mpdulen, 0),
|
||||||
pos);
|
pos);
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_TSFT));
|
||||||
pos += 8;
|
pos += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,7 +401,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
*pos = 0;
|
*pos = 0;
|
||||||
} else {
|
} else {
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_RATE));
|
||||||
if (status->bw == RATE_INFO_BW_10)
|
if (status->bw == RATE_INFO_BW_10)
|
||||||
shift = 1;
|
shift = 1;
|
||||||
else if (status->bw == RATE_INFO_BW_5)
|
else if (status->bw == RATE_INFO_BW_5)
|
||||||
|
@ -433,7 +438,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
|
!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
|
||||||
*pos = status->signal;
|
*pos = status->signal;
|
||||||
rthdr->it_present |=
|
rthdr->it_present |=
|
||||||
cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
|
cpu_to_le32(BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL));
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +464,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
if (status->encoding == RX_ENC_HT) {
|
if (status->encoding == RX_ENC_HT) {
|
||||||
unsigned int stbc;
|
unsigned int stbc;
|
||||||
|
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_MCS));
|
||||||
*pos++ = local->hw.radiotap_mcs_details;
|
*pos++ = local->hw.radiotap_mcs_details;
|
||||||
*pos = 0;
|
*pos = 0;
|
||||||
if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
|
if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
|
||||||
|
@ -483,7 +488,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
while ((pos - (u8 *)rthdr) & 3)
|
while ((pos - (u8 *)rthdr) & 3)
|
||||||
pos++;
|
pos++;
|
||||||
rthdr->it_present |=
|
rthdr->it_present |=
|
||||||
cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
|
cpu_to_le32(BIT(IEEE80211_RADIOTAP_AMPDU_STATUS));
|
||||||
put_unaligned_le32(status->ampdu_reference, pos);
|
put_unaligned_le32(status->ampdu_reference, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN)
|
if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN)
|
||||||
|
@ -510,7 +515,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
if (status->encoding == RX_ENC_VHT) {
|
if (status->encoding == RX_ENC_VHT) {
|
||||||
u16 known = local->hw.radiotap_vht_details;
|
u16 known = local->hw.radiotap_vht_details;
|
||||||
|
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_VHT));
|
||||||
put_unaligned_le16(known, pos);
|
put_unaligned_le16(known, pos);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
/* flags */
|
/* flags */
|
||||||
|
@ -554,7 +559,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
u8 flags = IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT;
|
u8 flags = IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT;
|
||||||
|
|
||||||
rthdr->it_present |=
|
rthdr->it_present |=
|
||||||
cpu_to_le32(1 << IEEE80211_RADIOTAP_TIMESTAMP);
|
cpu_to_le32(BIT(IEEE80211_RADIOTAP_TIMESTAMP));
|
||||||
|
|
||||||
/* ensure 8 byte alignment */
|
/* ensure 8 byte alignment */
|
||||||
while ((pos - (u8 *)rthdr) & 7)
|
while ((pos - (u8 *)rthdr) & 7)
|
||||||
|
@ -642,7 +647,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
/* ensure 2 byte alignment */
|
/* ensure 2 byte alignment */
|
||||||
while ((pos - (u8 *)rthdr) & 1)
|
while ((pos - (u8 *)rthdr) & 1)
|
||||||
pos++;
|
pos++;
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_HE));
|
||||||
memcpy(pos, &he, sizeof(he));
|
memcpy(pos, &he, sizeof(he));
|
||||||
pos += sizeof(he);
|
pos += sizeof(he);
|
||||||
}
|
}
|
||||||
|
@ -652,14 +657,14 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
/* ensure 2 byte alignment */
|
/* ensure 2 byte alignment */
|
||||||
while ((pos - (u8 *)rthdr) & 1)
|
while ((pos - (u8 *)rthdr) & 1)
|
||||||
pos++;
|
pos++;
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE_MU);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_HE_MU));
|
||||||
memcpy(pos, &he_mu, sizeof(he_mu));
|
memcpy(pos, &he_mu, sizeof(he_mu));
|
||||||
pos += sizeof(he_mu);
|
pos += sizeof(he_mu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status->flag & RX_FLAG_NO_PSDU) {
|
if (status->flag & RX_FLAG_NO_PSDU) {
|
||||||
rthdr->it_present |=
|
rthdr->it_present |=
|
||||||
cpu_to_le32(1 << IEEE80211_RADIOTAP_ZERO_LEN_PSDU);
|
cpu_to_le32(BIT(IEEE80211_RADIOTAP_ZERO_LEN_PSDU));
|
||||||
*pos++ = status->zero_length_psdu_type;
|
*pos++ = status->zero_length_psdu_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,7 +672,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||||
/* ensure 2 byte alignment */
|
/* ensure 2 byte alignment */
|
||||||
while ((pos - (u8 *)rthdr) & 1)
|
while ((pos - (u8 *)rthdr) & 1)
|
||||||
pos++;
|
pos++;
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_LSIG);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_LSIG));
|
||||||
memcpy(pos, &lsig, sizeof(lsig));
|
memcpy(pos, &lsig, sizeof(lsig));
|
||||||
pos += sizeof(lsig);
|
pos += sizeof(lsig);
|
||||||
}
|
}
|
||||||
|
|
|
@ -543,7 +543,7 @@ static int sta_info_insert_check(struct sta_info *sta)
|
||||||
return -ENETDOWN;
|
return -ENETDOWN;
|
||||||
|
|
||||||
if (WARN_ON(ether_addr_equal(sta->sta.addr, sdata->vif.addr) ||
|
if (WARN_ON(ether_addr_equal(sta->sta.addr, sdata->vif.addr) ||
|
||||||
is_multicast_ether_addr(sta->sta.addr)))
|
!is_valid_ether_addr(sta->sta.addr)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* The RCU read lock is required by rhashtable due to
|
/* The RCU read lock is required by rhashtable due to
|
||||||
|
|
|
@ -305,8 +305,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
|
||||||
memset(rthdr, 0, rtap_len);
|
memset(rthdr, 0, rtap_len);
|
||||||
rthdr->it_len = cpu_to_le16(rtap_len);
|
rthdr->it_len = cpu_to_le16(rtap_len);
|
||||||
rthdr->it_present =
|
rthdr->it_present =
|
||||||
cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
|
cpu_to_le32(BIT(IEEE80211_RADIOTAP_TX_FLAGS) |
|
||||||
(1 << IEEE80211_RADIOTAP_DATA_RETRIES));
|
BIT(IEEE80211_RADIOTAP_DATA_RETRIES));
|
||||||
pos = (unsigned char *)(rthdr + 1);
|
pos = (unsigned char *)(rthdr + 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -331,7 +331,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
|
||||||
sband->bitrates[info->status.rates[0].idx].bitrate;
|
sband->bitrates[info->status.rates[0].idx].bitrate;
|
||||||
|
|
||||||
if (legacy_rate) {
|
if (legacy_rate) {
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_RATE));
|
||||||
*pos = DIV_ROUND_UP(legacy_rate, 5 * (1 << shift));
|
*pos = DIV_ROUND_UP(legacy_rate, 5 * (1 << shift));
|
||||||
/* padding for tx flags */
|
/* padding for tx flags */
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
@ -358,7 +358,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
|
||||||
|
|
||||||
if (status && status->rate &&
|
if (status && status->rate &&
|
||||||
(status->rate->flags & RATE_INFO_FLAGS_MCS)) {
|
(status->rate->flags & RATE_INFO_FLAGS_MCS)) {
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
|
rthdr->it_present |= cpu_to_le32(BIT(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 |
|
||||||
IEEE80211_RADIOTAP_MCS_HAVE_BW;
|
IEEE80211_RADIOTAP_MCS_HAVE_BW;
|
||||||
|
@ -374,7 +374,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
|
||||||
(IEEE80211_RADIOTAP_VHT_KNOWN_GI |
|
(IEEE80211_RADIOTAP_VHT_KNOWN_GI |
|
||||||
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
|
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
|
||||||
|
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_VHT));
|
||||||
|
|
||||||
/* required alignment from rthdr */
|
/* required alignment from rthdr */
|
||||||
pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
|
pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
|
||||||
|
@ -419,7 +419,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
|
||||||
(status->rate->flags & RATE_INFO_FLAGS_HE_MCS)) {
|
(status->rate->flags & RATE_INFO_FLAGS_HE_MCS)) {
|
||||||
struct ieee80211_radiotap_he *he;
|
struct ieee80211_radiotap_he *he;
|
||||||
|
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_HE));
|
||||||
|
|
||||||
/* required alignment from rthdr */
|
/* required alignment from rthdr */
|
||||||
pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
|
pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
|
||||||
|
@ -495,7 +495,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
|
||||||
/* IEEE80211_RADIOTAP_MCS
|
/* IEEE80211_RADIOTAP_MCS
|
||||||
* IEEE80211_RADIOTAP_VHT */
|
* IEEE80211_RADIOTAP_VHT */
|
||||||
if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
|
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(BIT(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 |
|
||||||
IEEE80211_RADIOTAP_MCS_HAVE_BW;
|
IEEE80211_RADIOTAP_MCS_HAVE_BW;
|
||||||
|
@ -512,7 +512,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
|
||||||
(IEEE80211_RADIOTAP_VHT_KNOWN_GI |
|
(IEEE80211_RADIOTAP_VHT_KNOWN_GI |
|
||||||
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
|
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
|
||||||
|
|
||||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
|
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_VHT));
|
||||||
|
|
||||||
/* required alignment from rthdr */
|
/* required alignment from rthdr */
|
||||||
pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
|
pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
|
||||||
|
|
|
@ -3242,7 +3242,9 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
|
||||||
if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
|
if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr)))
|
if (!ieee80211_amsdu_realloc_pad(local, skb,
|
||||||
|
sizeof(*amsdu_hdr) +
|
||||||
|
local->hw.extra_tx_headroom))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
data = skb_push(skb, sizeof(*amsdu_hdr));
|
data = skb_push(skb, sizeof(*amsdu_hdr));
|
||||||
|
@ -4782,11 +4784,11 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
|
||||||
static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata,
|
static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata,
|
||||||
struct beacon_data *beacon)
|
struct beacon_data *beacon)
|
||||||
{
|
{
|
||||||
|
u8 *beacon_data, count, max_count = 1;
|
||||||
struct probe_resp *resp;
|
struct probe_resp *resp;
|
||||||
u8 *beacon_data;
|
|
||||||
size_t beacon_data_len;
|
size_t beacon_data_len;
|
||||||
|
u16 *bcn_offsets;
|
||||||
int i;
|
int i;
|
||||||
u8 count = beacon->cntdwn_current_counter;
|
|
||||||
|
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
|
@ -4806,21 +4808,27 @@ static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; ++i) {
|
|
||||||
resp = rcu_dereference(sdata->u.ap.probe_resp);
|
resp = rcu_dereference(sdata->u.ap.probe_resp);
|
||||||
|
|
||||||
if (beacon->cntdwn_counter_offsets[i]) {
|
bcn_offsets = beacon->cntdwn_counter_offsets;
|
||||||
if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[i] >=
|
count = beacon->cntdwn_current_counter;
|
||||||
beacon_data_len)) {
|
if (sdata->vif.csa_active)
|
||||||
|
max_count = IEEE80211_MAX_CNTDWN_COUNTERS_NUM;
|
||||||
|
|
||||||
|
for (i = 0; i < max_count; ++i) {
|
||||||
|
if (bcn_offsets[i]) {
|
||||||
|
if (WARN_ON_ONCE(bcn_offsets[i] >= beacon_data_len)) {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
beacon_data[bcn_offsets[i]] = count;
|
||||||
beacon_data[beacon->cntdwn_counter_offsets[i]] = count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_AP && resp)
|
if (sdata->vif.type == NL80211_IFTYPE_AP && resp) {
|
||||||
resp->data[resp->cntdwn_counter_offsets[i]] = count;
|
u16 *resp_offsets = resp->cntdwn_counter_offsets;
|
||||||
|
|
||||||
|
resp->data[resp_offsets[i]] = count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
@ -5030,6 +5038,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||||
if (offs) {
|
if (offs) {
|
||||||
offs->tim_offset = beacon->head_len;
|
offs->tim_offset = beacon->head_len;
|
||||||
offs->tim_length = skb->len - beacon->head_len;
|
offs->tim_length = skb->len - beacon->head_len;
|
||||||
|
offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
|
||||||
|
|
||||||
/* for AP the csa offsets are from tail */
|
/* for AP the csa offsets are from tail */
|
||||||
csa_off_base = skb->len;
|
csa_off_base = skb->len;
|
||||||
|
|
|
@ -759,6 +759,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||||
[NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
|
[NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
|
||||||
[NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
|
[NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
|
||||||
[NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
|
[NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
|
||||||
|
[NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
|
||||||
|
[NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
|
||||||
|
[NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
|
||||||
|
[NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* policy for the key attributes */
|
/* policy for the key attributes */
|
||||||
|
@ -14800,6 +14804,106 @@ bad_tid_conf:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
|
||||||
|
{
|
||||||
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
|
struct cfg80211_color_change_settings params = {};
|
||||||
|
struct net_device *dev = info->user_ptr[1];
|
||||||
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
|
struct nlattr **tb;
|
||||||
|
u16 offset;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!rdev->ops->color_change)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||||
|
NL80211_EXT_FEATURE_BSS_COLOR))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (wdev->iftype != NL80211_IFTYPE_AP)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] ||
|
||||||
|
!info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] ||
|
||||||
|
!info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]);
|
||||||
|
params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]);
|
||||||
|
|
||||||
|
err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_next);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL);
|
||||||
|
if (!tb)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
err = nla_parse_nested(tb, NL80211_ATTR_MAX,
|
||||||
|
info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS],
|
||||||
|
nl80211_policy, info->extack);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
err = nl80211_parse_beacon(rdev, tb, ¶ms.beacon_color_change);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
|
||||||
|
if (offset >= params.beacon_color_change.tail_len) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.beacon_color_change.tail[offset] != params.count) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.counter_offset_beacon = offset;
|
||||||
|
|
||||||
|
if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
|
||||||
|
if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) !=
|
||||||
|
sizeof(u16)) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
|
||||||
|
if (offset >= params.beacon_color_change.probe_resp_len) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.beacon_color_change.probe_resp[offset] !=
|
||||||
|
params.count) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.counter_offset_presp = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
wdev_lock(wdev);
|
||||||
|
err = rdev_color_change(rdev, dev, ¶ms);
|
||||||
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree(tb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
#define NL80211_FLAG_NEED_WIPHY 0x01
|
#define NL80211_FLAG_NEED_WIPHY 0x01
|
||||||
#define NL80211_FLAG_NEED_NETDEV 0x02
|
#define NL80211_FLAG_NEED_NETDEV 0x02
|
||||||
#define NL80211_FLAG_NEED_RTNL 0x04
|
#define NL80211_FLAG_NEED_RTNL 0x04
|
||||||
|
@ -15795,6 +15899,14 @@ static const struct genl_small_ops nl80211_small_ops[] = {
|
||||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||||
NL80211_FLAG_NEED_RTNL,
|
NL80211_FLAG_NEED_RTNL,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
|
||||||
|
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||||
|
.doit = nl80211_color_change,
|
||||||
|
.flags = GENL_UNS_ADMIN_PERM,
|
||||||
|
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||||
|
NL80211_FLAG_NEED_RTNL,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct genl_family nl80211_fam __ro_after_init = {
|
static struct genl_family nl80211_fam __ro_after_init = {
|
||||||
|
@ -17424,6 +17536,51 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
|
EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
|
||||||
|
|
||||||
|
int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
|
||||||
|
enum nl80211_commands cmd, u8 count,
|
||||||
|
u64 color_bitmap)
|
||||||
|
{
|
||||||
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
|
struct wiphy *wiphy = wdev->wiphy;
|
||||||
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||||
|
struct sk_buff *msg;
|
||||||
|
void *hdr;
|
||||||
|
|
||||||
|
ASSERT_WDEV_LOCK(wdev);
|
||||||
|
|
||||||
|
trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
|
||||||
|
|
||||||
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
|
||||||
|
if (!msg)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
|
||||||
|
if (!hdr)
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
|
||||||
|
nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION &&
|
||||||
|
nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP,
|
||||||
|
color_bitmap, NL80211_ATTR_PAD))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
genlmsg_end(msg, hdr);
|
||||||
|
|
||||||
|
return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
|
||||||
|
msg, 0, NL80211_MCGRP_MLME, gfp);
|
||||||
|
|
||||||
|
nla_put_failure:
|
||||||
|
nlmsg_free(msg);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(cfg80211_bss_color_notify);
|
||||||
|
|
||||||
void
|
void
|
||||||
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
||||||
const struct cfg80211_chan_def *chandef,
|
const struct cfg80211_chan_def *chandef,
|
||||||
|
|
|
@ -115,23 +115,22 @@ int ieee80211_radiotap_iterator_init(
|
||||||
iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len);
|
iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len);
|
||||||
iterator->_arg_index = 0;
|
iterator->_arg_index = 0;
|
||||||
iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
|
iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
|
||||||
iterator->_arg = (uint8_t *)radiotap_header + sizeof(*radiotap_header);
|
iterator->_arg = (uint8_t *)radiotap_header->it_optional;
|
||||||
iterator->_reset_on_ext = 0;
|
iterator->_reset_on_ext = 0;
|
||||||
iterator->_next_bitmap = &radiotap_header->it_present;
|
iterator->_next_bitmap = radiotap_header->it_optional;
|
||||||
iterator->_next_bitmap++;
|
|
||||||
iterator->_vns = vns;
|
iterator->_vns = vns;
|
||||||
iterator->current_namespace = &radiotap_ns;
|
iterator->current_namespace = &radiotap_ns;
|
||||||
iterator->is_radiotap_ns = 1;
|
iterator->is_radiotap_ns = 1;
|
||||||
|
|
||||||
/* find payload start allowing for extended bitmap(s) */
|
/* find payload start allowing for extended bitmap(s) */
|
||||||
|
|
||||||
if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
|
if (iterator->_bitmap_shifter & (BIT(IEEE80211_RADIOTAP_EXT))) {
|
||||||
if ((unsigned long)iterator->_arg -
|
if ((unsigned long)iterator->_arg -
|
||||||
(unsigned long)iterator->_rtheader + sizeof(uint32_t) >
|
(unsigned long)iterator->_rtheader + sizeof(uint32_t) >
|
||||||
(unsigned long)iterator->_max_length)
|
(unsigned long)iterator->_max_length)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
while (get_unaligned_le32(iterator->_arg) &
|
while (get_unaligned_le32(iterator->_arg) &
|
||||||
(1 << IEEE80211_RADIOTAP_EXT)) {
|
(BIT(IEEE80211_RADIOTAP_EXT))) {
|
||||||
iterator->_arg += sizeof(uint32_t);
|
iterator->_arg += sizeof(uint32_t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1368,4 +1368,17 @@ static inline int rdev_set_sar_specs(struct cfg80211_registered_device *rdev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int rdev_color_change(struct cfg80211_registered_device *rdev,
|
||||||
|
struct net_device *dev,
|
||||||
|
struct cfg80211_color_change_settings *params)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
trace_rdev_color_change(&rdev->wiphy, dev, params);
|
||||||
|
ret = rdev->ops->color_change(&rdev->wiphy, dev, params);
|
||||||
|
trace_rdev_return_int(&rdev->wiphy, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __CFG80211_RDEV_OPS */
|
#endif /* __CFG80211_RDEV_OPS */
|
||||||
|
|
|
@ -3597,6 +3597,52 @@ TRACE_EVENT(rdev_set_sar_specs,
|
||||||
WIPHY_PR_ARG, __entry->type, __entry->num)
|
WIPHY_PR_ARG, __entry->type, __entry->num)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(rdev_color_change,
|
||||||
|
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
|
||||||
|
struct cfg80211_color_change_settings *params),
|
||||||
|
TP_ARGS(wiphy, netdev, params),
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
WIPHY_ENTRY
|
||||||
|
NETDEV_ENTRY
|
||||||
|
__field(u8, count)
|
||||||
|
__field(u16, bcn_ofs)
|
||||||
|
__field(u16, pres_ofs)
|
||||||
|
),
|
||||||
|
TP_fast_assign(
|
||||||
|
WIPHY_ASSIGN;
|
||||||
|
NETDEV_ASSIGN;
|
||||||
|
__entry->count = params->count;
|
||||||
|
__entry->bcn_ofs = params->counter_offset_beacon;
|
||||||
|
__entry->pres_ofs = params->counter_offset_presp;
|
||||||
|
),
|
||||||
|
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT
|
||||||
|
", count: %u",
|
||||||
|
WIPHY_PR_ARG, NETDEV_PR_ARG,
|
||||||
|
__entry->count)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(cfg80211_bss_color_notify,
|
||||||
|
TP_PROTO(struct net_device *netdev,
|
||||||
|
enum nl80211_commands cmd,
|
||||||
|
u8 count, u64 color_bitmap),
|
||||||
|
TP_ARGS(netdev, cmd, count, color_bitmap),
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
NETDEV_ENTRY
|
||||||
|
__field(u32, cmd)
|
||||||
|
__field(u8, count)
|
||||||
|
__field(u64, color_bitmap)
|
||||||
|
),
|
||||||
|
TP_fast_assign(
|
||||||
|
NETDEV_ASSIGN;
|
||||||
|
__entry->cmd = cmd;
|
||||||
|
__entry->count = count;
|
||||||
|
__entry->color_bitmap = color_bitmap;
|
||||||
|
),
|
||||||
|
TP_printk(NETDEV_PR_FMT ", cmd: %x, count: %u, bitmap: %llx",
|
||||||
|
NETDEV_PR_ARG, __entry->cmd, __entry->count,
|
||||||
|
__entry->color_bitmap)
|
||||||
|
);
|
||||||
|
|
||||||
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
|
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
|
||||||
|
|
||||||
#undef TRACE_INCLUDE_PATH
|
#undef TRACE_INCLUDE_PATH
|
||||||
|
|
Загрузка…
Ссылка в новой задаче