mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 15:19:51 +00:00
A few big new things:
* 802.11 frame encapsulation offload support * more HE (802.11ax) support, including some for 6 GHz band * powersave in hwsim, for better testing Of course as usual there are various cleanups and small fixes. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAl5GggsACgkQB8qZga/f l8Qgdg//R42bSv94JYPcwZ5phgTgraCRZODWjBJq08n2T5m0EmEufgX79d9uEdgT u9npvn+ich5/VZhmuSbGrW9TT6/FPLAZyghV1fj79o971Qd7ky2Mp8G1fcTEbtDn IG2e9vauY9XDSb2O3wNj8dA8rAN/kLNmhsPqWxn2CgLPqjdbf+W15dvo4rnaL2gs ffGyE47dHuAFwCruyT8UPbw3iu4+tQhruN9eVg+UkU8rJGvEMqfrLK20zl1weIV9 a7IuXdxacdsHO8Y+tl6GtvgOURQPpvf55+leLOUhcmHPJ3f/eAal6wmWRxDxs/qB IWSe8BC81cZZ5pYWk1A+0sXfJMlYjNsN0xw5SQRSrbgyb5saz8aLUIlHsOBM4iPH SwzCMN5A1GOPOUFsugzPwbiki9g6dh0/EC2NyXE4A26CAd967dVXTvTY5SMNgiB+ bZaaUDaPQUm1jgDT5bLRhTipTHbekDkYzG/e+wNO+HKyStoEYM485MwY4MQCYzEh HKDmkAbFuCwEUeXXw1y8GybUknApCRru9FtY+oiN/+y/aESfB7HJfmDFFU/KYgPu HOuqJoNAxdMdycDCb24/cLjUiehzfM6sujwBxZOD5WHhAcXrBo5dGd6ibfurIrjj XI36/mwTiMtyyb0/5xM1AKvoic2j+a5YU3MB7KSc9TlaPa5j2NA= =CgmJ -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-net-next-2020-02-14' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== A few big new things: * 802.11 frame encapsulation offload support * more HE (802.11ax) support, including some for 6 GHz band * powersave in hwsim, for better testing Of course as usual there are various cleanups and small fixes. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ddb535a6a0
@ -5103,7 +5103,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar)
|
|||||||
lockdep_assert_held(&ar->conf_mutex);
|
lockdep_assert_held(&ar->conf_mutex);
|
||||||
|
|
||||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||||
if (arvif->txpower <= 0)
|
/* txpower not initialized yet? */
|
||||||
|
if (arvif->txpower == INT_MIN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (txpower == -1)
|
if (txpower == -1)
|
||||||
|
@ -1196,6 +1196,9 @@ static void ath9k_tpc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
|||||||
{
|
{
|
||||||
int *power = data;
|
int *power = data;
|
||||||
|
|
||||||
|
if (vif->bss_conf.txpower == INT_MIN)
|
||||||
|
return;
|
||||||
|
|
||||||
if (*power < vif->bss_conf.txpower)
|
if (*power < vif->bss_conf.txpower)
|
||||||
*power = vif->bss_conf.txpower;
|
*power = vif->bss_conf.txpower;
|
||||||
}
|
}
|
||||||
|
@ -2095,10 +2095,13 @@ static void setup_frame_info(struct ieee80211_hw *hw,
|
|||||||
|
|
||||||
if (tx_info->control.vif) {
|
if (tx_info->control.vif) {
|
||||||
struct ieee80211_vif *vif = tx_info->control.vif;
|
struct ieee80211_vif *vif = tx_info->control.vif;
|
||||||
|
if (vif->bss_conf.txpower == INT_MIN)
|
||||||
|
goto nonvifpower;
|
||||||
txpower = 2 * vif->bss_conf.txpower;
|
txpower = 2 * vif->bss_conf.txpower;
|
||||||
} else {
|
} else {
|
||||||
struct ath_softc *sc = hw->priv;
|
struct ath_softc *sc;
|
||||||
|
nonvifpower:
|
||||||
|
sc = hw->priv;
|
||||||
|
|
||||||
txpower = sc->cur_chan->cur_txpower;
|
txpower = sc->cur_chan->cur_txpower;
|
||||||
}
|
}
|
||||||
|
@ -2019,7 +2019,7 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
|
|||||||
struct iwl_he_sta_context_cmd sta_ctxt_cmd = {
|
struct iwl_he_sta_context_cmd sta_ctxt_cmd = {
|
||||||
.sta_id = sta_id,
|
.sta_id = sta_id,
|
||||||
.tid_limit = IWL_MAX_TID_COUNT,
|
.tid_limit = IWL_MAX_TID_COUNT,
|
||||||
.bss_color = vif->bss_conf.bss_color,
|
.bss_color = vif->bss_conf.he_bss_color.color,
|
||||||
.htc_trig_based_pkt_ext = vif->bss_conf.htc_trig_based_pkt_ext,
|
.htc_trig_based_pkt_ext = vif->bss_conf.htc_trig_based_pkt_ext,
|
||||||
.frame_time_rts_th =
|
.frame_time_rts_th =
|
||||||
cpu_to_le16(vif->bss_conf.frame_time_rts_th),
|
cpu_to_le16(vif->bss_conf.frame_time_rts_th),
|
||||||
|
@ -300,14 +300,12 @@ static struct net_device *hwsim_mon; /* global monitor netdev */
|
|||||||
.band = NL80211_BAND_2GHZ, \
|
.band = NL80211_BAND_2GHZ, \
|
||||||
.center_freq = (_freq), \
|
.center_freq = (_freq), \
|
||||||
.hw_value = (_freq), \
|
.hw_value = (_freq), \
|
||||||
.max_power = 20, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHAN5G(_freq) { \
|
#define CHAN5G(_freq) { \
|
||||||
.band = NL80211_BAND_5GHZ, \
|
.band = NL80211_BAND_5GHZ, \
|
||||||
.center_freq = (_freq), \
|
.center_freq = (_freq), \
|
||||||
.hw_value = (_freq), \
|
.hw_value = (_freq), \
|
||||||
.max_power = 20, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ieee80211_channel hwsim_channels_2ghz[] = {
|
static const struct ieee80211_channel hwsim_channels_2ghz[] = {
|
||||||
@ -1595,6 +1593,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
|
|||||||
mac80211_hwsim_tx_frame(hw, skb,
|
mac80211_hwsim_tx_frame(hw, skb,
|
||||||
rcu_dereference(vif->chanctx_conf)->def.chan);
|
rcu_dereference(vif->chanctx_conf)->def.chan);
|
||||||
|
|
||||||
|
while ((skb = ieee80211_get_buffered_bc(hw, vif)) != NULL) {
|
||||||
|
mac80211_hwsim_tx_frame(hw, skb,
|
||||||
|
rcu_dereference(vif->chanctx_conf)->def.chan);
|
||||||
|
}
|
||||||
|
|
||||||
if (vif->csa_active && ieee80211_csa_is_complete(vif))
|
if (vif->csa_active && ieee80211_csa_is_complete(vif))
|
||||||
ieee80211_csa_finish(vif);
|
ieee80211_csa_finish(vif);
|
||||||
}
|
}
|
||||||
@ -2925,11 +2928,15 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||||||
ieee80211_hw_set(hw, MFP_CAPABLE);
|
ieee80211_hw_set(hw, MFP_CAPABLE);
|
||||||
ieee80211_hw_set(hw, SIGNAL_DBM);
|
ieee80211_hw_set(hw, SIGNAL_DBM);
|
||||||
ieee80211_hw_set(hw, SUPPORTS_PS);
|
ieee80211_hw_set(hw, SUPPORTS_PS);
|
||||||
|
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
|
||||||
|
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
|
||||||
|
ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
|
||||||
ieee80211_hw_set(hw, TDLS_WIDER_BW);
|
ieee80211_hw_set(hw, TDLS_WIDER_BW);
|
||||||
if (rctbl)
|
if (rctbl)
|
||||||
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
|
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
|
||||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||||
|
|
||||||
|
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
|
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
|
||||||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
|
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
|
||||||
WIPHY_FLAG_AP_UAPSD |
|
WIPHY_FLAG_AP_UAPSD |
|
||||||
|
@ -619,6 +619,15 @@ static inline bool ieee80211_is_qos_nullfunc(__le16 fc)
|
|||||||
cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
|
cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_is_any_nullfunc - check if frame is regular or QoS nullfunc frame
|
||||||
|
* @fc: frame control bytes in little-endian byteorder
|
||||||
|
*/
|
||||||
|
static inline bool ieee80211_is_any_nullfunc(__le16 fc)
|
||||||
|
{
|
||||||
|
return (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
|
* ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
|
||||||
* @fc: frame control field in little-endian byteorder
|
* @fc: frame control field in little-endian byteorder
|
||||||
@ -2053,7 +2062,7 @@ ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size
|
* ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size
|
||||||
* @he_oper_ie: byte data of the He Operations IE, stating from the the byte
|
* @he_oper_ie: byte data of the He Operations IE, stating from the byte
|
||||||
* after the ext ID byte. It is assumed that he_oper_ie has at least
|
* after the ext ID byte. It is assumed that he_oper_ie has at least
|
||||||
* sizeof(struct ieee80211_he_operation) bytes, the caller must have
|
* sizeof(struct ieee80211_he_operation) bytes, the caller must have
|
||||||
* validated this.
|
* validated this.
|
||||||
@ -2091,7 +2100,7 @@ ieee80211_he_oper_size(const u8 *he_oper_ie)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size
|
* ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size
|
||||||
* @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the the byte
|
* @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the byte
|
||||||
* after the ext ID byte. It is assumed that he_spr_ie has at least
|
* after the ext ID byte. It is assumed that he_spr_ie has at least
|
||||||
* sizeof(struct ieee80211_he_spr) bytes, the caller must have validated
|
* sizeof(struct ieee80211_he_spr) bytes, the caller must have validated
|
||||||
* this
|
* this
|
||||||
@ -2523,6 +2532,7 @@ enum ieee80211_eid {
|
|||||||
WLAN_EID_FILS_INDICATION = 240,
|
WLAN_EID_FILS_INDICATION = 240,
|
||||||
WLAN_EID_DILS = 241,
|
WLAN_EID_DILS = 241,
|
||||||
WLAN_EID_FRAGMENT = 242,
|
WLAN_EID_FRAGMENT = 242,
|
||||||
|
WLAN_EID_RSNX = 244,
|
||||||
WLAN_EID_EXTENSION = 255
|
WLAN_EID_EXTENSION = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2734,7 +2744,7 @@ enum ieee80211_tdls_actioncode {
|
|||||||
*/
|
*/
|
||||||
#define WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT BIT(6)
|
#define WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT BIT(6)
|
||||||
|
|
||||||
/* TDLS capabilities in the the 4th byte of @WLAN_EID_EXT_CAPABILITY */
|
/* TDLS capabilities in the 4th byte of @WLAN_EID_EXT_CAPABILITY */
|
||||||
#define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4)
|
#define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4)
|
||||||
#define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5)
|
#define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5)
|
||||||
#define WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH BIT(6)
|
#define WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH BIT(6)
|
||||||
@ -3034,6 +3044,7 @@ struct ieee80211_multiple_bssid_configuration {
|
|||||||
#define WLAN_AKM_SUITE_FILS_SHA384 SUITE(0x000FAC, 15)
|
#define WLAN_AKM_SUITE_FILS_SHA384 SUITE(0x000FAC, 15)
|
||||||
#define WLAN_AKM_SUITE_FT_FILS_SHA256 SUITE(0x000FAC, 16)
|
#define WLAN_AKM_SUITE_FT_FILS_SHA256 SUITE(0x000FAC, 16)
|
||||||
#define WLAN_AKM_SUITE_FT_FILS_SHA384 SUITE(0x000FAC, 17)
|
#define WLAN_AKM_SUITE_FT_FILS_SHA384 SUITE(0x000FAC, 17)
|
||||||
|
#define WLAN_AKM_SUITE_OWE SUITE(0x000FAC, 18)
|
||||||
|
|
||||||
#define WLAN_MAX_KEY_LEN 32
|
#define WLAN_MAX_KEY_LEN 32
|
||||||
|
|
||||||
@ -3412,4 +3423,11 @@ static inline bool for_each_element_completed(const struct element *element,
|
|||||||
return (const u8 *)element == (const u8 *)data + datalen;
|
return (const u8 *)element == (const u8 *)data + datalen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSNX Capabilities:
|
||||||
|
* bits 0-3: Field length (n-1)
|
||||||
|
*/
|
||||||
|
#define WLAN_RSNX_CAPA_PROTECTED_TWT BIT(4)
|
||||||
|
#define WLAN_RSNX_CAPA_SAE_H2E BIT(5)
|
||||||
|
|
||||||
#endif /* LINUX_IEEE80211_H */
|
#endif /* LINUX_IEEE80211_H */
|
||||||
|
@ -95,6 +95,7 @@ struct wiphy;
|
|||||||
* on this channel.
|
* on this channel.
|
||||||
* @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted
|
* @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted
|
||||||
* on this channel.
|
* on this channel.
|
||||||
|
* @IEEE80211_CHAN_NO_HE: HE operation is not permitted on this channel.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
enum ieee80211_channel_flags {
|
enum ieee80211_channel_flags {
|
||||||
@ -111,6 +112,7 @@ enum ieee80211_channel_flags {
|
|||||||
IEEE80211_CHAN_IR_CONCURRENT = 1<<10,
|
IEEE80211_CHAN_IR_CONCURRENT = 1<<10,
|
||||||
IEEE80211_CHAN_NO_20MHZ = 1<<11,
|
IEEE80211_CHAN_NO_20MHZ = 1<<11,
|
||||||
IEEE80211_CHAN_NO_10MHZ = 1<<12,
|
IEEE80211_CHAN_NO_10MHZ = 1<<12,
|
||||||
|
IEEE80211_CHAN_NO_HE = 1<<13,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IEEE80211_CHAN_NO_HT40 \
|
#define IEEE80211_CHAN_NO_HT40 \
|
||||||
@ -259,6 +261,32 @@ struct ieee80211_he_obss_pd {
|
|||||||
u8 max_offset;
|
u8 max_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cfg80211_he_bss_color - AP settings for BSS coloring
|
||||||
|
*
|
||||||
|
* @color: the current color.
|
||||||
|
* @disabled: is the feature disabled.
|
||||||
|
* @partial: define the AID equation.
|
||||||
|
*/
|
||||||
|
struct cfg80211_he_bss_color {
|
||||||
|
u8 color;
|
||||||
|
bool disabled;
|
||||||
|
bool partial;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_he_bss_color - AP settings for BSS coloring
|
||||||
|
*
|
||||||
|
* @color: the current color.
|
||||||
|
* @disabled: is the feature disabled.
|
||||||
|
* @partial: define the AID equation.
|
||||||
|
*/
|
||||||
|
struct ieee80211_he_bss_color {
|
||||||
|
u8 color;
|
||||||
|
bool disabled;
|
||||||
|
bool partial;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ieee80211_sta_ht_cap - STA's HT capabilities
|
* struct ieee80211_sta_ht_cap - STA's HT capabilities
|
||||||
*
|
*
|
||||||
@ -990,6 +1018,7 @@ enum cfg80211_ap_settings_flags {
|
|||||||
* @twt_responder: Enable Target Wait Time
|
* @twt_responder: Enable Target Wait Time
|
||||||
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
|
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
|
||||||
* @he_obss_pd: OBSS Packet Detection settings
|
* @he_obss_pd: OBSS Packet Detection settings
|
||||||
|
* @he_bss_color: BSS Color settings
|
||||||
*/
|
*/
|
||||||
struct cfg80211_ap_settings {
|
struct cfg80211_ap_settings {
|
||||||
struct cfg80211_chan_def chandef;
|
struct cfg80211_chan_def chandef;
|
||||||
@ -1018,6 +1047,7 @@ struct cfg80211_ap_settings {
|
|||||||
bool twt_responder;
|
bool twt_responder;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
struct ieee80211_he_obss_pd he_obss_pd;
|
struct ieee80211_he_obss_pd he_obss_pd;
|
||||||
|
struct cfg80211_he_bss_color he_bss_color;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3944,7 +3974,8 @@ struct cfg80211_ops {
|
|||||||
int (*tx_control_port)(struct wiphy *wiphy,
|
int (*tx_control_port)(struct wiphy *wiphy,
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
const u8 *buf, size_t len,
|
const u8 *buf, size_t len,
|
||||||
const u8 *dest, const __be16 proto,
|
const u8 *dest, const u8 *src,
|
||||||
|
const __be16 proto,
|
||||||
const bool noencrypt);
|
const bool noencrypt);
|
||||||
|
|
||||||
int (*get_ftm_responder_stats)(struct wiphy *wiphy,
|
int (*get_ftm_responder_stats)(struct wiphy *wiphy,
|
||||||
@ -4375,6 +4406,21 @@ struct cfg80211_pmsr_capabilities {
|
|||||||
} ftm;
|
} ftm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wiphy_iftype_akm_suites - This structure encapsulates supported akm
|
||||||
|
* suites for interface types defined in @iftypes_mask. Each type in the
|
||||||
|
* @iftypes_mask must be unique across all instances of iftype_akm_suites.
|
||||||
|
*
|
||||||
|
* @iftypes_mask: bitmask of interfaces types
|
||||||
|
* @akm_suites: points to an array of supported akm suites
|
||||||
|
* @n_akm_suites: number of supported AKM suites
|
||||||
|
*/
|
||||||
|
struct wiphy_iftype_akm_suites {
|
||||||
|
u16 iftypes_mask;
|
||||||
|
const u32 *akm_suites;
|
||||||
|
int n_akm_suites;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct wiphy - wireless hardware description
|
* struct wiphy - wireless hardware description
|
||||||
* @reg_notifier: the driver's regulatory notification callback,
|
* @reg_notifier: the driver's regulatory notification callback,
|
||||||
@ -4387,8 +4433,16 @@ struct cfg80211_pmsr_capabilities {
|
|||||||
* @signal_type: signal type reported in &struct cfg80211_bss.
|
* @signal_type: signal type reported in &struct cfg80211_bss.
|
||||||
* @cipher_suites: supported cipher suites
|
* @cipher_suites: supported cipher suites
|
||||||
* @n_cipher_suites: number of supported cipher suites
|
* @n_cipher_suites: number of supported cipher suites
|
||||||
* @akm_suites: supported AKM suites
|
* @akm_suites: supported AKM suites. These are the default AKMs supported if
|
||||||
|
* the supported AKMs not advertized for a specific interface type in
|
||||||
|
* iftype_akm_suites.
|
||||||
* @n_akm_suites: number of supported AKM suites
|
* @n_akm_suites: number of supported AKM suites
|
||||||
|
* @iftype_akm_suites: array of supported akm suites info per interface type.
|
||||||
|
* Note that the bits in @iftypes_mask inside this structure cannot
|
||||||
|
* overlap (i.e. only one occurrence of each type is allowed across all
|
||||||
|
* instances of iftype_akm_suites).
|
||||||
|
* @num_iftype_akm_suites: number of interface types for which supported akm
|
||||||
|
* suites are specified separately.
|
||||||
* @retry_short: Retry limit for short frames (dot11ShortRetryLimit)
|
* @retry_short: Retry limit for short frames (dot11ShortRetryLimit)
|
||||||
* @retry_long: Retry limit for long frames (dot11LongRetryLimit)
|
* @retry_long: Retry limit for long frames (dot11LongRetryLimit)
|
||||||
* @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
|
* @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
|
||||||
@ -4595,6 +4649,9 @@ struct wiphy {
|
|||||||
int n_akm_suites;
|
int n_akm_suites;
|
||||||
const u32 *akm_suites;
|
const u32 *akm_suites;
|
||||||
|
|
||||||
|
const struct wiphy_iftype_akm_suites *iftype_akm_suites;
|
||||||
|
unsigned int num_iftype_akm_suites;
|
||||||
|
|
||||||
u8 retry_short;
|
u8 retry_short;
|
||||||
u8 retry_long;
|
u8 retry_long;
|
||||||
u32 frag_threshold;
|
u32 frag_threshold;
|
||||||
@ -4687,6 +4744,8 @@ struct wiphy {
|
|||||||
u32 txq_memory_limit;
|
u32 txq_memory_limit;
|
||||||
u32 txq_quantum;
|
u32 txq_quantum;
|
||||||
|
|
||||||
|
unsigned long tx_queue_len;
|
||||||
|
|
||||||
u8 support_mbssid:1,
|
u8 support_mbssid:1,
|
||||||
support_only_he_mbssid:1;
|
support_only_he_mbssid:1;
|
||||||
|
|
||||||
|
@ -316,6 +316,7 @@ struct ieee80211_vif_chanctx_switch {
|
|||||||
* functionality changed for this BSS (AP mode).
|
* functionality changed for this BSS (AP mode).
|
||||||
* @BSS_CHANGED_TWT: TWT status changed
|
* @BSS_CHANGED_TWT: TWT status changed
|
||||||
* @BSS_CHANGED_HE_OBSS_PD: OBSS Packet Detection status changed.
|
* @BSS_CHANGED_HE_OBSS_PD: OBSS Packet Detection status changed.
|
||||||
|
* @BSS_CHANGED_HE_BSS_COLOR: BSS Color has changed
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
enum ieee80211_bss_change {
|
enum ieee80211_bss_change {
|
||||||
@ -348,6 +349,7 @@ enum ieee80211_bss_change {
|
|||||||
BSS_CHANGED_FTM_RESPONDER = 1<<26,
|
BSS_CHANGED_FTM_RESPONDER = 1<<26,
|
||||||
BSS_CHANGED_TWT = 1<<27,
|
BSS_CHANGED_TWT = 1<<27,
|
||||||
BSS_CHANGED_HE_OBSS_PD = 1<<28,
|
BSS_CHANGED_HE_OBSS_PD = 1<<28,
|
||||||
|
BSS_CHANGED_HE_BSS_COLOR = 1<<29,
|
||||||
|
|
||||||
/* when adding here, make sure to change ieee80211_reconfig */
|
/* when adding here, make sure to change ieee80211_reconfig */
|
||||||
};
|
};
|
||||||
@ -494,7 +496,6 @@ struct ieee80211_ftm_responder_params {
|
|||||||
* This structure keeps information about a BSS (and an association
|
* This structure keeps information about a BSS (and an association
|
||||||
* to that BSS) that can change during the lifetime of the BSS.
|
* to that BSS) that can change during the lifetime of the BSS.
|
||||||
*
|
*
|
||||||
* @bss_color: 6-bit value to mark inter-BSS frame, if BSS supports HE
|
|
||||||
* @htc_trig_based_pkt_ext: default PE in 4us units, if BSS supports HE
|
* @htc_trig_based_pkt_ext: default PE in 4us units, if BSS supports HE
|
||||||
* @multi_sta_back_32bit: supports BA bitmap of 32-bits in Multi-STA BACK
|
* @multi_sta_back_32bit: supports BA bitmap of 32-bits in Multi-STA BACK
|
||||||
* @uora_exists: is the UORA element advertised by AP
|
* @uora_exists: is the UORA element advertised by AP
|
||||||
@ -573,7 +574,7 @@ struct ieee80211_ftm_responder_params {
|
|||||||
* @ssid: The SSID of the current vif. Valid in AP and IBSS mode.
|
* @ssid: The SSID of the current vif. Valid in AP and IBSS mode.
|
||||||
* @ssid_len: Length of SSID given in @ssid.
|
* @ssid_len: Length of SSID given in @ssid.
|
||||||
* @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
|
* @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
|
||||||
* @txpower: TX power in dBm
|
* @txpower: TX power in dBm. INT_MIN means not configured.
|
||||||
* @txpower_type: TX power adjustment used to control per packet Transmit
|
* @txpower_type: TX power adjustment used to control per packet Transmit
|
||||||
* Power Control (TPC) in lower driver for the current vif. In particular
|
* Power Control (TPC) in lower driver for the current vif. In particular
|
||||||
* TPC is enabled if value passed in %txpower_type is
|
* TPC is enabled if value passed in %txpower_type is
|
||||||
@ -604,10 +605,10 @@ struct ieee80211_ftm_responder_params {
|
|||||||
* in order to discover all the nontransmitted BSSIDs in the set.
|
* in order to discover all the nontransmitted BSSIDs in the set.
|
||||||
* @he_operation: HE operation information of the AP we are connected to
|
* @he_operation: HE operation information of the AP we are connected to
|
||||||
* @he_obss_pd: OBSS Packet Detection parameters.
|
* @he_obss_pd: OBSS Packet Detection parameters.
|
||||||
|
* @he_bss_color: BSS coloring settings, if BSS supports HE
|
||||||
*/
|
*/
|
||||||
struct ieee80211_bss_conf {
|
struct ieee80211_bss_conf {
|
||||||
const u8 *bssid;
|
const u8 *bssid;
|
||||||
u8 bss_color;
|
|
||||||
u8 htc_trig_based_pkt_ext;
|
u8 htc_trig_based_pkt_ext;
|
||||||
bool multi_sta_back_32bit;
|
bool multi_sta_back_32bit;
|
||||||
bool uora_exists;
|
bool uora_exists;
|
||||||
@ -667,6 +668,7 @@ struct ieee80211_bss_conf {
|
|||||||
u8 profile_periodicity;
|
u8 profile_periodicity;
|
||||||
struct ieee80211_he_operation he_operation;
|
struct ieee80211_he_operation he_operation;
|
||||||
struct ieee80211_he_obss_pd he_obss_pd;
|
struct ieee80211_he_obss_pd he_obss_pd;
|
||||||
|
struct cfg80211_he_bss_color he_bss_color;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -826,6 +828,7 @@ enum mac80211_tx_control_flags {
|
|||||||
IEEE80211_TX_CTRL_AMSDU = BIT(3),
|
IEEE80211_TX_CTRL_AMSDU = BIT(3),
|
||||||
IEEE80211_TX_CTRL_FAST_XMIT = BIT(4),
|
IEEE80211_TX_CTRL_FAST_XMIT = BIT(4),
|
||||||
IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP = BIT(5),
|
IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP = BIT(5),
|
||||||
|
IEEE80211_TX_CTRL_HW_80211_ENCAP = BIT(6),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4659,6 +4662,26 @@ static inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw,
|
|||||||
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
|
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_tx_status_8023 - transmit status callback for 802.3 frame format
|
||||||
|
*
|
||||||
|
* Call this function for all transmitted data frames after their transmit
|
||||||
|
* completion. This callback should only be called for data frames which
|
||||||
|
* are are using driver's (or hardware's) offload capability of encap/decap
|
||||||
|
* 802.11 frames.
|
||||||
|
*
|
||||||
|
* This function may not be called in IRQ context. Calls to this function
|
||||||
|
* for a single hardware must be synchronized against each other and all
|
||||||
|
* calls in the same tx status family.
|
||||||
|
*
|
||||||
|
* @hw: the hardware the frame was transmitted by
|
||||||
|
* @vif: the interface for which the frame was transmitted
|
||||||
|
* @skb: the frame that was transmitted, owned by mac80211 after this call
|
||||||
|
*/
|
||||||
|
void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct sk_buff *skb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_report_low_ack - report non-responding station
|
* ieee80211_report_low_ack - report non-responding station
|
||||||
*
|
*
|
||||||
@ -6479,5 +6502,16 @@ u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
|
|||||||
u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
|
u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_tx_info *info,
|
struct ieee80211_tx_info *info,
|
||||||
int len);
|
int len);
|
||||||
|
/**
|
||||||
|
* ieee80211_set_hw_80211_encap - enable hardware encapsulation offloading.
|
||||||
|
*
|
||||||
|
* This function is used to notify mac80211 that a vif can be passed raw 802.3
|
||||||
|
* frames. The driver needs to then handle the 802.11 encapsulation inside the
|
||||||
|
* hardware or firmware.
|
||||||
|
*
|
||||||
|
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||||
|
* @enable: indicate if the feature should be turned on or off
|
||||||
|
*/
|
||||||
|
bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable);
|
||||||
|
|
||||||
#endif /* MAC80211_H */
|
#endif /* MAC80211_H */
|
||||||
|
@ -1039,11 +1039,14 @@
|
|||||||
* a control port frame and as a notification that a control port frame
|
* a control port frame and as a notification that a control port frame
|
||||||
* has been received. %NL80211_ATTR_FRAME is used to specify the
|
* has been received. %NL80211_ATTR_FRAME is used to specify the
|
||||||
* frame contents. The frame is the raw EAPoL data, without ethernet or
|
* frame contents. The frame is the raw EAPoL data, without ethernet or
|
||||||
* 802.11 headers.
|
* 802.11 headers. An optional %NL80211_ATTR_SRC_MAC can be used to send
|
||||||
|
* pre-auth frames to STAs on behalf of other APs.
|
||||||
* When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
|
* When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
|
||||||
* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added
|
* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added
|
||||||
* indicating the protocol type of the received frame; whether the frame
|
* indicating the protocol type of the received frame; whether the frame
|
||||||
* was received unencrypted and the MAC address of the peer respectively.
|
* was received unencrypted and the MAC address of the peer respectively.
|
||||||
|
* %NL80211_ATTR_DST_MAC can be used to forward pre-auth frames in
|
||||||
|
* userspace while using AP mode.
|
||||||
*
|
*
|
||||||
* @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
|
* @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
|
||||||
*
|
*
|
||||||
@ -2400,6 +2403,18 @@ enum nl80211_commands {
|
|||||||
* @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key
|
* @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key
|
||||||
* (u16).
|
* (u16).
|
||||||
*
|
*
|
||||||
|
* @NL80211_ATTR_HE_BSS_COLOR: nested attribute for BSS Color Settings.
|
||||||
|
*
|
||||||
|
* @NL80211_ATTR_IFTYPE_AKM_SUITES: nested array attribute, with each entry
|
||||||
|
* using attributes from &enum nl80211_iftype_akm_attributes. This
|
||||||
|
* attribute is sent in a response to %NL80211_CMD_GET_WIPHY indicating
|
||||||
|
* supported AKM suites capability per interface. AKMs advertised in
|
||||||
|
* %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not
|
||||||
|
* advertised for a specific interface type.
|
||||||
|
*
|
||||||
|
* @NL80211_ATTR_SRC_MAC: MAC address used in control port over nl80211 transmit
|
||||||
|
* @NL80211_ATTR_DST_MAC: MAC address used in control port over nl80211 receive
|
||||||
|
*
|
||||||
* @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
|
||||||
@ -2864,6 +2879,13 @@ enum nl80211_attrs {
|
|||||||
|
|
||||||
NL80211_ATTR_VLAN_ID,
|
NL80211_ATTR_VLAN_ID,
|
||||||
|
|
||||||
|
NL80211_ATTR_HE_BSS_COLOR,
|
||||||
|
|
||||||
|
NL80211_ATTR_IFTYPE_AKM_SUITES,
|
||||||
|
|
||||||
|
NL80211_ATTR_SRC_MAC,
|
||||||
|
NL80211_ATTR_DST_MAC,
|
||||||
|
|
||||||
/* 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,
|
||||||
@ -3583,6 +3605,8 @@ enum nl80211_wmm_rule {
|
|||||||
* @NL80211_FREQUENCY_ATTR_WMM: this channel has wmm limitations.
|
* @NL80211_FREQUENCY_ATTR_WMM: this channel has wmm limitations.
|
||||||
* This is a nested attribute that contains the wmm limitation per AC.
|
* This is a nested attribute that contains the wmm limitation per AC.
|
||||||
* (see &enum nl80211_wmm_rule)
|
* (see &enum nl80211_wmm_rule)
|
||||||
|
* @NL80211_FREQUENCY_ATTR_NO_HE: HE operation is not allowed on this channel
|
||||||
|
* in current regulatory domain.
|
||||||
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
|
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
|
||||||
* currently defined
|
* currently defined
|
||||||
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
|
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
|
||||||
@ -3612,6 +3636,7 @@ enum nl80211_frequency_attr {
|
|||||||
NL80211_FREQUENCY_ATTR_NO_20MHZ,
|
NL80211_FREQUENCY_ATTR_NO_20MHZ,
|
||||||
NL80211_FREQUENCY_ATTR_NO_10MHZ,
|
NL80211_FREQUENCY_ATTR_NO_10MHZ,
|
||||||
NL80211_FREQUENCY_ATTR_WMM,
|
NL80211_FREQUENCY_ATTR_WMM,
|
||||||
|
NL80211_FREQUENCY_ATTR_NO_HE,
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
|
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
|
||||||
@ -3809,6 +3834,7 @@ enum nl80211_sched_scan_match_attr {
|
|||||||
* @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation
|
* @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation
|
||||||
* @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed
|
* @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed
|
||||||
* @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed
|
* @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed
|
||||||
|
* @NL80211_RRF_NO_HE: HE operation not allowed
|
||||||
*/
|
*/
|
||||||
enum nl80211_reg_rule_flags {
|
enum nl80211_reg_rule_flags {
|
||||||
NL80211_RRF_NO_OFDM = 1<<0,
|
NL80211_RRF_NO_OFDM = 1<<0,
|
||||||
@ -3826,6 +3852,7 @@ enum nl80211_reg_rule_flags {
|
|||||||
NL80211_RRF_NO_HT40PLUS = 1<<14,
|
NL80211_RRF_NO_HT40PLUS = 1<<14,
|
||||||
NL80211_RRF_NO_80MHZ = 1<<15,
|
NL80211_RRF_NO_80MHZ = 1<<15,
|
||||||
NL80211_RRF_NO_160MHZ = 1<<16,
|
NL80211_RRF_NO_160MHZ = 1<<16,
|
||||||
|
NL80211_RRF_NO_HE = 1<<17,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
|
#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
|
||||||
@ -5521,6 +5548,10 @@ enum nl80211_feature_flags {
|
|||||||
* feature, which prevents bufferbloat by using the expected transmission
|
* feature, which prevents bufferbloat by using the expected transmission
|
||||||
* time to limit the amount of data buffered in the hardware.
|
* time to limit the amount of data buffered in the hardware.
|
||||||
*
|
*
|
||||||
|
* @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS: The driver
|
||||||
|
* can use src and dst MAC addresses with control port over nl80211 rx
|
||||||
|
* and tx operations.
|
||||||
|
*
|
||||||
* @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.
|
||||||
*/
|
*/
|
||||||
@ -5568,6 +5599,7 @@ enum nl80211_ext_feature_index {
|
|||||||
NL80211_EXT_FEATURE_SAE_OFFLOAD,
|
NL80211_EXT_FEATURE_SAE_OFFLOAD,
|
||||||
NL80211_EXT_FEATURE_VLAN_OFFLOAD,
|
NL80211_EXT_FEATURE_VLAN_OFFLOAD,
|
||||||
NL80211_EXT_FEATURE_AQL,
|
NL80211_EXT_FEATURE_AQL,
|
||||||
|
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS,
|
||||||
|
|
||||||
/* add new features before the definition below */
|
/* add new features before the definition below */
|
||||||
NUM_NL80211_EXT_FEATURES,
|
NUM_NL80211_EXT_FEATURES,
|
||||||
@ -6587,5 +6619,51 @@ enum nl80211_obss_pd_attributes {
|
|||||||
NL80211_HE_OBSS_PD_ATTR_MAX = __NL80211_HE_OBSS_PD_ATTR_LAST - 1,
|
NL80211_HE_OBSS_PD_ATTR_MAX = __NL80211_HE_OBSS_PD_ATTR_LAST - 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum nl80211_bss_color_attributes - BSS Color attributes
|
||||||
|
* @__NL80211_HE_BSS_COLOR_ATTR_INVALID: Invalid
|
||||||
|
*
|
||||||
|
* @NL80211_HE_BSS_COLOR_ATTR_COLOR: the current BSS Color.
|
||||||
|
* @NL80211_HE_BSS_COLOR_ATTR_DISABLED: is BSS coloring disabled.
|
||||||
|
* @NL80211_HE_BSS_COLOR_ATTR_PARTIAL: the AID equation to be used..
|
||||||
|
*
|
||||||
|
* @__NL80211_HE_BSS_COLOR_ATTR_LAST: Internal
|
||||||
|
* @NL80211_HE_BSS_COLOR_ATTR_MAX: highest BSS Color attribute.
|
||||||
|
*/
|
||||||
|
enum nl80211_bss_color_attributes {
|
||||||
|
__NL80211_HE_BSS_COLOR_ATTR_INVALID,
|
||||||
|
|
||||||
|
NL80211_HE_BSS_COLOR_ATTR_COLOR,
|
||||||
|
NL80211_HE_BSS_COLOR_ATTR_DISABLED,
|
||||||
|
NL80211_HE_BSS_COLOR_ATTR_PARTIAL,
|
||||||
|
|
||||||
|
/* keep last */
|
||||||
|
__NL80211_HE_BSS_COLOR_ATTR_LAST,
|
||||||
|
NL80211_HE_BSS_COLOR_ATTR_MAX = __NL80211_HE_BSS_COLOR_ATTR_LAST - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum nl80211_iftype_akm_attributes - interface type AKM attributes
|
||||||
|
* @__NL80211_IFTYPE_AKM_ATTR_INVALID: Invalid
|
||||||
|
*
|
||||||
|
* @NL80211_IFTYPE_AKM_ATTR_IFTYPES: nested attribute containing a flag
|
||||||
|
* attribute for each interface type that supports AKM suites specified in
|
||||||
|
* %NL80211_IFTYPE_AKM_ATTR_SUITES
|
||||||
|
* @NL80211_IFTYPE_AKM_ATTR_SUITES: an array of u32. Used to indicate supported
|
||||||
|
* AKM suites for the specified interface types.
|
||||||
|
*
|
||||||
|
* @__NL80211_IFTYPE_AKM_ATTR_LAST: Internal
|
||||||
|
* @NL80211_IFTYPE_AKM_ATTR_MAX: highest interface type AKM attribute.
|
||||||
|
*/
|
||||||
|
enum nl80211_iftype_akm_attributes {
|
||||||
|
__NL80211_IFTYPE_AKM_ATTR_INVALID,
|
||||||
|
|
||||||
|
NL80211_IFTYPE_AKM_ATTR_IFTYPES,
|
||||||
|
NL80211_IFTYPE_AKM_ATTR_SUITES,
|
||||||
|
|
||||||
|
/* keep last */
|
||||||
|
__NL80211_IFTYPE_AKM_ATTR_LAST,
|
||||||
|
NL80211_IFTYPE_AKM_ATTR_MAX = __NL80211_IFTYPE_AKM_ATTR_LAST - 1,
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* __LINUX_NL80211_H */
|
#endif /* __LINUX_NL80211_H */
|
||||||
|
@ -74,6 +74,8 @@
|
|||||||
#include <linux/socket.h> /* for "struct sockaddr" et al */
|
#include <linux/socket.h> /* for "struct sockaddr" et al */
|
||||||
#include <linux/if.h> /* for IFNAMSIZ and co... */
|
#include <linux/if.h> /* for IFNAMSIZ and co... */
|
||||||
|
|
||||||
|
#include <stddef.h> /* for offsetof */
|
||||||
|
|
||||||
/***************************** VERSION *****************************/
|
/***************************** VERSION *****************************/
|
||||||
/*
|
/*
|
||||||
* This constant is used to know the availability of the wireless
|
* This constant is used to know the availability of the wireless
|
||||||
@ -1090,8 +1092,7 @@ struct iw_event {
|
|||||||
/* iw_point events are special. First, the payload (extra data) come at
|
/* iw_point events are special. First, the payload (extra data) come at
|
||||||
* the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
|
* the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
|
||||||
* we omit the pointer, so start at an offset. */
|
* we omit the pointer, so start at an offset. */
|
||||||
#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
|
#define IW_EV_POINT_OFF offsetof(struct iw_point, length)
|
||||||
(char *) NULL)
|
|
||||||
#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
|
#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
|
||||||
IW_EV_POINT_OFF)
|
IW_EV_POINT_OFF)
|
||||||
|
|
||||||
|
@ -981,7 +981,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
BSS_CHANGED_P2P_PS |
|
BSS_CHANGED_P2P_PS |
|
||||||
BSS_CHANGED_TXPOWER |
|
BSS_CHANGED_TXPOWER |
|
||||||
BSS_CHANGED_TWT |
|
BSS_CHANGED_TWT |
|
||||||
BSS_CHANGED_HE_OBSS_PD;
|
BSS_CHANGED_HE_OBSS_PD |
|
||||||
|
BSS_CHANGED_HE_BSS_COLOR;
|
||||||
int err;
|
int err;
|
||||||
int prev_beacon_int;
|
int prev_beacon_int;
|
||||||
|
|
||||||
@ -989,20 +990,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
if (old)
|
if (old)
|
||||||
return -EALREADY;
|
return -EALREADY;
|
||||||
|
|
||||||
switch (params->smps_mode) {
|
if (params->smps_mode != NL80211_SMPS_OFF)
|
||||||
case NL80211_SMPS_OFF:
|
return -ENOTSUPP;
|
||||||
|
|
||||||
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
||||||
break;
|
|
||||||
case NL80211_SMPS_STATIC:
|
|
||||||
sdata->smps_mode = IEEE80211_SMPS_STATIC;
|
|
||||||
break;
|
|
||||||
case NL80211_SMPS_DYNAMIC:
|
|
||||||
sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
sdata->u.ap.req_smps = sdata->smps_mode;
|
|
||||||
|
|
||||||
sdata->needed_rx_chains = sdata->local->rx_chains;
|
sdata->needed_rx_chains = sdata->local->rx_chains;
|
||||||
|
|
||||||
@ -1054,6 +1045,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
sdata->vif.bss_conf.twt_responder = params->twt_responder;
|
sdata->vif.bss_conf.twt_responder = params->twt_responder;
|
||||||
memcpy(&sdata->vif.bss_conf.he_obss_pd, ¶ms->he_obss_pd,
|
memcpy(&sdata->vif.bss_conf.he_obss_pd, ¶ms->he_obss_pd,
|
||||||
sizeof(struct ieee80211_he_obss_pd));
|
sizeof(struct ieee80211_he_obss_pd));
|
||||||
|
memcpy(&sdata->vif.bss_conf.he_bss_color, ¶ms->he_bss_color,
|
||||||
|
sizeof(struct ieee80211_he_bss_color));
|
||||||
|
|
||||||
sdata->vif.bss_conf.ssid_len = params->ssid_len;
|
sdata->vif.bss_conf.ssid_len = params->ssid_len;
|
||||||
if (params->ssid_len)
|
if (params->ssid_len)
|
||||||
@ -1166,7 +1159,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||||||
kfree_rcu(old_beacon, rcu_head);
|
kfree_rcu(old_beacon, rcu_head);
|
||||||
if (old_probe_resp)
|
if (old_probe_resp)
|
||||||
kfree_rcu(old_probe_resp, rcu_head);
|
kfree_rcu(old_probe_resp, rcu_head);
|
||||||
sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
|
|
||||||
|
|
||||||
kfree(sdata->vif.bss_conf.ftmr_params);
|
kfree(sdata->vif.bss_conf.ftmr_params);
|
||||||
sdata->vif.bss_conf.ftmr_params = NULL;
|
sdata->vif.bss_conf.ftmr_params = NULL;
|
||||||
@ -1691,20 +1683,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
|
|||||||
|
|
||||||
mutex_unlock(&local->sta_mtx);
|
mutex_unlock(&local->sta_mtx);
|
||||||
|
|
||||||
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
|
|
||||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
|
|
||||||
sta->known_smps_mode != sta->sdata->bss->req_smps &&
|
|
||||||
test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
|
|
||||||
sta_info_tx_streams(sta) != 1) {
|
|
||||||
ht_dbg(sta->sdata,
|
|
||||||
"%pM just authorized and MIMO capable - update SMPS\n",
|
|
||||||
sta->sta.addr);
|
|
||||||
ieee80211_send_smps_action(sta->sdata,
|
|
||||||
sta->sdata->bss->req_smps,
|
|
||||||
sta->sta.addr,
|
|
||||||
sta->sdata->vif.bss_conf.bssid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||||
params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
|
params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
|
||||||
ieee80211_recalc_ps(local);
|
ieee80211_recalc_ps(local);
|
||||||
@ -2636,74 +2614,6 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
|
|
||||||
enum ieee80211_smps_mode smps_mode)
|
|
||||||
{
|
|
||||||
struct sta_info *sta;
|
|
||||||
enum ieee80211_smps_mode old_req;
|
|
||||||
|
|
||||||
if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
old_req = sdata->u.ap.req_smps;
|
|
||||||
sdata->u.ap.req_smps = smps_mode;
|
|
||||||
|
|
||||||
/* AUTOMATIC doesn't mean much for AP - don't allow it */
|
|
||||||
if (old_req == smps_mode ||
|
|
||||||
smps_mode == IEEE80211_SMPS_AUTOMATIC)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ht_dbg(sdata,
|
|
||||||
"SMPS %d requested in AP mode, sending Action frame to %d stations\n",
|
|
||||||
smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));
|
|
||||||
|
|
||||||
mutex_lock(&sdata->local->sta_mtx);
|
|
||||||
list_for_each_entry(sta, &sdata->local->sta_list, list) {
|
|
||||||
/*
|
|
||||||
* Only stations associated to our AP and
|
|
||||||
* associated VLANs
|
|
||||||
*/
|
|
||||||
if (sta->sdata->bss != &sdata->u.ap)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* This station doesn't support MIMO - skip it */
|
|
||||||
if (sta_info_tx_streams(sta) == 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't wake up a STA just to send the action frame
|
|
||||||
* unless we are getting more restrictive.
|
|
||||||
*/
|
|
||||||
if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
|
|
||||||
!ieee80211_smps_is_restrictive(sta->known_smps_mode,
|
|
||||||
smps_mode)) {
|
|
||||||
ht_dbg(sdata, "Won't send SMPS to sleeping STA %pM\n",
|
|
||||||
sta->sta.addr);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the STA is not authorized, wait until it gets
|
|
||||||
* authorized and the action frame will be sent then.
|
|
||||||
*/
|
|
||||||
if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ht_dbg(sdata, "Sending SMPS to %pM\n", sta->sta.addr);
|
|
||||||
ieee80211_send_smps_action(sdata, smps_mode, sta->sta.addr,
|
|
||||||
sdata->vif.bss_conf.bssid);
|
|
||||||
}
|
|
||||||
mutex_unlock(&sdata->local->sta_mtx);
|
|
||||||
|
|
||||||
sdata->smps_mode = smps_mode;
|
|
||||||
ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
|
int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
|
||||||
enum ieee80211_smps_mode smps_mode)
|
enum ieee80211_smps_mode smps_mode)
|
||||||
{
|
{
|
||||||
|
@ -150,6 +150,59 @@ static const struct file_operations aqm_ops = {
|
|||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ssize_t airtime_flags_read(struct file *file,
|
||||||
|
char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = file->private_data;
|
||||||
|
char buf[128] = {}, *pos, *end;
|
||||||
|
|
||||||
|
pos = buf;
|
||||||
|
end = pos + sizeof(buf) - 1;
|
||||||
|
|
||||||
|
if (local->airtime_flags & AIRTIME_USE_TX)
|
||||||
|
pos += scnprintf(pos, end - pos, "AIRTIME_TX\t(%lx)\n",
|
||||||
|
AIRTIME_USE_TX);
|
||||||
|
if (local->airtime_flags & AIRTIME_USE_RX)
|
||||||
|
pos += scnprintf(pos, end - pos, "AIRTIME_RX\t(%lx)\n",
|
||||||
|
AIRTIME_USE_RX);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf,
|
||||||
|
strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t airtime_flags_write(struct file *file,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = file->private_data;
|
||||||
|
char buf[16];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (count > sizeof(buf))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (copy_from_user(buf, user_buf, count))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
buf[sizeof(buf) - 1] = 0;
|
||||||
|
len = strlen(buf);
|
||||||
|
if (len > 0 && buf[len - 1] == '\n')
|
||||||
|
buf[len - 1] = 0;
|
||||||
|
|
||||||
|
if (kstrtou16(buf, 0, &local->airtime_flags))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations airtime_flags_ops = {
|
||||||
|
.write = airtime_flags_write,
|
||||||
|
.read = airtime_flags_read,
|
||||||
|
.open = simple_open,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
static ssize_t aql_txq_limit_read(struct file *file,
|
static ssize_t aql_txq_limit_read(struct file *file,
|
||||||
char __user *user_buf,
|
char __user *user_buf,
|
||||||
size_t count,
|
size_t count,
|
||||||
@ -522,8 +575,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
|
|||||||
if (local->ops->wake_tx_queue)
|
if (local->ops->wake_tx_queue)
|
||||||
DEBUGFS_ADD_MODE(aqm, 0600);
|
DEBUGFS_ADD_MODE(aqm, 0600);
|
||||||
|
|
||||||
debugfs_create_u16("airtime_flags", 0600,
|
DEBUGFS_ADD_MODE(airtime_flags, 0600);
|
||||||
phyd, &local->airtime_flags);
|
|
||||||
|
|
||||||
DEBUGFS_ADD(aql_txq_limit);
|
DEBUGFS_ADD(aql_txq_limit);
|
||||||
debugfs_create_u32("aql_threshold", 0600,
|
debugfs_create_u32("aql_threshold", 0600,
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
|
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
|
||||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||||
|
* Copyright (C) 2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -254,15 +255,11 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
|||||||
smps_mode == IEEE80211_SMPS_AUTOMATIC))
|
smps_mode == IEEE80211_SMPS_AUTOMATIC))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
|
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||||
sdata->vif.type != NL80211_IFTYPE_AP)
|
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
sdata_lock(sdata);
|
sdata_lock(sdata);
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
|
||||||
err = __ieee80211_request_smps_mgd(sdata, smps_mode);
|
err = __ieee80211_request_smps_mgd(sdata, smps_mode);
|
||||||
else
|
|
||||||
err = __ieee80211_request_smps_ap(sdata, smps_mode);
|
|
||||||
sdata_unlock(sdata);
|
sdata_unlock(sdata);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@ -282,10 +279,6 @@ static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
|
|||||||
return snprintf(buf, buflen, "request: %s\nused: %s\n",
|
return snprintf(buf, buflen, "request: %s\nused: %s\n",
|
||||||
smps_modes[sdata->u.mgd.req_smps],
|
smps_modes[sdata->u.mgd.req_smps],
|
||||||
smps_modes[sdata->smps_mode]);
|
smps_modes[sdata->smps_mode]);
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_AP)
|
|
||||||
return snprintf(buf, buflen, "request: %s\nused: %s\n",
|
|
||||||
smps_modes[sdata->u.ap.req_smps],
|
|
||||||
smps_modes[sdata->smps_mode]);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,12 +1025,10 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
|
|||||||
DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments);
|
DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments);
|
||||||
DEBUGFS_ADD_COUNTER(tx_filtered, status_stats.filtered);
|
DEBUGFS_ADD_COUNTER(tx_filtered, status_stats.filtered);
|
||||||
|
|
||||||
if (local->ops->wake_tx_queue)
|
if (local->ops->wake_tx_queue) {
|
||||||
DEBUGFS_ADD(aqm);
|
DEBUGFS_ADD(aqm);
|
||||||
|
|
||||||
if (wiphy_ext_feature_isset(local->hw.wiphy,
|
|
||||||
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
|
|
||||||
DEBUGFS_ADD(airtime);
|
DEBUGFS_ADD(airtime);
|
||||||
|
}
|
||||||
|
|
||||||
if (wiphy_ext_feature_isset(local->hw.wiphy,
|
if (wiphy_ext_feature_isset(local->hw.wiphy,
|
||||||
NL80211_EXT_FEATURE_AQL))
|
NL80211_EXT_FEATURE_AQL))
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
* HE handling
|
* HE handling
|
||||||
*
|
*
|
||||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright(c) 2019 - 2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ieee80211_i.h"
|
#include "ieee80211_i.h"
|
||||||
@ -49,6 +50,9 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
|
|||||||
he_ppe_size);
|
he_ppe_size);
|
||||||
|
|
||||||
he_cap->has_he = true;
|
he_cap->has_he = true;
|
||||||
|
|
||||||
|
sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta);
|
||||||
|
sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||||
* Copyright 2007-2010, Intel Corporation
|
* Copyright 2007-2010, Intel Corporation
|
||||||
* Copyright 2017 Intel Deutschland GmbH
|
* Copyright 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright(c) 2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
@ -144,7 +145,6 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
|
|||||||
int i, max_tx_streams;
|
int i, max_tx_streams;
|
||||||
bool changed;
|
bool changed;
|
||||||
enum ieee80211_sta_rx_bandwidth bw;
|
enum ieee80211_sta_rx_bandwidth bw;
|
||||||
enum ieee80211_smps_mode smps_mode;
|
|
||||||
|
|
||||||
memset(&ht_cap, 0, sizeof(ht_cap));
|
memset(&ht_cap, 0, sizeof(ht_cap));
|
||||||
|
|
||||||
@ -270,6 +270,10 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
|
|||||||
ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
|
ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
|
||||||
IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
|
IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
|
||||||
|
|
||||||
|
if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||||
|
sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
|
||||||
|
enum ieee80211_smps_mode smps_mode;
|
||||||
|
|
||||||
switch ((ht_cap.cap & IEEE80211_HT_CAP_SM_PS)
|
switch ((ht_cap.cap & IEEE80211_HT_CAP_SM_PS)
|
||||||
>> IEEE80211_HT_CAP_SM_PS_SHIFT) {
|
>> IEEE80211_HT_CAP_SM_PS_SHIFT) {
|
||||||
case WLAN_HT_CAP_SM_PS_INVALID:
|
case WLAN_HT_CAP_SM_PS_INVALID:
|
||||||
@ -287,7 +291,9 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
|
|||||||
if (smps_mode != sta->sta.smps_mode)
|
if (smps_mode != sta->sta.smps_mode)
|
||||||
changed = true;
|
changed = true;
|
||||||
sta->sta.smps_mode = smps_mode;
|
sta->sta.smps_mode = smps_mode;
|
||||||
|
} else {
|
||||||
|
sta->sta.smps_mode = IEEE80211_SMPS_OFF;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,19 +550,6 @@ void ieee80211_request_smps_mgd_work(struct work_struct *work)
|
|||||||
sdata_unlock(sdata);
|
sdata_unlock(sdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ieee80211_request_smps_ap_work(struct work_struct *work)
|
|
||||||
{
|
|
||||||
struct ieee80211_sub_if_data *sdata =
|
|
||||||
container_of(work, struct ieee80211_sub_if_data,
|
|
||||||
u.ap.request_smps_work);
|
|
||||||
|
|
||||||
sdata_lock(sdata);
|
|
||||||
if (sdata_dereference(sdata->u.ap.beacon, sdata))
|
|
||||||
__ieee80211_request_smps_ap(sdata,
|
|
||||||
sdata->u.ap.driver_smps_mode);
|
|
||||||
sdata_unlock(sdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ieee80211_request_smps(struct ieee80211_vif *vif,
|
void ieee80211_request_smps(struct ieee80211_vif *vif,
|
||||||
enum ieee80211_smps_mode smps_mode)
|
enum ieee80211_smps_mode smps_mode)
|
||||||
{
|
{
|
||||||
@ -572,15 +565,6 @@ void ieee80211_request_smps(struct ieee80211_vif *vif,
|
|||||||
sdata->u.mgd.driver_smps_mode = smps_mode;
|
sdata->u.mgd.driver_smps_mode = smps_mode;
|
||||||
ieee80211_queue_work(&sdata->local->hw,
|
ieee80211_queue_work(&sdata->local->hw,
|
||||||
&sdata->u.mgd.request_smps_work);
|
&sdata->u.mgd.request_smps_work);
|
||||||
} else {
|
|
||||||
/* AUTOMATIC is meaningless in AP mode */
|
|
||||||
if (WARN_ON_ONCE(smps_mode == IEEE80211_SMPS_AUTOMATIC))
|
|
||||||
return;
|
|
||||||
if (sdata->u.ap.driver_smps_mode == smps_mode)
|
|
||||||
return;
|
|
||||||
sdata->u.ap.driver_smps_mode = smps_mode;
|
|
||||||
ieee80211_queue_work(&sdata->local->hw,
|
|
||||||
&sdata->u.ap.request_smps_work);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* this might change ... don't want non-open drivers using it */
|
/* this might change ... don't want non-open drivers using it */
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||||
* Copyright 2013-2015 Intel Mobile Communications GmbH
|
* Copyright 2013-2015 Intel Mobile Communications GmbH
|
||||||
* Copyright (C) 2018-2019 Intel Corporation
|
* Copyright (C) 2018-2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef IEEE80211_I_H
|
#ifndef IEEE80211_I_H
|
||||||
@ -292,10 +292,7 @@ struct ieee80211_if_ap {
|
|||||||
|
|
||||||
struct ps_data ps;
|
struct ps_data ps;
|
||||||
atomic_t num_mcast_sta; /* number of stations receiving multicast */
|
atomic_t num_mcast_sta; /* number of stations receiving multicast */
|
||||||
enum ieee80211_smps_mode req_smps, /* requested smps mode */
|
|
||||||
driver_smps_mode; /* smps mode request */
|
|
||||||
|
|
||||||
struct work_struct request_smps_work;
|
|
||||||
bool multicast_to_unicast;
|
bool multicast_to_unicast;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -984,6 +981,8 @@ struct ieee80211_sub_if_data {
|
|||||||
} debugfs;
|
} debugfs;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool hw_80211_encap;
|
||||||
|
|
||||||
/* must be last, dynamically sized area in this! */
|
/* must be last, dynamically sized area in this! */
|
||||||
struct ieee80211_vif vif;
|
struct ieee80211_vif vif;
|
||||||
};
|
};
|
||||||
@ -1473,6 +1472,7 @@ struct ieee802_11_elems {
|
|||||||
const struct ieee80211_tim_ie *tim;
|
const struct ieee80211_tim_ie *tim;
|
||||||
const u8 *challenge;
|
const u8 *challenge;
|
||||||
const u8 *rsn;
|
const u8 *rsn;
|
||||||
|
const u8 *rsnx;
|
||||||
const u8 *erp_info;
|
const u8 *erp_info;
|
||||||
const u8 *ext_supp_rates;
|
const u8 *ext_supp_rates;
|
||||||
const u8 *wmm_info;
|
const u8 *wmm_info;
|
||||||
@ -1520,6 +1520,7 @@ struct ieee802_11_elems {
|
|||||||
u8 tim_len;
|
u8 tim_len;
|
||||||
u8 challenge_len;
|
u8 challenge_len;
|
||||||
u8 rsn_len;
|
u8 rsn_len;
|
||||||
|
u8 rsnx_len;
|
||||||
u8 ext_supp_rates_len;
|
u8 ext_supp_rates_len;
|
||||||
u8 wmm_info_len;
|
u8 wmm_info_len;
|
||||||
u8 wmm_param_len;
|
u8 wmm_param_len;
|
||||||
@ -1727,6 +1728,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
struct cfg80211_csa_settings *params);
|
struct cfg80211_csa_settings *params);
|
||||||
|
|
||||||
/* interface handling */
|
/* interface handling */
|
||||||
|
#define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
|
||||||
|
NETIF_F_HW_CSUM | NETIF_F_SG | \
|
||||||
|
NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE)
|
||||||
|
#define MAC80211_SUPPORTED_FEATURES_RX (NETIF_F_RXCSUM)
|
||||||
|
#define MAC80211_SUPPORTED_FEATURES (MAC80211_SUPPORTED_FEATURES_TX | \
|
||||||
|
MAC80211_SUPPORTED_FEATURES_RX)
|
||||||
|
|
||||||
int ieee80211_iface_init(void);
|
int ieee80211_iface_init(void);
|
||||||
void ieee80211_iface_exit(void);
|
void ieee80211_iface_exit(void);
|
||||||
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
||||||
@ -1762,6 +1770,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
|||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
|
netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
|
||||||
|
struct net_device *dev);
|
||||||
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
u32 info_flags,
|
u32 info_flags,
|
||||||
@ -1782,7 +1792,8 @@ void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata);
|
|||||||
void ieee80211_clear_fast_xmit(struct sta_info *sta);
|
void ieee80211_clear_fast_xmit(struct sta_info *sta);
|
||||||
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||||
const u8 *buf, size_t len,
|
const u8 *buf, size_t len,
|
||||||
const u8 *dest, __be16 proto, bool unencrypted);
|
const u8 *dest, const u8 *src, __be16 proto,
|
||||||
|
bool unencrypted);
|
||||||
int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
|
int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
|
||||||
const u8 *buf, size_t len);
|
const u8 *buf, size_t len);
|
||||||
|
|
||||||
@ -1948,6 +1959,11 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
|||||||
struct sk_buff *skb, int tid,
|
struct sk_buff *skb, int tid,
|
||||||
enum nl80211_band band, u32 txdata_flags);
|
enum nl80211_band band, u32 txdata_flags);
|
||||||
|
|
||||||
|
/* sta_out needs to be checked for ERR_PTR() before using */
|
||||||
|
int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
struct sta_info **sta_out);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb, int tid,
|
struct sk_buff *skb, int tid,
|
||||||
@ -2132,8 +2148,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
|
|||||||
enum nl80211_band band, u32 *basic_rates);
|
enum nl80211_band band, u32 *basic_rates);
|
||||||
int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
|
int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
|
||||||
enum ieee80211_smps_mode smps_mode);
|
enum ieee80211_smps_mode smps_mode);
|
||||||
int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
|
|
||||||
enum ieee80211_smps_mode smps_mode);
|
|
||||||
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
|
||||||
void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
|
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
|
||||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
* Copyright (c) 2016 Intel Deutschland GmbH
|
* Copyright (c) 2016 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018-2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -824,9 +824,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
|||||||
case NL80211_IFTYPE_ADHOC:
|
case NL80211_IFTYPE_ADHOC:
|
||||||
ieee80211_ibss_stop(sdata);
|
ieee80211_ibss_stop(sdata);
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_AP:
|
|
||||||
cancel_work_sync(&sdata->u.ap.request_smps_work);
|
|
||||||
break;
|
|
||||||
case NL80211_IFTYPE_MONITOR:
|
case NL80211_IFTYPE_MONITOR:
|
||||||
if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)
|
if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)
|
||||||
break;
|
break;
|
||||||
@ -1205,6 +1202,72 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
|
|||||||
.ndo_get_stats64 = ieee80211_get_stats64,
|
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||||
|
.ndo_open = ieee80211_open,
|
||||||
|
.ndo_stop = ieee80211_stop,
|
||||||
|
.ndo_uninit = ieee80211_uninit,
|
||||||
|
.ndo_start_xmit = ieee80211_subif_start_xmit_8023,
|
||||||
|
.ndo_set_rx_mode = ieee80211_set_multicast_list,
|
||||||
|
.ndo_set_mac_address = ieee80211_change_mac,
|
||||||
|
.ndo_select_queue = ieee80211_netdev_select_queue,
|
||||||
|
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __ieee80211_set_hw_80211_encap(struct ieee80211_sub_if_data *sdata,
|
||||||
|
bool enable)
|
||||||
|
{
|
||||||
|
sdata->dev->netdev_ops = enable ? &ieee80211_dataif_8023_ops :
|
||||||
|
&ieee80211_dataif_ops;
|
||||||
|
sdata->hw_80211_encap = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
struct ieee80211_sub_if_data *iter;
|
||||||
|
struct ieee80211_key *key;
|
||||||
|
|
||||||
|
mutex_lock(&local->iflist_mtx);
|
||||||
|
list_for_each_entry(iter, &local->interfaces, list) {
|
||||||
|
struct ieee80211_sub_if_data *disable = NULL;
|
||||||
|
|
||||||
|
if (vif->type == NL80211_IFTYPE_MONITOR) {
|
||||||
|
disable = iter;
|
||||||
|
__ieee80211_set_hw_80211_encap(iter, false);
|
||||||
|
} else if (iter->vif.type == NL80211_IFTYPE_MONITOR) {
|
||||||
|
disable = sdata;
|
||||||
|
enable = false;
|
||||||
|
}
|
||||||
|
if (disable)
|
||||||
|
sdata_dbg(disable,
|
||||||
|
"disable hw 80211 encap due to mon co-exist\n");
|
||||||
|
}
|
||||||
|
mutex_unlock(&local->iflist_mtx);
|
||||||
|
|
||||||
|
if (enable == sdata->hw_80211_encap)
|
||||||
|
return enable;
|
||||||
|
|
||||||
|
if (!sdata->dev)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
|
||||||
|
(local->hw.wiphy->frag_threshold != (u32)-1))
|
||||||
|
enable = false;
|
||||||
|
|
||||||
|
mutex_lock(&sdata->local->key_mtx);
|
||||||
|
list_for_each_entry(key, &sdata->key_list, list) {
|
||||||
|
if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
|
||||||
|
enable = false;
|
||||||
|
}
|
||||||
|
mutex_unlock(&sdata->local->key_mtx);
|
||||||
|
|
||||||
|
__ieee80211_set_hw_80211_encap(sdata, enable);
|
||||||
|
|
||||||
|
return enable;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ieee80211_set_hw_80211_encap);
|
||||||
|
|
||||||
static void ieee80211_if_free(struct net_device *dev)
|
static void ieee80211_if_free(struct net_device *dev)
|
||||||
{
|
{
|
||||||
free_percpu(dev->tstats);
|
free_percpu(dev->tstats);
|
||||||
@ -1402,8 +1465,10 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
|
|||||||
sdata->control_port_no_encrypt = false;
|
sdata->control_port_no_encrypt = false;
|
||||||
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||||
sdata->vif.bss_conf.idle = true;
|
sdata->vif.bss_conf.idle = true;
|
||||||
|
sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
|
||||||
|
|
||||||
sdata->noack_map = 0;
|
sdata->noack_map = 0;
|
||||||
|
sdata->hw_80211_encap = false;
|
||||||
|
|
||||||
/* only monitor/p2p-device differ */
|
/* only monitor/p2p-device differ */
|
||||||
if (sdata->dev) {
|
if (sdata->dev) {
|
||||||
@ -1427,10 +1492,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
|
|||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
|
skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
|
||||||
INIT_LIST_HEAD(&sdata->u.ap.vlans);
|
INIT_LIST_HEAD(&sdata->u.ap.vlans);
|
||||||
INIT_WORK(&sdata->u.ap.request_smps_work,
|
|
||||||
ieee80211_request_smps_ap_work);
|
|
||||||
sdata->vif.bss_conf.bssid = sdata->vif.addr;
|
sdata->vif.bss_conf.bssid = sdata->vif.addr;
|
||||||
sdata->u.ap.req_smps = IEEE80211_SMPS_OFF;
|
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_P2P_CLIENT:
|
case NL80211_IFTYPE_P2P_CLIENT:
|
||||||
type = NL80211_IFTYPE_STATION;
|
type = NL80211_IFTYPE_STATION;
|
||||||
@ -1772,6 +1834,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
|||||||
if_setup, txqs, 1);
|
if_setup, txqs, 1);
|
||||||
if (!ndev)
|
if (!ndev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (!local->ops->wake_tx_queue && local->hw.wiphy->tx_queue_len)
|
||||||
|
ndev->tx_queue_len = local->hw.wiphy->tx_queue_len;
|
||||||
|
|
||||||
dev_net_set(ndev, wiphy_net(local->hw.wiphy));
|
dev_net_set(ndev, wiphy_net(local->hw.wiphy));
|
||||||
|
|
||||||
ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
||||||
@ -1871,6 +1937,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
|||||||
sdata->u.mgd.use_4addr = params->use_4addr;
|
sdata->u.mgd.use_4addr = params->use_4addr;
|
||||||
|
|
||||||
ndev->features |= local->hw.netdev_features;
|
ndev->features |= local->hw.netdev_features;
|
||||||
|
ndev->hw_features |= ndev->features &
|
||||||
|
MAC80211_SUPPORTED_FEATURES_TX;
|
||||||
|
|
||||||
netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
|
netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
|
||||||
|
|
||||||
|
@ -177,6 +177,13 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TKIP countermeasures don't work in encap offload mode */
|
||||||
|
if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
|
||||||
|
sdata->hw_80211_encap) {
|
||||||
|
sdata_dbg(sdata, "TKIP is not allowed in hw 80211 encap mode\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = drv_set_key(key->local, SET_KEY, sdata,
|
ret = drv_set_key(key->local, SET_KEY, sdata,
|
||||||
sta ? &sta->sta : NULL, &key->conf);
|
sta ? &sta->sta : NULL, &key->conf);
|
||||||
|
|
||||||
@ -210,12 +217,20 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
|
|||||||
case WLAN_CIPHER_SUITE_TKIP:
|
case WLAN_CIPHER_SUITE_TKIP:
|
||||||
case WLAN_CIPHER_SUITE_CCMP:
|
case WLAN_CIPHER_SUITE_CCMP:
|
||||||
case WLAN_CIPHER_SUITE_CCMP_256:
|
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||||
|
case WLAN_CIPHER_SUITE_GCMP:
|
||||||
|
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||||
|
/* We cannot do software crypto of data frames with
|
||||||
|
* encapsulation offload enabled. However for 802.11w to
|
||||||
|
* function properly we need cmac/gmac keys.
|
||||||
|
*/
|
||||||
|
if (sdata->hw_80211_encap)
|
||||||
|
return -EINVAL;
|
||||||
|
/* Fall through */
|
||||||
|
|
||||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||||
case WLAN_CIPHER_SUITE_GCMP:
|
|
||||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
|
||||||
/* all of these we can do in software - if driver can */
|
/* all of these we can do in software - if driver can */
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -146,6 +146,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
|||||||
continue;
|
continue;
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||||
continue;
|
continue;
|
||||||
|
if (sdata->vif.bss_conf.txpower == INT_MIN)
|
||||||
|
continue;
|
||||||
power = min(power, sdata->vif.bss_conf.txpower);
|
power = min(power, sdata->vif.bss_conf.txpower);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
@ -416,7 +418,20 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
|
|||||||
},
|
},
|
||||||
[NL80211_IFTYPE_STATION] = {
|
[NL80211_IFTYPE_STATION] = {
|
||||||
.tx = 0xffff,
|
.tx = 0xffff,
|
||||||
|
/*
|
||||||
|
* To support Pre Association Security Negotiation (PASN) while
|
||||||
|
* already associated to one AP, allow user space to register to
|
||||||
|
* Rx authentication frames, so that the user space logic would
|
||||||
|
* be able to receive/handle authentication frames from a
|
||||||
|
* different AP as part of PASN.
|
||||||
|
* It is expected that user space would intelligently register
|
||||||
|
* for Rx authentication frames, i.e., only when PASN is used
|
||||||
|
* and configure a match filter only for PASN authentication
|
||||||
|
* algorithm, as otherwise the MLME functionality of mac80211
|
||||||
|
* would be broken.
|
||||||
|
*/
|
||||||
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
|
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
|
||||||
|
BIT(IEEE80211_STYPE_AUTH >> 4) |
|
||||||
BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
|
BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
|
||||||
},
|
},
|
||||||
[NL80211_IFTYPE_AP] = {
|
[NL80211_IFTYPE_AP] = {
|
||||||
@ -574,6 +589,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
|||||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
|
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
|
||||||
wiphy_ext_feature_set(wiphy,
|
wiphy_ext_feature_set(wiphy,
|
||||||
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
|
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
|
||||||
|
wiphy_ext_feature_set(wiphy,
|
||||||
|
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS);
|
||||||
|
|
||||||
if (!ops->hw_scan) {
|
if (!ops->hw_scan) {
|
||||||
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
|
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
|
||||||
@ -872,7 +889,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||||||
enum nl80211_band band;
|
enum nl80211_band band;
|
||||||
int channels, max_bitrates;
|
int channels, max_bitrates;
|
||||||
bool supp_ht, supp_vht, supp_he;
|
bool supp_ht, supp_vht, supp_he;
|
||||||
netdev_features_t feature_whitelist;
|
|
||||||
struct cfg80211_chan_def dflt_chandef = {};
|
struct cfg80211_chan_def dflt_chandef = {};
|
||||||
|
|
||||||
if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
|
if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
|
||||||
@ -931,10 +947,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Only HW csum features are currently compatible with mac80211 */
|
/* Only HW csum features are currently compatible with mac80211 */
|
||||||
feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
if (WARN_ON(hw->netdev_features & ~MAC80211_SUPPORTED_FEATURES))
|
||||||
NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA |
|
|
||||||
NETIF_F_GSO_SOFTWARE | NETIF_F_RXCSUM;
|
|
||||||
if (WARN_ON(hw->netdev_features & ~feature_whitelist))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (hw->max_report_rates == 0)
|
if (hw->max_report_rates == 0)
|
||||||
@ -981,6 +994,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||||||
if (!supp_he)
|
if (!supp_he)
|
||||||
supp_he = !!ieee80211_get_he_sta_cap(sband);
|
supp_he = !!ieee80211_get_he_sta_cap(sband);
|
||||||
|
|
||||||
|
/* HT, VHT, HE require QoS, thus >= 4 queues */
|
||||||
|
if (WARN_ON(local->hw.queues < IEEE80211_NUM_ACS &&
|
||||||
|
(supp_ht || supp_vht || supp_he)))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (!sband->ht_cap.ht_supported)
|
if (!sband->ht_cap.ht_supported)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1184,10 +1202,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||||||
if (!local->hw.weight_multiplier)
|
if (!local->hw.weight_multiplier)
|
||||||
local->hw.weight_multiplier = 1;
|
local->hw.weight_multiplier = 1;
|
||||||
|
|
||||||
result = ieee80211_wep_init(local);
|
ieee80211_wep_init(local);
|
||||||
if (result < 0)
|
|
||||||
wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
|
|
||||||
result);
|
|
||||||
|
|
||||||
local->hw.conf.flags = IEEE80211_CONF_IDLE;
|
local->hw.conf.flags = IEEE80211_CONF_IDLE;
|
||||||
|
|
||||||
|
@ -164,7 +164,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
|||||||
chandef->center_freq1 = channel->center_freq;
|
chandef->center_freq1 = channel->center_freq;
|
||||||
|
|
||||||
if (!ht_oper || !sta_ht_cap.ht_supported) {
|
if (!ht_oper || !sta_ht_cap.ht_supported) {
|
||||||
ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
|
ret = IEEE80211_STA_DISABLE_HT |
|
||||||
|
IEEE80211_STA_DISABLE_VHT |
|
||||||
|
IEEE80211_STA_DISABLE_HE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +187,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
|||||||
"Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
|
"Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
|
||||||
channel->center_freq, ht_cfreq,
|
channel->center_freq, ht_cfreq,
|
||||||
ht_oper->primary_chan, channel->band);
|
ht_oper->primary_chan, channel->band);
|
||||||
ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
|
ret = IEEE80211_STA_DISABLE_HT |
|
||||||
|
IEEE80211_STA_DISABLE_VHT |
|
||||||
|
IEEE80211_STA_DISABLE_HE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,13 +305,18 @@ out:
|
|||||||
IEEE80211_CHAN_DISABLED)) {
|
IEEE80211_CHAN_DISABLED)) {
|
||||||
if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
|
if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
|
||||||
ret = IEEE80211_STA_DISABLE_HT |
|
ret = IEEE80211_STA_DISABLE_HT |
|
||||||
IEEE80211_STA_DISABLE_VHT;
|
IEEE80211_STA_DISABLE_VHT |
|
||||||
|
IEEE80211_STA_DISABLE_HE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret |= ieee80211_chandef_downgrade(chandef);
|
ret |= ieee80211_chandef_downgrade(chandef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!he_oper || !cfg80211_chandef_usable(sdata->wdev.wiphy, chandef,
|
||||||
|
IEEE80211_CHAN_NO_HE))
|
||||||
|
ret |= IEEE80211_STA_DISABLE_HE;
|
||||||
|
|
||||||
if (chandef->width != vht_chandef.width && !tracking)
|
if (chandef->width != vht_chandef.width && !tracking)
|
||||||
sdata_info(sdata,
|
sdata_info(sdata,
|
||||||
"capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
|
"capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
|
||||||
@ -393,6 +402,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
|
|||||||
|
|
||||||
if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
|
if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
|
||||||
IEEE80211_STA_DISABLE_VHT |
|
IEEE80211_STA_DISABLE_VHT |
|
||||||
|
IEEE80211_STA_DISABLE_HE |
|
||||||
IEEE80211_STA_DISABLE_40MHZ |
|
IEEE80211_STA_DISABLE_40MHZ |
|
||||||
IEEE80211_STA_DISABLE_80P80MHZ |
|
IEEE80211_STA_DISABLE_80P80MHZ |
|
||||||
IEEE80211_STA_DISABLE_160MHZ)) ||
|
IEEE80211_STA_DISABLE_160MHZ)) ||
|
||||||
@ -616,10 +626,21 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
|
|||||||
{
|
{
|
||||||
u8 *pos;
|
u8 *pos;
|
||||||
const struct ieee80211_sta_he_cap *he_cap = NULL;
|
const struct ieee80211_sta_he_cap *he_cap = NULL;
|
||||||
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
u8 he_cap_size;
|
u8 he_cap_size;
|
||||||
|
bool reg_cap = false;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||||
|
if (!WARN_ON_ONCE(!chanctx_conf))
|
||||||
|
reg_cap = cfg80211_chandef_usable(sdata->wdev.wiphy,
|
||||||
|
&chanctx_conf->def,
|
||||||
|
IEEE80211_CHAN_NO_HE);
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
he_cap = ieee80211_get_he_sta_cap(sband);
|
he_cap = ieee80211_get_he_sta_cap(sband);
|
||||||
if (!he_cap)
|
if (!he_cap || !reg_cap)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -650,6 +671,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
|||||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
struct ieee80211_channel *chan;
|
struct ieee80211_channel *chan;
|
||||||
u32 rates = 0;
|
u32 rates = 0;
|
||||||
|
struct element *ext_capa = NULL;
|
||||||
|
|
||||||
|
/* we know it's writable, cast away the const */
|
||||||
|
if (assoc_data->ie_len)
|
||||||
|
ext_capa = (void *)cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
|
||||||
|
assoc_data->ie,
|
||||||
|
assoc_data->ie_len);
|
||||||
|
|
||||||
sdata_assert_lock(sdata);
|
sdata_assert_lock(sdata);
|
||||||
|
|
||||||
@ -800,7 +828,15 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
|||||||
*pos++ = ieee80211_chandef_max_power(&chanctx_conf->def);
|
*pos++ = ieee80211_chandef_max_power(&chanctx_conf->def);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
|
/*
|
||||||
|
* Per spec, we shouldn't include the list of channels if we advertise
|
||||||
|
* support for extended channel switching, but we've always done that;
|
||||||
|
* (for now?) apply this restriction only on the (new) 6 GHz band.
|
||||||
|
*/
|
||||||
|
if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT &&
|
||||||
|
(sband->band != NL80211_BAND_6GHZ ||
|
||||||
|
!ext_capa || ext_capa->datalen < 1 ||
|
||||||
|
!(ext_capa->data[0] & WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING))) {
|
||||||
/* TODO: get this in reg domain format */
|
/* TODO: get this in reg domain format */
|
||||||
pos = skb_put(skb, 2 * sband->n_channels + 2);
|
pos = skb_put(skb, 2 * sband->n_channels + 2);
|
||||||
*pos++ = WLAN_EID_SUPPORTED_CHANNELS;
|
*pos++ = WLAN_EID_SUPPORTED_CHANNELS;
|
||||||
@ -814,18 +850,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
|||||||
|
|
||||||
/* Set MBSSID support for HE AP if needed */
|
/* Set MBSSID support for HE AP if needed */
|
||||||
if (ieee80211_hw_check(&local->hw, SUPPORTS_ONLY_HE_MULTI_BSSID) &&
|
if (ieee80211_hw_check(&local->hw, SUPPORTS_ONLY_HE_MULTI_BSSID) &&
|
||||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && assoc_data->ie_len) {
|
!(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && assoc_data->ie_len &&
|
||||||
struct element *elem;
|
ext_capa && ext_capa->datalen >= 3)
|
||||||
|
ext_capa->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
|
||||||
/* we know it's writable, cast away the const */
|
|
||||||
elem = (void *)cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
|
|
||||||
assoc_data->ie,
|
|
||||||
assoc_data->ie_len);
|
|
||||||
|
|
||||||
/* We can probably assume both always true */
|
|
||||||
if (elem && elem->datalen >= 3)
|
|
||||||
elem->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if present, add any custom IEs that go before HT */
|
/* if present, add any custom IEs that go before HT */
|
||||||
if (assoc_data->ie_len) {
|
if (assoc_data->ie_len) {
|
||||||
@ -2460,7 +2487,7 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
|
|||||||
if (!ieee80211_is_data(hdr->frame_control))
|
if (!ieee80211_is_data(hdr->frame_control))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ieee80211_is_nullfunc(hdr->frame_control) &&
|
if (ieee80211_is_any_nullfunc(hdr->frame_control) &&
|
||||||
sdata->u.mgd.probe_send_count > 0) {
|
sdata->u.mgd.probe_send_count > 0) {
|
||||||
if (ack)
|
if (ack)
|
||||||
ieee80211_sta_reset_conn_monitor(sdata);
|
ieee80211_sta_reset_conn_monitor(sdata);
|
||||||
@ -3368,9 +3395,16 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bss_conf->he_support) {
|
if (bss_conf->he_support) {
|
||||||
bss_conf->bss_color =
|
bss_conf->he_bss_color.color =
|
||||||
le32_get_bits(elems->he_operation->he_oper_params,
|
le32_get_bits(elems->he_operation->he_oper_params,
|
||||||
IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
|
IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
|
||||||
|
bss_conf->he_bss_color.partial =
|
||||||
|
le32_get_bits(elems->he_operation->he_oper_params,
|
||||||
|
IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR);
|
||||||
|
bss_conf->he_bss_color.disabled =
|
||||||
|
le32_get_bits(elems->he_operation->he_oper_params,
|
||||||
|
IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED);
|
||||||
|
changed |= BSS_CHANGED_HE_BSS_COLOR;
|
||||||
|
|
||||||
bss_conf->htc_trig_based_pkt_ext =
|
bss_conf->htc_trig_based_pkt_ext =
|
||||||
le32_get_bits(elems->he_operation->he_oper_params,
|
le32_get_bits(elems->he_operation->he_oper_params,
|
||||||
@ -3649,13 +3683,28 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
|
|||||||
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
||||||
struct ieee80211_if_managed *ifmgd;
|
struct ieee80211_if_managed *ifmgd;
|
||||||
struct ieee80211_rx_status *rx_status = (void *) skb->cb;
|
struct ieee80211_rx_status *rx_status = (void *) skb->cb;
|
||||||
|
struct ieee80211_channel *channel;
|
||||||
size_t baselen, len = skb->len;
|
size_t baselen, len = skb->len;
|
||||||
|
|
||||||
ifmgd = &sdata->u.mgd;
|
ifmgd = &sdata->u.mgd;
|
||||||
|
|
||||||
sdata_assert_lock(sdata);
|
sdata_assert_lock(sdata);
|
||||||
|
|
||||||
if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
|
/*
|
||||||
|
* According to Draft P802.11ax D6.0 clause 26.17.2.3.2:
|
||||||
|
* "If a 6 GHz AP receives a Probe Request frame and responds with
|
||||||
|
* a Probe Response frame [..], the Address 1 field of the Probe
|
||||||
|
* Response frame shall be set to the broadcast address [..]"
|
||||||
|
* So, on 6GHz band we should also accept broadcast responses.
|
||||||
|
*/
|
||||||
|
channel = ieee80211_get_channel(sdata->local->hw.wiphy,
|
||||||
|
rx_status->freq);
|
||||||
|
if (!channel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
|
||||||
|
(channel->band != NL80211_BAND_6GHZ ||
|
||||||
|
!is_broadcast_ether_addr(mgmt->da)))
|
||||||
return; /* ignore ProbeResp to foreign address */
|
return; /* ignore ProbeResp to foreign address */
|
||||||
|
|
||||||
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
|
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
|
||||||
@ -4753,10 +4802,22 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
|||||||
IEEE80211_STA_DISABLE_80P80MHZ |
|
IEEE80211_STA_DISABLE_80P80MHZ |
|
||||||
IEEE80211_STA_DISABLE_160MHZ);
|
IEEE80211_STA_DISABLE_160MHZ);
|
||||||
|
|
||||||
|
/* disable HT/VHT/HE if we don't support them */
|
||||||
|
if (!sband->ht_cap.ht_supported) {
|
||||||
|
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
||||||
|
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||||
|
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sband->vht_cap.vht_supported)
|
||||||
|
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||||
|
|
||||||
|
if (!ieee80211_get_he_sta_cap(sband))
|
||||||
|
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
|
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
|
||||||
sband->ht_cap.ht_supported) {
|
|
||||||
const u8 *ht_oper_ie, *ht_cap_ie;
|
const u8 *ht_oper_ie, *ht_cap_ie;
|
||||||
|
|
||||||
ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
|
ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
|
||||||
@ -4773,8 +4834,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
|
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
|
||||||
sband->vht_cap.vht_supported) {
|
|
||||||
const u8 *vht_oper_ie, *vht_cap;
|
const u8 *vht_oper_ie, *vht_cap;
|
||||||
|
|
||||||
vht_oper_ie = ieee80211_bss_get_ie(cbss,
|
vht_oper_ie = ieee80211_bss_get_ie(cbss,
|
||||||
@ -4784,9 +4844,10 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
|||||||
if (vht_oper && !ht_oper) {
|
if (vht_oper && !ht_oper) {
|
||||||
vht_oper = NULL;
|
vht_oper = NULL;
|
||||||
sdata_info(sdata,
|
sdata_info(sdata,
|
||||||
"AP advertised VHT without HT, disabling both\n");
|
"AP advertised VHT without HT, disabling HT/VHT/HE\n");
|
||||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
||||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||||
|
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||||
}
|
}
|
||||||
|
|
||||||
vht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
|
vht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
|
||||||
@ -4796,9 +4857,6 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ieee80211_get_he_sta_cap(sband))
|
|
||||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
|
||||||
|
|
||||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) {
|
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) {
|
||||||
const struct cfg80211_bss_ies *ies;
|
const struct cfg80211_bss_ies *ies;
|
||||||
const u8 *he_oper_ie;
|
const u8 *he_oper_ie;
|
||||||
@ -5297,27 +5355,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Also disable HT if we don't support it or the AP doesn't use WMM */
|
|
||||||
sband = local->hw.wiphy->bands[req->bss->channel->band];
|
sband = local->hw.wiphy->bands[req->bss->channel->band];
|
||||||
if (!sband->ht_cap.ht_supported ||
|
|
||||||
local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used ||
|
|
||||||
ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
|
|
||||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
|
||||||
if (!bss->wmm_used &&
|
|
||||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM))
|
|
||||||
netdev_info(sdata->dev,
|
|
||||||
"disabling HT as WMM/QoS is not supported by the AP\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* disable VHT if we don't support it or the AP doesn't use WMM */
|
/* also disable HT/VHT/HE if the AP doesn't use WMM */
|
||||||
if (!sband->vht_cap.vht_supported ||
|
if (!bss->wmm_used) {
|
||||||
local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used ||
|
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
||||||
ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
|
|
||||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||||
if (!bss->wmm_used &&
|
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM))
|
|
||||||
netdev_info(sdata->dev,
|
netdev_info(sdata->dev,
|
||||||
"disabling VHT as WMM/QoS is not supported by the AP\n");
|
"disabling HT/VHT/HE as WMM/QoS is not supported by the AP\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
|
memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
|
||||||
@ -5449,6 +5495,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
|||||||
if (req->flags & ASSOC_REQ_DISABLE_HT) {
|
if (req->flags & ASSOC_REQ_DISABLE_HT) {
|
||||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
||||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
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)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018-2019 Intel Corporation
|
* Copyright (C) 2018-2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
@ -1450,8 +1450,7 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
|
|||||||
return RX_CONTINUE;
|
return RX_CONTINUE;
|
||||||
|
|
||||||
if (ieee80211_is_ctl(hdr->frame_control) ||
|
if (ieee80211_is_ctl(hdr->frame_control) ||
|
||||||
ieee80211_is_nullfunc(hdr->frame_control) ||
|
ieee80211_is_any_nullfunc(hdr->frame_control) ||
|
||||||
ieee80211_is_qos_nullfunc(hdr->frame_control) ||
|
|
||||||
is_multicast_ether_addr(hdr->addr1))
|
is_multicast_ether_addr(hdr->addr1))
|
||||||
return RX_CONTINUE;
|
return RX_CONTINUE;
|
||||||
|
|
||||||
@ -1838,8 +1837,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||||||
* Drop (qos-)data::nullfunc frames silently, since they
|
* Drop (qos-)data::nullfunc frames silently, since they
|
||||||
* are used only to control station power saving mode.
|
* are used only to control station power saving mode.
|
||||||
*/
|
*/
|
||||||
if (ieee80211_is_nullfunc(hdr->frame_control) ||
|
if (ieee80211_is_any_nullfunc(hdr->frame_control)) {
|
||||||
ieee80211_is_qos_nullfunc(hdr->frame_control)) {
|
|
||||||
I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
|
I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2319,7 +2317,7 @@ static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
|
|||||||
|
|
||||||
/* Drop unencrypted frames if key is set. */
|
/* Drop unencrypted frames if key is set. */
|
||||||
if (unlikely(!ieee80211_has_protected(fc) &&
|
if (unlikely(!ieee80211_has_protected(fc) &&
|
||||||
!ieee80211_is_nullfunc(fc) &&
|
!ieee80211_is_any_nullfunc(fc) &&
|
||||||
ieee80211_is_data(fc) && rx->key))
|
ieee80211_is_data(fc) && rx->key))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
|
||||||
@ -3084,6 +3082,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|||||||
enum ieee80211_smps_mode smps_mode;
|
enum ieee80211_smps_mode smps_mode;
|
||||||
struct sta_opmode_info sta_opmode = {};
|
struct sta_opmode_info sta_opmode = {};
|
||||||
|
|
||||||
|
if (sdata->vif.type != NL80211_IFTYPE_AP &&
|
||||||
|
sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
|
||||||
|
goto handled;
|
||||||
|
|
||||||
/* convert to HT capability */
|
/* convert to HT capability */
|
||||||
switch (mgmt->u.action.u.ht_smps.smps_control) {
|
switch (mgmt->u.action.u.ht_smps.smps_control) {
|
||||||
case WLAN_HT_SMPS_CONTROL_DISABLED:
|
case WLAN_HT_SMPS_CONTROL_DISABLED:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018-2019 Intel Corporation
|
* Copyright (C) 2018-2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -1351,20 +1351,6 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
|||||||
|
|
||||||
atomic_dec(&ps->num_sta_ps);
|
atomic_dec(&ps->num_sta_ps);
|
||||||
|
|
||||||
/* This station just woke up and isn't aware of our SMPS state */
|
|
||||||
if (!ieee80211_vif_is_mesh(&sdata->vif) &&
|
|
||||||
!ieee80211_smps_is_restrictive(sta->known_smps_mode,
|
|
||||||
sdata->smps_mode) &&
|
|
||||||
sta->known_smps_mode != sdata->bss->req_smps &&
|
|
||||||
sta_info_tx_streams(sta) != 1) {
|
|
||||||
ht_dbg(sdata,
|
|
||||||
"%pM just woke up and MIMO capable - update SMPS\n",
|
|
||||||
sta->sta.addr);
|
|
||||||
ieee80211_send_smps_action(sdata, sdata->bss->req_smps,
|
|
||||||
sta->sta.addr,
|
|
||||||
sdata->vif.bss_conf.bssid);
|
|
||||||
}
|
|
||||||
|
|
||||||
local->total_ps_buffered -= buffered;
|
local->total_ps_buffered -= buffered;
|
||||||
|
|
||||||
sta_info_recalc_tim(sta);
|
sta_info_recalc_tim(sta);
|
||||||
|
@ -643,8 +643,7 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
|
|||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
sdata = ieee80211_sdata_from_skb(local, skb);
|
sdata = ieee80211_sdata_from_skb(local, skb);
|
||||||
if (sdata) {
|
if (sdata) {
|
||||||
if (ieee80211_is_nullfunc(hdr->frame_control) ||
|
if (ieee80211_is_any_nullfunc(hdr->frame_control))
|
||||||
ieee80211_is_qos_nullfunc(hdr->frame_control))
|
|
||||||
cfg80211_probe_status(sdata->dev, hdr->addr1,
|
cfg80211_probe_status(sdata->dev, hdr->addr1,
|
||||||
cookie, acked,
|
cookie, acked,
|
||||||
info->status.ack_signal,
|
info->status.ack_signal,
|
||||||
@ -888,6 +887,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
|||||||
int rates_idx;
|
int rates_idx;
|
||||||
bool send_to_cooked;
|
bool send_to_cooked;
|
||||||
bool acked;
|
bool acked;
|
||||||
|
bool noack_success;
|
||||||
struct ieee80211_bar *bar;
|
struct ieee80211_bar *bar;
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
int tid = IEEE80211_NUM_TIDS;
|
int tid = IEEE80211_NUM_TIDS;
|
||||||
@ -906,6 +906,8 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
|||||||
clear_sta_flag(sta, WLAN_STA_SP);
|
clear_sta_flag(sta, WLAN_STA_SP);
|
||||||
|
|
||||||
acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
||||||
|
noack_success = !!(info->flags &
|
||||||
|
IEEE80211_TX_STAT_NOACK_TRANSMITTED);
|
||||||
|
|
||||||
/* mesh Peer Service Period support */
|
/* mesh Peer Service Period support */
|
||||||
if (ieee80211_vif_is_mesh(&sta->sdata->vif) &&
|
if (ieee80211_vif_is_mesh(&sta->sdata->vif) &&
|
||||||
@ -970,12 +972,12 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
|||||||
ieee80211_handle_filtered_frame(local, sta, skb);
|
ieee80211_handle_filtered_frame(local, sta, skb);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!acked)
|
if (!acked && !noack_success)
|
||||||
sta->status_stats.retry_failed++;
|
sta->status_stats.retry_failed++;
|
||||||
sta->status_stats.retry_count += retry_count;
|
sta->status_stats.retry_count += retry_count;
|
||||||
|
|
||||||
if (ieee80211_is_data_present(fc)) {
|
if (ieee80211_is_data_present(fc)) {
|
||||||
if (!acked)
|
if (!acked && !noack_success)
|
||||||
sta->status_stats.msdu_failed[tid]++;
|
sta->status_stats.msdu_failed[tid]++;
|
||||||
|
|
||||||
sta->status_stats.msdu_retries[tid] +=
|
sta->status_stats.msdu_retries[tid] +=
|
||||||
@ -1013,7 +1015,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
|
if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
|
||||||
if (info->flags & IEEE80211_TX_STAT_ACK) {
|
if (acked) {
|
||||||
if (sta->status_stats.lost_packets)
|
if (sta->status_stats.lost_packets)
|
||||||
sta->status_stats.lost_packets = 0;
|
sta->status_stats.lost_packets = 0;
|
||||||
|
|
||||||
@ -1021,6 +1023,8 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
|||||||
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
||||||
sta->status_stats.last_tdls_pkt_time =
|
sta->status_stats.last_tdls_pkt_time =
|
||||||
jiffies;
|
jiffies;
|
||||||
|
} else if (noack_success) {
|
||||||
|
/* nothing to do here, do not account as lost */
|
||||||
} else {
|
} else {
|
||||||
ieee80211_lost_packet(sta, info);
|
ieee80211_lost_packet(sta, info);
|
||||||
}
|
}
|
||||||
@ -1056,7 +1060,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
|||||||
I802_DEBUG_INC(local->dot11FailedCount);
|
I802_DEBUG_INC(local->dot11FailedCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) &&
|
if (ieee80211_is_any_nullfunc(fc) &&
|
||||||
ieee80211_has_pm(fc) &&
|
ieee80211_has_pm(fc) &&
|
||||||
ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS) &&
|
ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS) &&
|
||||||
!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
|
!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
|
||||||
@ -1141,7 +1145,7 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
|||||||
|
|
||||||
sta = container_of(pubsta, struct sta_info, sta);
|
sta = container_of(pubsta, struct sta_info, sta);
|
||||||
|
|
||||||
if (!acked)
|
if (!acked && !noack_success)
|
||||||
sta->status_stats.retry_failed++;
|
sta->status_stats.retry_failed++;
|
||||||
sta->status_stats.retry_count += retry_count;
|
sta->status_stats.retry_count += retry_count;
|
||||||
|
|
||||||
@ -1156,6 +1160,8 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
|||||||
sta->status_stats.last_tdls_pkt_time = jiffies;
|
sta->status_stats.last_tdls_pkt_time = jiffies;
|
||||||
} else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
} else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||||
return;
|
return;
|
||||||
|
} else if (noack_success) {
|
||||||
|
/* nothing to do here, do not account as lost */
|
||||||
} else {
|
} else {
|
||||||
ieee80211_lost_packet(sta, info);
|
ieee80211_lost_packet(sta, info);
|
||||||
}
|
}
|
||||||
@ -1198,6 +1204,77 @@ void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_tx_rate_update);
|
EXPORT_SYMBOL(ieee80211_tx_rate_update);
|
||||||
|
|
||||||
|
void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = hw_to_local(hw);
|
||||||
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
struct sta_info *sta;
|
||||||
|
int retry_count;
|
||||||
|
int rates_idx;
|
||||||
|
bool acked;
|
||||||
|
|
||||||
|
sdata = vif_to_sdata(vif);
|
||||||
|
|
||||||
|
acked = info->flags & IEEE80211_TX_STAT_ACK;
|
||||||
|
rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
|
||||||
|
goto counters_update;
|
||||||
|
|
||||||
|
if (IS_ERR(sta))
|
||||||
|
goto counters_update;
|
||||||
|
|
||||||
|
if (!acked)
|
||||||
|
sta->status_stats.retry_failed++;
|
||||||
|
|
||||||
|
if (rates_idx != -1)
|
||||||
|
sta->tx_stats.last_rate = info->status.rates[rates_idx];
|
||||||
|
|
||||||
|
sta->status_stats.retry_count += retry_count;
|
||||||
|
|
||||||
|
if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
|
||||||
|
if (acked && vif->type == NL80211_IFTYPE_STATION)
|
||||||
|
ieee80211_sta_reset_conn_monitor(sdata);
|
||||||
|
|
||||||
|
sta->status_stats.last_ack = jiffies;
|
||||||
|
if (info->flags & IEEE80211_TX_STAT_ACK) {
|
||||||
|
if (sta->status_stats.lost_packets)
|
||||||
|
sta->status_stats.lost_packets = 0;
|
||||||
|
|
||||||
|
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
||||||
|
sta->status_stats.last_tdls_pkt_time = jiffies;
|
||||||
|
} else {
|
||||||
|
ieee80211_lost_packet(sta, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
counters_update:
|
||||||
|
rcu_read_unlock();
|
||||||
|
ieee80211_led_tx(local);
|
||||||
|
|
||||||
|
if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
|
||||||
|
!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED))
|
||||||
|
goto skip_stats_update;
|
||||||
|
|
||||||
|
I802_DEBUG_INC(local->dot11TransmittedFrameCount);
|
||||||
|
if (is_multicast_ether_addr(skb->data))
|
||||||
|
I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
|
||||||
|
if (retry_count > 0)
|
||||||
|
I802_DEBUG_INC(local->dot11RetryCount);
|
||||||
|
if (retry_count > 1)
|
||||||
|
I802_DEBUG_INC(local->dot11MultipleRetryCount);
|
||||||
|
|
||||||
|
skip_stats_update:
|
||||||
|
ieee80211_report_used_skb(local, skb, false);
|
||||||
|
dev_kfree_skb(skb);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ieee80211_tx_status_8023);
|
||||||
|
|
||||||
void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
|
void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
|
||||||
{
|
{
|
||||||
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
|
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
|
||||||
|
@ -297,7 +297,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
|
|||||||
if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
|
if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
|
||||||
test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
|
test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
|
||||||
!ieee80211_is_probe_req(hdr->frame_control) &&
|
!ieee80211_is_probe_req(hdr->frame_control) &&
|
||||||
!ieee80211_is_nullfunc(hdr->frame_control))
|
!ieee80211_is_any_nullfunc(hdr->frame_control))
|
||||||
/*
|
/*
|
||||||
* When software scanning only nullfunc frames (to notify
|
* When software scanning only nullfunc frames (to notify
|
||||||
* the sleep state to the AP) and probe requests (for the
|
* the sleep state to the AP) and probe requests (for the
|
||||||
@ -1250,7 +1250,8 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
|
|||||||
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
|
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
|
if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
|
||||||
|
unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
|
||||||
if ((!ieee80211_is_mgmt(hdr->frame_control) ||
|
if ((!ieee80211_is_mgmt(hdr->frame_control) ||
|
||||||
ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
|
ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
|
||||||
vif->type == NL80211_IFTYPE_STATION) &&
|
vif->type == NL80211_IFTYPE_STATION) &&
|
||||||
@ -2360,7 +2361,7 @@ static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
|
|||||||
skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
|
skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
|
int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
struct sta_info **sta_out)
|
struct sta_info **sta_out)
|
||||||
{
|
{
|
||||||
@ -3616,6 +3617,9 @@ begin:
|
|||||||
else
|
else
|
||||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||||
|
|
||||||
|
if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
|
||||||
|
goto encap_out;
|
||||||
|
|
||||||
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
|
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
|
||||||
struct sta_info *sta = container_of(txq->sta, struct sta_info,
|
struct sta_info *sta = container_of(txq->sta, struct sta_info,
|
||||||
sta);
|
sta);
|
||||||
@ -3675,6 +3679,7 @@ begin:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encap_out:
|
||||||
IEEE80211_SKB_CB(skb)->control.vif = vif;
|
IEEE80211_SKB_CB(skb)->control.vif = vif;
|
||||||
|
|
||||||
if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
|
if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
|
||||||
@ -4103,6 +4108,153 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
|||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct sk_buff *skb, int led_len,
|
||||||
|
struct sta_info *sta,
|
||||||
|
bool txpending)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
struct ieee80211_tx_control control = {};
|
||||||
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
struct ieee80211_sta *pubsta = NULL;
|
||||||
|
unsigned long flags;
|
||||||
|
int q = info->hw_queue;
|
||||||
|
|
||||||
|
if (ieee80211_queue_skb(local, sdata, sta, skb))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||||
|
|
||||||
|
if (local->queue_stop_reasons[q] ||
|
||||||
|
(!txpending && !skb_queue_empty(&local->pending[q]))) {
|
||||||
|
if (txpending)
|
||||||
|
skb_queue_head(&local->pending[q], skb);
|
||||||
|
else
|
||||||
|
skb_queue_tail(&local->pending[q], skb);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||||
|
|
||||||
|
if (sta && sta->uploaded)
|
||||||
|
pubsta = &sta->sta;
|
||||||
|
|
||||||
|
control.sta = pubsta;
|
||||||
|
|
||||||
|
drv_tx(local, &control, skb);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct net_device *dev, struct sta_info *sta,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
struct ethhdr *ehdr = (struct ethhdr *)skb->data;
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
bool authorized = false;
|
||||||
|
bool multicast;
|
||||||
|
unsigned char *ra = ehdr->h_dest;
|
||||||
|
|
||||||
|
if (IS_ERR(sta) || (sta && !sta->uploaded))
|
||||||
|
sta = NULL;
|
||||||
|
|
||||||
|
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||||
|
(!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER)))
|
||||||
|
ra = sdata->u.mgd.bssid;
|
||||||
|
|
||||||
|
if (!is_valid_ether_addr(ra))
|
||||||
|
goto out_free;
|
||||||
|
|
||||||
|
multicast = is_multicast_ether_addr(ra);
|
||||||
|
|
||||||
|
if (sta)
|
||||||
|
authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
|
||||||
|
|
||||||
|
if (!multicast && !authorized &&
|
||||||
|
(ehdr->h_proto != sdata->control_port_protocol ||
|
||||||
|
!ether_addr_equal(sdata->vif.addr, ehdr->h_source)))
|
||||||
|
goto out_free;
|
||||||
|
|
||||||
|
if (multicast && sdata->vif.type == NL80211_IFTYPE_AP &&
|
||||||
|
!atomic_read(&sdata->u.ap.num_mcast_sta))
|
||||||
|
goto out_free;
|
||||||
|
|
||||||
|
if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
|
||||||
|
test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
|
||||||
|
goto out_free;
|
||||||
|
|
||||||
|
if (unlikely(!multicast && skb->sk &&
|
||||||
|
skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
|
||||||
|
ieee80211_store_ack_skb(local, skb, &info->flags);
|
||||||
|
|
||||||
|
memset(info, 0, sizeof(*info));
|
||||||
|
|
||||||
|
if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) {
|
||||||
|
if (sdata->control_port_no_encrypt)
|
||||||
|
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||||
|
info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multicast)
|
||||||
|
info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||||
|
|
||||||
|
info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
|
||||||
|
|
||||||
|
ieee80211_tx_stats(dev, skb->len);
|
||||||
|
|
||||||
|
if (sta) {
|
||||||
|
sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
|
||||||
|
sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||||
|
sdata = container_of(sdata->bss,
|
||||||
|
struct ieee80211_sub_if_data, u.ap);
|
||||||
|
|
||||||
|
info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
|
||||||
|
info->control.vif = &sdata->vif;
|
||||||
|
|
||||||
|
ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
out_free:
|
||||||
|
kfree_skb(skb);
|
||||||
|
}
|
||||||
|
|
||||||
|
netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
|
||||||
|
struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
struct sta_info *sta;
|
||||||
|
|
||||||
|
if (WARN_ON(!sdata->hw_80211_encap)) {
|
||||||
|
kfree_skb(skb);
|
||||||
|
return NETDEV_TX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(skb->len < ETH_HLEN)) {
|
||||||
|
kfree_skb(skb);
|
||||||
|
return NETDEV_TX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
|
||||||
|
kfree_skb(skb);
|
||||||
|
else
|
||||||
|
ieee80211_8023_xmit(sdata, dev, sta, skb);
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return NETDEV_TX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
struct sk_buff *
|
struct sk_buff *
|
||||||
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb, u32 info_flags)
|
struct sk_buff *skb, u32 info_flags)
|
||||||
@ -4181,6 +4333,16 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
|
|||||||
}
|
}
|
||||||
info->band = chanctx_conf->def.chan->band;
|
info->band = chanctx_conf->def.chan->band;
|
||||||
result = ieee80211_tx(sdata, NULL, skb, true, 0);
|
result = ieee80211_tx(sdata, NULL, skb, true, 0);
|
||||||
|
} else if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
|
||||||
|
if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
|
||||||
|
dev_kfree_skb(skb);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ERR(sta) || (sta && !sta->uploaded))
|
||||||
|
sta = NULL;
|
||||||
|
|
||||||
|
result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true);
|
||||||
} else {
|
} else {
|
||||||
struct sk_buff_head skbs;
|
struct sk_buff_head skbs;
|
||||||
|
|
||||||
@ -5120,7 +5282,8 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
|||||||
|
|
||||||
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||||
const u8 *buf, size_t len,
|
const u8 *buf, size_t len,
|
||||||
const u8 *dest, __be16 proto, bool unencrypted)
|
const u8 *dest, const u8 *src, __be16 proto,
|
||||||
|
bool unencrypted)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
@ -5151,7 +5314,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
|
|
||||||
ehdr = skb_push(skb, sizeof(struct ethhdr));
|
ehdr = skb_push(skb, sizeof(struct ethhdr));
|
||||||
memcpy(ehdr->h_dest, dest, ETH_ALEN);
|
memcpy(ehdr->h_dest, dest, ETH_ALEN);
|
||||||
memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
|
memcpy(ehdr->h_source, src, ETH_ALEN);
|
||||||
ehdr->h_proto = proto;
|
ehdr->h_proto = proto;
|
||||||
|
|
||||||
skb->dev = dev;
|
skb->dev = dev;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018-2019 Intel Corporation
|
* Copyright (C) 2018-2020 Intel Corporation
|
||||||
*
|
*
|
||||||
* utilities for mac80211
|
* utilities for mac80211
|
||||||
*/
|
*/
|
||||||
@ -39,7 +39,6 @@ const void *const mac80211_wiphy_privid = &mac80211_wiphy_privid;
|
|||||||
struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
|
struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local;
|
struct ieee80211_local *local;
|
||||||
BUG_ON(!wiphy);
|
|
||||||
|
|
||||||
local = wiphy_priv(wiphy);
|
local = wiphy_priv(wiphy);
|
||||||
return &local->hw;
|
return &local->hw;
|
||||||
@ -891,6 +890,51 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
|
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
|
||||||
|
|
||||||
|
static void ieee80211_parse_extension_element(u32 *crc,
|
||||||
|
const struct element *elem,
|
||||||
|
struct ieee802_11_elems *elems)
|
||||||
|
{
|
||||||
|
const void *data = elem->data + 1;
|
||||||
|
u8 len = elem->datalen - 1;
|
||||||
|
|
||||||
|
switch (elem->data[0]) {
|
||||||
|
case WLAN_EID_EXT_HE_MU_EDCA:
|
||||||
|
if (len == sizeof(*elems->mu_edca_param_set)) {
|
||||||
|
elems->mu_edca_param_set = data;
|
||||||
|
if (crc)
|
||||||
|
*crc = crc32_be(*crc, (void *)elem,
|
||||||
|
elem->datalen + 2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WLAN_EID_EXT_HE_CAPABILITY:
|
||||||
|
elems->he_cap = data;
|
||||||
|
elems->he_cap_len = len;
|
||||||
|
break;
|
||||||
|
case WLAN_EID_EXT_HE_OPERATION:
|
||||||
|
if (len >= sizeof(*elems->he_operation) &&
|
||||||
|
len == ieee80211_he_oper_size(data) - 1)
|
||||||
|
elems->he_operation = data;
|
||||||
|
break;
|
||||||
|
case WLAN_EID_EXT_UORA:
|
||||||
|
if (len == 1)
|
||||||
|
elems->uora_element = data;
|
||||||
|
break;
|
||||||
|
case WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME:
|
||||||
|
if (len == 3)
|
||||||
|
elems->max_channel_switch_time = data;
|
||||||
|
break;
|
||||||
|
case WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION:
|
||||||
|
if (len == sizeof(*elems->mbssid_config_ie))
|
||||||
|
elems->mbssid_config_ie = data;
|
||||||
|
break;
|
||||||
|
case WLAN_EID_EXT_HE_SPR:
|
||||||
|
if (len >= sizeof(*elems->he_spr) &&
|
||||||
|
len >= ieee80211_he_spr_size(data))
|
||||||
|
elems->he_spr = data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static u32
|
static u32
|
||||||
_ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
_ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
||||||
struct ieee802_11_elems *elems,
|
struct ieee802_11_elems *elems,
|
||||||
@ -950,6 +994,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
|||||||
case WLAN_EID_CHAN_SWITCH_TIMING:
|
case WLAN_EID_CHAN_SWITCH_TIMING:
|
||||||
case WLAN_EID_LINK_ID:
|
case WLAN_EID_LINK_ID:
|
||||||
case WLAN_EID_BSS_MAX_IDLE_PERIOD:
|
case WLAN_EID_BSS_MAX_IDLE_PERIOD:
|
||||||
|
case WLAN_EID_RSNX:
|
||||||
/*
|
/*
|
||||||
* not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
|
* not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
|
||||||
* that if the content gets bigger it might be needed more than once
|
* that if the content gets bigger it might be needed more than once
|
||||||
@ -1226,34 +1271,14 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
|||||||
if (elen >= sizeof(*elems->max_idle_period_ie))
|
if (elen >= sizeof(*elems->max_idle_period_ie))
|
||||||
elems->max_idle_period_ie = (void *)pos;
|
elems->max_idle_period_ie = (void *)pos;
|
||||||
break;
|
break;
|
||||||
|
case WLAN_EID_RSNX:
|
||||||
|
elems->rsnx = pos;
|
||||||
|
elems->rsnx_len = elen;
|
||||||
|
break;
|
||||||
case WLAN_EID_EXTENSION:
|
case WLAN_EID_EXTENSION:
|
||||||
if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
|
ieee80211_parse_extension_element(calc_crc ?
|
||||||
elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
|
&crc : NULL,
|
||||||
elems->mu_edca_param_set = (void *)&pos[1];
|
elem, elems);
|
||||||
if (calc_crc)
|
|
||||||
crc = crc32_be(crc, pos - 2, elen + 2);
|
|
||||||
} else if (pos[0] == WLAN_EID_EXT_HE_CAPABILITY) {
|
|
||||||
elems->he_cap = (void *)&pos[1];
|
|
||||||
elems->he_cap_len = elen - 1;
|
|
||||||
} else if (pos[0] == WLAN_EID_EXT_HE_OPERATION &&
|
|
||||||
elen >= sizeof(*elems->he_operation) &&
|
|
||||||
elen >= ieee80211_he_oper_size(&pos[1])) {
|
|
||||||
elems->he_operation = (void *)&pos[1];
|
|
||||||
} else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) {
|
|
||||||
elems->uora_element = (void *)&pos[1];
|
|
||||||
} else if (pos[0] ==
|
|
||||||
WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME &&
|
|
||||||
elen == 4) {
|
|
||||||
elems->max_channel_switch_time = pos + 1;
|
|
||||||
} else if (pos[0] ==
|
|
||||||
WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION &&
|
|
||||||
elen == 3) {
|
|
||||||
elems->mbssid_config_ie = (void *)&pos[1];
|
|
||||||
} else if (pos[0] == WLAN_EID_EXT_HE_SPR &&
|
|
||||||
elen >= sizeof(*elems->he_spr) &&
|
|
||||||
elen >= ieee80211_he_spr_size(&pos[1])) {
|
|
||||||
elems->he_spr = (void *)&pos[1];
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -333,11 +333,33 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: move this to some better location - parses HE now */
|
||||||
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
|
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
|
||||||
{
|
{
|
||||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
|
struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
|
||||||
|
struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap;
|
||||||
u32 cap_width;
|
u32 cap_width;
|
||||||
|
|
||||||
|
if (he_cap->has_he) {
|
||||||
|
u8 info = he_cap->he_cap_elem.phy_cap_info[0];
|
||||||
|
|
||||||
|
if (sta->sdata->vif.bss_conf.chandef.chan->band ==
|
||||||
|
NL80211_BAND_2GHZ) {
|
||||||
|
if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G)
|
||||||
|
return IEEE80211_STA_RX_BW_40;
|
||||||
|
else
|
||||||
|
return IEEE80211_STA_RX_BW_20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G ||
|
||||||
|
info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
|
||||||
|
return IEEE80211_STA_RX_BW_160;
|
||||||
|
else if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)
|
||||||
|
return IEEE80211_STA_RX_BW_80;
|
||||||
|
|
||||||
|
return IEEE80211_STA_RX_BW_20;
|
||||||
|
}
|
||||||
|
|
||||||
if (!vht_cap->vht_supported)
|
if (!vht_cap->vht_supported)
|
||||||
return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
|
return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
|
||||||
IEEE80211_STA_RX_BW_40 :
|
IEEE80211_STA_RX_BW_40 :
|
||||||
@ -433,6 +455,7 @@ ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: rename/move - this deals with everything not just VHT */
|
||||||
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
|
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||||
@ -458,12 +481,40 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
|
|||||||
|
|
||||||
void ieee80211_sta_set_rx_nss(struct sta_info *sta)
|
void ieee80211_sta_set_rx_nss(struct sta_info *sta)
|
||||||
{
|
{
|
||||||
u8 ht_rx_nss = 0, vht_rx_nss = 0;
|
u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, rx_nss;
|
||||||
|
|
||||||
/* if we received a notification already don't overwrite it */
|
/* if we received a notification already don't overwrite it */
|
||||||
if (sta->sta.rx_nss)
|
if (sta->sta.rx_nss)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (sta->sta.he_cap.has_he) {
|
||||||
|
int i;
|
||||||
|
u8 rx_mcs_80 = 0, rx_mcs_160 = 0;
|
||||||
|
const struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap;
|
||||||
|
u16 mcs_160_map =
|
||||||
|
le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
|
||||||
|
u16 mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
|
||||||
|
|
||||||
|
for (i = 7; i >= 0; i--) {
|
||||||
|
u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
|
||||||
|
|
||||||
|
if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
|
||||||
|
rx_mcs_160 = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 7; i >= 0; i--) {
|
||||||
|
u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
|
||||||
|
|
||||||
|
if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
|
||||||
|
rx_mcs_80 = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
he_rx_nss = min(rx_mcs_80, rx_mcs_160);
|
||||||
|
}
|
||||||
|
|
||||||
if (sta->sta.ht_cap.ht_supported) {
|
if (sta->sta.ht_cap.ht_supported) {
|
||||||
if (sta->sta.ht_cap.mcs.rx_mask[0])
|
if (sta->sta.ht_cap.mcs.rx_mask[0])
|
||||||
ht_rx_nss++;
|
ht_rx_nss++;
|
||||||
@ -493,8 +544,9 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
|
|||||||
/* FIXME: consider rx_highest? */
|
/* FIXME: consider rx_highest? */
|
||||||
}
|
}
|
||||||
|
|
||||||
ht_rx_nss = max(ht_rx_nss, vht_rx_nss);
|
rx_nss = max(vht_rx_nss, ht_rx_nss);
|
||||||
sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss);
|
rx_nss = max(he_rx_nss, rx_nss);
|
||||||
|
sta->sta.rx_nss = max_t(u8, 1, rx_nss);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||||
|
@ -22,12 +22,10 @@
|
|||||||
#include "wep.h"
|
#include "wep.h"
|
||||||
|
|
||||||
|
|
||||||
int ieee80211_wep_init(struct ieee80211_local *local)
|
void ieee80211_wep_init(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
/* start WEP IV from a random value */
|
/* start WEP IV from a random value */
|
||||||
get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
|
get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
|
static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "ieee80211_i.h"
|
#include "ieee80211_i.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
|
||||||
int ieee80211_wep_init(struct ieee80211_local *local);
|
void ieee80211_wep_init(struct ieee80211_local *local);
|
||||||
int ieee80211_wep_encrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
|
int ieee80211_wep_encrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
|
||||||
size_t klen, u8 *data, size_t data_len);
|
size_t klen, u8 *data, size_t data_len);
|
||||||
int ieee80211_wep_encrypt(struct ieee80211_local *local,
|
int ieee80211_wep_encrypt(struct ieee80211_local *local,
|
||||||
|
@ -385,7 +385,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
|
|||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
|
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
|
||||||
u16 frame_type, const u8 *match_data,
|
u16 frame_type, const u8 *match_data,
|
||||||
int match_len);
|
int match_len, struct netlink_ext_ack *extack);
|
||||||
void cfg80211_mlme_unreg_wk(struct work_struct *wk);
|
void cfg80211_mlme_unreg_wk(struct work_struct *wk);
|
||||||
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
|
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
|
||||||
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
|
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||||
* Copyright (c) 2015 Intel Deutschland GmbH
|
* Copyright (c) 2015 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -470,7 +471,7 @@ void cfg80211_mlme_unreg_wk(struct work_struct *wk)
|
|||||||
|
|
||||||
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
||||||
u16 frame_type, const u8 *match_data,
|
u16 frame_type, const u8 *match_data,
|
||||||
int match_len)
|
int match_len, struct netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
struct wiphy *wiphy = wdev->wiphy;
|
struct wiphy *wiphy = wdev->wiphy;
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||||
@ -481,15 +482,38 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
|||||||
if (!wdev->wiphy->mgmt_stypes)
|
if (!wdev->wiphy->mgmt_stypes)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
|
if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) {
|
||||||
|
NL_SET_ERR_MSG(extack, "frame type not management");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
|
if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Invalid frame type");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
|
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
|
||||||
if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type)))
|
if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) {
|
||||||
|
NL_SET_ERR_MSG(extack,
|
||||||
|
"Registration to specific type not supported");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To support Pre Association Security Negotiation (PASN), registration
|
||||||
|
* for authentication frames should be supported. However, as some
|
||||||
|
* versions of the user space daemons wrongly register to all types of
|
||||||
|
* authentication frames (which might result in unexpected behavior)
|
||||||
|
* allow such registration if the request is for a specific
|
||||||
|
* authentication algorithm number.
|
||||||
|
*/
|
||||||
|
if (wdev->iftype == NL80211_IFTYPE_STATION &&
|
||||||
|
(frame_type & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_AUTH &&
|
||||||
|
!(match_data && match_len >= 2)) {
|
||||||
|
NL_SET_ERR_MSG(extack,
|
||||||
|
"Authentication algorithm number required");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
|
nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
|
||||||
if (!nreg)
|
if (!nreg)
|
||||||
@ -504,6 +528,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (memcmp(reg->match, match_data, mlen) == 0) {
|
if (memcmp(reg->match, match_data, mlen) == 0) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Match already configured");
|
||||||
err = -EALREADY;
|
err = -EALREADY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -321,6 +321,13 @@ he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
|
|||||||
NLA_POLICY_RANGE(NLA_U8, 1, 20),
|
NLA_POLICY_RANGE(NLA_U8, 1, 20),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct nla_policy
|
||||||
|
he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
|
||||||
|
[NL80211_HE_BSS_COLOR_ATTR_COLOR] = NLA_POLICY_RANGE(NLA_U8, 1, 63),
|
||||||
|
[NL80211_HE_BSS_COLOR_ATTR_DISABLED] = { .type = NLA_FLAG },
|
||||||
|
[NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
|
||||||
|
};
|
||||||
|
|
||||||
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||||
[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
|
[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
|
||||||
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
|
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
|
||||||
@ -626,6 +633,9 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||||||
[NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
|
[NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
|
||||||
[NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
|
[NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
|
||||||
[NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
|
[NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
|
||||||
|
[NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
|
||||||
|
[NL80211_ATTR_SRC_MAC] = NLA_POLICY_ETH_ADDR,
|
||||||
|
[NL80211_ATTR_DST_MAC] = NLA_POLICY_ETH_ADDR,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* policy for the key attributes */
|
/* policy for the key attributes */
|
||||||
@ -965,6 +975,9 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
|
|||||||
if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
|
if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
|
||||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
|
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
|
||||||
|
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
|
||||||
|
goto nla_put_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
|
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
|
||||||
@ -1886,6 +1899,46 @@ static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
|
||||||
|
struct sk_buff *msg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct nlattr *nested, *nested_akms;
|
||||||
|
const struct wiphy_iftype_akm_suites *iftype_akms;
|
||||||
|
|
||||||
|
if (!rdev->wiphy.num_iftype_akm_suites ||
|
||||||
|
!rdev->wiphy.iftype_akm_suites)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
|
||||||
|
if (!nested)
|
||||||
|
return -ENOBUFS;
|
||||||
|
|
||||||
|
for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
|
||||||
|
nested_akms = nla_nest_start(msg, i + 1);
|
||||||
|
if (!nested_akms)
|
||||||
|
return -ENOBUFS;
|
||||||
|
|
||||||
|
iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
|
||||||
|
|
||||||
|
if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
|
||||||
|
iftype_akms->iftypes_mask))
|
||||||
|
return -ENOBUFS;
|
||||||
|
|
||||||
|
if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
|
||||||
|
sizeof(u32) * iftype_akms->n_akm_suites,
|
||||||
|
iftype_akms->akm_suites)) {
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
nla_nest_end(msg, nested_akms);
|
||||||
|
}
|
||||||
|
|
||||||
|
nla_nest_end(msg, nested);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct nl80211_dump_wiphy_state {
|
struct nl80211_dump_wiphy_state {
|
||||||
s64 filter_wiphy;
|
s64 filter_wiphy;
|
||||||
long start;
|
long start;
|
||||||
@ -2444,6 +2497,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||||||
rdev->wiphy.akm_suites))
|
rdev->wiphy.akm_suites))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
if (nl80211_put_iftype_akm_suites(rdev, msg))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
/* done */
|
/* done */
|
||||||
state->split_start = 0;
|
state->split_start = 0;
|
||||||
break;
|
break;
|
||||||
@ -4512,6 +4568,30 @@ static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nl80211_parse_he_bss_color(struct nlattr *attrs,
|
||||||
|
struct cfg80211_he_bss_color *he_bss_color)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
|
||||||
|
he_bss_color_policy, NULL);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
he_bss_color->color =
|
||||||
|
nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
|
||||||
|
he_bss_color->disabled =
|
||||||
|
nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
|
||||||
|
he_bss_color->partial =
|
||||||
|
nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
|
static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
|
||||||
const u8 *rates)
|
const u8 *rates)
|
||||||
{
|
{
|
||||||
@ -4804,6 +4884,14 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
|
||||||
|
err = nl80211_parse_he_bss_color(
|
||||||
|
info->attrs[NL80211_ATTR_HE_BSS_COLOR],
|
||||||
|
¶ms.he_bss_color);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
nl80211_calculate_ap_params(¶ms);
|
nl80211_calculate_ap_params(¶ms);
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
||||||
@ -10540,7 +10628,8 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
|
|||||||
|
|
||||||
return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
|
return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
|
||||||
nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
|
nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
|
||||||
nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
|
nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
|
||||||
|
info->extack);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
@ -13609,6 +13698,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
|
|||||||
const u8 *buf;
|
const u8 *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
u8 *dest;
|
u8 *dest;
|
||||||
|
u8 src[ETH_ALEN];
|
||||||
u16 proto;
|
u16 proto;
|
||||||
bool noencrypt;
|
bool noencrypt;
|
||||||
int err;
|
int err;
|
||||||
@ -13646,6 +13736,13 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy src address under wdev_lock, as we may copy wdev_address */
|
||||||
|
if (info->attrs[NL80211_ATTR_SRC_MAC])
|
||||||
|
ether_addr_copy(src,
|
||||||
|
nla_data(info->attrs[NL80211_ATTR_SRC_MAC]));
|
||||||
|
else
|
||||||
|
ether_addr_copy(src, wdev_address(wdev));
|
||||||
|
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
|
buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
|
||||||
@ -13656,7 +13753,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
|
|||||||
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
|
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
|
||||||
|
|
||||||
return rdev_tx_control_port(rdev, dev, buf, len,
|
return rdev_tx_control_port(rdev, dev, buf, len,
|
||||||
dest, cpu_to_be16(proto), noencrypt);
|
dest, src, cpu_to_be16(proto), noencrypt);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
@ -15913,7 +16010,8 @@ static int __nl80211_rx_control_port(struct net_device *dev,
|
|||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||||
struct ethhdr *ehdr = eth_hdr(skb);
|
struct ethhdr *ehdr = eth_hdr(skb);
|
||||||
const u8 *addr = ehdr->h_source;
|
const u8 *daddr = ehdr->h_dest;
|
||||||
|
const u8 *saddr = ehdr->h_source;
|
||||||
u16 proto = be16_to_cpu(skb->protocol);
|
u16 proto = be16_to_cpu(skb->protocol);
|
||||||
struct sk_buff *msg;
|
struct sk_buff *msg;
|
||||||
void *hdr;
|
void *hdr;
|
||||||
@ -15938,7 +16036,8 @@ static int __nl80211_rx_control_port(struct net_device *dev,
|
|||||||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
|
nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
|
||||||
nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
|
nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
|
||||||
NL80211_ATTR_PAD) ||
|
NL80211_ATTR_PAD) ||
|
||||||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
|
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, saddr) ||
|
||||||
|
nla_put(msg, NL80211_ATTR_DST_MAC, ETH_ALEN, daddr) ||
|
||||||
nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
|
nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
|
||||||
(unencrypted && nla_put_flag(msg,
|
(unencrypted && nla_put_flag(msg,
|
||||||
NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
|
NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
|
||||||
|
@ -734,14 +734,14 @@ static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev,
|
|||||||
static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev,
|
static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev,
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
const void *buf, size_t len,
|
const void *buf, size_t len,
|
||||||
const u8 *dest, __be16 proto,
|
const u8 *dest, const u8 *src,
|
||||||
const bool noencrypt)
|
__be16 proto, const bool noencrypt)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,
|
trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,
|
||||||
dest, proto, noencrypt);
|
dest, src, proto, noencrypt);
|
||||||
ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,
|
ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,
|
||||||
dest, proto, noencrypt);
|
dest, src, proto, noencrypt);
|
||||||
trace_rdev_return_int(&rdev->wiphy, ret);
|
trace_rdev_return_int(&rdev->wiphy, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1569,6 +1569,8 @@ static u32 map_regdom_flags(u32 rd_flags)
|
|||||||
channel_flags |= IEEE80211_CHAN_NO_80MHZ;
|
channel_flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||||
if (rd_flags & NL80211_RRF_NO_160MHZ)
|
if (rd_flags & NL80211_RRF_NO_160MHZ)
|
||||||
channel_flags |= IEEE80211_CHAN_NO_160MHZ;
|
channel_flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||||
|
if (rd_flags & NL80211_RRF_NO_HE)
|
||||||
|
channel_flags |= IEEE80211_CHAN_NO_HE;
|
||||||
return channel_flags;
|
return channel_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1928,27 +1928,31 @@ TRACE_EVENT(rdev_mgmt_tx,
|
|||||||
|
|
||||||
TRACE_EVENT(rdev_tx_control_port,
|
TRACE_EVENT(rdev_tx_control_port,
|
||||||
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
|
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
|
||||||
const u8 *buf, size_t len, const u8 *dest, __be16 proto,
|
const u8 *buf, size_t len,
|
||||||
|
const u8 *dest, const u8 *src, __be16 proto,
|
||||||
bool unencrypted),
|
bool unencrypted),
|
||||||
TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted),
|
TP_ARGS(wiphy, netdev, buf, len, dest, src, proto, unencrypted),
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
WIPHY_ENTRY
|
WIPHY_ENTRY
|
||||||
NETDEV_ENTRY
|
NETDEV_ENTRY
|
||||||
MAC_ENTRY(dest)
|
MAC_ENTRY(dest)
|
||||||
__field(__be16, proto)
|
MAC_ENTRY(src)
|
||||||
|
__field(u16, proto)
|
||||||
__field(bool, unencrypted)
|
__field(bool, unencrypted)
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
NETDEV_ASSIGN;
|
NETDEV_ASSIGN;
|
||||||
MAC_ASSIGN(dest, dest);
|
MAC_ASSIGN(dest, dest);
|
||||||
__entry->proto = proto;
|
MAC_ASSIGN(src, src);
|
||||||
|
__entry->proto = be16_to_cpu(proto);
|
||||||
__entry->unencrypted = unencrypted;
|
__entry->unencrypted = unencrypted;
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ","
|
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", dest: " MAC_PR_FMT
|
||||||
" proto: 0x%x, unencrypted: %s",
|
", src: " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
|
||||||
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest),
|
WIPHY_PR_ARG, NETDEV_PR_ARG,
|
||||||
be16_to_cpu(__entry->proto),
|
MAC_PR_ARG(dest), MAC_PR_ARG(src),
|
||||||
|
__entry->proto,
|
||||||
BOOL_TO_STR(__entry->unencrypted))
|
BOOL_TO_STR(__entry->unencrypted))
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2840,6 +2844,7 @@ TRACE_EVENT(cfg80211_rx_control_port,
|
|||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
NETDEV_ENTRY
|
NETDEV_ENTRY
|
||||||
__field(int, len)
|
__field(int, len)
|
||||||
|
MAC_ENTRY(to)
|
||||||
MAC_ENTRY(from)
|
MAC_ENTRY(from)
|
||||||
__field(u16, proto)
|
__field(u16, proto)
|
||||||
__field(bool, unencrypted)
|
__field(bool, unencrypted)
|
||||||
@ -2847,12 +2852,14 @@ TRACE_EVENT(cfg80211_rx_control_port,
|
|||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
NETDEV_ASSIGN;
|
NETDEV_ASSIGN;
|
||||||
__entry->len = skb->len;
|
__entry->len = skb->len;
|
||||||
|
MAC_ASSIGN(to, eth_hdr(skb)->h_dest);
|
||||||
MAC_ASSIGN(from, eth_hdr(skb)->h_source);
|
MAC_ASSIGN(from, eth_hdr(skb)->h_source);
|
||||||
__entry->proto = be16_to_cpu(skb->protocol);
|
__entry->proto = be16_to_cpu(skb->protocol);
|
||||||
__entry->unencrypted = unencrypted;
|
__entry->unencrypted = unencrypted;
|
||||||
),
|
),
|
||||||
TP_printk(NETDEV_PR_FMT ", len=%d, " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
|
TP_printk(NETDEV_PR_FMT ", len=%d, dest: " MAC_PR_FMT
|
||||||
NETDEV_PR_ARG, __entry->len, MAC_PR_ARG(from),
|
", src: " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
|
||||||
|
NETDEV_PR_ARG, __entry->len, MAC_PR_ARG(to), MAC_PR_ARG(from),
|
||||||
__entry->proto, BOOL_TO_STR(__entry->unencrypted))
|
__entry->proto, BOOL_TO_STR(__entry->unencrypted))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user