forked from Minki/linux
This time we have:
* ndo_fill_forward_path support in mac80211, to let drivers use it * association comeback notification for userspace, to be able to react more sensibly to long delays * support for background radar detection hardware in some chipsets * SA Query Procedures offload on the AP side * more logging if we find problems with HT/VHT/HE * various cleanups and minor fixes -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAmHBuIoACgkQB8qZga/f l8SDNQ//bWl1fnVTzXcva16NGXNtQc8ufOdDfEHsusTA0qP1EfCDfhiMmRZ+jUQH Xdg7F3Yube0fgij1sEgpcoVOFm5wr7p861nljR8m71t9FI832gfd+qdCJicNxGGI B3zEhHCkcZ4yBhT35+cKG/H3WBysI8RO65dC6NVlzCyY1iM9TVkHBtbEKrdNljcM cKKWRp/fk7lCRVqLtunUd5kJauwJxjwHOm4GTH5BajbT/06m91GLoj/tZEjr9rQL aSsBa1nR0/LcMyYbbQYIxLikTZnkzILIJGLakb7k5ZJ2W4/hUv0Zn6LUCyMDM1mK 7+Bt6qvB3Wz/TwjKYDm2qOniaD4IDVOtEpVPaXGau8c5Cj6rjnJ/cgF3ydBk4+xB 5xngZBCk6Y4+epg9V7EWfqmV0vVqlWqfUfARwPulLWA1X15mVVBmcrafGEaLvGrC mvkq0n0XZzf+ObrILK7yjafOdLC4ATCj8j6RW85mH4yU+PqKrx3gOCrWn3Zm+6BN n6y7vs5x6zEitqjap4zsiVxqJf3jtAVcdVy7k52VF2BBpF8xoyrIMYZw5CNUG2Jv aTmW5aE8X9mQ2VT88JewZst0IX4jjfK/B8wOj24tokC2mXRdM5uKTOWK7uTFQJfM lLFcRYzo6n6epHrA5oBN4SnQ3/QpZNJOEsRxyROXemDxnQ9de+w= =u1jf -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-net-next-2021-12-21' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== This time we have: * ndo_fill_forward_path support in mac80211, to let drivers use it * association comeback notification for userspace, to be able to react more sensibly to long delays * support for background radar detection hardware in some chipsets * SA Query Procedures offload on the AP side * more logging if we find problems with HT/VHT/HE * various cleanups and minor fixes Conflicts: net/wireless/reg.c:e08ebd6d7b
("cfg80211: Acquire wiphy mutex on regulatory work")701fdfe348
("cfg80211: Enable regulatory enforcement checks for drivers supporting mesh iface") https://lore.kernel.org/r/20211221111950.57ecc6a7@canb.auug.org.au drivers/net/wireless/ath/ath10k/wmi.c:7f599aeccb
("cfg80211: Use the HE operation IE to determine a 6GHz BSS channel")3bf2537ec2
("ath10k: drop beacon and probe response which leak from other channel") https://lore.kernel.org/r/20211221115004.1cd6b262@canb.auug.org.au * tag 'mac80211-next-for-net-next-2021-12-21' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next: (32 commits) cfg80211: Enable regulatory enforcement checks for drivers supporting mesh iface rfkill: allow to get the software rfkill state cfg80211: refactor cfg80211_get_ies_channel_number() nl82011: clarify interface combinations wrt. channels nl80211: Add support to offload SA Query procedures for AP SME device nl80211: Add support to set AP settings flags with single attribute mac80211: add more HT/VHT/HE state logging cfg80211: Use the HE operation IE to determine a 6GHz BSS channel cfg80211: rename offchannel_chain structs to background_chain to avoid confusion with ETSI standard mac80211: Notify cfg80211 about association comeback cfg80211: Add support for notifying association comeback mac80211: introduce channel switch disconnect function cfg80211: Fix order of enum nl80211_band_iftype_attr documentation cfg80211: simplify cfg80211_chandef_valid() mac80211: Remove a couple of obsolete TODO mac80211: fix FEC flag in radio tap header mac80211: use coarse boottime for airtime fairness code ieee80211: change HE nominal packet padding value defines cfg80211: use ieee80211_bss_get_elem() instead of _get_ie() mac80211: Use memset_after() to clear tx status ... ==================== Link: https://lore.kernel.org/r/20211221112532.28708-1-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
294e70c952
@ -2613,6 +2613,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
if (ieee80211_is_beacon(hdr->frame_control) ||
|
||||
ieee80211_is_probe_resp(hdr->frame_control)) {
|
||||
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
||||
enum cfg80211_bss_frame_type ftype;
|
||||
u8 *ies;
|
||||
int ies_ch;
|
||||
|
||||
@ -2623,9 +2624,14 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
|
||||
ies = mgmt->u.beacon.variable;
|
||||
|
||||
if (ieee80211_is_beacon(mgmt->frame_control))
|
||||
ftype = CFG80211_BSS_FTYPE_BEACON;
|
||||
else
|
||||
ftype = CFG80211_BSS_FTYPE_PRESP;
|
||||
|
||||
ies_ch = cfg80211_get_ies_channel_number(mgmt->u.beacon.variable,
|
||||
skb_tail_pointer(skb) - ies,
|
||||
sband->band);
|
||||
sband->band, ftype);
|
||||
|
||||
if (ies_ch > 0 && ies_ch != channel) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MGMT,
|
||||
|
@ -275,12 +275,12 @@ static void carl9170_tx_release(struct kref *ref)
|
||||
if (WARN_ON_ONCE(!ar))
|
||||
return;
|
||||
|
||||
BUILD_BUG_ON(
|
||||
offsetof(struct ieee80211_tx_info, status.ack_signal) != 20);
|
||||
|
||||
memset(&txinfo->status.ack_signal, 0,
|
||||
sizeof(struct ieee80211_tx_info) -
|
||||
offsetof(struct ieee80211_tx_info, status.ack_signal));
|
||||
/*
|
||||
* This does not call ieee80211_tx_info_clear_status() because
|
||||
* carl9170_tx_fill_rateinfo() has filled the rate information
|
||||
* before we get to this point.
|
||||
*/
|
||||
memset_after(&txinfo->status, 0, rates);
|
||||
|
||||
if (atomic_read(&ar->tx_total_queued))
|
||||
ar->tx_schedule = true;
|
||||
|
@ -608,7 +608,8 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
|
||||
.phy_cap_info[9] =
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |
|
||||
IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED,
|
||||
(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED <<
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS),
|
||||
.phy_cap_info[10] =
|
||||
IEEE80211_HE_PHY_CAP10_HE_MU_M1RU_MAX_LTF,
|
||||
},
|
||||
@ -665,7 +666,8 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
|
||||
IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
|
||||
IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242,
|
||||
.phy_cap_info[9] =
|
||||
IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED,
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED
|
||||
<< IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS,
|
||||
},
|
||||
/*
|
||||
* Set default Tx/Rx HE MCS NSS Support field.
|
||||
|
@ -2209,24 +2209,24 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
flags |= STA_CTXT_HE_PACKET_EXT;
|
||||
} else if ((sta->he_cap.he_cap_elem.phy_cap_info[9] &
|
||||
IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) !=
|
||||
IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED) {
|
||||
} else if (u8_get_bits(sta->he_cap.he_cap_elem.phy_cap_info[9],
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK)
|
||||
!= IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED) {
|
||||
int low_th = -1;
|
||||
int high_th = -1;
|
||||
|
||||
/* Take the PPE thresholds from the nominal padding info */
|
||||
switch (sta->he_cap.he_cap_elem.phy_cap_info[9] &
|
||||
IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) {
|
||||
case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US:
|
||||
switch (u8_get_bits(sta->he_cap.he_cap_elem.phy_cap_info[9],
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK)) {
|
||||
case IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_0US:
|
||||
low_th = IWL_HE_PKT_EXT_NONE;
|
||||
high_th = IWL_HE_PKT_EXT_NONE;
|
||||
break;
|
||||
case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US:
|
||||
case IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_8US:
|
||||
low_th = IWL_HE_PKT_EXT_BPSK;
|
||||
high_th = IWL_HE_PKT_EXT_NONE;
|
||||
break;
|
||||
case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US:
|
||||
case IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US:
|
||||
low_th = IWL_HE_PKT_EXT_NONE;
|
||||
high_th = IWL_HE_PKT_EXT_BPSK;
|
||||
break;
|
||||
|
@ -431,11 +431,7 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb)
|
||||
* Clear manually, ieee80211_tx_info_clear_status would
|
||||
* clear the counts too and we need them.
|
||||
*/
|
||||
memset(&info->status.ack_signal, 0,
|
||||
sizeof(struct ieee80211_tx_info) -
|
||||
offsetof(struct ieee80211_tx_info, status.ack_signal));
|
||||
BUILD_BUG_ON(offsetof(struct ieee80211_tx_info,
|
||||
status.ack_signal) != 20);
|
||||
memset_after(&info->status, 0, rates);
|
||||
|
||||
if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
|
||||
pad = entry_data->align[0];
|
||||
|
@ -1276,7 +1276,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
|
||||
/* If the queue contains MAX_QUEUE skb's drop some */
|
||||
if (skb_queue_len(&data->pending) >= MAX_QUEUE) {
|
||||
/* Droping until WARN_QUEUE level */
|
||||
/* Dropping until WARN_QUEUE level */
|
||||
while (skb_queue_len(&data->pending) >= WARN_QUEUE) {
|
||||
ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
|
||||
data->tx_dropped++;
|
||||
|
@ -853,7 +853,8 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
mt7915_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
} else {
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US;
|
||||
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
@ -140,7 +140,8 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
|
||||
mt7921_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
} else {
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US;
|
||||
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
|
||||
}
|
||||
|
||||
if (band == NL80211_BAND_6GHZ) {
|
||||
|
@ -2119,7 +2119,8 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev,
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |
|
||||
IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US;
|
||||
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
|
||||
if (i == NL80211_IFTYPE_STATION)
|
||||
phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
|
@ -781,7 +781,7 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev,
|
||||
if (!ppe_th) {
|
||||
u8 pad;
|
||||
|
||||
pad = FIELD_GET(IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK,
|
||||
pad = FIELD_GET(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK,
|
||||
sta->he_cap.he_cap_elem.phy_cap_info[9]);
|
||||
|
||||
for (i = 0; i < RTW89_PPE_BW_NUM; i++)
|
||||
|
@ -2258,11 +2258,12 @@ enum ieee80211_client_reg_power {
|
||||
#define IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU 0x08
|
||||
#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB 0x10
|
||||
#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB 0x20
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US 0x00
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US 0x40
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US 0x80
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED 0xc0
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK 0xc0
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_0US 0x0
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_8US 0x1
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US 0x2
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED 0x3
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS 6
|
||||
#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK 0xc0
|
||||
|
||||
#define IEEE80211_HE_PHY_CAP10_HE_MU_M1RU_MAX_LTF 0x01
|
||||
|
||||
|
@ -229,6 +229,13 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw);
|
||||
*/
|
||||
bool rfkill_blocked(struct rfkill *rfkill);
|
||||
|
||||
/**
|
||||
* rfkill_soft_blocked - Query soft rfkill block state
|
||||
*
|
||||
* @rfkill: rfkill struct to query
|
||||
*/
|
||||
bool rfkill_soft_blocked(struct rfkill *rfkill);
|
||||
|
||||
/**
|
||||
* rfkill_find_type - Helper for finding rfkill type by name
|
||||
* @name: the name of the type
|
||||
|
@ -1187,17 +1187,6 @@ struct cfg80211_unsol_bcast_probe_resp {
|
||||
const u8 *tmpl;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cfg80211_ap_settings_flags - AP settings flags
|
||||
*
|
||||
* Used by cfg80211_ap_settings
|
||||
*
|
||||
* @AP_SETTINGS_EXTERNAL_AUTH_SUPPORT: AP supports external authentication
|
||||
*/
|
||||
enum cfg80211_ap_settings_flags {
|
||||
AP_SETTINGS_EXTERNAL_AUTH_SUPPORT = BIT(0),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_ap_settings - AP configuration
|
||||
*
|
||||
@ -4072,6 +4061,15 @@ struct mgmt_frame_regs {
|
||||
* @set_fils_aad: Set FILS AAD data to the AP driver so that the driver can use
|
||||
* those to decrypt (Re)Association Request and encrypt (Re)Association
|
||||
* Response frame.
|
||||
*
|
||||
* @set_radar_background: Configure dedicated offchannel chain available for
|
||||
* radar/CAC detection on some hw. This chain can't be used to transmit
|
||||
* or receive frames and it is bounded to a running wdev.
|
||||
* Background radar/CAC detection allows to avoid the CAC downtime
|
||||
* switching to a different channel during CAC detection on the selected
|
||||
* radar channel.
|
||||
* The caller is expected to set chandef pointer to NULL in order to
|
||||
* disable background CAC/radar detection.
|
||||
*/
|
||||
struct cfg80211_ops {
|
||||
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
||||
@ -4404,6 +4402,8 @@ struct cfg80211_ops {
|
||||
struct cfg80211_color_change_settings *params);
|
||||
int (*set_fils_aad)(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_fils_aad *fils_aad);
|
||||
int (*set_radar_background)(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -6374,17 +6374,6 @@ static inline void cfg80211_gen_new_bssid(const u8 *bssid, u8 max_bssid,
|
||||
u64_to_ether_addr(new_bssid_u64, new_bssid);
|
||||
}
|
||||
|
||||
/**
|
||||
* cfg80211_get_ies_channel_number - returns the channel number from ies
|
||||
* @ie: IEs
|
||||
* @ielen: length of IEs
|
||||
* @band: enum nl80211_band of the channel
|
||||
*
|
||||
* Returns the channel number, or -1 if none could be determined.
|
||||
*/
|
||||
int cfg80211_get_ies_channel_number(const u8 *ie, size_t ielen,
|
||||
enum nl80211_band band);
|
||||
|
||||
/**
|
||||
* cfg80211_is_element_inherited - returns if element ID should be inherited
|
||||
* @element: element to check
|
||||
@ -6420,6 +6409,19 @@ enum cfg80211_bss_frame_type {
|
||||
CFG80211_BSS_FTYPE_PRESP,
|
||||
};
|
||||
|
||||
/**
|
||||
* cfg80211_get_ies_channel_number - returns the channel number from ies
|
||||
* @ie: IEs
|
||||
* @ielen: length of IEs
|
||||
* @band: enum nl80211_band of the channel
|
||||
* @ftype: frame type
|
||||
*
|
||||
* Returns the channel number, or -1 if none could be determined.
|
||||
*/
|
||||
int cfg80211_get_ies_channel_number(const u8 *ie, size_t ielen,
|
||||
enum nl80211_band band,
|
||||
enum cfg80211_bss_frame_type ftype);
|
||||
|
||||
/**
|
||||
* cfg80211_inform_bss_data - inform cfg80211 of a new BSS
|
||||
*
|
||||
@ -7594,15 +7596,33 @@ void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer,
|
||||
void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_radar_event - radar detection event
|
||||
* __cfg80211_radar_event - radar detection event
|
||||
* @wiphy: the wiphy
|
||||
* @chandef: chandef for the current channel
|
||||
* @offchan: the radar has been detected on the offchannel chain
|
||||
* @gfp: context flags
|
||||
*
|
||||
* This function is called when a radar is detected on the current chanenl.
|
||||
*/
|
||||
void cfg80211_radar_event(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef, gfp_t gfp);
|
||||
void __cfg80211_radar_event(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
bool offchan, gfp_t gfp);
|
||||
|
||||
static inline void
|
||||
cfg80211_radar_event(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
gfp_t gfp)
|
||||
{
|
||||
__cfg80211_radar_event(wiphy, chandef, false, gfp);
|
||||
}
|
||||
|
||||
static inline void
|
||||
cfg80211_background_radar_event(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
gfp_t gfp)
|
||||
{
|
||||
__cfg80211_radar_event(wiphy, chandef, true, gfp);
|
||||
}
|
||||
|
||||
/**
|
||||
* cfg80211_sta_opmode_change_notify - STA's ht/vht operation mode change event
|
||||
@ -7633,6 +7653,14 @@ void cfg80211_cac_event(struct net_device *netdev,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_radar_event event, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_background_cac_abort - Channel Availability Check offchan abort event
|
||||
* @wiphy: the wiphy
|
||||
*
|
||||
* This function is called by the driver when a Channel Availability Check
|
||||
* (CAC) is aborted by a offchannel dedicated chain.
|
||||
*/
|
||||
void cfg80211_background_cac_abort(struct wiphy *wiphy);
|
||||
|
||||
/**
|
||||
* cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
|
||||
@ -8250,6 +8278,18 @@ bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
|
||||
bool is_4addr, u8 check_swif);
|
||||
|
||||
|
||||
/**
|
||||
* cfg80211_assoc_comeback - notification of association that was
|
||||
* temporarly rejected with a comeback
|
||||
* @netdev: network device
|
||||
* @bss: the bss entry with which association is in progress.
|
||||
* @timeout: timeout interval value TUs.
|
||||
*
|
||||
* this function may sleep. the caller must hold the corresponding wdev's mutex.
|
||||
*/
|
||||
void cfg80211_assoc_comeback(struct net_device *netdev,
|
||||
struct cfg80211_bss *bss, u32 timeout);
|
||||
|
||||
/* Logging, debugging and troubleshooting/diagnostic helpers. */
|
||||
|
||||
/* wiphy_printk helpers, similar to dev_printk */
|
||||
|
@ -1205,12 +1205,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
|
||||
/* clear the rate counts */
|
||||
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++)
|
||||
info->status.rates[i].count = 0;
|
||||
|
||||
BUILD_BUG_ON(
|
||||
offsetof(struct ieee80211_tx_info, status.ack_signal) != 20);
|
||||
memset(&info->status.ampdu_ack_len, 0,
|
||||
sizeof(struct ieee80211_tx_info) -
|
||||
offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
|
||||
memset_after(&info->status, 0, rates);
|
||||
}
|
||||
|
||||
|
||||
@ -3944,6 +3939,16 @@ struct ieee80211_prep_tx_info {
|
||||
* twt structure.
|
||||
* @twt_teardown_request: Update the hw with TWT teardown request received
|
||||
* from the peer.
|
||||
* @set_radar_background: Configure dedicated offchannel chain available for
|
||||
* radar/CAC detection on some hw. This chain can't be used to transmit
|
||||
* or receive frames and it is bounded to a running wdev.
|
||||
* Background radar/CAC detection allows to avoid the CAC downtime
|
||||
* switching to a different channel during CAC detection on the selected
|
||||
* radar channel.
|
||||
* The caller is expected to set chandef pointer to NULL in order to
|
||||
* disable background CAC/radar detection.
|
||||
* @net_fill_forward_path: Called from .ndo_fill_forward_path in order to
|
||||
* resolve a path for hardware flow offloading
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
@ -4272,6 +4277,13 @@ struct ieee80211_ops {
|
||||
struct ieee80211_twt_setup *twt);
|
||||
void (*twt_teardown_request)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, u8 flowid);
|
||||
int (*set_radar_background)(struct ieee80211_hw *hw,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
int (*net_fill_forward_path)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct net_device_path_ctx *ctx,
|
||||
struct net_device_path *path);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -6063,6 +6075,18 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw);
|
||||
*/
|
||||
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success);
|
||||
|
||||
/**
|
||||
* ieee80211_channel_switch_disconnect - disconnect due to channel switch error
|
||||
* @vif &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @block_tx: if %true, do not send deauth frame.
|
||||
*
|
||||
* Instruct mac80211 to disconnect due to a channel switch error. The channel
|
||||
* switch can request to block the tx and so, we need to make sure we do not send
|
||||
* a deauth frame in this case.
|
||||
*/
|
||||
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif,
|
||||
bool block_tx);
|
||||
|
||||
/**
|
||||
* ieee80211_request_smps - request SM PS transition
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
|
@ -1232,6 +1232,11 @@
|
||||
* &NL80211_ATTR_FILS_NONCES - for FILS Nonces
|
||||
* (STA Nonce 16 bytes followed by AP Nonce 16 bytes)
|
||||
*
|
||||
* @NL80211_CMD_ASSOC_COMEBACK: notification about an association
|
||||
* temporal rejection with comeback. The event includes %NL80211_ATTR_MAC
|
||||
* to describe the BSSID address of the AP and %NL80211_ATTR_TIMEOUT to
|
||||
* specify the timeout value.
|
||||
*
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
@ -1474,6 +1479,8 @@ enum nl80211_commands {
|
||||
|
||||
NL80211_CMD_SET_FILS_AAD,
|
||||
|
||||
NL80211_CMD_ASSOC_COMEBACK,
|
||||
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
@ -2470,7 +2477,9 @@ enum nl80211_commands {
|
||||
* space supports external authentication. This attribute shall be used
|
||||
* with %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP request. The driver
|
||||
* may offload authentication processing to user space if this capability
|
||||
* is indicated in the respective requests from the user space.
|
||||
* is indicated in the respective requests from the user space. (This flag
|
||||
* attribute deprecated for %NL80211_CMD_START_AP, use
|
||||
* %NL80211_ATTR_AP_SETTINGS_FLAGS)
|
||||
*
|
||||
* @NL80211_ATTR_NSS: Station's New/updated RX_NSS value notified using this
|
||||
* u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED.
|
||||
@ -2639,6 +2648,17 @@ enum nl80211_commands {
|
||||
* Mandatory parameter for the transmitting interface to enable MBSSID.
|
||||
* Optional for the non-transmitting interfaces.
|
||||
*
|
||||
* @NL80211_ATTR_RADAR_BACKGROUND: Configure dedicated offchannel chain
|
||||
* available for radar/CAC detection on some hw. This chain can't be used
|
||||
* to transmit or receive frames and it is bounded to a running wdev.
|
||||
* Background radar/CAC detection allows to avoid the CAC downtime
|
||||
* switching on a different channel during CAC detection on the selected
|
||||
* radar channel.
|
||||
*
|
||||
* @NL80211_ATTR_AP_SETTINGS_FLAGS: u32 attribute contains ap settings flags,
|
||||
* enumerated in &enum nl80211_ap_settings_flags. This attribute shall be
|
||||
* used with %NL80211_CMD_START_AP request.
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@ -3145,6 +3165,10 @@ enum nl80211_attrs {
|
||||
NL80211_ATTR_MBSSID_CONFIG,
|
||||
NL80211_ATTR_MBSSID_ELEMS,
|
||||
|
||||
NL80211_ATTR_RADAR_BACKGROUND,
|
||||
|
||||
NL80211_ATTR_AP_SETTINGS_FLAGS,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@ -3738,13 +3762,12 @@ enum nl80211_mpath_info {
|
||||
* capabilities IE
|
||||
* @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE: HE PPE thresholds information as
|
||||
* defined in HE capabilities IE
|
||||
* @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently
|
||||
* defined
|
||||
* @NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA: HE 6GHz band capabilities (__le16),
|
||||
* given for all 6 GHz band channels
|
||||
* @NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS: vendor element capabilities that are
|
||||
* advertised on this band/for this iftype (binary)
|
||||
* @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use
|
||||
* @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined
|
||||
*/
|
||||
enum nl80211_band_iftype_attr {
|
||||
__NL80211_BAND_IFTYPE_ATTR_INVALID,
|
||||
@ -5555,7 +5578,7 @@ enum nl80211_iface_limit_attrs {
|
||||
* => allows 8 of AP/GO that can have BI gcd >= min gcd
|
||||
*
|
||||
* numbers = [ #{STA} <= 2 ], channels = 2, max = 2
|
||||
* => allows two STAs on different channels
|
||||
* => allows two STAs on the same or on different channels
|
||||
*
|
||||
* numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4
|
||||
* => allows a STA plus three P2P interfaces
|
||||
@ -5737,13 +5760,15 @@ enum nl80211_tdls_operation {
|
||||
NL80211_TDLS_DISABLE_LINK,
|
||||
};
|
||||
|
||||
/*
|
||||
/**
|
||||
* enum nl80211_ap_sme_features - device-integrated AP features
|
||||
* Reserved for future use, no bits are defined in
|
||||
* NL80211_ATTR_DEVICE_AP_SME yet.
|
||||
enum nl80211_ap_sme_features {
|
||||
};
|
||||
* @NL80211_AP_SME_SA_QUERY_OFFLOAD: SA Query procedures offloaded to driver
|
||||
* when user space indicates support for SA Query procedures offload during
|
||||
* "start ap" with %NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT.
|
||||
*/
|
||||
enum nl80211_ap_sme_features {
|
||||
NL80211_AP_SME_SA_QUERY_OFFLOAD = 1 << 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_feature_flags - device/driver features
|
||||
@ -6051,6 +6076,9 @@ enum nl80211_feature_flags {
|
||||
* frames. Userspace has to share FILS AAD details to the driver by using
|
||||
* @NL80211_CMD_SET_FILS_AAD.
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC
|
||||
* detection.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
@ -6117,6 +6145,7 @@ enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
|
||||
NL80211_EXT_FEATURE_BSS_COLOR,
|
||||
NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD,
|
||||
NL80211_EXT_FEATURE_RADAR_BACKGROUND,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
@ -7462,4 +7491,20 @@ enum nl80211_mbssid_config_attributes {
|
||||
NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_ap_settings_flags - AP settings flags
|
||||
*
|
||||
* @NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT: AP supports external
|
||||
* authentication.
|
||||
* @NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT: Userspace supports SA Query
|
||||
* procedures offload to driver. If driver advertises
|
||||
* %NL80211_AP_SME_SA_QUERY_OFFLOAD in AP SME features, userspace shall
|
||||
* ignore SA Query procedures and validations when this flag is set by
|
||||
* userspace.
|
||||
*/
|
||||
enum nl80211_ap_settings_flags {
|
||||
NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT = 1 << 0,
|
||||
NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1,
|
||||
};
|
||||
|
||||
#endif /* __LINUX_NL80211_H */
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
* Copyright (C) 2018-2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
@ -3198,6 +3198,18 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif)
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_finish);
|
||||
|
||||
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, bool block_tx)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
sdata->csa_block_tx = block_tx;
|
||||
sdata_info(sdata, "channel switch failed, disconnecting\n");
|
||||
ieee80211_queue_work(&local->hw, &ifmgd->csa_connection_drop_work);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_channel_switch_disconnect);
|
||||
|
||||
static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
u32 *changed)
|
||||
{
|
||||
@ -4268,6 +4280,21 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
|
||||
changed |= BSS_CHANGED_HE_BSS_COLOR;
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
|
||||
if (!sdata->vif.bss_conf.nontransmitted && sdata->vif.mbssid_tx_vif) {
|
||||
struct ieee80211_sub_if_data *child;
|
||||
|
||||
mutex_lock(&sdata->local->iflist_mtx);
|
||||
list_for_each_entry(child, &sdata->local->interfaces, list) {
|
||||
if (child != sdata && child->vif.mbssid_tx_vif == &sdata->vif) {
|
||||
child->vif.bss_conf.he_bss_color.color = color;
|
||||
child->vif.bss_conf.he_bss_color.enabled = enable;
|
||||
ieee80211_bss_info_change_notify(child,
|
||||
BSS_CHANGED_HE_BSS_COLOR);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&sdata->local->iflist_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata)
|
||||
@ -4352,6 +4379,9 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
if (sdata->vif.bss_conf.nontransmitted)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
|
||||
/* don't allow another color change if one is already active or if csa
|
||||
@ -4383,6 +4413,18 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_set_radar_background(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
|
||||
if (!local->ops->set_radar_background)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return local->ops->set_radar_background(&local->hw, chandef);
|
||||
}
|
||||
|
||||
const struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
@ -4487,4 +4529,5 @@ const struct cfg80211_ops mac80211_config_ops = {
|
||||
.reset_tid_config = ieee80211_reset_tid_config,
|
||||
.set_sar_specs = ieee80211_set_sar_specs,
|
||||
.color_change = ieee80211_color_change,
|
||||
.set_radar_background = ieee80211_set_radar_background,
|
||||
};
|
||||
|
@ -936,14 +936,15 @@ static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf,
|
||||
PFLAG(PHY, 9, RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB,
|
||||
"RX-FULL-BW-SU-USING-MU-WITH-NON-COMP-SIGB");
|
||||
|
||||
switch (cap[9] & IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) {
|
||||
case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US:
|
||||
switch (u8_get_bits(cap[9],
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK)) {
|
||||
case IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_0US:
|
||||
PRINT("NOMINAL-PACKET-PADDING-0US");
|
||||
break;
|
||||
case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US:
|
||||
case IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_8US:
|
||||
PRINT("NOMINAL-PACKET-PADDING-8US");
|
||||
break;
|
||||
case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US:
|
||||
case IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US:
|
||||
PRINT("NOMINAL-PACKET-PADDING-16US");
|
||||
break;
|
||||
}
|
||||
|
@ -1486,4 +1486,26 @@ static inline void drv_twt_teardown_request(struct ieee80211_local *local,
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta,
|
||||
struct net_device_path_ctx *ctx,
|
||||
struct net_device_path *path)
|
||||
{
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_net_fill_forward_path(local, sdata, sta);
|
||||
if (local->ops->net_fill_forward_path)
|
||||
ret = local->ops->net_fill_forward_path(&local->hw,
|
||||
&sdata->vif, sta,
|
||||
ctx, path);
|
||||
trace_drv_return_int(local, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
|
@ -1463,7 +1463,7 @@ struct ieee80211_local {
|
||||
};
|
||||
|
||||
static inline struct ieee80211_sub_if_data *
|
||||
IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
|
||||
IEEE80211_DEV_TO_SUB_IF(const struct net_device *dev)
|
||||
{
|
||||
return netdev_priv(dev);
|
||||
}
|
||||
|
@ -789,6 +789,64 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
|
||||
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||
};
|
||||
|
||||
static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
struct net_device_path *path)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_local *local;
|
||||
struct sta_info *sta;
|
||||
int ret = -ENOENT;
|
||||
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(ctx->dev);
|
||||
local = sdata->local;
|
||||
|
||||
if (!local->ops->net_fill_forward_path)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rcu_read_lock();
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
sta = rcu_dereference(sdata->u.vlan.sta);
|
||||
if (sta)
|
||||
break;
|
||||
if (sdata->wdev.use_4addr)
|
||||
goto out;
|
||||
if (is_multicast_ether_addr(ctx->daddr))
|
||||
goto out;
|
||||
sta = sta_info_get_bss(sdata, ctx->daddr);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
if (is_multicast_ether_addr(ctx->daddr))
|
||||
goto out;
|
||||
sta = sta_info_get(sdata, ctx->daddr);
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
|
||||
sta = sta_info_get(sdata, ctx->daddr);
|
||||
if (sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
|
||||
if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
||||
goto out;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sta = sta_info_get(sdata, sdata->u.mgd.bssid);
|
||||
break;
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!sta)
|
||||
goto out;
|
||||
|
||||
ret = drv_net_fill_forward_path(local, sdata, &sta->sta, ctx, path);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
.ndo_open = ieee80211_open,
|
||||
.ndo_stop = ieee80211_stop,
|
||||
@ -798,6 +856,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
.ndo_set_mac_address = ieee80211_change_mac,
|
||||
.ndo_select_queue = ieee80211_netdev_select_queue,
|
||||
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||
.ndo_fill_forward_path = ieee80211_netdev_fill_forward_path,
|
||||
};
|
||||
|
||||
static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
|
||||
|
@ -1131,17 +1131,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
local->scan_ies_len +=
|
||||
2 + sizeof(struct ieee80211_vht_cap);
|
||||
|
||||
/* HE cap element is variable in size - set len to allow max size */
|
||||
/*
|
||||
* TODO: 1 is added at the end of the calculation to accommodate for
|
||||
* the temporary placing of the HE capabilities IE under EXT.
|
||||
* Remove it once it is placed in the final place.
|
||||
*/
|
||||
if (supp_he)
|
||||
* HE cap element is variable in size - set len to allow max size */
|
||||
if (supp_he) {
|
||||
local->scan_ies_len +=
|
||||
2 + sizeof(struct ieee80211_he_cap_elem) +
|
||||
3 + sizeof(struct ieee80211_he_cap_elem) +
|
||||
sizeof(struct ieee80211_he_mcs_nss_supp) +
|
||||
IEEE80211_HE_PPE_THRES_MAX_LEN + 1;
|
||||
IEEE80211_HE_PPE_THRES_MAX_LEN;
|
||||
}
|
||||
|
||||
if (!local->ops->hw_scan) {
|
||||
/* For hw_scan, driver needs to set these up. */
|
||||
|
@ -164,12 +164,15 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
chandef->freq1_offset = channel->freq_offset;
|
||||
|
||||
if (channel->band == NL80211_BAND_6GHZ) {
|
||||
if (!ieee80211_chandef_he_6ghz_oper(sdata, he_oper, chandef))
|
||||
if (!ieee80211_chandef_he_6ghz_oper(sdata, he_oper, chandef)) {
|
||||
mlme_dbg(sdata,
|
||||
"bad 6 GHz operation, disabling HT/VHT/HE\n");
|
||||
ret = IEEE80211_STA_DISABLE_HT |
|
||||
IEEE80211_STA_DISABLE_VHT |
|
||||
IEEE80211_STA_DISABLE_HE;
|
||||
else
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
vht_chandef = *chandef;
|
||||
goto out;
|
||||
} else if (sband->band == NL80211_BAND_S1GHZ) {
|
||||
@ -190,6 +193,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
|
||||
|
||||
if (!ht_oper || !sta_ht_cap.ht_supported) {
|
||||
mlme_dbg(sdata, "HT operation missing / HT not supported\n");
|
||||
ret = IEEE80211_STA_DISABLE_HT |
|
||||
IEEE80211_STA_DISABLE_VHT |
|
||||
IEEE80211_STA_DISABLE_HE;
|
||||
@ -223,6 +227,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
if (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
|
||||
ieee80211_chandef_ht_oper(ht_oper, chandef);
|
||||
} else {
|
||||
mlme_dbg(sdata, "40 MHz not supported\n");
|
||||
/* 40 MHz (and 80 MHz) must be supported for VHT */
|
||||
ret = IEEE80211_STA_DISABLE_VHT;
|
||||
/* also mark 40 MHz disabled */
|
||||
@ -231,6 +236,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
if (!vht_oper || !sband->vht_cap.vht_supported) {
|
||||
mlme_dbg(sdata, "VHT operation missing / VHT not supported\n");
|
||||
ret = IEEE80211_STA_DISABLE_VHT;
|
||||
goto out;
|
||||
}
|
||||
@ -253,7 +259,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
&vht_chandef)) {
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE))
|
||||
sdata_info(sdata,
|
||||
"HE AP VHT information is invalid, disable HE\n");
|
||||
"HE AP VHT information is invalid, disabling HE\n");
|
||||
ret = IEEE80211_STA_DISABLE_HE;
|
||||
goto out;
|
||||
}
|
||||
@ -263,7 +269,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
&vht_chandef)) {
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
|
||||
sdata_info(sdata,
|
||||
"AP VHT information is invalid, disable VHT\n");
|
||||
"AP VHT information is invalid, disabling VHT\n");
|
||||
ret = IEEE80211_STA_DISABLE_VHT;
|
||||
goto out;
|
||||
}
|
||||
@ -271,7 +277,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
if (!cfg80211_chandef_valid(&vht_chandef)) {
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
|
||||
sdata_info(sdata,
|
||||
"AP VHT information is invalid, disable VHT\n");
|
||||
"AP VHT information is invalid, disabling VHT\n");
|
||||
ret = IEEE80211_STA_DISABLE_VHT;
|
||||
goto out;
|
||||
}
|
||||
@ -284,7 +290,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
|
||||
sdata_info(sdata,
|
||||
"AP VHT information doesn't match HT, disable VHT\n");
|
||||
"AP VHT information doesn't match HT, disabling VHT\n");
|
||||
ret = IEEE80211_STA_DISABLE_VHT;
|
||||
goto out;
|
||||
}
|
||||
@ -649,10 +655,6 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
|
||||
if (!he_cap || !reg_cap)
|
||||
return;
|
||||
|
||||
/*
|
||||
* TODO: the 1 added is because this temporarily is under the EXTENSION
|
||||
* IE. Get rid of it when it moves.
|
||||
*/
|
||||
he_cap_size =
|
||||
2 + 1 + sizeof(he_cap->he_cap_elem) +
|
||||
ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem) +
|
||||
@ -3741,6 +3743,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
||||
elems->timeout_int &&
|
||||
elems->timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
|
||||
u32 tu, ms;
|
||||
|
||||
cfg80211_assoc_comeback(sdata->dev, assoc_data->bss,
|
||||
le32_to_cpu(elems->timeout_int->value));
|
||||
|
||||
tu = le32_to_cpu(elems->timeout_int->value);
|
||||
ms = tu * 1024 / 1000;
|
||||
sdata_info(sdata,
|
||||
@ -5043,19 +5049,23 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
/* disable HT/VHT/HE if we don't support them */
|
||||
if (!sband->ht_cap.ht_supported && !is_6ghz) {
|
||||
mlme_dbg(sdata, "HT not supported, disabling HT/VHT/HE\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||
}
|
||||
|
||||
if (!sband->vht_cap.vht_supported && is_5ghz) {
|
||||
mlme_dbg(sdata, "VHT not supported, disabling VHT/HE\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||
}
|
||||
|
||||
if (!ieee80211_get_he_iftype_cap(sband,
|
||||
ieee80211_vif_type_p2p(&sdata->vif)))
|
||||
ieee80211_vif_type_p2p(&sdata->vif))) {
|
||||
mlme_dbg(sdata, "HE not supported, disabling it\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||
}
|
||||
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && !is_6ghz) {
|
||||
ht_oper = elems->ht_operation;
|
||||
@ -5079,6 +5089,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
if (!elems->vht_cap_elem) {
|
||||
sdata_info(sdata,
|
||||
"bad VHT capabilities, disabling VHT\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
vht_oper = NULL;
|
||||
}
|
||||
@ -5126,8 +5138,10 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!have_80mhz)
|
||||
if (!have_80mhz) {
|
||||
sdata_info(sdata, "80 MHz not supported, disabling VHT\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
}
|
||||
|
||||
if (sband->band == NL80211_BAND_S1GHZ) {
|
||||
s1g_oper = elems->s1g_oper;
|
||||
@ -5691,12 +5705,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
else if (!is_6ghz)
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
||||
vht_elem = ieee80211_bss_get_elem(req->bss, WLAN_EID_VHT_CAPABILITY);
|
||||
if (vht_elem && vht_elem->datalen >= sizeof(struct ieee80211_vht_cap))
|
||||
if (vht_elem && vht_elem->datalen >= sizeof(struct ieee80211_vht_cap)) {
|
||||
memcpy(&assoc_data->ap_vht_cap, vht_elem->data,
|
||||
sizeof(struct ieee80211_vht_cap));
|
||||
else if (is_5ghz)
|
||||
} else if (is_5ghz) {
|
||||
sdata_info(sdata, "VHT capa missing/short, disabling VHT/HE\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT |
|
||||
IEEE80211_STA_DISABLE_HE;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (WARN((sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD) &&
|
||||
@ -5770,16 +5786,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
if (req->flags & ASSOC_REQ_DISABLE_HT) {
|
||||
mlme_dbg(sdata, "HT disabled by flag, disabling HT/VHT/HE\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||
}
|
||||
|
||||
if (req->flags & ASSOC_REQ_DISABLE_VHT)
|
||||
if (req->flags & ASSOC_REQ_DISABLE_VHT) {
|
||||
mlme_dbg(sdata, "VHT disabled by flag, disabling VHT\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
}
|
||||
|
||||
if (req->flags & ASSOC_REQ_DISABLE_HE)
|
||||
if (req->flags & ASSOC_REQ_DISABLE_HE) {
|
||||
mlme_dbg(sdata, "HE disabled by flag, disabling VHT\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||
}
|
||||
|
||||
err = ieee80211_prep_connection(sdata, req->bss, true, override);
|
||||
if (err)
|
||||
|
@ -18,8 +18,6 @@
|
||||
#define AVG_AMPDU_SIZE 16
|
||||
#define AVG_PKT_SIZE 1200
|
||||
|
||||
#define SAMPLE_SWITCH_THR 100
|
||||
|
||||
/* Number of bits for an average sized packet */
|
||||
#define MCS_NBITS ((AVG_PKT_SIZE * AVG_AMPDU_SIZE) << 3)
|
||||
|
||||
|
@ -465,7 +465,12 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||
unsigned int stbc;
|
||||
|
||||
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_MCS));
|
||||
*pos++ = local->hw.radiotap_mcs_details;
|
||||
*pos = local->hw.radiotap_mcs_details;
|
||||
if (status->enc_flags & RX_ENC_FLAG_HT_GF)
|
||||
*pos |= IEEE80211_RADIOTAP_MCS_HAVE_FMT;
|
||||
if (status->enc_flags & RX_ENC_FLAG_LDPC)
|
||||
*pos |= IEEE80211_RADIOTAP_MCS_HAVE_FEC;
|
||||
pos++;
|
||||
*pos = 0;
|
||||
if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
|
||||
*pos |= IEEE80211_RADIOTAP_MCS_SGI;
|
||||
|
@ -2892,6 +2892,13 @@ TRACE_EVENT(drv_twt_teardown_request,
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sta_event, drv_net_fill_forward_path,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta),
|
||||
TP_ARGS(local, sdata, sta)
|
||||
);
|
||||
|
||||
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
@ -3821,7 +3821,7 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct airtime_sched_info *air_sched;
|
||||
u64 now = ktime_get_boottime_ns();
|
||||
u64 now = ktime_get_coarse_boottime_ns();
|
||||
struct ieee80211_txq *ret = NULL;
|
||||
struct airtime_info *air_info;
|
||||
struct txq_info *txqi = NULL;
|
||||
@ -3948,7 +3948,7 @@ void ieee80211_update_airtime_weight(struct ieee80211_local *local,
|
||||
u64 weight_sum = 0;
|
||||
|
||||
if (unlikely(!now))
|
||||
now = ktime_get_boottime_ns();
|
||||
now = ktime_get_coarse_boottime_ns();
|
||||
|
||||
lockdep_assert_held(&air_sched->lock);
|
||||
|
||||
@ -3974,7 +3974,7 @@ void ieee80211_schedule_txq(struct ieee80211_hw *hw,
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct txq_info *txqi = to_txq_info(txq);
|
||||
struct airtime_sched_info *air_sched;
|
||||
u64 now = ktime_get_boottime_ns();
|
||||
u64 now = ktime_get_coarse_boottime_ns();
|
||||
struct airtime_info *air_info;
|
||||
u8 ac = txq->ac;
|
||||
bool was_active;
|
||||
@ -4032,7 +4032,7 @@ static void __ieee80211_unschedule_txq(struct ieee80211_hw *hw,
|
||||
|
||||
if (!purge)
|
||||
airtime_set_active(air_sched, air_info,
|
||||
ktime_get_boottime_ns());
|
||||
ktime_get_coarse_boottime_ns());
|
||||
|
||||
rb_erase_cached(&txqi->schedule_order,
|
||||
&air_sched->active_txqs);
|
||||
@ -4120,7 +4120,7 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
|
||||
if (RB_EMPTY_NODE(&txqi->schedule_order))
|
||||
goto out;
|
||||
|
||||
now = ktime_get_boottime_ns();
|
||||
now = ktime_get_coarse_boottime_ns();
|
||||
|
||||
/* Like in ieee80211_next_txq(), make sure the first station in the
|
||||
* scheduling order is eligible for transmission to avoid starvation.
|
||||
|
@ -449,7 +449,6 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
|
||||
(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
|
||||
return 0;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) pos;
|
||||
pos += hdrlen;
|
||||
|
||||
pn64 = atomic64_inc_return(&key->conf.tx_pn);
|
||||
@ -686,7 +685,6 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
||||
(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
|
||||
return 0;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)pos;
|
||||
pos += hdrlen;
|
||||
|
||||
pn64 = atomic64_inc_return(&key->conf.tx_pn);
|
||||
@ -881,8 +879,6 @@ ieee80211_crypto_cs_decrypt(struct ieee80211_rx_data *rx)
|
||||
if (skb_linearize(rx->skb))
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||
|
||||
rx_pn = key->u.gen.rx_pn[qos_tid];
|
||||
skb_pn = rx->skb->data + hdrlen + cs->pn_off;
|
||||
|
||||
|
@ -946,6 +946,18 @@ bool rfkill_blocked(struct rfkill *rfkill)
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_blocked);
|
||||
|
||||
bool rfkill_soft_blocked(struct rfkill *rfkill)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 state;
|
||||
|
||||
spin_lock_irqsave(&rfkill->lock, flags);
|
||||
state = rfkill->state;
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
return !!(state & RFKILL_BLOCK_SW);
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_soft_blocked);
|
||||
|
||||
struct rfkill * __must_check rfkill_alloc(const char *name,
|
||||
struct device *parent,
|
||||
|
@ -245,19 +245,7 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
|
||||
oper_freq - MHZ_TO_KHZ(oper_width) / 2)
|
||||
return false;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
if (chandef->center_freq1 != control_freq + 10 &&
|
||||
chandef->center_freq1 != control_freq - 10)
|
||||
return false;
|
||||
if (chandef->center_freq2)
|
||||
return false;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
if (chandef->center_freq1 != control_freq + 30 &&
|
||||
chandef->center_freq1 != control_freq + 10 &&
|
||||
chandef->center_freq1 != control_freq - 10 &&
|
||||
chandef->center_freq1 != control_freq - 30)
|
||||
return false;
|
||||
if (!chandef->center_freq2)
|
||||
return false;
|
||||
/* adjacent is not allowed -- that's a 160 MHz channel */
|
||||
@ -265,28 +253,42 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
|
||||
chandef->center_freq2 - chandef->center_freq1 == 80)
|
||||
return false;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
if (chandef->center_freq1 != control_freq + 30 &&
|
||||
chandef->center_freq1 != control_freq + 10 &&
|
||||
chandef->center_freq1 != control_freq - 10 &&
|
||||
chandef->center_freq1 != control_freq - 30)
|
||||
return false;
|
||||
default:
|
||||
if (chandef->center_freq2)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (chandef->width) {
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
case NL80211_CHAN_WIDTH_10:
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
case NL80211_CHAN_WIDTH_1:
|
||||
case NL80211_CHAN_WIDTH_2:
|
||||
case NL80211_CHAN_WIDTH_4:
|
||||
case NL80211_CHAN_WIDTH_8:
|
||||
case NL80211_CHAN_WIDTH_16:
|
||||
/* all checked above */
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
if (chandef->center_freq1 != control_freq + 70 &&
|
||||
chandef->center_freq1 != control_freq + 50 &&
|
||||
chandef->center_freq1 != control_freq + 30 &&
|
||||
chandef->center_freq1 != control_freq + 10 &&
|
||||
chandef->center_freq1 != control_freq - 10 &&
|
||||
chandef->center_freq1 != control_freq - 30 &&
|
||||
chandef->center_freq1 != control_freq - 50 &&
|
||||
chandef->center_freq1 != control_freq - 70)
|
||||
return false;
|
||||
if (chandef->center_freq2)
|
||||
return false;
|
||||
break;
|
||||
if (chandef->center_freq1 == control_freq + 70 ||
|
||||
chandef->center_freq1 == control_freq + 50 ||
|
||||
chandef->center_freq1 == control_freq - 50 ||
|
||||
chandef->center_freq1 == control_freq - 70)
|
||||
break;
|
||||
fallthrough;
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
if (chandef->center_freq1 == control_freq + 30 ||
|
||||
chandef->center_freq1 == control_freq - 30)
|
||||
break;
|
||||
fallthrough;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
if (chandef->center_freq1 == control_freq + 10 ||
|
||||
chandef->center_freq1 == control_freq - 10)
|
||||
break;
|
||||
fallthrough;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -712,6 +714,19 @@ static bool cfg80211_is_wiphy_oper_chan(struct wiphy *wiphy,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
cfg80211_offchan_chain_is_active(struct cfg80211_registered_device *rdev,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
if (!rdev->background_radar_wdev)
|
||||
return false;
|
||||
|
||||
if (!cfg80211_chandef_valid(&rdev->background_radar_chandef))
|
||||
return false;
|
||||
|
||||
return cfg80211_is_sub_chan(&rdev->background_radar_chandef, channel);
|
||||
}
|
||||
|
||||
bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *chan)
|
||||
{
|
||||
@ -728,6 +743,9 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
|
||||
|
||||
if (cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan))
|
||||
return true;
|
||||
|
||||
if (cfg80211_offchan_chain_is_active(rdev, chan))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -545,6 +545,10 @@ use_default_name:
|
||||
INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work);
|
||||
INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
|
||||
INIT_WORK(&rdev->event_work, cfg80211_event_work);
|
||||
INIT_WORK(&rdev->background_cac_abort_wk,
|
||||
cfg80211_background_cac_abort_wk);
|
||||
INIT_DELAYED_WORK(&rdev->background_cac_done_wk,
|
||||
cfg80211_background_cac_done_wk);
|
||||
|
||||
init_waitqueue_head(&rdev->dev_wait);
|
||||
|
||||
@ -733,6 +737,7 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
if (wiphy->interface_modes & ~(BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE) |
|
||||
@ -1054,11 +1059,13 @@ void wiphy_unregister(struct wiphy *wiphy)
|
||||
cancel_work_sync(&rdev->conn_work);
|
||||
flush_work(&rdev->event_work);
|
||||
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
|
||||
cancel_delayed_work_sync(&rdev->background_cac_done_wk);
|
||||
flush_work(&rdev->destroy_work);
|
||||
flush_work(&rdev->sched_scan_stop_wk);
|
||||
flush_work(&rdev->propagate_radar_detect_wk);
|
||||
flush_work(&rdev->propagate_cac_done_wk);
|
||||
flush_work(&rdev->mgmt_registrations_update_wk);
|
||||
flush_work(&rdev->background_cac_abort_wk);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
|
||||
@ -1207,6 +1214,8 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
|
||||
cfg80211_pmsr_wdev_down(wdev);
|
||||
|
||||
cfg80211_stop_background_radar_detection(wdev);
|
||||
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
__cfg80211_leave_ibss(rdev, dev, true);
|
||||
|
@ -84,6 +84,11 @@ struct cfg80211_registered_device {
|
||||
|
||||
struct delayed_work dfs_update_channels_wk;
|
||||
|
||||
struct wireless_dev *background_radar_wdev;
|
||||
struct cfg80211_chan_def background_radar_chandef;
|
||||
struct delayed_work background_cac_done_wk;
|
||||
struct work_struct background_cac_abort_wk;
|
||||
|
||||
/* netlink port which started critical protocol (0 means not started) */
|
||||
u32 crit_proto_nlportid;
|
||||
|
||||
@ -491,6 +496,17 @@ cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
|
||||
|
||||
void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev);
|
||||
|
||||
int
|
||||
cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
|
||||
void cfg80211_stop_background_radar_detection(struct wireless_dev *wdev);
|
||||
|
||||
void cfg80211_background_cac_done_wk(struct work_struct *work);
|
||||
|
||||
void cfg80211_background_cac_abort_wk(struct work_struct *work);
|
||||
|
||||
bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *chan);
|
||||
|
||||
|
@ -905,13 +905,13 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
|
||||
void cfg80211_radar_event(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
gfp_t gfp)
|
||||
void __cfg80211_radar_event(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
bool offchan, gfp_t gfp)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
trace_cfg80211_radar_event(wiphy, chandef);
|
||||
trace_cfg80211_radar_event(wiphy, chandef, offchan);
|
||||
|
||||
/* only set the chandef supplied channel to unavailable, in
|
||||
* case the radar is detected on only one of multiple channels
|
||||
@ -919,6 +919,9 @@ void cfg80211_radar_event(struct wiphy *wiphy,
|
||||
*/
|
||||
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
|
||||
|
||||
if (offchan)
|
||||
queue_work(cfg80211_wq, &rdev->background_cac_abort_wk);
|
||||
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
|
||||
nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
|
||||
@ -926,7 +929,7 @@ void cfg80211_radar_event(struct wiphy *wiphy,
|
||||
memcpy(&rdev->radar_chandef, chandef, sizeof(struct cfg80211_chan_def));
|
||||
queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_radar_event);
|
||||
EXPORT_SYMBOL(__cfg80211_radar_event);
|
||||
|
||||
void cfg80211_cac_event(struct net_device *netdev,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
@ -970,3 +973,143 @@ void cfg80211_cac_event(struct net_device *netdev,
|
||||
nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_cac_event);
|
||||
|
||||
static void
|
||||
__cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_radar_event event)
|
||||
{
|
||||
struct wiphy *wiphy = &rdev->wiphy;
|
||||
struct net_device *netdev;
|
||||
|
||||
lockdep_assert_wiphy(&rdev->wiphy);
|
||||
|
||||
if (!cfg80211_chandef_valid(chandef))
|
||||
return;
|
||||
|
||||
if (!rdev->background_radar_wdev)
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
case NL80211_RADAR_CAC_FINISHED:
|
||||
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
|
||||
memcpy(&rdev->cac_done_chandef, chandef, sizeof(*chandef));
|
||||
queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
wdev = rdev->background_radar_wdev;
|
||||
break;
|
||||
case NL80211_RADAR_CAC_ABORTED:
|
||||
if (!cancel_delayed_work(&rdev->background_cac_done_wk))
|
||||
return;
|
||||
wdev = rdev->background_radar_wdev;
|
||||
break;
|
||||
case NL80211_RADAR_CAC_STARTED:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
netdev = wdev ? wdev->netdev : NULL;
|
||||
nl80211_radar_notify(rdev, chandef, event, netdev, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void
|
||||
cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_radar_event event)
|
||||
{
|
||||
wiphy_lock(&rdev->wiphy);
|
||||
__cfg80211_background_cac_event(rdev, rdev->background_radar_wdev,
|
||||
chandef, event);
|
||||
wiphy_unlock(&rdev->wiphy);
|
||||
}
|
||||
|
||||
void cfg80211_background_cac_done_wk(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work = to_delayed_work(work);
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
rdev = container_of(delayed_work, struct cfg80211_registered_device,
|
||||
background_cac_done_wk);
|
||||
cfg80211_background_cac_event(rdev, &rdev->background_radar_chandef,
|
||||
NL80211_RADAR_CAC_FINISHED);
|
||||
}
|
||||
|
||||
void cfg80211_background_cac_abort_wk(struct work_struct *work)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
rdev = container_of(work, struct cfg80211_registered_device,
|
||||
background_cac_abort_wk);
|
||||
cfg80211_background_cac_event(rdev, &rdev->background_radar_chandef,
|
||||
NL80211_RADAR_CAC_ABORTED);
|
||||
}
|
||||
|
||||
void cfg80211_background_cac_abort(struct wiphy *wiphy)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
queue_work(cfg80211_wq, &rdev->background_cac_abort_wk);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_background_cac_abort);
|
||||
|
||||
int
|
||||
cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
unsigned int cac_time_ms;
|
||||
int err;
|
||||
|
||||
lockdep_assert_wiphy(&rdev->wiphy);
|
||||
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_RADAR_BACKGROUND))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Offchannel chain already locked by another wdev */
|
||||
if (rdev->background_radar_wdev && rdev->background_radar_wdev != wdev)
|
||||
return -EBUSY;
|
||||
|
||||
/* CAC already in progress on the offchannel chain */
|
||||
if (rdev->background_radar_wdev == wdev &&
|
||||
delayed_work_pending(&rdev->background_cac_done_wk))
|
||||
return -EBUSY;
|
||||
|
||||
err = rdev_set_radar_background(rdev, chandef);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, chandef);
|
||||
if (!cac_time_ms)
|
||||
cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
|
||||
|
||||
rdev->background_radar_chandef = *chandef;
|
||||
rdev->background_radar_wdev = wdev; /* Get offchain ownership */
|
||||
|
||||
__cfg80211_background_cac_event(rdev, wdev, chandef,
|
||||
NL80211_RADAR_CAC_STARTED);
|
||||
queue_delayed_work(cfg80211_wq, &rdev->background_cac_done_wk,
|
||||
msecs_to_jiffies(cac_time_ms));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cfg80211_stop_background_radar_detection(struct wireless_dev *wdev)
|
||||
{
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
lockdep_assert_wiphy(wiphy);
|
||||
|
||||
if (wdev != rdev->background_radar_wdev)
|
||||
return;
|
||||
|
||||
rdev_set_radar_background(rdev, NULL);
|
||||
rdev->background_radar_wdev = NULL; /* Release offchain ownership */
|
||||
|
||||
__cfg80211_background_cac_event(rdev, wdev,
|
||||
&rdev->background_radar_chandef,
|
||||
NL80211_RADAR_CAC_ABORTED);
|
||||
}
|
||||
|
@ -776,6 +776,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||
[NL80211_ATTR_MBSSID_CONFIG] =
|
||||
NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
|
||||
[NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
|
||||
[NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@ -3669,14 +3671,16 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_ADHOC: {
|
||||
const u8 *ssid_ie;
|
||||
const struct element *ssid_elem;
|
||||
|
||||
if (!wdev->current_bss)
|
||||
break;
|
||||
rcu_read_lock();
|
||||
ssid_ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
|
||||
WLAN_EID_SSID);
|
||||
if (ssid_ie &&
|
||||
nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2))
|
||||
ssid_elem = ieee80211_bss_get_elem(&wdev->current_bss->pub,
|
||||
WLAN_EID_SSID);
|
||||
if (ssid_elem &&
|
||||
nla_put(msg, NL80211_ATTR_SSID, ssid_elem->datalen,
|
||||
ssid_elem->data))
|
||||
goto nla_put_failure_rcu_locked;
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
@ -5711,8 +5715,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
nl80211_calculate_ap_params(params);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
||||
params->flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
|
||||
if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS])
|
||||
params->flags = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]);
|
||||
else if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
||||
params->flags |= NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
|
||||
|
||||
wdev_lock(wdev);
|
||||
err = rdev_start_ap(rdev, dev, params);
|
||||
@ -9274,38 +9281,60 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
||||
struct cfg80211_chan_def chandef;
|
||||
enum nl80211_dfs_regions dfs_region;
|
||||
unsigned int cac_time_ms;
|
||||
int err;
|
||||
int err = -EINVAL;
|
||||
|
||||
flush_delayed_work(&rdev->dfs_update_channels_wk);
|
||||
|
||||
wiphy_lock(wiphy);
|
||||
|
||||
dfs_region = reg_get_dfs_region(wiphy);
|
||||
if (dfs_region == NL80211_DFS_UNSET)
|
||||
return -EINVAL;
|
||||
goto unlock;
|
||||
|
||||
err = nl80211_parse_chandef(rdev, info, &chandef);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (netif_carrier_ok(dev))
|
||||
return -EBUSY;
|
||||
|
||||
if (wdev->cac_started)
|
||||
return -EBUSY;
|
||||
goto unlock;
|
||||
|
||||
err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto unlock;
|
||||
|
||||
if (err == 0)
|
||||
return -EINVAL;
|
||||
if (err == 0) {
|
||||
err = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
|
||||
return -EINVAL;
|
||||
if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) {
|
||||
err = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) {
|
||||
err = cfg80211_start_background_radar_detection(rdev, wdev,
|
||||
&chandef);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (netif_carrier_ok(dev)) {
|
||||
err = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (wdev->cac_started) {
|
||||
err = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* CAC start is offloaded to HW and can't be started manually */
|
||||
if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
|
||||
return -EOPNOTSUPP;
|
||||
if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!rdev->ops->start_radar_detection)
|
||||
return -EOPNOTSUPP;
|
||||
if (!rdev->ops->start_radar_detection) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
|
||||
if (WARN_ON(!cac_time_ms))
|
||||
@ -9318,6 +9347,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
||||
wdev->cac_start_time = jiffies;
|
||||
wdev->cac_time_ms = cac_time_ms;
|
||||
}
|
||||
unlock:
|
||||
wiphy_unlock(wiphy);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -15954,7 +15986,8 @@ static const struct genl_small_ops nl80211_small_ops[] = {
|
||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
.doit = nl80211_start_radar_detection,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NO_WIPHY_MTX,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
|
||||
@ -17035,6 +17068,44 @@ static void nl80211_send_remain_on_chan_event(
|
||||
nlmsg_free(msg);
|
||||
}
|
||||
|
||||
void cfg80211_assoc_comeback(struct net_device *netdev,
|
||||
struct cfg80211_bss *bss, u32 timeout)
|
||||
{
|
||||
struct wireless_dev *wdev = netdev->ieee80211_ptr;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
trace_cfg80211_assoc_comeback(wdev, bss->bssid, timeout);
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ASSOC_COMEBACK);
|
||||
if (!hdr) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
|
||||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bss->bssid) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_TIMEOUT, timeout))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
|
||||
NL80211_MCGRP_MLME, GFP_KERNEL);
|
||||
return;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(msg);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_assoc_comeback);
|
||||
|
||||
void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration, gfp_t gfp)
|
||||
|
@ -1395,4 +1395,21 @@ rdev_set_fils_aad(struct cfg80211_registered_device *rdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
rdev_set_radar_background(struct cfg80211_registered_device *rdev,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct wiphy *wiphy = &rdev->wiphy;
|
||||
int ret;
|
||||
|
||||
if (!rdev->ops->set_radar_background)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
trace_rdev_set_radar_background(wiphy, chandef);
|
||||
ret = rdev->ops->set_radar_background(wiphy, chandef);
|
||||
trace_rdev_return_int(wiphy, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __CFG80211_RDEV_OPS */
|
||||
|
@ -2371,6 +2371,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
if (!wdev->beacon_interval)
|
||||
goto wdev_inactive_unlock;
|
||||
chandef = wdev->chandef;
|
||||
@ -2409,6 +2410,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
wiphy_lock(wiphy);
|
||||
ret = cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
|
||||
wiphy_unlock(wiphy);
|
||||
|
@ -406,22 +406,20 @@ static int
|
||||
cfg80211_add_nontrans_list(struct cfg80211_bss *trans_bss,
|
||||
struct cfg80211_bss *nontrans_bss)
|
||||
{
|
||||
const u8 *ssid;
|
||||
size_t ssid_len;
|
||||
const struct element *ssid_elem;
|
||||
struct cfg80211_bss *bss = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
|
||||
if (!ssid) {
|
||||
ssid_elem = ieee80211_bss_get_elem(nontrans_bss, WLAN_EID_SSID);
|
||||
if (!ssid_elem) {
|
||||
rcu_read_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
ssid_len = ssid[1];
|
||||
ssid = ssid + 2;
|
||||
|
||||
/* check if nontrans_bss is in the list */
|
||||
list_for_each_entry(bss, &trans_bss->nontrans_list, nontrans_list) {
|
||||
if (is_bss(bss, nontrans_bss->bssid, ssid, ssid_len)) {
|
||||
if (is_bss(bss, nontrans_bss->bssid, ssid_elem->data,
|
||||
ssid_elem->datalen)) {
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
@ -1795,33 +1793,52 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
|
||||
}
|
||||
|
||||
int cfg80211_get_ies_channel_number(const u8 *ie, size_t ielen,
|
||||
enum nl80211_band band)
|
||||
enum nl80211_band band,
|
||||
enum cfg80211_bss_frame_type ftype)
|
||||
{
|
||||
const u8 *tmp;
|
||||
int channel_number = -1;
|
||||
const struct element *tmp;
|
||||
|
||||
if (band == NL80211_BAND_S1GHZ) {
|
||||
tmp = cfg80211_find_ie(WLAN_EID_S1G_OPERATION, ie, ielen);
|
||||
if (tmp && tmp[1] >= sizeof(struct ieee80211_s1g_oper_ie)) {
|
||||
struct ieee80211_s1g_oper_ie *s1gop = (void *)(tmp + 2);
|
||||
if (band == NL80211_BAND_6GHZ) {
|
||||
struct ieee80211_he_operation *he_oper;
|
||||
|
||||
channel_number = s1gop->primary_ch;
|
||||
tmp = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ie,
|
||||
ielen);
|
||||
if (tmp && tmp->datalen >= sizeof(*he_oper) &&
|
||||
tmp->datalen >= ieee80211_he_oper_size(&tmp->data[1])) {
|
||||
const struct ieee80211_he_6ghz_oper *he_6ghz_oper;
|
||||
|
||||
he_oper = (void *)&tmp->data[1];
|
||||
|
||||
he_6ghz_oper = ieee80211_he_6ghz_oper(he_oper);
|
||||
if (!he_6ghz_oper)
|
||||
return -1;
|
||||
|
||||
if (ftype != CFG80211_BSS_FTYPE_BEACON ||
|
||||
he_6ghz_oper->control & IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON)
|
||||
return he_6ghz_oper->primary;
|
||||
}
|
||||
} else if (band == NL80211_BAND_S1GHZ) {
|
||||
tmp = cfg80211_find_elem(WLAN_EID_S1G_OPERATION, ie, ielen);
|
||||
if (tmp && tmp->datalen >= sizeof(struct ieee80211_s1g_oper_ie)) {
|
||||
struct ieee80211_s1g_oper_ie *s1gop = (void *)tmp->data;
|
||||
|
||||
return s1gop->primary_ch;
|
||||
}
|
||||
} else {
|
||||
tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen);
|
||||
if (tmp && tmp[1] == 1) {
|
||||
channel_number = tmp[2];
|
||||
} else {
|
||||
tmp = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, ielen);
|
||||
if (tmp && tmp[1] >= sizeof(struct ieee80211_ht_operation)) {
|
||||
struct ieee80211_ht_operation *htop = (void *)(tmp + 2);
|
||||
tmp = cfg80211_find_elem(WLAN_EID_DS_PARAMS, ie, ielen);
|
||||
if (tmp && tmp->datalen == 1)
|
||||
return tmp->data[0];
|
||||
|
||||
channel_number = htop->primary_chan;
|
||||
}
|
||||
tmp = cfg80211_find_elem(WLAN_EID_HT_OPERATION, ie, ielen);
|
||||
if (tmp &&
|
||||
tmp->datalen >= sizeof(struct ieee80211_ht_operation)) {
|
||||
struct ieee80211_ht_operation *htop = (void *)tmp->data;
|
||||
|
||||
return htop->primary_chan;
|
||||
}
|
||||
}
|
||||
|
||||
return channel_number;
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_get_ies_channel_number);
|
||||
|
||||
@ -1831,18 +1848,20 @@ EXPORT_SYMBOL(cfg80211_get_ies_channel_number);
|
||||
* from neighboring channels and the Beacon frames use the DSSS Parameter Set
|
||||
* element to indicate the current (transmitting) channel, but this might also
|
||||
* be needed on other bands if RX frequency does not match with the actual
|
||||
* operating channel of a BSS.
|
||||
* operating channel of a BSS, or if the AP reports a different primary channel.
|
||||
*/
|
||||
static struct ieee80211_channel *
|
||||
cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
|
||||
struct ieee80211_channel *channel,
|
||||
enum nl80211_bss_scan_width scan_width)
|
||||
enum nl80211_bss_scan_width scan_width,
|
||||
enum cfg80211_bss_frame_type ftype)
|
||||
{
|
||||
u32 freq;
|
||||
int channel_number;
|
||||
struct ieee80211_channel *alt_channel;
|
||||
|
||||
channel_number = cfg80211_get_ies_channel_number(ie, ielen, channel->band);
|
||||
channel_number = cfg80211_get_ies_channel_number(ie, ielen,
|
||||
channel->band, ftype);
|
||||
|
||||
if (channel_number < 0) {
|
||||
/* No channel information in frame payload */
|
||||
@ -1850,6 +1869,16 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
|
||||
}
|
||||
|
||||
freq = ieee80211_channel_to_freq_khz(channel_number, channel->band);
|
||||
|
||||
/*
|
||||
* In 6GHz, duplicated beacon indication is relevant for
|
||||
* beacons only.
|
||||
*/
|
||||
if (channel->band == NL80211_BAND_6GHZ &&
|
||||
(freq == channel->center_freq ||
|
||||
abs(freq - channel->center_freq) > 80))
|
||||
return channel;
|
||||
|
||||
alt_channel = ieee80211_get_channel_khz(wiphy, freq);
|
||||
if (!alt_channel) {
|
||||
if (channel->band == NL80211_BAND_2GHZ) {
|
||||
@ -1911,7 +1940,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
|
||||
return NULL;
|
||||
|
||||
channel = cfg80211_get_bss_channel(wiphy, ie, ielen, data->chan,
|
||||
data->scan_width);
|
||||
data->scan_width, ftype);
|
||||
if (!channel)
|
||||
return NULL;
|
||||
|
||||
@ -2234,7 +2263,8 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
|
||||
struct ieee80211_mgmt *mgmt, size_t len)
|
||||
{
|
||||
u8 *ie, *new_ie, *pos;
|
||||
const u8 *nontrans_ssid, *trans_ssid, *mbssid;
|
||||
const struct element *nontrans_ssid;
|
||||
const u8 *trans_ssid, *mbssid;
|
||||
size_t ielen = len - offsetof(struct ieee80211_mgmt,
|
||||
u.probe_resp.variable);
|
||||
size_t new_ie_len;
|
||||
@ -2261,11 +2291,11 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
|
||||
return;
|
||||
new_ie_len -= mbssid[1];
|
||||
|
||||
nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
|
||||
nontrans_ssid = ieee80211_bss_get_elem(nontrans_bss, WLAN_EID_SSID);
|
||||
if (!nontrans_ssid)
|
||||
return;
|
||||
|
||||
new_ie_len += nontrans_ssid[1];
|
||||
new_ie_len += nontrans_ssid->datalen;
|
||||
|
||||
/* generate new ie for nontrans BSS
|
||||
* 1. replace SSID with nontrans BSS' SSID
|
||||
@ -2282,7 +2312,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
|
||||
pos = new_ie;
|
||||
|
||||
/* copy the nontransmitted SSID */
|
||||
cpy_len = nontrans_ssid[1] + 2;
|
||||
cpy_len = nontrans_ssid->datalen + 2;
|
||||
memcpy(pos, nontrans_ssid, cpy_len);
|
||||
pos += cpy_len;
|
||||
/* copy the IEs between SSID and MBSSID */
|
||||
@ -2333,6 +2363,7 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
|
||||
size_t ielen, min_hdr_len = offsetof(struct ieee80211_mgmt,
|
||||
u.probe_resp.variable);
|
||||
int bss_type;
|
||||
enum cfg80211_bss_frame_type ftype;
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
|
||||
offsetof(struct ieee80211_mgmt, u.beacon.variable));
|
||||
@ -2369,8 +2400,16 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
|
||||
variable = ext->u.s1g_beacon.variable;
|
||||
}
|
||||
|
||||
if (ieee80211_is_beacon(mgmt->frame_control))
|
||||
ftype = CFG80211_BSS_FTYPE_BEACON;
|
||||
else if (ieee80211_is_probe_resp(mgmt->frame_control))
|
||||
ftype = CFG80211_BSS_FTYPE_PRESP;
|
||||
else
|
||||
ftype = CFG80211_BSS_FTYPE_UNKNOWN;
|
||||
|
||||
channel = cfg80211_get_bss_channel(wiphy, variable,
|
||||
ielen, data->chan, data->scan_width);
|
||||
ielen, data->chan, data->scan_width,
|
||||
ftype);
|
||||
if (!channel)
|
||||
return NULL;
|
||||
|
||||
@ -2687,7 +2726,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy;
|
||||
struct iw_scan_req *wreq = NULL;
|
||||
struct cfg80211_scan_request *creq = NULL;
|
||||
struct cfg80211_scan_request *creq;
|
||||
int i, err, n_channels = 0;
|
||||
enum nl80211_band band;
|
||||
|
||||
@ -2702,10 +2741,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
||||
if (IS_ERR(rdev))
|
||||
return PTR_ERR(rdev);
|
||||
|
||||
if (rdev->scan_req || rdev->scan_msg) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
if (rdev->scan_req || rdev->scan_msg)
|
||||
return -EBUSY;
|
||||
|
||||
wiphy = &rdev->wiphy;
|
||||
|
||||
@ -2718,10 +2755,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
||||
creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
|
||||
n_channels * sizeof(void *),
|
||||
GFP_ATOMIC);
|
||||
if (!creq) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!creq)
|
||||
return -ENOMEM;
|
||||
|
||||
creq->wiphy = wiphy;
|
||||
creq->wdev = dev->ieee80211_ptr;
|
||||
|
@ -680,7 +680,9 @@ void __cfg80211_connect_result(struct net_device *dev,
|
||||
bool wextev)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
const u8 *country_ie;
|
||||
const struct element *country_elem;
|
||||
const u8 *country_data;
|
||||
u8 country_datalen;
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
union iwreq_data wrqu;
|
||||
#endif
|
||||
@ -762,26 +764,22 @@ void __cfg80211_connect_result(struct net_device *dev,
|
||||
cfg80211_upload_connect_keys(wdev);
|
||||
|
||||
rcu_read_lock();
|
||||
country_ie = ieee80211_bss_get_ie(cr->bss, WLAN_EID_COUNTRY);
|
||||
if (!country_ie) {
|
||||
country_elem = ieee80211_bss_get_elem(cr->bss, WLAN_EID_COUNTRY);
|
||||
if (!country_elem) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
country_ie = kmemdup(country_ie, 2 + country_ie[1], GFP_ATOMIC);
|
||||
country_datalen = country_elem->datalen;
|
||||
country_data = kmemdup(country_elem->data, country_datalen, GFP_ATOMIC);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!country_ie)
|
||||
if (!country_data)
|
||||
return;
|
||||
|
||||
/*
|
||||
* ieee80211_bss_get_ie() ensures we can access:
|
||||
* - country_ie + 2, the start of the country ie data, and
|
||||
* - and country_ie[1] which is the IE length
|
||||
*/
|
||||
regulatory_hint_country_ie(wdev->wiphy, cr->bss->channel->band,
|
||||
country_ie + 2, country_ie[1]);
|
||||
kfree(country_ie);
|
||||
country_data, country_datalen);
|
||||
kfree(country_data);
|
||||
}
|
||||
|
||||
/* Consumes bss object one way or another */
|
||||
|
@ -3053,18 +3053,21 @@ TRACE_EVENT(cfg80211_ch_switch_started_notify,
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_radar_event,
|
||||
TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
|
||||
TP_ARGS(wiphy, chandef),
|
||||
TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
|
||||
bool offchan),
|
||||
TP_ARGS(wiphy, chandef, offchan),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
CHAN_DEF_ENTRY
|
||||
__field(bool, offchan)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
CHAN_DEF_ASSIGN(chandef);
|
||||
__entry->offchan = offchan;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
|
||||
WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", offchan %d",
|
||||
WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->offchan)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_cac_event,
|
||||
@ -3674,6 +3677,42 @@ TRACE_EVENT(cfg80211_bss_color_notify,
|
||||
__entry->color_bitmap)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_set_radar_background,
|
||||
TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
|
||||
|
||||
TP_ARGS(wiphy, chandef),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
CHAN_DEF_ENTRY
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
CHAN_DEF_ASSIGN(chandef)
|
||||
),
|
||||
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
|
||||
WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_assoc_comeback,
|
||||
TP_PROTO(struct wireless_dev *wdev, const u8 *bssid, u32 timeout),
|
||||
TP_ARGS(wdev, bssid, timeout),
|
||||
TP_STRUCT__entry(
|
||||
WDEV_ENTRY
|
||||
MAC_ENTRY(bssid)
|
||||
__field(u32, timeout)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WDEV_ASSIGN;
|
||||
MAC_ASSIGN(bssid, bssid);
|
||||
__entry->timeout = timeout;
|
||||
),
|
||||
TP_printk(WDEV_PR_FMT ", " MAC_PR_FMT ", timeout: %u TUs",
|
||||
WDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->timeout)
|
||||
);
|
||||
|
||||
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
@ -212,18 +212,18 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
|
||||
|
||||
wdev_lock(wdev);
|
||||
if (wdev->current_bss) {
|
||||
const u8 *ie;
|
||||
const struct element *ssid_elem;
|
||||
|
||||
rcu_read_lock();
|
||||
ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
|
||||
WLAN_EID_SSID);
|
||||
if (ie) {
|
||||
ssid_elem = ieee80211_bss_get_elem(&wdev->current_bss->pub,
|
||||
WLAN_EID_SSID);
|
||||
if (ssid_elem) {
|
||||
data->flags = 1;
|
||||
data->length = ie[1];
|
||||
data->length = ssid_elem->datalen;
|
||||
if (data->length > IW_ESSID_MAX_SIZE)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
memcpy(ssid, ie + 2, data->length);
|
||||
memcpy(ssid, ssid_elem->data, data->length);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
} else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
|
||||
|
Loading…
Reference in New Issue
Block a user