mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +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);
|
||||
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
if (arvif->txpower <= 0)
|
||||
/* txpower not initialized yet? */
|
||||
if (arvif->txpower == INT_MIN)
|
||||
continue;
|
||||
|
||||
if (txpower == -1)
|
||||
|
@ -1196,6 +1196,9 @@ static void ath9k_tpc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
int *power = data;
|
||||
|
||||
if (vif->bss_conf.txpower == INT_MIN)
|
||||
return;
|
||||
|
||||
if (*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) {
|
||||
struct ieee80211_vif *vif = tx_info->control.vif;
|
||||
|
||||
if (vif->bss_conf.txpower == INT_MIN)
|
||||
goto nonvifpower;
|
||||
txpower = 2 * vif->bss_conf.txpower;
|
||||
} else {
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_softc *sc;
|
||||
nonvifpower:
|
||||
sc = hw->priv;
|
||||
|
||||
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 = {
|
||||
.sta_id = sta_id,
|
||||
.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,
|
||||
.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, \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_freq), \
|
||||
.max_power = 20, \
|
||||
}
|
||||
|
||||
#define CHAN5G(_freq) { \
|
||||
.band = NL80211_BAND_5GHZ, \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_freq), \
|
||||
.max_power = 20, \
|
||||
}
|
||||
|
||||
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,
|
||||
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))
|
||||
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, SIGNAL_DBM);
|
||||
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);
|
||||
if (rctbl)
|
||||
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
|
||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||
|
||||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
|
||||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @fc: frame control field in little-endian byteorder
|
||||
@ -2047,13 +2056,13 @@ ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
|
||||
#define IEEE80211_HE_OPERATION_ER_SU_DISABLE 0x00010000
|
||||
#define IEEE80211_HE_OPERATION_6GHZ_OP_INFO 0x00020000
|
||||
#define IEEE80211_HE_OPERATION_BSS_COLOR_MASK 0x3f000000
|
||||
#define IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET 24
|
||||
#define IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET 24
|
||||
#define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR 0x40000000
|
||||
#define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED 0x80000000
|
||||
|
||||
/*
|
||||
* 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
|
||||
* sizeof(struct ieee80211_he_operation) bytes, the caller must have
|
||||
* 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
|
||||
* @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
|
||||
* sizeof(struct ieee80211_he_spr) bytes, the caller must have validated
|
||||
* this
|
||||
@ -2523,6 +2532,7 @@ enum ieee80211_eid {
|
||||
WLAN_EID_FILS_INDICATION = 240,
|
||||
WLAN_EID_DILS = 241,
|
||||
WLAN_EID_FRAGMENT = 242,
|
||||
WLAN_EID_RSNX = 244,
|
||||
WLAN_EID_EXTENSION = 255
|
||||
};
|
||||
|
||||
@ -2734,7 +2744,7 @@ enum ieee80211_tdls_actioncode {
|
||||
*/
|
||||
#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_PEER_PSM BIT(5)
|
||||
#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_FT_FILS_SHA256 SUITE(0x000FAC, 16)
|
||||
#define WLAN_AKM_SUITE_FT_FILS_SHA384 SUITE(0x000FAC, 17)
|
||||
#define WLAN_AKM_SUITE_OWE SUITE(0x000FAC, 18)
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
@ -95,6 +95,7 @@ struct wiphy;
|
||||
* on this channel.
|
||||
* @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted
|
||||
* on this channel.
|
||||
* @IEEE80211_CHAN_NO_HE: HE operation is not permitted on this channel.
|
||||
*
|
||||
*/
|
||||
enum ieee80211_channel_flags {
|
||||
@ -111,6 +112,7 @@ enum ieee80211_channel_flags {
|
||||
IEEE80211_CHAN_IR_CONCURRENT = 1<<10,
|
||||
IEEE80211_CHAN_NO_20MHZ = 1<<11,
|
||||
IEEE80211_CHAN_NO_10MHZ = 1<<12,
|
||||
IEEE80211_CHAN_NO_HE = 1<<13,
|
||||
};
|
||||
|
||||
#define IEEE80211_CHAN_NO_HT40 \
|
||||
@ -259,6 +261,32 @@ struct ieee80211_he_obss_pd {
|
||||
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
|
||||
*
|
||||
@ -990,6 +1018,7 @@ enum cfg80211_ap_settings_flags {
|
||||
* @twt_responder: Enable Target Wait Time
|
||||
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
|
||||
* @he_obss_pd: OBSS Packet Detection settings
|
||||
* @he_bss_color: BSS Color settings
|
||||
*/
|
||||
struct cfg80211_ap_settings {
|
||||
struct cfg80211_chan_def chandef;
|
||||
@ -1018,6 +1047,7 @@ struct cfg80211_ap_settings {
|
||||
bool twt_responder;
|
||||
u32 flags;
|
||||
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,
|
||||
struct net_device *dev,
|
||||
const u8 *buf, size_t len,
|
||||
const u8 *dest, const __be16 proto,
|
||||
const u8 *dest, const u8 *src,
|
||||
const __be16 proto,
|
||||
const bool noencrypt);
|
||||
|
||||
int (*get_ftm_responder_stats)(struct wiphy *wiphy,
|
||||
@ -4375,6 +4406,21 @@ struct cfg80211_pmsr_capabilities {
|
||||
} 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
|
||||
* @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.
|
||||
* @cipher_suites: 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
|
||||
* @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_long: Retry limit for long frames (dot11LongRetryLimit)
|
||||
* @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
|
||||
@ -4595,6 +4649,9 @@ struct wiphy {
|
||||
int n_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_long;
|
||||
u32 frag_threshold;
|
||||
@ -4687,6 +4744,8 @@ struct wiphy {
|
||||
u32 txq_memory_limit;
|
||||
u32 txq_quantum;
|
||||
|
||||
unsigned long tx_queue_len;
|
||||
|
||||
u8 support_mbssid:1,
|
||||
support_only_he_mbssid:1;
|
||||
|
||||
|
@ -316,6 +316,7 @@ struct ieee80211_vif_chanctx_switch {
|
||||
* functionality changed for this BSS (AP mode).
|
||||
* @BSS_CHANGED_TWT: TWT 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 {
|
||||
@ -348,6 +349,7 @@ enum ieee80211_bss_change {
|
||||
BSS_CHANGED_FTM_RESPONDER = 1<<26,
|
||||
BSS_CHANGED_TWT = 1<<27,
|
||||
BSS_CHANGED_HE_OBSS_PD = 1<<28,
|
||||
BSS_CHANGED_HE_BSS_COLOR = 1<<29,
|
||||
|
||||
/* 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
|
||||
* 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
|
||||
* @multi_sta_back_32bit: supports BA bitmap of 32-bits in Multi-STA BACK
|
||||
* @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_len: Length of SSID given in @ssid.
|
||||
* @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
|
||||
* Power Control (TPC) in lower driver for the current vif. In particular
|
||||
* 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.
|
||||
* @he_operation: HE operation information of the AP we are connected to
|
||||
* @he_obss_pd: OBSS Packet Detection parameters.
|
||||
* @he_bss_color: BSS coloring settings, if BSS supports HE
|
||||
*/
|
||||
struct ieee80211_bss_conf {
|
||||
const u8 *bssid;
|
||||
u8 bss_color;
|
||||
u8 htc_trig_based_pkt_ext;
|
||||
bool multi_sta_back_32bit;
|
||||
bool uora_exists;
|
||||
@ -667,6 +668,7 @@ struct ieee80211_bss_conf {
|
||||
u8 profile_periodicity;
|
||||
struct ieee80211_he_operation he_operation;
|
||||
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_FAST_XMIT = BIT(4),
|
||||
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,
|
||||
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
|
||||
*
|
||||
@ -6479,5 +6502,16 @@ u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
|
||||
u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_info *info,
|
||||
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 */
|
||||
|
@ -1039,11 +1039,14 @@
|
||||
* a control port frame and as a notification that a control port frame
|
||||
* has been received. %NL80211_ATTR_FRAME is used to specify the
|
||||
* 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,
|
||||
* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added
|
||||
* indicating the protocol type of the received frame; whether the frame
|
||||
* 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.
|
||||
*
|
||||
@ -2400,6 +2403,18 @@ enum nl80211_commands {
|
||||
* @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key
|
||||
* (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
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@ -2864,6 +2879,13 @@ enum nl80211_attrs {
|
||||
|
||||
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 */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@ -3583,6 +3605,8 @@ enum nl80211_wmm_rule {
|
||||
* @NL80211_FREQUENCY_ATTR_WMM: this channel has wmm limitations.
|
||||
* This is a nested attribute that contains the wmm limitation per AC.
|
||||
* (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
|
||||
* currently defined
|
||||
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
|
||||
@ -3612,6 +3636,7 @@ enum nl80211_frequency_attr {
|
||||
NL80211_FREQUENCY_ATTR_NO_20MHZ,
|
||||
NL80211_FREQUENCY_ATTR_NO_10MHZ,
|
||||
NL80211_FREQUENCY_ATTR_WMM,
|
||||
NL80211_FREQUENCY_ATTR_NO_HE,
|
||||
|
||||
/* keep 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_80MHZ: 80MHz operation not allowed
|
||||
* @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed
|
||||
* @NL80211_RRF_NO_HE: HE operation not allowed
|
||||
*/
|
||||
enum nl80211_reg_rule_flags {
|
||||
NL80211_RRF_NO_OFDM = 1<<0,
|
||||
@ -3826,6 +3852,7 @@ enum nl80211_reg_rule_flags {
|
||||
NL80211_RRF_NO_HT40PLUS = 1<<14,
|
||||
NL80211_RRF_NO_80MHZ = 1<<15,
|
||||
NL80211_RRF_NO_160MHZ = 1<<16,
|
||||
NL80211_RRF_NO_HE = 1<<17,
|
||||
};
|
||||
|
||||
#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
|
||||
* 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.
|
||||
* @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_VLAN_OFFLOAD,
|
||||
NL80211_EXT_FEATURE_AQL,
|
||||
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS,
|
||||
|
||||
/* add new features before the definition below */
|
||||
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,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
@ -74,6 +74,8 @@
|
||||
#include <linux/socket.h> /* for "struct sockaddr" et al */
|
||||
#include <linux/if.h> /* for IFNAMSIZ and co... */
|
||||
|
||||
#include <stddef.h> /* for offsetof */
|
||||
|
||||
/***************************** VERSION *****************************/
|
||||
/*
|
||||
* 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
|
||||
* the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
|
||||
* we omit the pointer, so start at an offset. */
|
||||
#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
|
||||
(char *) NULL)
|
||||
#define IW_EV_POINT_OFF offsetof(struct iw_point, length)
|
||||
#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
|
||||
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_TXPOWER |
|
||||
BSS_CHANGED_TWT |
|
||||
BSS_CHANGED_HE_OBSS_PD;
|
||||
BSS_CHANGED_HE_OBSS_PD |
|
||||
BSS_CHANGED_HE_BSS_COLOR;
|
||||
int err;
|
||||
int prev_beacon_int;
|
||||
|
||||
@ -989,20 +990,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
if (old)
|
||||
return -EALREADY;
|
||||
|
||||
switch (params->smps_mode) {
|
||||
case NL80211_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;
|
||||
if (params->smps_mode != NL80211_SMPS_OFF)
|
||||
return -ENOTSUPP;
|
||||
|
||||
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
||||
|
||||
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;
|
||||
memcpy(&sdata->vif.bss_conf.he_obss_pd, ¶ms->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;
|
||||
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);
|
||||
if (old_probe_resp)
|
||||
kfree_rcu(old_probe_resp, rcu_head);
|
||||
sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
|
||||
|
||||
kfree(sdata->vif.bss_conf.ftmr_params);
|
||||
sdata->vif.bss_conf.ftmr_params = NULL;
|
||||
@ -1691,20 +1683,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
|
||||
|
||||
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 &&
|
||||
params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
|
||||
ieee80211_recalc_ps(local);
|
||||
@ -2636,74 +2614,6 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy,
|
||||
}
|
||||
#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,
|
||||
enum ieee80211_smps_mode smps_mode)
|
||||
{
|
||||
|
@ -150,6 +150,59 @@ static const struct file_operations aqm_ops = {
|
||||
.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,
|
||||
char __user *user_buf,
|
||||
size_t count,
|
||||
@ -522,8 +575,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
|
||||
if (local->ops->wake_tx_queue)
|
||||
DEBUGFS_ADD_MODE(aqm, 0600);
|
||||
|
||||
debugfs_create_u16("airtime_flags", 0600,
|
||||
phyd, &local->airtime_flags);
|
||||
DEBUGFS_ADD_MODE(airtime_flags, 0600);
|
||||
|
||||
DEBUGFS_ADD(aql_txq_limit);
|
||||
debugfs_create_u32("aql_threshold", 0600,
|
||||
|
@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -254,15 +255,11 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
||||
smps_mode == IEEE80211_SMPS_AUTOMATIC))
|
||||
return -EINVAL;
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
|
||||
sdata->vif.type != NL80211_IFTYPE_AP)
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
sdata_lock(sdata);
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
err = __ieee80211_request_smps_mgd(sdata, smps_mode);
|
||||
else
|
||||
err = __ieee80211_request_smps_ap(sdata, smps_mode);
|
||||
err = __ieee80211_request_smps_mgd(sdata, smps_mode);
|
||||
sdata_unlock(sdata);
|
||||
|
||||
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",
|
||||
smps_modes[sdata->u.mgd.req_smps],
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1025,12 +1025,10 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
|
||||
DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments);
|
||||
DEBUGFS_ADD_COUNTER(tx_filtered, status_stats.filtered);
|
||||
|
||||
if (local->ops->wake_tx_queue)
|
||||
if (local->ops->wake_tx_queue) {
|
||||
DEBUGFS_ADD(aqm);
|
||||
|
||||
if (wiphy_ext_feature_isset(local->hw.wiphy,
|
||||
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
|
||||
DEBUGFS_ADD(airtime);
|
||||
}
|
||||
|
||||
if (wiphy_ext_feature_isset(local->hw.wiphy,
|
||||
NL80211_EXT_FEATURE_AQL))
|
||||
|
@ -3,6 +3,7 @@
|
||||
* HE handling
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2019 - 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#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_cap->has_he = true;
|
||||
|
||||
sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta);
|
||||
sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -9,6 +9,7 @@
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2007-2010, Intel Corporation
|
||||
* Copyright 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#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;
|
||||
bool changed;
|
||||
enum ieee80211_sta_rx_bandwidth bw;
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
|
||||
memset(&ht_cap, 0, sizeof(ht_cap));
|
||||
|
||||
@ -270,24 +270,30 @@ 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 ?
|
||||
IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
|
||||
|
||||
switch ((ht_cap.cap & IEEE80211_HT_CAP_SM_PS)
|
||||
>> IEEE80211_HT_CAP_SM_PS_SHIFT) {
|
||||
case WLAN_HT_CAP_SM_PS_INVALID:
|
||||
case WLAN_HT_CAP_SM_PS_STATIC:
|
||||
smps_mode = IEEE80211_SMPS_STATIC;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DYNAMIC:
|
||||
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DISABLED:
|
||||
smps_mode = IEEE80211_SMPS_OFF;
|
||||
break;
|
||||
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)
|
||||
>> IEEE80211_HT_CAP_SM_PS_SHIFT) {
|
||||
case WLAN_HT_CAP_SM_PS_INVALID:
|
||||
case WLAN_HT_CAP_SM_PS_STATIC:
|
||||
smps_mode = IEEE80211_SMPS_STATIC;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DYNAMIC:
|
||||
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DISABLED:
|
||||
smps_mode = IEEE80211_SMPS_OFF;
|
||||
break;
|
||||
}
|
||||
|
||||
if (smps_mode != sta->sta.smps_mode)
|
||||
changed = true;
|
||||
sta->sta.smps_mode = smps_mode;
|
||||
} else {
|
||||
sta->sta.smps_mode = IEEE80211_SMPS_OFF;
|
||||
}
|
||||
|
||||
if (smps_mode != sta->sta.smps_mode)
|
||||
changed = true;
|
||||
sta->sta.smps_mode = smps_mode;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@ -544,19 +550,6 @@ void ieee80211_request_smps_mgd_work(struct work_struct *work)
|
||||
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,
|
||||
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;
|
||||
ieee80211_queue_work(&sdata->local->hw,
|
||||
&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 */
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef IEEE80211_I_H
|
||||
@ -292,10 +292,7 @@ struct ieee80211_if_ap {
|
||||
|
||||
struct ps_data ps;
|
||||
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;
|
||||
};
|
||||
|
||||
@ -984,6 +981,8 @@ struct ieee80211_sub_if_data {
|
||||
} debugfs;
|
||||
#endif
|
||||
|
||||
bool hw_80211_encap;
|
||||
|
||||
/* must be last, dynamically sized area in this! */
|
||||
struct ieee80211_vif vif;
|
||||
};
|
||||
@ -1473,6 +1472,7 @@ struct ieee802_11_elems {
|
||||
const struct ieee80211_tim_ie *tim;
|
||||
const u8 *challenge;
|
||||
const u8 *rsn;
|
||||
const u8 *rsnx;
|
||||
const u8 *erp_info;
|
||||
const u8 *ext_supp_rates;
|
||||
const u8 *wmm_info;
|
||||
@ -1520,6 +1520,7 @@ struct ieee802_11_elems {
|
||||
u8 tim_len;
|
||||
u8 challenge_len;
|
||||
u8 rsn_len;
|
||||
u8 rsnx_len;
|
||||
u8 ext_supp_rates_len;
|
||||
u8 wmm_info_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);
|
||||
|
||||
/* 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);
|
||||
void ieee80211_iface_exit(void);
|
||||
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);
|
||||
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||
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,
|
||||
struct net_device *dev,
|
||||
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);
|
||||
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||
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,
|
||||
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,
|
||||
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
|
||||
ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
||||
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);
|
||||
int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
|
||||
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_min_chandef(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (c) 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*/
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -824,9 +824,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
ieee80211_ibss_stop(sdata);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
cancel_work_sync(&sdata->u.ap.request_smps_work);
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)
|
||||
break;
|
||||
@ -1205,6 +1202,72 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
|
||||
.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)
|
||||
{
|
||||
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->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||
sdata->vif.bss_conf.idle = true;
|
||||
sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
|
||||
|
||||
sdata->noack_map = 0;
|
||||
sdata->hw_80211_encap = false;
|
||||
|
||||
/* only monitor/p2p-device differ */
|
||||
if (sdata->dev) {
|
||||
@ -1427,10 +1492,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
|
||||
case NL80211_IFTYPE_AP:
|
||||
skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
|
||||
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->u.ap.req_smps = IEEE80211_SMPS_OFF;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
type = NL80211_IFTYPE_STATION;
|
||||
@ -1772,6 +1834,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
||||
if_setup, txqs, 1);
|
||||
if (!ndev)
|
||||
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));
|
||||
|
||||
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;
|
||||
|
||||
ndev->features |= local->hw.netdev_features;
|
||||
ndev->hw_features |= ndev->features &
|
||||
MAC80211_SUPPORTED_FEATURES_TX;
|
||||
|
||||
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,
|
||||
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_CCMP:
|
||||
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_BIP_CMAC_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
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 */
|
||||
if (ret == 1)
|
||||
return 0;
|
||||
|
@ -146,6 +146,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
||||
continue;
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
continue;
|
||||
if (sdata->vif.bss_conf.txpower == INT_MIN)
|
||||
continue;
|
||||
power = min(power, sdata->vif.bss_conf.txpower);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
@ -416,7 +418,20 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
|
||||
},
|
||||
[NL80211_IFTYPE_STATION] = {
|
||||
.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) |
|
||||
BIT(IEEE80211_STYPE_AUTH >> 4) |
|
||||
BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
|
||||
},
|
||||
[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_CONTROL_PORT_OVER_NL80211);
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS);
|
||||
|
||||
if (!ops->hw_scan) {
|
||||
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
|
||||
@ -872,7 +889,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
enum nl80211_band band;
|
||||
int channels, max_bitrates;
|
||||
bool supp_ht, supp_vht, supp_he;
|
||||
netdev_features_t feature_whitelist;
|
||||
struct cfg80211_chan_def dflt_chandef = {};
|
||||
|
||||
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 */
|
||||
feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||
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))
|
||||
if (WARN_ON(hw->netdev_features & ~MAC80211_SUPPORTED_FEATURES))
|
||||
return -EINVAL;
|
||||
|
||||
if (hw->max_report_rates == 0)
|
||||
@ -981,6 +994,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
if (!supp_he)
|
||||
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)
|
||||
continue;
|
||||
|
||||
@ -1184,10 +1202,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
if (!local->hw.weight_multiplier)
|
||||
local->hw.weight_multiplier = 1;
|
||||
|
||||
result = ieee80211_wep_init(local);
|
||||
if (result < 0)
|
||||
wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
|
||||
result);
|
||||
ieee80211_wep_init(local);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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",
|
||||
channel->center_freq, ht_cfreq,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -301,13 +305,18 @@ out:
|
||||
IEEE80211_CHAN_DISABLED)) {
|
||||
if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
|
||||
ret = IEEE80211_STA_DISABLE_HT |
|
||||
IEEE80211_STA_DISABLE_VHT;
|
||||
IEEE80211_STA_DISABLE_VHT |
|
||||
IEEE80211_STA_DISABLE_HE;
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
sdata_info(sdata,
|
||||
"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 |
|
||||
IEEE80211_STA_DISABLE_VHT |
|
||||
IEEE80211_STA_DISABLE_HE |
|
||||
IEEE80211_STA_DISABLE_40MHZ |
|
||||
IEEE80211_STA_DISABLE_80P80MHZ |
|
||||
IEEE80211_STA_DISABLE_160MHZ)) ||
|
||||
@ -616,10 +626,21 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
|
||||
{
|
||||
u8 *pos;
|
||||
const struct ieee80211_sta_he_cap *he_cap = NULL;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
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);
|
||||
if (!he_cap)
|
||||
if (!he_cap || !reg_cap)
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -650,6 +671,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_channel *chan;
|
||||
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);
|
||||
|
||||
@ -800,7 +828,15 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
||||
*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 */
|
||||
pos = skb_put(skb, 2 * sband->n_channels + 2);
|
||||
*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 */
|
||||
if (ieee80211_hw_check(&local->hw, SUPPORTS_ONLY_HE_MULTI_BSSID) &&
|
||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && assoc_data->ie_len) {
|
||||
struct element *elem;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && assoc_data->ie_len &&
|
||||
ext_capa && ext_capa->datalen >= 3)
|
||||
ext_capa->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
|
||||
|
||||
/* if present, add any custom IEs that go before HT */
|
||||
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))
|
||||
return;
|
||||
|
||||
if (ieee80211_is_nullfunc(hdr->frame_control) &&
|
||||
if (ieee80211_is_any_nullfunc(hdr->frame_control) &&
|
||||
sdata->u.mgd.probe_send_count > 0) {
|
||||
if (ack)
|
||||
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) {
|
||||
bss_conf->bss_color =
|
||||
bss_conf->he_bss_color.color =
|
||||
le32_get_bits(elems->he_operation->he_oper_params,
|
||||
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 =
|
||||
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_if_managed *ifmgd;
|
||||
struct ieee80211_rx_status *rx_status = (void *) skb->cb;
|
||||
struct ieee80211_channel *channel;
|
||||
size_t baselen, len = skb->len;
|
||||
|
||||
ifmgd = &sdata->u.mgd;
|
||||
|
||||
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 */
|
||||
|
||||
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_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();
|
||||
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
|
||||
sband->ht_cap.ht_supported) {
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
|
||||
const u8 *ht_oper_ie, *ht_cap_ie;
|
||||
|
||||
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) &&
|
||||
sband->vht_cap.vht_supported) {
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
|
||||
const u8 *vht_oper_ie, *vht_cap;
|
||||
|
||||
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) {
|
||||
vht_oper = NULL;
|
||||
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_VHT;
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||
}
|
||||
|
||||
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)) {
|
||||
const struct cfg80211_bss_ies *ies;
|
||||
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];
|
||||
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 */
|
||||
if (!sband->vht_cap.vht_supported ||
|
||||
local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used ||
|
||||
ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
|
||||
/* also disable HT/VHT/HE if the AP doesn't use WMM */
|
||||
if (!bss->wmm_used) {
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
if (!bss->wmm_used &&
|
||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM))
|
||||
netdev_info(sdata->dev,
|
||||
"disabling VHT as WMM/QoS is not supported by the AP\n");
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||
netdev_info(sdata->dev,
|
||||
"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));
|
||||
@ -5449,6 +5495,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
if (req->flags & ASSOC_REQ_DISABLE_HT) {
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
|
||||
}
|
||||
|
||||
if (req->flags & ASSOC_REQ_DISABLE_VHT)
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/jiffies.h>
|
||||
@ -1450,8 +1450,7 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
|
||||
return RX_CONTINUE;
|
||||
|
||||
if (ieee80211_is_ctl(hdr->frame_control) ||
|
||||
ieee80211_is_nullfunc(hdr->frame_control) ||
|
||||
ieee80211_is_qos_nullfunc(hdr->frame_control) ||
|
||||
ieee80211_is_any_nullfunc(hdr->frame_control) ||
|
||||
is_multicast_ether_addr(hdr->addr1))
|
||||
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
|
||||
* are used only to control station power saving mode.
|
||||
*/
|
||||
if (ieee80211_is_nullfunc(hdr->frame_control) ||
|
||||
ieee80211_is_qos_nullfunc(hdr->frame_control)) {
|
||||
if (ieee80211_is_any_nullfunc(hdr->frame_control)) {
|
||||
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. */
|
||||
if (unlikely(!ieee80211_has_protected(fc) &&
|
||||
!ieee80211_is_nullfunc(fc) &&
|
||||
!ieee80211_is_any_nullfunc(fc) &&
|
||||
ieee80211_is_data(fc) && rx->key))
|
||||
return -EACCES;
|
||||
|
||||
@ -3084,6 +3082,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
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 */
|
||||
switch (mgmt->u.action.u.ht_smps.smps_control) {
|
||||
case WLAN_HT_SMPS_CONTROL_DISABLED:
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -1351,20 +1351,6 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
||||
|
||||
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;
|
||||
|
||||
sta_info_recalc_tim(sta);
|
||||
|
@ -643,8 +643,7 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
|
||||
rcu_read_lock();
|
||||
sdata = ieee80211_sdata_from_skb(local, skb);
|
||||
if (sdata) {
|
||||
if (ieee80211_is_nullfunc(hdr->frame_control) ||
|
||||
ieee80211_is_qos_nullfunc(hdr->frame_control))
|
||||
if (ieee80211_is_any_nullfunc(hdr->frame_control))
|
||||
cfg80211_probe_status(sdata->dev, hdr->addr1,
|
||||
cookie, acked,
|
||||
info->status.ack_signal,
|
||||
@ -888,6 +887,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
||||
int rates_idx;
|
||||
bool send_to_cooked;
|
||||
bool acked;
|
||||
bool noack_success;
|
||||
struct ieee80211_bar *bar;
|
||||
int shift = 0;
|
||||
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);
|
||||
|
||||
acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
||||
noack_success = !!(info->flags &
|
||||
IEEE80211_TX_STAT_NOACK_TRANSMITTED);
|
||||
|
||||
/* mesh Peer Service Period support */
|
||||
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);
|
||||
return;
|
||||
} else {
|
||||
if (!acked)
|
||||
if (!acked && !noack_success)
|
||||
sta->status_stats.retry_failed++;
|
||||
sta->status_stats.retry_count += retry_count;
|
||||
|
||||
if (ieee80211_is_data_present(fc)) {
|
||||
if (!acked)
|
||||
if (!acked && !noack_success)
|
||||
sta->status_stats.msdu_failed[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 (info->flags & IEEE80211_TX_STAT_ACK) {
|
||||
if (acked) {
|
||||
if (sta->status_stats.lost_packets)
|
||||
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))
|
||||
sta->status_stats.last_tdls_pkt_time =
|
||||
jiffies;
|
||||
} else if (noack_success) {
|
||||
/* nothing to do here, do not account as lost */
|
||||
} else {
|
||||
ieee80211_lost_packet(sta, info);
|
||||
}
|
||||
@ -1056,7 +1060,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
||||
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_hw_check(&local->hw, REPORTS_TX_ACK_STATUS) &&
|
||||
!(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);
|
||||
|
||||
if (!acked)
|
||||
if (!acked && !noack_success)
|
||||
sta->status_stats.retry_failed++;
|
||||
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;
|
||||
} else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||
return;
|
||||
} else if (noack_success) {
|
||||
/* nothing to do here, do not account as lost */
|
||||
} else {
|
||||
ieee80211_lost_packet(sta, info);
|
||||
}
|
||||
@ -1198,6 +1204,77 @@ void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)) &&
|
||||
test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
|
||||
!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
|
||||
* 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))
|
||||
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) ||
|
||||
ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
|
||||
vif->type == NL80211_IFTYPE_STATION) &&
|
||||
@ -2360,9 +2361,9 @@ static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
|
||||
skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
|
||||
}
|
||||
|
||||
static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb,
|
||||
struct sta_info **sta_out)
|
||||
int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb,
|
||||
struct sta_info **sta_out)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
@ -3616,6 +3617,9 @@ begin:
|
||||
else
|
||||
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) {
|
||||
struct sta_info *sta = container_of(txq->sta, struct sta_info,
|
||||
sta);
|
||||
@ -3675,6 +3679,7 @@ begin:
|
||||
break;
|
||||
}
|
||||
|
||||
encap_out:
|
||||
IEEE80211_SKB_CB(skb)->control.vif = vif;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 *
|
||||
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
||||
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;
|
||||
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 {
|
||||
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,
|
||||
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_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));
|
||||
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;
|
||||
|
||||
skb->dev = dev;
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* 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_local *local;
|
||||
BUG_ON(!wiphy);
|
||||
|
||||
local = wiphy_priv(wiphy);
|
||||
return &local->hw;
|
||||
@ -891,6 +890,51 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
|
||||
}
|
||||
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
|
||||
_ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
||||
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_LINK_ID:
|
||||
case WLAN_EID_BSS_MAX_IDLE_PERIOD:
|
||||
case WLAN_EID_RSNX:
|
||||
/*
|
||||
* not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
|
||||
* 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))
|
||||
elems->max_idle_period_ie = (void *)pos;
|
||||
break;
|
||||
case WLAN_EID_RSNX:
|
||||
elems->rsnx = pos;
|
||||
elems->rsnx_len = elen;
|
||||
break;
|
||||
case WLAN_EID_EXTENSION:
|
||||
if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
|
||||
elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
|
||||
elems->mu_edca_param_set = (void *)&pos[1];
|
||||
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];
|
||||
}
|
||||
ieee80211_parse_extension_element(calc_crc ?
|
||||
&crc : NULL,
|
||||
elem, elems);
|
||||
break;
|
||||
default:
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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)
|
||||
return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 (sta->sta.rx_nss)
|
||||
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.mcs.rx_mask[0])
|
||||
ht_rx_nss++;
|
||||
@ -493,8 +544,9 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
|
||||
/* FIXME: consider rx_highest? */
|
||||
}
|
||||
|
||||
ht_rx_nss = max(ht_rx_nss, vht_rx_nss);
|
||||
sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss);
|
||||
rx_nss = max(vht_rx_nss, 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,
|
||||
|
@ -22,12 +22,10 @@
|
||||
#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 */
|
||||
get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "ieee80211_i.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,
|
||||
size_t klen, u8 *data, size_t data_len);
|
||||
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);
|
||||
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
|
||||
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_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
|
||||
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
|
||||
|
@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2015 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#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,
|
||||
u16 frame_type, const u8 *match_data,
|
||||
int match_len)
|
||||
int match_len, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct wiphy *wiphy = wdev->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)
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (!nreg)
|
||||
@ -504,6 +528,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
||||
continue;
|
||||
|
||||
if (memcmp(reg->match, match_data, mlen) == 0) {
|
||||
NL_SET_ERR_MSG(extack, "Match already configured");
|
||||
err = -EALREADY;
|
||||
break;
|
||||
}
|
||||
|
@ -321,6 +321,13 @@ he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
|
||||
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] = {
|
||||
[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
|
||||
[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_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_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 */
|
||||
@ -965,6 +975,9 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
|
||||
if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
|
||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
|
||||
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,
|
||||
@ -1886,6 +1899,46 @@ static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
|
||||
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 {
|
||||
s64 filter_wiphy;
|
||||
long start;
|
||||
@ -2444,6 +2497,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
||||
rdev->wiphy.akm_suites))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nl80211_put_iftype_akm_suites(rdev, msg))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
break;
|
||||
@ -4512,6 +4568,30 @@ static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
|
||||
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,
|
||||
const u8 *rates)
|
||||
{
|
||||
@ -4804,6 +4884,14 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||
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);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
||||
@ -10539,8 +10627,9 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
|
||||
nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
|
||||
nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
|
||||
nla_data(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)
|
||||
@ -13609,6 +13698,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
|
||||
const u8 *buf;
|
||||
size_t len;
|
||||
u8 *dest;
|
||||
u8 src[ETH_ALEN];
|
||||
u16 proto;
|
||||
bool noencrypt;
|
||||
int err;
|
||||
@ -13646,6 +13736,13 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
|
||||
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);
|
||||
|
||||
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]);
|
||||
|
||||
return rdev_tx_control_port(rdev, dev, buf, len,
|
||||
dest, cpu_to_be16(proto), noencrypt);
|
||||
dest, src, cpu_to_be16(proto), noencrypt);
|
||||
|
||||
out:
|
||||
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 cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
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);
|
||||
struct sk_buff *msg;
|
||||
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_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
|
||||
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) ||
|
||||
(unencrypted && nla_put_flag(msg,
|
||||
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,
|
||||
struct net_device *dev,
|
||||
const void *buf, size_t len,
|
||||
const u8 *dest, __be16 proto,
|
||||
const bool noencrypt)
|
||||
const u8 *dest, const u8 *src,
|
||||
__be16 proto, const bool noencrypt)
|
||||
{
|
||||
int ret;
|
||||
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,
|
||||
dest, proto, noencrypt);
|
||||
dest, src, proto, noencrypt);
|
||||
trace_rdev_return_int(&rdev->wiphy, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1569,6 +1569,8 @@ static u32 map_regdom_flags(u32 rd_flags)
|
||||
channel_flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||
if (rd_flags & NL80211_RRF_NO_160MHZ)
|
||||
channel_flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||
if (rd_flags & NL80211_RRF_NO_HE)
|
||||
channel_flags |= IEEE80211_CHAN_NO_HE;
|
||||
return channel_flags;
|
||||
}
|
||||
|
||||
|
@ -1928,27 +1928,31 @@ TRACE_EVENT(rdev_mgmt_tx,
|
||||
|
||||
TRACE_EVENT(rdev_tx_control_port,
|
||||
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),
|
||||
TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted),
|
||||
TP_ARGS(wiphy, netdev, buf, len, dest, src, proto, unencrypted),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
NETDEV_ENTRY
|
||||
MAC_ENTRY(dest)
|
||||
__field(__be16, proto)
|
||||
MAC_ENTRY(src)
|
||||
__field(u16, proto)
|
||||
__field(bool, unencrypted)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
NETDEV_ASSIGN;
|
||||
MAC_ASSIGN(dest, dest);
|
||||
__entry->proto = proto;
|
||||
MAC_ASSIGN(src, src);
|
||||
__entry->proto = be16_to_cpu(proto);
|
||||
__entry->unencrypted = unencrypted;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ","
|
||||
" proto: 0x%x, unencrypted: %s",
|
||||
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest),
|
||||
be16_to_cpu(__entry->proto),
|
||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", dest: " MAC_PR_FMT
|
||||
", src: " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
|
||||
WIPHY_PR_ARG, NETDEV_PR_ARG,
|
||||
MAC_PR_ARG(dest), MAC_PR_ARG(src),
|
||||
__entry->proto,
|
||||
BOOL_TO_STR(__entry->unencrypted))
|
||||
);
|
||||
|
||||
@ -2840,6 +2844,7 @@ TRACE_EVENT(cfg80211_rx_control_port,
|
||||
TP_STRUCT__entry(
|
||||
NETDEV_ENTRY
|
||||
__field(int, len)
|
||||
MAC_ENTRY(to)
|
||||
MAC_ENTRY(from)
|
||||
__field(u16, proto)
|
||||
__field(bool, unencrypted)
|
||||
@ -2847,12 +2852,14 @@ TRACE_EVENT(cfg80211_rx_control_port,
|
||||
TP_fast_assign(
|
||||
NETDEV_ASSIGN;
|
||||
__entry->len = skb->len;
|
||||
MAC_ASSIGN(to, eth_hdr(skb)->h_dest);
|
||||
MAC_ASSIGN(from, eth_hdr(skb)->h_source);
|
||||
__entry->proto = be16_to_cpu(skb->protocol);
|
||||
__entry->unencrypted = unencrypted;
|
||||
),
|
||||
TP_printk(NETDEV_PR_FMT ", len=%d, " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
|
||||
NETDEV_PR_ARG, __entry->len, MAC_PR_ARG(from),
|
||||
TP_printk(NETDEV_PR_FMT ", len=%d, dest: " MAC_PR_FMT
|
||||
", 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))
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user