mirror of https://gitee.com/openkylin/linux.git
For this round, we have various things all over the place, notably
* a fix for a race in aggregation, which I want to let bake for a bit longer before sending to stable * some new statistics (ACK RSSI, TXQ) * TXQ configuration * preparations for HE, particularly radiotap * replace confusing "country IE" by "country element" since it's not referring to Ireland Note that I merged net-next to get a fix from mac80211 that got there via net, to apply one patch that would otherwise conflict. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAlsFWnEACgkQB8qZga/f l8Ry2xAAmOLiTrZ8VlZIwzXEoIrr2b7VM0jQsbCLGmBDu82EV4aRRtX9ZeZm9PuR a6t9kvQFyT0/7tInTfv6I9JlNCZpwT9Mc3Ttw2JQgJ9zm/IYsxmWJ4TtjIz7F+AA rqmxdplSCSJUcIVQ/mJ1oINl3p4ewoAv1doxtQx0Ucavb31ROwjVRUX24OJd1SeK YOFSjoTLHcCDS5jaTbzAGwI31F3plHG8NKMLlwGtrYMhN2SmaQV2YU+YTPJuiQbt EGa3MukngxF7ck+D57CJM+OcLrPF4RiuT6pmJHR8as5Yz5u40bgn3wZu361EcmSy wpJKFNsTOJS+nFHS/zMTWiVbB12bBGNWf3rZXUv5yH1TwVf8y8B2p2jrEasmVcjB PgwNcylNJYfqd2W439xwt1ChGAzc388U2yyzMtWmnNQeAAUFMthtjhEv2Vnowxf3 cFvO5okRpVpOP42JB57VZfNoPeeUHnPfrlDl40AwbKUkKeVOom5oJQIi5WMg4nAV +MXooiJStZxMsY1PDyQgE06dL40r2HlmaX0DB/UbbWeVAaJ2c4aS3ptApEWrfedY FDTL0XhfqejPbK2Au/KX64TTj8ID2bGsundM4ErcilOK3Pu63FMv9b0mziBd8jX1 6lJE2oIR8w10dFZG4O5itVE8n6PE2Fgx728480Lsjuz56GVxMB0= =G98y -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-davem-2018-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: For this round, we have various things all over the place, notably * a fix for a race in aggregation, which I want to let bake for a bit longer before sending to stable * some new statistics (ACK RSSI, TXQ) * TXQ configuration * preparations for HE, particularly radiotap * replace confusing "country IE" by "country element" since it's not referring to Ireland Note that I merged net-next to get a fix from mac80211 that got there via net, to apply one patch that would otherwise conflict. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
5ee6ad201e
|
@ -2544,7 +2544,8 @@ static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
struct ieee80211_vif *vif,
|
||||
u16 duration)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
|
|
|
@ -2844,7 +2844,8 @@ static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
struct ieee80211_vif *vif,
|
||||
u16 req_duration)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
|
||||
|
@ -2857,6 +2858,9 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
|
|||
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
|
||||
return;
|
||||
|
||||
if (req_duration > duration)
|
||||
duration = req_duration;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
/* Try really hard to protect the session and hear a beacon */
|
||||
iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500, false);
|
||||
|
|
|
@ -2650,6 +2650,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||
ieee80211_hw_set(hw, AMPDU_AGGREGATION);
|
||||
ieee80211_hw_set(hw, MFP_CAPABLE);
|
||||
ieee80211_hw_set(hw, SIGNAL_DBM);
|
||||
ieee80211_hw_set(hw, SUPPORTS_PS);
|
||||
ieee80211_hw_set(hw, TDLS_WIDER_BW);
|
||||
if (rctbl)
|
||||
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
|
||||
|
|
|
@ -1079,6 +1079,37 @@ struct sta_bss_parameters {
|
|||
u16 beacon_interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_txq_stats - TXQ statistics for this TID
|
||||
* @filled: bitmap of flags using the bits of &enum nl80211_txq_stats to
|
||||
* indicate the relevant values in this struct are filled
|
||||
* @backlog_bytes: total number of bytes currently backlogged
|
||||
* @backlog_packets: total number of packets currently backlogged
|
||||
* @flows: number of new flows seen
|
||||
* @drops: total number of packets dropped
|
||||
* @ecn_marks: total number of packets marked with ECN CE
|
||||
* @overlimit: number of drops due to queue space overflow
|
||||
* @overmemory: number of drops due to memory limit overflow
|
||||
* @collisions: number of hash collisions
|
||||
* @tx_bytes: total number of bytes dequeued
|
||||
* @tx_packets: total number of packets dequeued
|
||||
* @max_flows: maximum number of flows supported
|
||||
*/
|
||||
struct cfg80211_txq_stats {
|
||||
u32 filled;
|
||||
u32 backlog_bytes;
|
||||
u32 backlog_packets;
|
||||
u32 flows;
|
||||
u32 drops;
|
||||
u32 ecn_marks;
|
||||
u32 overlimit;
|
||||
u32 overmemory;
|
||||
u32 collisions;
|
||||
u32 tx_bytes;
|
||||
u32 tx_packets;
|
||||
u32 max_flows;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_tid_stats - per-TID statistics
|
||||
* @filled: bitmap of flags using the bits of &enum nl80211_tid_stats to
|
||||
|
@ -1088,6 +1119,7 @@ struct sta_bss_parameters {
|
|||
* @tx_msdu_retries: number of retries (not counting the first) for
|
||||
* transmitted MSDUs
|
||||
* @tx_msdu_failed: number of failed transmitted MSDUs
|
||||
* @txq_stats: TXQ statistics
|
||||
*/
|
||||
struct cfg80211_tid_stats {
|
||||
u32 filled;
|
||||
|
@ -1095,6 +1127,7 @@ struct cfg80211_tid_stats {
|
|||
u64 tx_msdu;
|
||||
u64 tx_msdu_retries;
|
||||
u64 tx_msdu_failed;
|
||||
struct cfg80211_txq_stats txq_stats;
|
||||
};
|
||||
|
||||
#define IEEE80211_MAX_CHAINS 4
|
||||
|
@ -1151,7 +1184,10 @@ struct cfg80211_tid_stats {
|
|||
* @rx_duration: aggregate PPDU duration(usecs) for all the frames from a peer
|
||||
* @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last
|
||||
* (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs.
|
||||
* Note that this doesn't use the @filled bit, but is used if non-NULL.
|
||||
* @ack_signal: signal strength (in dBm) of the last ACK frame.
|
||||
* @avg_ack_signal: average rssi value of ack packet for the no of msdu's has
|
||||
* been sent.
|
||||
*/
|
||||
struct station_info {
|
||||
u64 filled;
|
||||
|
@ -1195,8 +1231,9 @@ struct station_info {
|
|||
u64 rx_beacon;
|
||||
u64 rx_duration;
|
||||
u8 rx_beacon_signal_avg;
|
||||
struct cfg80211_tid_stats pertid[IEEE80211_NUM_TIDS + 1];
|
||||
struct cfg80211_tid_stats *pertid;
|
||||
s8 ack_signal;
|
||||
s8 avg_ack_signal;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_CFG80211)
|
||||
|
@ -2188,9 +2225,14 @@ struct cfg80211_connect_params {
|
|||
* have to be updated as part of update_connect_params() call.
|
||||
*
|
||||
* @UPDATE_ASSOC_IES: Indicates whether association request IEs are updated
|
||||
* @UPDATE_FILS_ERP_INFO: Indicates that FILS connection parameters (realm,
|
||||
* username, erp sequence number and rrk) are updated
|
||||
* @UPDATE_AUTH_TYPE: Indicates that authentication type is updated
|
||||
*/
|
||||
enum cfg80211_connect_params_changed {
|
||||
UPDATE_ASSOC_IES = BIT(0),
|
||||
UPDATE_FILS_ERP_INFO = BIT(1),
|
||||
UPDATE_AUTH_TYPE = BIT(2),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2201,6 +2243,9 @@ enum cfg80211_connect_params_changed {
|
|||
* @WIPHY_PARAM_RTS_THRESHOLD: wiphy->rts_threshold has changed
|
||||
* @WIPHY_PARAM_COVERAGE_CLASS: coverage class changed
|
||||
* @WIPHY_PARAM_DYN_ACK: dynack has been enabled
|
||||
* @WIPHY_PARAM_TXQ_LIMIT: TXQ packet limit has been changed
|
||||
* @WIPHY_PARAM_TXQ_MEMORY_LIMIT: TXQ memory limit has been changed
|
||||
* @WIPHY_PARAM_TXQ_QUANTUM: TXQ scheduler quantum
|
||||
*/
|
||||
enum wiphy_params_flags {
|
||||
WIPHY_PARAM_RETRY_SHORT = 1 << 0,
|
||||
|
@ -2209,6 +2254,9 @@ enum wiphy_params_flags {
|
|||
WIPHY_PARAM_RTS_THRESHOLD = 1 << 3,
|
||||
WIPHY_PARAM_COVERAGE_CLASS = 1 << 4,
|
||||
WIPHY_PARAM_DYN_ACK = 1 << 5,
|
||||
WIPHY_PARAM_TXQ_LIMIT = 1 << 6,
|
||||
WIPHY_PARAM_TXQ_MEMORY_LIMIT = 1 << 7,
|
||||
WIPHY_PARAM_TXQ_QUANTUM = 1 << 8,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2961,6 +3009,9 @@ struct cfg80211_external_auth_params {
|
|||
*
|
||||
* @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
|
||||
*
|
||||
* @get_txq_stats: Get TXQ stats for interface or phy. If wdev is %NULL, this
|
||||
* function should return phy stats, and interface stats otherwise.
|
||||
*
|
||||
* @set_pmk: configure the PMK to be used for offloaded 802.1X 4-Way handshake.
|
||||
* If not deleted through @del_pmk the PMK remains valid until disconnect
|
||||
* upon which the driver should clear it.
|
||||
|
@ -3262,6 +3313,10 @@ struct cfg80211_ops {
|
|||
struct net_device *dev,
|
||||
const bool enabled);
|
||||
|
||||
int (*get_txq_stats)(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
struct cfg80211_txq_stats *txqstats);
|
||||
|
||||
int (*set_pmk)(struct wiphy *wiphy, struct net_device *dev,
|
||||
const struct cfg80211_pmk_conf *conf);
|
||||
int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
@ -3806,6 +3861,10 @@ struct wiphy_iftype_ext_capab {
|
|||
* bitmap of &enum nl80211_band values. For instance, for
|
||||
* NL80211_BAND_2GHZ, bit 0 would be set
|
||||
* (i.e. BIT(NL80211_BAND_2GHZ)).
|
||||
*
|
||||
* @txq_limit: configuration of internal TX queue frame limit
|
||||
* @txq_memory_limit: configuration internal TX queue memory limit
|
||||
* @txq_quantum: configuration of internal TX queue scheduler quantum
|
||||
*/
|
||||
struct wiphy {
|
||||
/* assign these fields before you register the wiphy */
|
||||
|
@ -3940,6 +3999,10 @@ struct wiphy {
|
|||
|
||||
u8 nan_supported_bands;
|
||||
|
||||
u32 txq_limit;
|
||||
u32 txq_memory_limit;
|
||||
u32 txq_quantum;
|
||||
|
||||
char priv[0] __aligned(NETDEV_ALIGN);
|
||||
};
|
||||
|
||||
|
@ -5362,6 +5425,30 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
|
|||
#define CFG80211_TESTMODE_DUMP(cmd)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct cfg80211_fils_resp_params - FILS connection response params
|
||||
* @kek: KEK derived from a successful FILS connection (may be %NULL)
|
||||
* @kek_len: Length of @fils_kek in octets
|
||||
* @update_erp_next_seq_num: Boolean value to specify whether the value in
|
||||
* @erp_next_seq_num is valid.
|
||||
* @erp_next_seq_num: The next sequence number to use in ERP message in
|
||||
* FILS Authentication. This value should be specified irrespective of the
|
||||
* status for a FILS connection.
|
||||
* @pmk: A new PMK if derived from a successful FILS connection (may be %NULL).
|
||||
* @pmk_len: Length of @pmk in octets
|
||||
* @pmkid: A new PMKID if derived from a successful FILS connection or the PMKID
|
||||
* used for this FILS connection (may be %NULL).
|
||||
*/
|
||||
struct cfg80211_fils_resp_params {
|
||||
const u8 *kek;
|
||||
size_t kek_len;
|
||||
bool update_erp_next_seq_num;
|
||||
u16 erp_next_seq_num;
|
||||
const u8 *pmk;
|
||||
size_t pmk_len;
|
||||
const u8 *pmkid;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_connect_resp_params - Connection response params
|
||||
* @status: Status code, %WLAN_STATUS_SUCCESS for successful connection, use
|
||||
|
@ -5380,17 +5467,7 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
|
|||
* @req_ie_len: Association request IEs length
|
||||
* @resp_ie: Association response IEs (may be %NULL)
|
||||
* @resp_ie_len: Association response IEs length
|
||||
* @fils_kek: KEK derived from a successful FILS connection (may be %NULL)
|
||||
* @fils_kek_len: Length of @fils_kek in octets
|
||||
* @update_erp_next_seq_num: Boolean value to specify whether the value in
|
||||
* @fils_erp_next_seq_num is valid.
|
||||
* @fils_erp_next_seq_num: The next sequence number to use in ERP message in
|
||||
* FILS Authentication. This value should be specified irrespective of the
|
||||
* status for a FILS connection.
|
||||
* @pmk: A new PMK if derived from a successful FILS connection (may be %NULL).
|
||||
* @pmk_len: Length of @pmk in octets
|
||||
* @pmkid: A new PMKID if derived from a successful FILS connection or the PMKID
|
||||
* used for this FILS connection (may be %NULL).
|
||||
* @fils: FILS connection response parameters.
|
||||
* @timeout_reason: Reason for connection timeout. This is used when the
|
||||
* connection fails due to a timeout instead of an explicit rejection from
|
||||
* the AP. %NL80211_TIMEOUT_UNSPECIFIED is used when the timeout reason is
|
||||
|
@ -5406,13 +5483,7 @@ struct cfg80211_connect_resp_params {
|
|||
size_t req_ie_len;
|
||||
const u8 *resp_ie;
|
||||
size_t resp_ie_len;
|
||||
const u8 *fils_kek;
|
||||
size_t fils_kek_len;
|
||||
bool update_erp_next_seq_num;
|
||||
u16 fils_erp_next_seq_num;
|
||||
const u8 *pmk;
|
||||
size_t pmk_len;
|
||||
const u8 *pmkid;
|
||||
struct cfg80211_fils_resp_params fils;
|
||||
enum nl80211_timeout_reason timeout_reason;
|
||||
};
|
||||
|
||||
|
@ -5558,6 +5629,7 @@ cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid,
|
|||
* @req_ie_len: association request IEs length
|
||||
* @resp_ie: association response IEs (may be %NULL)
|
||||
* @resp_ie_len: assoc response IEs length
|
||||
* @fils: FILS related roaming information.
|
||||
*/
|
||||
struct cfg80211_roam_info {
|
||||
struct ieee80211_channel *channel;
|
||||
|
@ -5567,6 +5639,7 @@ struct cfg80211_roam_info {
|
|||
size_t req_ie_len;
|
||||
const u8 *resp_ie;
|
||||
size_t resp_ie_len;
|
||||
struct cfg80211_fils_resp_params fils;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -5648,6 +5721,26 @@ void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
|
|||
struct ieee80211_channel *chan,
|
||||
gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_sinfo_alloc_tid_stats - allocate per-tid statistics.
|
||||
*
|
||||
* @sinfo: the station information
|
||||
* @gfp: allocation flags
|
||||
*/
|
||||
int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_sinfo_release_content - release contents of station info
|
||||
* @sinfo: the station information
|
||||
*
|
||||
* Releases any potentially allocated sub-information of the station
|
||||
* information, but not the struct itself (since it's typically on
|
||||
* the stack.)
|
||||
*/
|
||||
static inline void cfg80211_sinfo_release_content(struct station_info *sinfo)
|
||||
{
|
||||
kfree(sinfo->pertid);
|
||||
}
|
||||
|
||||
/**
|
||||
* cfg80211_new_sta - notify userspace about station
|
||||
|
|
|
@ -3378,6 +3378,8 @@ enum ieee80211_reconfig_type {
|
|||
* frame in case that no beacon was heard from the AP/P2P GO.
|
||||
* The callback will be called before each transmission and upon return
|
||||
* mac80211 will transmit the frame right away.
|
||||
* If duration is greater than zero, mac80211 hints to the driver the
|
||||
* duration for which the operation is requested.
|
||||
* The callback is optional and can (should!) sleep.
|
||||
*
|
||||
* @mgd_protect_tdls_discover: Protect a TDLS discovery session. After sending
|
||||
|
@ -3697,7 +3699,8 @@ struct ieee80211_ops {
|
|||
u32 sset, u8 *data);
|
||||
|
||||
void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
struct ieee80211_vif *vif,
|
||||
u16 duration);
|
||||
|
||||
void (*mgd_protect_tdls_discover)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
@ -4449,6 +4452,19 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|||
*/
|
||||
u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_csa_set_counter - request mac80211 to set csa counter
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @counter: the new value for the counter
|
||||
*
|
||||
* The csa counter can be changed by the device, this API should be
|
||||
* used by the device driver to update csa counter in mac80211.
|
||||
*
|
||||
* It should never be used together with ieee80211_csa_update_counter(),
|
||||
* as it will cause a race condition around the counter value.
|
||||
*/
|
||||
void ieee80211_csa_set_counter(struct ieee80211_vif *vif, u8 counter);
|
||||
|
||||
/**
|
||||
* ieee80211_csa_finish - notify mac80211 about channel switch
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
* Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
|
||||
* Copyright 2008 Colin McCabe <colin@cozybit.com>
|
||||
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -203,7 +204,8 @@
|
|||
* FILS shared key authentication offload should be able to construct the
|
||||
* authentication and association frames for FILS shared key authentication and
|
||||
* eventually do a key derivation as per IEEE 802.11ai. The below additional
|
||||
* parameters should be given to driver in %NL80211_CMD_CONNECT.
|
||||
* parameters should be given to driver in %NL80211_CMD_CONNECT and/or in
|
||||
* %NL80211_CMD_UPDATE_CONNECT_PARAMS.
|
||||
* %NL80211_ATTR_FILS_ERP_USERNAME - used to construct keyname_nai
|
||||
* %NL80211_ATTR_FILS_ERP_REALM - used to construct keyname_nai
|
||||
* %NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM - used to construct erp message
|
||||
|
@ -214,7 +216,8 @@
|
|||
* as specified in IETF RFC 6696.
|
||||
*
|
||||
* When FILS shared key authentication is completed, driver needs to provide the
|
||||
* below additional parameters to userspace.
|
||||
* below additional parameters to userspace, which can be either after setting
|
||||
* up a connection or after roaming.
|
||||
* %NL80211_ATTR_FILS_KEK - used for key renewal
|
||||
* %NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM - used in further EAP-RP exchanges
|
||||
* %NL80211_ATTR_PMKID - used to identify the PMKSA used/generated
|
||||
|
@ -2225,6 +2228,16 @@ enum nl80211_commands {
|
|||
* @NL80211_ATTR_NSS: Station's New/updated RX_NSS value notified using this
|
||||
* u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED.
|
||||
*
|
||||
* @NL80211_ATTR_TXQ_STATS: TXQ statistics (nested attribute, see &enum
|
||||
* nl80211_txq_stats)
|
||||
* @NL80211_ATTR_TXQ_LIMIT: Total packet limit for the TXQ queues for this phy.
|
||||
* The smaller of this and the memory limit is enforced.
|
||||
* @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory memory limit (in bytes) for the
|
||||
* TXQ queues for this phy. The smaller of this and the packet limit is
|
||||
* enforced.
|
||||
* @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes
|
||||
* a flow is assigned on each round of the DRR scheduler.
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
|
@ -2659,6 +2672,11 @@ enum nl80211_attrs {
|
|||
|
||||
NL80211_ATTR_CONTROL_PORT_OVER_NL80211,
|
||||
|
||||
NL80211_ATTR_TXQ_STATS,
|
||||
NL80211_ATTR_TXQ_LIMIT,
|
||||
NL80211_ATTR_TXQ_MEMORY_LIMIT,
|
||||
NL80211_ATTR_TXQ_QUANTUM,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
@ -2982,6 +3000,8 @@ enum nl80211_sta_bss_param {
|
|||
* received from the station (u64, usec)
|
||||
* @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment
|
||||
* @NL80211_STA_INFO_ACK_SIGNAL: signal strength of the last ACK frame(u8, dBm)
|
||||
* @NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG: avg signal strength of (data)
|
||||
* ACK frame (s8, dBm)
|
||||
* @__NL80211_STA_INFO_AFTER_LAST: internal
|
||||
* @NL80211_STA_INFO_MAX: highest possible station info attribute
|
||||
*/
|
||||
|
@ -3021,6 +3041,7 @@ enum nl80211_sta_info {
|
|||
NL80211_STA_INFO_RX_DURATION,
|
||||
NL80211_STA_INFO_PAD,
|
||||
NL80211_STA_INFO_ACK_SIGNAL,
|
||||
NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_STA_INFO_AFTER_LAST,
|
||||
|
@ -3038,6 +3059,7 @@ enum nl80211_sta_info {
|
|||
* @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted
|
||||
* MSDUs (u64)
|
||||
* @NL80211_TID_STATS_PAD: attribute used for padding for 64-bit alignment
|
||||
* @NL80211_TID_STATS_TXQ_STATS: TXQ stats (nested attribute)
|
||||
* @NUM_NL80211_TID_STATS: number of attributes here
|
||||
* @NL80211_TID_STATS_MAX: highest numbered attribute here
|
||||
*/
|
||||
|
@ -3048,12 +3070,51 @@ enum nl80211_tid_stats {
|
|||
NL80211_TID_STATS_TX_MSDU_RETRIES,
|
||||
NL80211_TID_STATS_TX_MSDU_FAILED,
|
||||
NL80211_TID_STATS_PAD,
|
||||
NL80211_TID_STATS_TXQ_STATS,
|
||||
|
||||
/* keep last */
|
||||
NUM_NL80211_TID_STATS,
|
||||
NL80211_TID_STATS_MAX = NUM_NL80211_TID_STATS - 1
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_txq_stats - per TXQ statistics attributes
|
||||
* @__NL80211_TXQ_STATS_INVALID: attribute number 0 is reserved
|
||||
* @NUM_NL80211_TXQ_STATS: number of attributes here
|
||||
* @NL80211_TXQ_STATS_BACKLOG_BYTES: number of bytes currently backlogged
|
||||
* @NL80211_TXQ_STATS_BACKLOG_PACKETS: number of packets currently
|
||||
* backlogged
|
||||
* @NL80211_TXQ_STATS_FLOWS: total number of new flows seen
|
||||
* @NL80211_TXQ_STATS_DROPS: total number of packet drops
|
||||
* @NL80211_TXQ_STATS_ECN_MARKS: total number of packet ECN marks
|
||||
* @NL80211_TXQ_STATS_OVERLIMIT: number of drops due to queue space overflow
|
||||
* @NL80211_TXQ_STATS_OVERMEMORY: number of drops due to memory limit overflow
|
||||
* (only for per-phy stats)
|
||||
* @NL80211_TXQ_STATS_COLLISIONS: number of hash collisions
|
||||
* @NL80211_TXQ_STATS_TX_BYTES: total number of bytes dequeued from TXQ
|
||||
* @NL80211_TXQ_STATS_TX_PACKETS: total number of packets dequeued from TXQ
|
||||
* @NL80211_TXQ_STATS_MAX_FLOWS: number of flow buckets for PHY
|
||||
* @NL80211_TXQ_STATS_MAX: highest numbered attribute here
|
||||
*/
|
||||
enum nl80211_txq_stats {
|
||||
__NL80211_TXQ_STATS_INVALID,
|
||||
NL80211_TXQ_STATS_BACKLOG_BYTES,
|
||||
NL80211_TXQ_STATS_BACKLOG_PACKETS,
|
||||
NL80211_TXQ_STATS_FLOWS,
|
||||
NL80211_TXQ_STATS_DROPS,
|
||||
NL80211_TXQ_STATS_ECN_MARKS,
|
||||
NL80211_TXQ_STATS_OVERLIMIT,
|
||||
NL80211_TXQ_STATS_OVERMEMORY,
|
||||
NL80211_TXQ_STATS_COLLISIONS,
|
||||
NL80211_TXQ_STATS_TX_BYTES,
|
||||
NL80211_TXQ_STATS_TX_PACKETS,
|
||||
NL80211_TXQ_STATS_MAX_FLOWS,
|
||||
|
||||
/* keep last */
|
||||
NUM_NL80211_TXQ_STATS,
|
||||
NL80211_TXQ_STATS_MAX = NUM_NL80211_TXQ_STATS - 1
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_mpath_flags - nl80211 mesh path flags
|
||||
*
|
||||
|
@ -3143,6 +3204,29 @@ enum nl80211_band_attr {
|
|||
|
||||
#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
|
||||
|
||||
/**
|
||||
* enum nl80211_wmm_rule - regulatory wmm rule
|
||||
*
|
||||
* @__NL80211_WMMR_INVALID: attribute number 0 is reserved
|
||||
* @NL80211_WMMR_CW_MIN: Minimum contention window slot.
|
||||
* @NL80211_WMMR_CW_MAX: Maximum contention window slot.
|
||||
* @NL80211_WMMR_AIFSN: Arbitration Inter Frame Space.
|
||||
* @NL80211_WMMR_TXOP: Maximum allowed tx operation time.
|
||||
* @nl80211_WMMR_MAX: highest possible wmm rule.
|
||||
* @__NL80211_WMMR_LAST: Internal use.
|
||||
*/
|
||||
enum nl80211_wmm_rule {
|
||||
__NL80211_WMMR_INVALID,
|
||||
NL80211_WMMR_CW_MIN,
|
||||
NL80211_WMMR_CW_MAX,
|
||||
NL80211_WMMR_AIFSN,
|
||||
NL80211_WMMR_TXOP,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_WMMR_LAST,
|
||||
NL80211_WMMR_MAX = __NL80211_WMMR_LAST - 1
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_frequency_attr - frequency attributes
|
||||
* @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved
|
||||
|
@ -3192,6 +3276,9 @@ enum nl80211_band_attr {
|
|||
* on this channel in current regulatory domain.
|
||||
* @NL80211_FREQUENCY_ATTR_NO_10MHZ: 10 MHz operation is not allowed
|
||||
* on this channel in current regulatory domain.
|
||||
* @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_MAX: highest frequency attribute number
|
||||
* currently defined
|
||||
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
|
||||
|
@ -3220,6 +3307,7 @@ enum nl80211_frequency_attr {
|
|||
NL80211_FREQUENCY_ATTR_IR_CONCURRENT,
|
||||
NL80211_FREQUENCY_ATTR_NO_20MHZ,
|
||||
NL80211_FREQUENCY_ATTR_NO_10MHZ,
|
||||
NL80211_FREQUENCY_ATTR_WMM,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
|
||||
|
@ -5040,6 +5128,11 @@ enum nl80211_feature_flags {
|
|||
* "radar detected" event.
|
||||
* @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211: Driver supports sending and
|
||||
* receiving control port frames over nl80211 instead of the netdevice.
|
||||
* @NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT: This Driver support data ack
|
||||
* rssi if firmware support, this flag is to intimate about ack rssi
|
||||
* support to nl80211.
|
||||
* @NL80211_EXT_FEATURE_TXQS: Driver supports FQ-CoDel-enabled intermediate
|
||||
* TXQs.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
|
@ -5072,6 +5165,8 @@ enum nl80211_ext_feature_index {
|
|||
NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN,
|
||||
NL80211_EXT_FEATURE_DFS_OFFLOAD,
|
||||
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211,
|
||||
NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT,
|
||||
NL80211_EXT_FEATURE_TXQS,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
|
|
|
@ -695,7 +695,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
if (sta) {
|
||||
ret = 0;
|
||||
memcpy(mac, sta->sta.addr, ETH_ALEN);
|
||||
sta_set_sinfo(sta, sinfo);
|
||||
sta_set_sinfo(sta, sinfo, true);
|
||||
}
|
||||
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
@ -724,7 +724,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
sta = sta_info_get_bss(sdata, mac);
|
||||
if (sta) {
|
||||
ret = 0;
|
||||
sta_set_sinfo(sta, sinfo);
|
||||
sta_set_sinfo(sta, sinfo, true);
|
||||
}
|
||||
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
@ -2376,6 +2376,11 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
|
|||
(WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
|
||||
|
||||
if (changed & (WIPHY_PARAM_TXQ_LIMIT |
|
||||
WIPHY_PARAM_TXQ_MEMORY_LIMIT |
|
||||
WIPHY_PARAM_TXQ_QUANTUM))
|
||||
ieee80211_txq_set_params(local);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3705,6 +3710,99 @@ static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ieee80211_fill_txq_stats(struct cfg80211_txq_stats *txqstats,
|
||||
struct txq_info *txqi)
|
||||
{
|
||||
if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_BACKLOG_BYTES))) {
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_BACKLOG_BYTES);
|
||||
txqstats->backlog_bytes = txqi->tin.backlog_bytes;
|
||||
}
|
||||
|
||||
if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_BACKLOG_PACKETS))) {
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_BACKLOG_PACKETS);
|
||||
txqstats->backlog_packets = txqi->tin.backlog_packets;
|
||||
}
|
||||
|
||||
if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_FLOWS))) {
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_FLOWS);
|
||||
txqstats->flows = txqi->tin.flows;
|
||||
}
|
||||
|
||||
if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_DROPS))) {
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_DROPS);
|
||||
txqstats->drops = txqi->cstats.drop_count;
|
||||
}
|
||||
|
||||
if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_ECN_MARKS))) {
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_ECN_MARKS);
|
||||
txqstats->ecn_marks = txqi->cstats.ecn_mark;
|
||||
}
|
||||
|
||||
if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_OVERLIMIT))) {
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_OVERLIMIT);
|
||||
txqstats->overlimit = txqi->tin.overlimit;
|
||||
}
|
||||
|
||||
if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_COLLISIONS))) {
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_COLLISIONS);
|
||||
txqstats->collisions = txqi->tin.collisions;
|
||||
}
|
||||
|
||||
if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_TX_BYTES))) {
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_TX_BYTES);
|
||||
txqstats->tx_bytes = txqi->tin.tx_bytes;
|
||||
}
|
||||
|
||||
if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_TX_PACKETS))) {
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_TX_PACKETS);
|
||||
txqstats->tx_packets = txqi->tin.tx_packets;
|
||||
}
|
||||
}
|
||||
|
||||
static int ieee80211_get_txq_stats(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
struct cfg80211_txq_stats *txqstats)
|
||||
{
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
int ret = 0;
|
||||
|
||||
if (!local->ops->wake_tx_queue)
|
||||
return 1;
|
||||
|
||||
spin_lock_bh(&local->fq.lock);
|
||||
rcu_read_lock();
|
||||
|
||||
if (wdev) {
|
||||
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||
if (!sdata->vif.txq) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
ieee80211_fill_txq_stats(txqstats, to_txq_info(sdata->vif.txq));
|
||||
} else {
|
||||
/* phy stats */
|
||||
txqstats->filled |= BIT(NL80211_TXQ_STATS_BACKLOG_PACKETS) |
|
||||
BIT(NL80211_TXQ_STATS_BACKLOG_BYTES) |
|
||||
BIT(NL80211_TXQ_STATS_OVERLIMIT) |
|
||||
BIT(NL80211_TXQ_STATS_OVERMEMORY) |
|
||||
BIT(NL80211_TXQ_STATS_COLLISIONS) |
|
||||
BIT(NL80211_TXQ_STATS_MAX_FLOWS);
|
||||
txqstats->backlog_packets = local->fq.backlog;
|
||||
txqstats->backlog_bytes = local->fq.memory_usage;
|
||||
txqstats->overlimit = local->fq.overlimit;
|
||||
txqstats->overmemory = local->fq.overmemory;
|
||||
txqstats->collisions = local->fq.collisions;
|
||||
txqstats->max_flows = local->fq.flows_cnt;
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
spin_unlock_bh(&local->fq.lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
|
@ -3798,4 +3896,5 @@ const struct cfg80211_ops mac80211_config_ops = {
|
|||
.del_nan_func = ieee80211_del_nan_func,
|
||||
.set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
|
||||
.tx_control_port = ieee80211_tx_control_port,
|
||||
.get_txq_stats = ieee80211_get_txq_stats,
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Portions of this file
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __MAC80211_DRIVER_OPS
|
||||
|
@ -813,7 +814,8 @@ drv_allow_buffered_frames(struct ieee80211_local *local,
|
|||
}
|
||||
|
||||
static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
u16 duration)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
|
@ -821,9 +823,9 @@ static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
|
|||
return;
|
||||
WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
|
||||
|
||||
trace_drv_mgd_prepare_tx(local, sdata);
|
||||
trace_drv_mgd_prepare_tx(local, sdata, duration);
|
||||
if (local->ops->mgd_prepare_tx)
|
||||
local->ops->mgd_prepare_tx(&local->hw, &sdata->vif);
|
||||
local->ops->mgd_prepare_tx(&local->hw, &sdata->vif, duration);
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copied from cfg.c - originally
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2014 Intel Corporation (Author: Johannes Berg)
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This file is GPLv2 as found in COPYING.
|
||||
*/
|
||||
|
@ -106,8 +107,8 @@ static void ieee80211_get_stats(struct net_device *dev,
|
|||
if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
|
||||
goto do_survey;
|
||||
|
||||
sinfo.filled = 0;
|
||||
sta_set_sinfo(sta, &sinfo);
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
sta_set_sinfo(sta, &sinfo, false);
|
||||
|
||||
i = 0;
|
||||
ADD_STA_STATS(sta);
|
||||
|
@ -116,11 +117,11 @@ static void ieee80211_get_stats(struct net_device *dev,
|
|||
|
||||
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))
|
||||
data[i] = 100000 *
|
||||
data[i] = 100000ULL *
|
||||
cfg80211_calculate_bitrate(&sinfo.txrate);
|
||||
i++;
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_RX_BITRATE))
|
||||
data[i] = 100000 *
|
||||
data[i] = 100000ULL *
|
||||
cfg80211_calculate_bitrate(&sinfo.rxrate);
|
||||
i++;
|
||||
|
||||
|
@ -133,8 +134,8 @@ static void ieee80211_get_stats(struct net_device *dev,
|
|||
if (sta->sdata->dev != dev)
|
||||
continue;
|
||||
|
||||
sinfo.filled = 0;
|
||||
sta_set_sinfo(sta, &sinfo);
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
sta_set_sinfo(sta, &sinfo, false);
|
||||
i = 0;
|
||||
ADD_STA_STATS(sta);
|
||||
}
|
||||
|
|
|
@ -301,14 +301,14 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
|
|||
___ieee80211_stop_tx_ba_session(sta, i, reason);
|
||||
mutex_unlock(&sta->ampdu_mlme.mtx);
|
||||
|
||||
/* stopping might queue the work again - so cancel only afterwards */
|
||||
cancel_work_sync(&sta->ampdu_mlme.work);
|
||||
|
||||
/*
|
||||
* In case the tear down is part of a reconfigure due to HW restart
|
||||
* request, it is possible that the low level driver requested to stop
|
||||
* the BA session, so handle it to properly clean tid_tx data.
|
||||
*/
|
||||
if(reason == AGG_STOP_DESTROY_STA) {
|
||||
cancel_work_sync(&sta->ampdu_mlme.work);
|
||||
|
||||
mutex_lock(&sta->ampdu_mlme.mtx);
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
|
||||
struct tid_ampdu_tx *tid_tx =
|
||||
|
@ -321,6 +321,7 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
|
|||
ieee80211_stop_tx_ba_cb(sta, i, tid_tx);
|
||||
}
|
||||
mutex_unlock(&sta->ampdu_mlme.mtx);
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_ba_session_work(struct work_struct *work)
|
||||
|
@ -328,16 +329,11 @@ void ieee80211_ba_session_work(struct work_struct *work)
|
|||
struct sta_info *sta =
|
||||
container_of(work, struct sta_info, ampdu_mlme.work);
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
bool blocked;
|
||||
int tid;
|
||||
|
||||
/*
|
||||
* When this flag is set, new sessions should be
|
||||
* blocked, and existing sessions will be torn
|
||||
* down by the code that set the flag, so this
|
||||
* need not run.
|
||||
*/
|
||||
if (test_sta_flag(sta, WLAN_STA_BLOCK_BA))
|
||||
return;
|
||||
/* When this flag is set, new sessions should be blocked. */
|
||||
blocked = test_sta_flag(sta, WLAN_STA_BLOCK_BA);
|
||||
|
||||
mutex_lock(&sta->ampdu_mlme.mtx);
|
||||
for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
|
||||
|
@ -352,7 +348,8 @@ void ieee80211_ba_session_work(struct work_struct *work)
|
|||
sta, tid, WLAN_BACK_RECIPIENT,
|
||||
WLAN_REASON_UNSPECIFIED, true);
|
||||
|
||||
if (test_and_clear_bit(tid,
|
||||
if (!blocked &&
|
||||
test_and_clear_bit(tid,
|
||||
sta->ampdu_mlme.tid_rx_manage_offl))
|
||||
___ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
|
||||
IEEE80211_MAX_AMPDU_BUF,
|
||||
|
@ -367,7 +364,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
|
|||
spin_lock_bh(&sta->lock);
|
||||
|
||||
tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
|
||||
if (tid_tx) {
|
||||
if (!blocked && tid_tx) {
|
||||
/*
|
||||
* Assign it over to the normal tid_tx array
|
||||
* where it "goes live".
|
||||
|
@ -390,7 +387,8 @@ void ieee80211_ba_session_work(struct work_struct *work)
|
|||
if (!tid_tx)
|
||||
continue;
|
||||
|
||||
if (test_and_clear_bit(HT_AGG_STATE_START_CB, &tid_tx->state))
|
||||
if (!blocked &&
|
||||
test_and_clear_bit(HT_AGG_STATE_START_CB, &tid_tx->state))
|
||||
ieee80211_start_tx_ba_cb(sta, tid, tid_tx);
|
||||
if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state))
|
||||
___ieee80211_stop_tx_ba_session(sta, tid,
|
||||
|
|
|
@ -2012,6 +2012,7 @@ static inline bool ieee80211_can_run_worker(struct ieee80211_local *local)
|
|||
}
|
||||
|
||||
int ieee80211_txq_setup_flows(struct ieee80211_local *local);
|
||||
void ieee80211_txq_set_params(struct ieee80211_local *local);
|
||||
void ieee80211_txq_teardown_flows(struct ieee80211_local *local);
|
||||
void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
|
@ -2020,6 +2021,8 @@ void ieee80211_txq_purge(struct ieee80211_local *local,
|
|||
struct txq_info *txqi);
|
||||
void ieee80211_txq_remove_vlan(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_fill_txq_stats(struct cfg80211_txq_stats *txqstats,
|
||||
struct txq_info *txqi);
|
||||
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
|
||||
u16 transaction, u16 auth_alg, u16 status,
|
||||
const u8 *extra, size_t extra_len, const u8 *bssid,
|
||||
|
|
|
@ -565,6 +565,9 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
|||
if (!ops->set_key)
|
||||
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||
|
||||
if (ops->wake_tx_queue)
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS);
|
||||
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
|
||||
|
||||
wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
|
||||
|
|
|
@ -864,7 +864,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
|||
return;
|
||||
}
|
||||
|
||||
drv_mgd_prepare_tx(local, sdata);
|
||||
drv_mgd_prepare_tx(local, sdata, 0);
|
||||
|
||||
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||
if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
|
||||
|
@ -2022,7 +2022,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
|||
*/
|
||||
if (ieee80211_hw_check(&local->hw, DEAUTH_NEED_MGD_TX_PREP) &&
|
||||
!ifmgd->have_beacon)
|
||||
drv_mgd_prepare_tx(sdata->local, sdata);
|
||||
drv_mgd_prepare_tx(sdata->local, sdata, 0);
|
||||
|
||||
ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype,
|
||||
reason, tx, frame_buf);
|
||||
|
@ -2560,7 +2560,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
|
|||
if (!elems.challenge)
|
||||
return;
|
||||
auth_data->expected_transaction = 4;
|
||||
drv_mgd_prepare_tx(sdata->local, sdata);
|
||||
drv_mgd_prepare_tx(sdata->local, sdata, 0);
|
||||
if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
|
||||
tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
IEEE80211_TX_INTFL_MLME_CONN_TX;
|
||||
|
@ -3769,6 +3769,7 @@ static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
|
|||
u32 tx_flags = 0;
|
||||
u16 trans = 1;
|
||||
u16 status = 0;
|
||||
u16 prepare_tx_duration = 0;
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
|
@ -3790,7 +3791,11 @@ static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
drv_mgd_prepare_tx(local, sdata);
|
||||
if (auth_data->algorithm == WLAN_AUTH_SAE)
|
||||
prepare_tx_duration =
|
||||
jiffies_to_msecs(IEEE80211_AUTH_TIMEOUT_SAE);
|
||||
|
||||
drv_mgd_prepare_tx(local, sdata, prepare_tx_duration);
|
||||
|
||||
sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
|
||||
auth_data->bss->bssid, auth_data->tries,
|
||||
|
@ -4994,7 +4999,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
|||
req->bssid, req->reason_code,
|
||||
ieee80211_get_reason_code_string(req->reason_code));
|
||||
|
||||
drv_mgd_prepare_tx(sdata->local, sdata);
|
||||
drv_mgd_prepare_tx(sdata->local, sdata, 0);
|
||||
ieee80211_send_deauth_disassoc(sdata, req->bssid,
|
||||
IEEE80211_STYPE_DEAUTH,
|
||||
req->reason_code, tx,
|
||||
|
@ -5014,7 +5019,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
|||
req->bssid, req->reason_code,
|
||||
ieee80211_get_reason_code_string(req->reason_code));
|
||||
|
||||
drv_mgd_prepare_tx(sdata->local, sdata);
|
||||
drv_mgd_prepare_tx(sdata->local, sdata, 0);
|
||||
ieee80211_send_deauth_disassoc(sdata, req->bssid,
|
||||
IEEE80211_STYPE_DEAUTH,
|
||||
req->reason_code, tx,
|
||||
|
|
|
@ -5,6 +5,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 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -97,27 +98,27 @@ static u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
|
|||
*/
|
||||
static void remove_monitor_info(struct sk_buff *skb,
|
||||
unsigned int present_fcs_len,
|
||||
unsigned int rtap_vendor_space)
|
||||
unsigned int rtap_space)
|
||||
{
|
||||
if (present_fcs_len)
|
||||
__pskb_trim(skb, skb->len - present_fcs_len);
|
||||
__pskb_pull(skb, rtap_vendor_space);
|
||||
__pskb_pull(skb, rtap_space);
|
||||
}
|
||||
|
||||
static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len,
|
||||
unsigned int rtap_vendor_space)
|
||||
unsigned int rtap_space)
|
||||
{
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
hdr = (void *)(skb->data + rtap_vendor_space);
|
||||
hdr = (void *)(skb->data + rtap_space);
|
||||
|
||||
if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
|
||||
RX_FLAG_FAILED_PLCP_CRC |
|
||||
RX_FLAG_ONLY_MONITOR))
|
||||
return true;
|
||||
|
||||
if (unlikely(skb->len < 16 + present_fcs_len + rtap_vendor_space))
|
||||
if (unlikely(skb->len < 16 + present_fcs_len + rtap_space))
|
||||
return true;
|
||||
|
||||
if (ieee80211_is_ctl(hdr->frame_control) &&
|
||||
|
@ -199,7 +200,7 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
|
|||
|
||||
static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb,
|
||||
int rtap_vendor_space)
|
||||
int rtap_space)
|
||||
{
|
||||
struct {
|
||||
struct ieee80211_hdr_3addr hdr;
|
||||
|
@ -212,14 +213,14 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
BUILD_BUG_ON(sizeof(action) != IEEE80211_MIN_ACTION_SIZE + 1);
|
||||
|
||||
if (skb->len < rtap_vendor_space + sizeof(action) +
|
||||
if (skb->len < rtap_space + sizeof(action) +
|
||||
VHT_MUMIMO_GROUPS_DATA_LEN)
|
||||
return;
|
||||
|
||||
if (!is_valid_ether_addr(sdata->u.mntr.mu_follow_addr))
|
||||
return;
|
||||
|
||||
skb_copy_bits(skb, rtap_vendor_space, &action, sizeof(action));
|
||||
skb_copy_bits(skb, rtap_space, &action, sizeof(action));
|
||||
|
||||
if (!ieee80211_is_action(action.hdr.frame_control))
|
||||
return;
|
||||
|
@ -545,7 +546,7 @@ static struct sk_buff *
|
|||
ieee80211_make_monitor_skb(struct ieee80211_local *local,
|
||||
struct sk_buff **origskb,
|
||||
struct ieee80211_rate *rate,
|
||||
int rtap_vendor_space, bool use_origskb)
|
||||
int rtap_space, bool use_origskb)
|
||||
{
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(*origskb);
|
||||
int rt_hdrlen, needed_headroom;
|
||||
|
@ -553,7 +554,7 @@ ieee80211_make_monitor_skb(struct ieee80211_local *local,
|
|||
|
||||
/* room for the radiotap header based on driver features */
|
||||
rt_hdrlen = ieee80211_rx_radiotap_hdrlen(local, status, *origskb);
|
||||
needed_headroom = rt_hdrlen - rtap_vendor_space;
|
||||
needed_headroom = rt_hdrlen - rtap_space;
|
||||
|
||||
if (use_origskb) {
|
||||
/* only need to expand headroom if necessary */
|
||||
|
@ -607,7 +608,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
struct ieee80211_sub_if_data *sdata;
|
||||
struct sk_buff *monskb = NULL;
|
||||
int present_fcs_len = 0;
|
||||
unsigned int rtap_vendor_space = 0;
|
||||
unsigned int rtap_space = 0;
|
||||
struct ieee80211_sub_if_data *monitor_sdata =
|
||||
rcu_dereference(local->monitor_sdata);
|
||||
bool only_monitor = false;
|
||||
|
@ -615,7 +616,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) {
|
||||
struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data;
|
||||
|
||||
rtap_vendor_space = sizeof(*rtap) + rtap->len + rtap->pad;
|
||||
rtap_space += sizeof(*rtap) + rtap->len + rtap->pad;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -638,13 +639,12 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
}
|
||||
|
||||
/* ensure hdr->frame_control and vendor radiotap data are in skb head */
|
||||
if (!pskb_may_pull(origskb, 2 + rtap_vendor_space)) {
|
||||
if (!pskb_may_pull(origskb, 2 + rtap_space)) {
|
||||
dev_kfree_skb(origskb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
only_monitor = should_drop_frame(origskb, present_fcs_len,
|
||||
rtap_vendor_space);
|
||||
only_monitor = should_drop_frame(origskb, present_fcs_len, rtap_space);
|
||||
|
||||
if (!local->monitors || (status->flag & RX_FLAG_SKIP_MONITOR)) {
|
||||
if (only_monitor) {
|
||||
|
@ -652,12 +652,11 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
remove_monitor_info(origskb, present_fcs_len,
|
||||
rtap_vendor_space);
|
||||
remove_monitor_info(origskb, present_fcs_len, rtap_space);
|
||||
return origskb;
|
||||
}
|
||||
|
||||
ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_vendor_space);
|
||||
ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_space);
|
||||
|
||||
list_for_each_entry_rcu(sdata, &local->mon_list, u.mntr.list) {
|
||||
bool last_monitor = list_is_last(&sdata->u.mntr.list,
|
||||
|
@ -665,8 +664,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
|
||||
if (!monskb)
|
||||
monskb = ieee80211_make_monitor_skb(local, &origskb,
|
||||
rate,
|
||||
rtap_vendor_space,
|
||||
rate, rtap_space,
|
||||
only_monitor &&
|
||||
last_monitor);
|
||||
|
||||
|
@ -698,7 +696,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
if (!origskb)
|
||||
return NULL;
|
||||
|
||||
remove_monitor_info(origskb, present_fcs_len, rtap_vendor_space);
|
||||
remove_monitor_info(origskb, present_fcs_len, rtap_space);
|
||||
return origskb;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,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 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -357,6 +358,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
sta->last_connected = ktime_get_seconds();
|
||||
ewma_signal_init(&sta->rx_stats_avg.signal);
|
||||
ewma_avg_signal_init(&sta->status_stats.avg_ack_signal);
|
||||
for (i = 0; i < ARRAY_SIZE(sta->rx_stats_avg.chain_signal); i++)
|
||||
ewma_signal_init(&sta->rx_stats_avg.chain_signal[i]);
|
||||
|
||||
|
@ -1006,7 +1008,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
|
|||
|
||||
sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
|
||||
if (sinfo)
|
||||
sta_set_sinfo(sta, sinfo);
|
||||
sta_set_sinfo(sta, sinfo, true);
|
||||
cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL);
|
||||
kfree(sinfo);
|
||||
|
||||
|
@ -1992,7 +1994,6 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate,
|
|||
int band = STA_STATS_GET(LEGACY_BAND, rate);
|
||||
int rate_idx = STA_STATS_GET(LEGACY_IDX, rate);
|
||||
|
||||
rinfo->flags = 0;
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
brate = sband->bitrates[rate_idx].bitrate;
|
||||
if (rinfo->bw == RATE_INFO_BW_5)
|
||||
|
@ -2051,6 +2052,18 @@ static void sta_set_tidstats(struct sta_info *sta,
|
|||
tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
|
||||
tidstats->tx_msdu_failed = sta->status_stats.msdu_failed[tid];
|
||||
}
|
||||
|
||||
if (local->ops->wake_tx_queue && tid < IEEE80211_NUM_TIDS) {
|
||||
spin_lock_bh(&local->fq.lock);
|
||||
rcu_read_lock();
|
||||
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_TXQ_STATS);
|
||||
ieee80211_fill_txq_stats(&tidstats->txq_stats,
|
||||
to_txq_info(sta->sta.txq[tid]));
|
||||
|
||||
rcu_read_unlock();
|
||||
spin_unlock_bh(&local->fq.lock);
|
||||
}
|
||||
}
|
||||
|
||||
static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
|
||||
|
@ -2066,7 +2079,8 @@ static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
|
|||
return value;
|
||||
}
|
||||
|
||||
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
||||
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
|
||||
bool tidstats)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
@ -2220,12 +2234,13 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
|
||||
}
|
||||
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TID_STATS);
|
||||
if (tidstats && !cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) {
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
|
||||
struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i];
|
||||
|
||||
sta_set_tidstats(sta, tidstats, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
|
@ -2294,6 +2309,15 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
sinfo->ack_signal = sta->status_stats.last_ack_signal;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
|
||||
}
|
||||
|
||||
if (ieee80211_hw_check(&sta->local->hw, REPORTS_TX_ACK_STATUS) &&
|
||||
!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG))) {
|
||||
sinfo->avg_ack_signal =
|
||||
-(s8)ewma_avg_signal_read(
|
||||
&sta->status_stats.avg_ack_signal);
|
||||
sinfo->filled |=
|
||||
BIT_ULL(NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG);
|
||||
}
|
||||
}
|
||||
|
||||
u32 sta_get_expected_throughput(struct sta_info *sta)
|
||||
|
|
|
@ -119,6 +119,7 @@ enum ieee80211_sta_info_flags {
|
|||
#define HT_AGG_STATE_START_CB 6
|
||||
#define HT_AGG_STATE_STOP_CB 7
|
||||
|
||||
DECLARE_EWMA(avg_signal, 10, 8)
|
||||
enum ieee80211_agg_stop_reason {
|
||||
AGG_STOP_DECLINED,
|
||||
AGG_STOP_LOCAL_REQUEST,
|
||||
|
@ -550,6 +551,7 @@ struct sta_info {
|
|||
unsigned long last_ack;
|
||||
s8 last_ack_signal;
|
||||
bool ack_signal_filled;
|
||||
struct ewma_avg_signal avg_ack_signal;
|
||||
} status_stats;
|
||||
|
||||
/* Updated from TX path only, no locking requirements */
|
||||
|
@ -742,7 +744,8 @@ static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata)
|
|||
void sta_set_rate_info_tx(struct sta_info *sta,
|
||||
const struct ieee80211_tx_rate *rate,
|
||||
struct rate_info *rinfo);
|
||||
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
|
||||
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
|
||||
bool tidstats);
|
||||
|
||||
u32 sta_get_expected_throughput(struct sta_info *sta);
|
||||
|
||||
|
|
|
@ -195,6 +195,8 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
|
|||
sta->status_stats.last_ack_signal =
|
||||
(s8)txinfo->status.ack_signal;
|
||||
sta->status_stats.ack_signal_filled = true;
|
||||
ewma_avg_signal_add(&sta->status_stats.avg_ack_signal,
|
||||
-txinfo->status.ack_signal);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Portions of this file
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
|
||||
|
@ -1413,11 +1414,29 @@ DEFINE_EVENT(release_evt, drv_allow_buffered_frames,
|
|||
TP_ARGS(local, sta, tids, num_frames, reason, more_data)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx,
|
||||
TRACE_EVENT(drv_mgd_prepare_tx,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata),
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
u16 duration),
|
||||
|
||||
TP_ARGS(local, sdata)
|
||||
TP_ARGS(local, sdata, duration),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
VIF_ENTRY
|
||||
__field(u32, duration)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
VIF_ASSIGN;
|
||||
__entry->duration = duration;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT VIF_PR_FMT " duration: %u",
|
||||
LOCAL_PR_ARG, VIF_PR_ARG, __entry->duration
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(local_sdata_evt, drv_mgd_protect_tdls_discover,
|
||||
|
|
|
@ -1460,6 +1460,24 @@ void ieee80211_txq_purge(struct ieee80211_local *local,
|
|||
ieee80211_purge_tx_queue(&local->hw, &txqi->frags);
|
||||
}
|
||||
|
||||
void ieee80211_txq_set_params(struct ieee80211_local *local)
|
||||
{
|
||||
if (local->hw.wiphy->txq_limit)
|
||||
local->fq.limit = local->hw.wiphy->txq_limit;
|
||||
else
|
||||
local->hw.wiphy->txq_limit = local->fq.limit;
|
||||
|
||||
if (local->hw.wiphy->txq_memory_limit)
|
||||
local->fq.memory_limit = local->hw.wiphy->txq_memory_limit;
|
||||
else
|
||||
local->hw.wiphy->txq_memory_limit = local->fq.memory_limit;
|
||||
|
||||
if (local->hw.wiphy->txq_quantum)
|
||||
local->fq.quantum = local->hw.wiphy->txq_quantum;
|
||||
else
|
||||
local->hw.wiphy->txq_quantum = local->fq.quantum;
|
||||
}
|
||||
|
||||
int ieee80211_txq_setup_flows(struct ieee80211_local *local)
|
||||
{
|
||||
struct fq *fq = &local->fq;
|
||||
|
@ -1509,6 +1527,8 @@ int ieee80211_txq_setup_flows(struct ieee80211_local *local)
|
|||
for (i = 0; i < fq->flows_cnt; i++)
|
||||
codel_vars_init(&local->cvars[i]);
|
||||
|
||||
ieee80211_txq_set_params(local);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4085,6 +4105,31 @@ u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_update_counter);
|
||||
|
||||
void ieee80211_csa_set_counter(struct ieee80211_vif *vif, u8 counter)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct beacon_data *beacon = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP)
|
||||
beacon = rcu_dereference(sdata->u.ap.beacon);
|
||||
else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
|
||||
beacon = rcu_dereference(sdata->u.ibss.presp);
|
||||
else if (ieee80211_vif_is_mesh(&sdata->vif))
|
||||
beacon = rcu_dereference(sdata->u.mesh.beacon);
|
||||
|
||||
if (!beacon)
|
||||
goto unlock;
|
||||
|
||||
if (counter < beacon->csa_current_counter)
|
||||
beacon->csa_current_counter = counter;
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_set_counter);
|
||||
|
||||
bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
|
|
|
@ -2793,12 +2793,13 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
|||
|
||||
memset(&ri, 0, sizeof(ri));
|
||||
|
||||
ri.bw = status->bw;
|
||||
|
||||
/* Fill cfg80211 rate info */
|
||||
switch (status->encoding) {
|
||||
case RX_ENC_HT:
|
||||
ri.mcs = status->rate_idx;
|
||||
ri.flags |= RATE_INFO_FLAGS_MCS;
|
||||
ri.bw = status->bw;
|
||||
if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
|
||||
ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
break;
|
||||
|
@ -2806,7 +2807,6 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
|||
ri.flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
ri.mcs = status->rate_idx;
|
||||
ri.nss = status->nss;
|
||||
ri.bw = status->bw;
|
||||
if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
|
||||
ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
break;
|
||||
|
@ -2818,8 +2818,6 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
|||
int shift = 0;
|
||||
int bitrate;
|
||||
|
||||
ri.bw = status->bw;
|
||||
|
||||
switch (status->bw) {
|
||||
case RATE_INFO_BW_10:
|
||||
shift = 1;
|
||||
|
|
|
@ -178,9 +178,10 @@ static void rfkill_led_trigger_unregister(struct rfkill *rfkill)
|
|||
}
|
||||
|
||||
static struct led_trigger rfkill_any_led_trigger;
|
||||
static struct work_struct rfkill_any_work;
|
||||
static struct led_trigger rfkill_none_led_trigger;
|
||||
static struct work_struct rfkill_global_led_trigger_work;
|
||||
|
||||
static void rfkill_any_led_trigger_worker(struct work_struct *work)
|
||||
static void rfkill_global_led_trigger_worker(struct work_struct *work)
|
||||
{
|
||||
enum led_brightness brightness = LED_OFF;
|
||||
struct rfkill *rfkill;
|
||||
|
@ -195,30 +196,43 @@ static void rfkill_any_led_trigger_worker(struct work_struct *work)
|
|||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
led_trigger_event(&rfkill_any_led_trigger, brightness);
|
||||
led_trigger_event(&rfkill_none_led_trigger,
|
||||
brightness == LED_OFF ? LED_FULL : LED_OFF);
|
||||
}
|
||||
|
||||
static void rfkill_any_led_trigger_event(void)
|
||||
static void rfkill_global_led_trigger_event(void)
|
||||
{
|
||||
schedule_work(&rfkill_any_work);
|
||||
schedule_work(&rfkill_global_led_trigger_work);
|
||||
}
|
||||
|
||||
static void rfkill_any_led_trigger_activate(struct led_classdev *led_cdev)
|
||||
static int rfkill_global_led_trigger_register(void)
|
||||
{
|
||||
rfkill_any_led_trigger_event();
|
||||
}
|
||||
int ret;
|
||||
|
||||
INIT_WORK(&rfkill_global_led_trigger_work,
|
||||
rfkill_global_led_trigger_worker);
|
||||
|
||||
static int rfkill_any_led_trigger_register(void)
|
||||
{
|
||||
INIT_WORK(&rfkill_any_work, rfkill_any_led_trigger_worker);
|
||||
rfkill_any_led_trigger.name = "rfkill-any";
|
||||
rfkill_any_led_trigger.activate = rfkill_any_led_trigger_activate;
|
||||
return led_trigger_register(&rfkill_any_led_trigger);
|
||||
ret = led_trigger_register(&rfkill_any_led_trigger);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rfkill_none_led_trigger.name = "rfkill-none";
|
||||
ret = led_trigger_register(&rfkill_none_led_trigger);
|
||||
if (ret)
|
||||
led_trigger_unregister(&rfkill_any_led_trigger);
|
||||
else
|
||||
/* Delay activation until all global triggers are registered */
|
||||
rfkill_global_led_trigger_event();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rfkill_any_led_trigger_unregister(void)
|
||||
static void rfkill_global_led_trigger_unregister(void)
|
||||
{
|
||||
led_trigger_unregister(&rfkill_none_led_trigger);
|
||||
led_trigger_unregister(&rfkill_any_led_trigger);
|
||||
cancel_work_sync(&rfkill_any_work);
|
||||
cancel_work_sync(&rfkill_global_led_trigger_work);
|
||||
}
|
||||
#else
|
||||
static void rfkill_led_trigger_event(struct rfkill *rfkill)
|
||||
|
@ -234,16 +248,16 @@ static inline void rfkill_led_trigger_unregister(struct rfkill *rfkill)
|
|||
{
|
||||
}
|
||||
|
||||
static void rfkill_any_led_trigger_event(void)
|
||||
static void rfkill_global_led_trigger_event(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int rfkill_any_led_trigger_register(void)
|
||||
static int rfkill_global_led_trigger_register(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rfkill_any_led_trigger_unregister(void)
|
||||
static void rfkill_global_led_trigger_unregister(void)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_RFKILL_LEDS */
|
||||
|
@ -354,7 +368,7 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
|
|||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
rfkill_any_led_trigger_event();
|
||||
rfkill_global_led_trigger_event();
|
||||
|
||||
if (prev != curr)
|
||||
rfkill_event(rfkill);
|
||||
|
@ -535,7 +549,7 @@ bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
|
|||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
rfkill_any_led_trigger_event();
|
||||
rfkill_global_led_trigger_event();
|
||||
|
||||
if (rfkill->registered && prev != blocked)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
@ -579,7 +593,7 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked)
|
|||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
rfkill_any_led_trigger_event();
|
||||
rfkill_global_led_trigger_event();
|
||||
|
||||
return blocked;
|
||||
}
|
||||
|
@ -629,7 +643,7 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
|
|||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
rfkill_any_led_trigger_event();
|
||||
rfkill_global_led_trigger_event();
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_set_states);
|
||||
|
@ -1046,7 +1060,7 @@ int __must_check rfkill_register(struct rfkill *rfkill)
|
|||
#endif
|
||||
}
|
||||
|
||||
rfkill_any_led_trigger_event();
|
||||
rfkill_global_led_trigger_event();
|
||||
rfkill_send_events(rfkill, RFKILL_OP_ADD);
|
||||
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
@ -1079,7 +1093,7 @@ void rfkill_unregister(struct rfkill *rfkill)
|
|||
mutex_lock(&rfkill_global_mutex);
|
||||
rfkill_send_events(rfkill, RFKILL_OP_DEL);
|
||||
list_del_init(&rfkill->node);
|
||||
rfkill_any_led_trigger_event();
|
||||
rfkill_global_led_trigger_event();
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
rfkill_led_trigger_unregister(rfkill);
|
||||
|
@ -1332,7 +1346,7 @@ static int __init rfkill_init(void)
|
|||
if (error)
|
||||
goto error_misc;
|
||||
|
||||
error = rfkill_any_led_trigger_register();
|
||||
error = rfkill_global_led_trigger_register();
|
||||
if (error)
|
||||
goto error_led_trigger;
|
||||
|
||||
|
@ -1346,7 +1360,7 @@ static int __init rfkill_init(void)
|
|||
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
error_input:
|
||||
rfkill_any_led_trigger_unregister();
|
||||
rfkill_global_led_trigger_unregister();
|
||||
#endif
|
||||
error_led_trigger:
|
||||
misc_deregister(&rfkill_miscdev);
|
||||
|
@ -1362,7 +1376,7 @@ static void __exit rfkill_exit(void)
|
|||
#ifdef CONFIG_RFKILL_INPUT
|
||||
rfkill_handler_exit();
|
||||
#endif
|
||||
rfkill_any_led_trigger_unregister();
|
||||
rfkill_global_led_trigger_unregister();
|
||||
misc_deregister(&rfkill_miscdev);
|
||||
class_unregister(&rfkill_class);
|
||||
}
|
||||
|
|
|
@ -725,6 +725,10 @@ int wiphy_register(struct wiphy *wiphy)
|
|||
(!rdev->ops->set_pmk || !rdev->ops->del_pmk)))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
|
||||
rdev->ops->update_connect_params))
|
||||
return -EINVAL;
|
||||
|
||||
if (wiphy->addresses)
|
||||
memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/if.h>
|
||||
|
@ -423,6 +424,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||
[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
|
||||
[NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
|
||||
|
||||
[NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
@ -645,7 +650,43 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
|
|||
return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
|
||||
}
|
||||
|
||||
static int nl80211_msg_put_channel(struct sk_buff *msg,
|
||||
static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
|
||||
const struct ieee80211_reg_rule *rule)
|
||||
{
|
||||
int j;
|
||||
struct nlattr *nl_wmm_rules =
|
||||
nla_nest_start(msg, NL80211_FREQUENCY_ATTR_WMM);
|
||||
|
||||
if (!nl_wmm_rules)
|
||||
goto nla_put_failure;
|
||||
|
||||
for (j = 0; j < IEEE80211_NUM_ACS; j++) {
|
||||
struct nlattr *nl_wmm_rule = nla_nest_start(msg, j);
|
||||
|
||||
if (!nl_wmm_rule)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
|
||||
rule->wmm_rule->client[j].cw_min) ||
|
||||
nla_put_u16(msg, NL80211_WMMR_CW_MAX,
|
||||
rule->wmm_rule->client[j].cw_max) ||
|
||||
nla_put_u8(msg, NL80211_WMMR_AIFSN,
|
||||
rule->wmm_rule->client[j].aifsn) ||
|
||||
nla_put_u8(msg, NL80211_WMMR_TXOP,
|
||||
rule->wmm_rule->client[j].cot))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, nl_wmm_rule);
|
||||
}
|
||||
nla_nest_end(msg, nl_wmm_rules);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
|
||||
struct ieee80211_channel *chan,
|
||||
bool large)
|
||||
{
|
||||
|
@ -721,12 +762,55 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
|
|||
DBM_TO_MBM(chan->max_power)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (large) {
|
||||
const struct ieee80211_reg_rule *rule =
|
||||
freq_reg_info(wiphy, chan->center_freq);
|
||||
|
||||
if (!IS_ERR(rule) && rule->wmm_rule) {
|
||||
if (nl80211_msg_put_wmm_rules(msg, rule))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
static bool nl80211_put_txq_stats(struct sk_buff *msg,
|
||||
struct cfg80211_txq_stats *txqstats,
|
||||
int attrtype)
|
||||
{
|
||||
struct nlattr *txqattr;
|
||||
|
||||
#define PUT_TXQVAL_U32(attr, memb) do { \
|
||||
if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) && \
|
||||
nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
|
||||
return false; \
|
||||
} while (0)
|
||||
|
||||
txqattr = nla_nest_start(msg, attrtype);
|
||||
if (!txqattr)
|
||||
return false;
|
||||
|
||||
PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
|
||||
PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
|
||||
PUT_TXQVAL_U32(FLOWS, flows);
|
||||
PUT_TXQVAL_U32(DROPS, drops);
|
||||
PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
|
||||
PUT_TXQVAL_U32(OVERLIMIT, overlimit);
|
||||
PUT_TXQVAL_U32(OVERMEMORY, overmemory);
|
||||
PUT_TXQVAL_U32(COLLISIONS, collisions);
|
||||
PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
|
||||
PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
|
||||
PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
|
||||
nla_nest_end(msg, txqattr);
|
||||
|
||||
#undef PUT_TXQVAL_U32
|
||||
return true;
|
||||
}
|
||||
|
||||
/* netlink command implementations */
|
||||
|
||||
struct key_parse {
|
||||
|
@ -1631,7 +1715,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
chan = &sband->channels[i];
|
||||
|
||||
if (nl80211_msg_put_channel(
|
||||
msg, chan,
|
||||
msg, &rdev->wiphy, chan,
|
||||
state->split))
|
||||
goto nla_put_failure;
|
||||
|
||||
|
@ -1926,6 +2010,28 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
rdev->wiphy.nan_supported_bands))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_TXQS)) {
|
||||
struct cfg80211_txq_stats txqstats = {};
|
||||
int res;
|
||||
|
||||
res = rdev_get_txq_stats(rdev, NULL, &txqstats);
|
||||
if (!res &&
|
||||
!nl80211_put_txq_stats(msg, &txqstats,
|
||||
NL80211_ATTR_TXQ_STATS))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
|
||||
rdev->wiphy.txq_limit))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
|
||||
rdev->wiphy.txq_memory_limit))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
|
||||
rdev->wiphy.txq_quantum))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
break;
|
||||
|
@ -2303,6 +2409,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
u8 retry_short = 0, retry_long = 0;
|
||||
u32 frag_threshold = 0, rts_threshold = 0;
|
||||
u8 coverage_class = 0;
|
||||
u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
|
@ -2509,10 +2616,38 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
changed |= WIPHY_PARAM_DYN_ACK;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_TXQS))
|
||||
return -EOPNOTSUPP;
|
||||
txq_limit = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_TXQ_LIMIT]);
|
||||
changed |= WIPHY_PARAM_TXQ_LIMIT;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_TXQS))
|
||||
return -EOPNOTSUPP;
|
||||
txq_memory_limit = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
|
||||
changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_TXQS))
|
||||
return -EOPNOTSUPP;
|
||||
txq_quantum = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
|
||||
changed |= WIPHY_PARAM_TXQ_QUANTUM;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
u8 old_retry_short, old_retry_long;
|
||||
u32 old_frag_threshold, old_rts_threshold;
|
||||
u8 old_coverage_class;
|
||||
u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
|
||||
|
||||
if (!rdev->ops->set_wiphy_params)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -2522,6 +2657,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
old_frag_threshold = rdev->wiphy.frag_threshold;
|
||||
old_rts_threshold = rdev->wiphy.rts_threshold;
|
||||
old_coverage_class = rdev->wiphy.coverage_class;
|
||||
old_txq_limit = rdev->wiphy.txq_limit;
|
||||
old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
|
||||
old_txq_quantum = rdev->wiphy.txq_quantum;
|
||||
|
||||
if (changed & WIPHY_PARAM_RETRY_SHORT)
|
||||
rdev->wiphy.retry_short = retry_short;
|
||||
|
@ -2533,6 +2671,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
rdev->wiphy.rts_threshold = rts_threshold;
|
||||
if (changed & WIPHY_PARAM_COVERAGE_CLASS)
|
||||
rdev->wiphy.coverage_class = coverage_class;
|
||||
if (changed & WIPHY_PARAM_TXQ_LIMIT)
|
||||
rdev->wiphy.txq_limit = txq_limit;
|
||||
if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
|
||||
rdev->wiphy.txq_memory_limit = txq_memory_limit;
|
||||
if (changed & WIPHY_PARAM_TXQ_QUANTUM)
|
||||
rdev->wiphy.txq_quantum = txq_quantum;
|
||||
|
||||
result = rdev_set_wiphy_params(rdev, changed);
|
||||
if (result) {
|
||||
|
@ -2541,6 +2685,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
rdev->wiphy.frag_threshold = old_frag_threshold;
|
||||
rdev->wiphy.rts_threshold = old_rts_threshold;
|
||||
rdev->wiphy.coverage_class = old_coverage_class;
|
||||
rdev->wiphy.txq_limit = old_txq_limit;
|
||||
rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
|
||||
rdev->wiphy.txq_quantum = old_txq_quantum;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -2662,6 +2809,16 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
|
|||
}
|
||||
wdev_unlock(wdev);
|
||||
|
||||
if (rdev->ops->get_txq_stats) {
|
||||
struct cfg80211_txq_stats txqstats = {};
|
||||
int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
|
||||
|
||||
if (ret == 0 &&
|
||||
!nl80211_put_txq_stats(msg, &txqstats,
|
||||
NL80211_ATTR_TXQ_STATS))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
return 0;
|
||||
|
||||
|
@ -4494,11 +4651,14 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
|
|||
PUT_SINFO_U64(BEACON_RX, rx_beacon);
|
||||
PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
|
||||
PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
|
||||
if (wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT))
|
||||
PUT_SINFO(DATA_ACK_SIGNAL_AVG, avg_ack_signal, s8);
|
||||
|
||||
#undef PUT_SINFO
|
||||
#undef PUT_SINFO_U64
|
||||
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) {
|
||||
if (sinfo->pertid) {
|
||||
struct nlattr *tidsattr;
|
||||
int tid;
|
||||
|
||||
|
@ -4532,6 +4692,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
|
|||
PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
|
||||
|
||||
#undef PUT_TIDVAL_U64
|
||||
if ((tidstats->filled &
|
||||
BIT(NL80211_TID_STATS_TXQ_STATS)) &&
|
||||
!nl80211_put_txq_stats(msg, &tidstats->txq_stats,
|
||||
NL80211_TID_STATS_TXQ_STATS))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, tidattr);
|
||||
}
|
||||
|
||||
|
@ -4545,10 +4711,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
|
|||
sinfo->assoc_req_ies))
|
||||
goto nla_put_failure;
|
||||
|
||||
cfg80211_sinfo_release_content(sinfo);
|
||||
genlmsg_end(msg, hdr);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
cfg80211_sinfo_release_content(sinfo);
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
@ -4630,8 +4798,10 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
|
|||
return err;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
if (!msg) {
|
||||
cfg80211_sinfo_release_content(&sinfo);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
|
||||
info->snd_portid, info->snd_seq, 0,
|
||||
|
@ -7930,6 +8100,14 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
|
||||
wdev_lock(wdev);
|
||||
spin_lock_bh(&rdev->bss_lock);
|
||||
|
||||
/*
|
||||
* dump_scan will be called multiple times to break up the scan results
|
||||
* into multiple messages. It is unlikely that any more bss-es will be
|
||||
* expired after the first call, so only call only call this on the
|
||||
* first dump_scan invocation.
|
||||
*/
|
||||
if (start == 0)
|
||||
cfg80211_bss_expire(rdev);
|
||||
|
||||
cb->seq = rdev->bss_generation;
|
||||
|
@ -8336,6 +8514,10 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
|
|||
const u8 *bssid, *ssid;
|
||||
int err, ssid_len = 0;
|
||||
|
||||
if (dev->ieee80211_ptr->conn_owner_nlportid &&
|
||||
dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
|
||||
return -EPERM;
|
||||
|
||||
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -8458,6 +8640,10 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
u16 reason_code;
|
||||
bool local_state_change;
|
||||
|
||||
if (dev->ieee80211_ptr->conn_owner_nlportid &&
|
||||
dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
|
||||
return -EPERM;
|
||||
|
||||
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -8505,6 +8691,10 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
|
|||
u16 reason_code;
|
||||
bool local_state_change;
|
||||
|
||||
if (dev->ieee80211_ptr->conn_owner_nlportid &&
|
||||
dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
|
||||
return -EPERM;
|
||||
|
||||
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -9251,6 +9441,8 @@ static int nl80211_update_connect_params(struct sk_buff *skb,
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
bool fils_sk_offload;
|
||||
u32 auth_type;
|
||||
u32 changed = 0;
|
||||
int ret;
|
||||
|
||||
|
@ -9265,6 +9457,56 @@ static int nl80211_update_connect_params(struct sk_buff *skb,
|
|||
changed |= UPDATE_ASSOC_IES;
|
||||
}
|
||||
|
||||
fils_sk_offload = wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
|
||||
|
||||
/*
|
||||
* when driver supports fils-sk offload all attributes must be
|
||||
* provided. So the else covers "fils-sk-not-all" and
|
||||
* "no-fils-sk-any".
|
||||
*/
|
||||
if (fils_sk_offload &&
|
||||
info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
|
||||
info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
|
||||
info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
|
||||
info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
|
||||
connect.fils_erp_username =
|
||||
nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
|
||||
connect.fils_erp_username_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
|
||||
connect.fils_erp_realm =
|
||||
nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
|
||||
connect.fils_erp_realm_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
|
||||
connect.fils_erp_next_seq_num =
|
||||
nla_get_u16(
|
||||
info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
|
||||
connect.fils_erp_rrk =
|
||||
nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
|
||||
connect.fils_erp_rrk_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
|
||||
changed |= UPDATE_FILS_ERP_INFO;
|
||||
} else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
|
||||
info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
|
||||
info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
|
||||
info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
|
||||
auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
|
||||
if (!nl80211_valid_auth_type(rdev, auth_type,
|
||||
NL80211_CMD_CONNECT))
|
||||
return -EINVAL;
|
||||
|
||||
if (auth_type == NL80211_AUTHTYPE_FILS_SK &&
|
||||
fils_sk_offload && !(changed & UPDATE_FILS_ERP_INFO))
|
||||
return -EINVAL;
|
||||
|
||||
connect.auth_type = auth_type;
|
||||
changed |= UPDATE_AUTH_TYPE;
|
||||
}
|
||||
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
if (!wdev->current_bss)
|
||||
ret = -ENOLINK;
|
||||
|
@ -9282,6 +9524,10 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
|
|||
u16 reason;
|
||||
int ret;
|
||||
|
||||
if (dev->ieee80211_ptr->conn_owner_nlportid &&
|
||||
dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
|
||||
return -EPERM;
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_REASON_CODE])
|
||||
reason = WLAN_REASON_DEAUTH_LEAVING;
|
||||
else
|
||||
|
@ -14028,8 +14274,8 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
|
|||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
|
||||
cr->fils_kek_len + cr->pmk_len +
|
||||
(cr->pmkid ? WLAN_PMKID_LEN : 0), gfp);
|
||||
cr->fils.kek_len + cr->fils.pmk_len +
|
||||
(cr->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
|
@ -14055,17 +14301,17 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
|
|||
(cr->resp_ie &&
|
||||
nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
|
||||
cr->resp_ie)) ||
|
||||
(cr->update_erp_next_seq_num &&
|
||||
(cr->fils.update_erp_next_seq_num &&
|
||||
nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
|
||||
cr->fils_erp_next_seq_num)) ||
|
||||
cr->fils.erp_next_seq_num)) ||
|
||||
(cr->status == WLAN_STATUS_SUCCESS &&
|
||||
((cr->fils_kek &&
|
||||
nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils_kek_len,
|
||||
cr->fils_kek)) ||
|
||||
(cr->pmk &&
|
||||
nla_put(msg, NL80211_ATTR_PMK, cr->pmk_len, cr->pmk)) ||
|
||||
(cr->pmkid &&
|
||||
nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->pmkid)))))
|
||||
((cr->fils.kek &&
|
||||
nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils.kek_len,
|
||||
cr->fils.kek)) ||
|
||||
(cr->fils.pmk &&
|
||||
nla_put(msg, NL80211_ATTR_PMK, cr->fils.pmk_len, cr->fils.pmk)) ||
|
||||
(cr->fils.pmkid &&
|
||||
nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
@ -14086,7 +14332,9 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
|
|||
void *hdr;
|
||||
const u8 *bssid = info->bss ? info->bss->bssid : info->bssid;
|
||||
|
||||
msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len, gfp);
|
||||
msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
|
||||
info->fils.kek_len + info->fils.pmk_len +
|
||||
(info->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
|
@ -14104,7 +14352,17 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
|
|||
info->req_ie)) ||
|
||||
(info->resp_ie &&
|
||||
nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
|
||||
info->resp_ie)))
|
||||
info->resp_ie)) ||
|
||||
(info->fils.update_erp_next_seq_num &&
|
||||
nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
|
||||
info->fils.erp_next_seq_num)) ||
|
||||
(info->fils.kek &&
|
||||
nla_put(msg, NL80211_ATTR_FILS_KEK, info->fils.kek_len,
|
||||
info->fils.kek)) ||
|
||||
(info->fils.pmk &&
|
||||
nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
|
||||
(info->fils.pmkid &&
|
||||
nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
@ -14321,7 +14579,8 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
|
|||
nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE);
|
||||
if (!nl_freq)
|
||||
goto nla_put_failure;
|
||||
if (nl80211_msg_put_channel(msg, channel_before, false))
|
||||
|
||||
if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
|
||||
goto nla_put_failure;
|
||||
nla_nest_end(msg, nl_freq);
|
||||
|
||||
|
@ -14329,7 +14588,8 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
|
|||
nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER);
|
||||
if (!nl_freq)
|
||||
goto nla_put_failure;
|
||||
if (nl80211_msg_put_channel(msg, channel_after, false))
|
||||
|
||||
if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
|
||||
goto nla_put_failure;
|
||||
nla_nest_end(msg, nl_freq);
|
||||
|
||||
|
@ -14456,8 +14716,10 @@ void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
|
|||
trace_cfg80211_del_sta(dev, mac_addr);
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
|
||||
if (!msg)
|
||||
if (!msg) {
|
||||
cfg80211_sinfo_release_content(sinfo);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
|
||||
rdev, dev, mac_addr, sinfo) < 0) {
|
||||
|
|
|
@ -586,6 +586,18 @@ rdev_set_multicast_to_unicast(struct cfg80211_registered_device *rdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
rdev_get_txq_stats(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
struct cfg80211_txq_stats *txqstats)
|
||||
{
|
||||
int ret;
|
||||
trace_rdev_get_txq_stats(&rdev->wiphy, wdev);
|
||||
ret = rdev->ops->get_txq_stats(&rdev->wiphy, wdev, txqstats);
|
||||
trace_rdev_return_int(&rdev->wiphy, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
trace_rdev_rfkill_poll(&rdev->wiphy);
|
||||
|
|
|
@ -1653,7 +1653,7 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
|
|||
case NL80211_REGDOM_SET_BY_DRIVER:
|
||||
return "driver";
|
||||
case NL80211_REGDOM_SET_BY_COUNTRY_IE:
|
||||
return "country IE";
|
||||
return "country element";
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return "bug";
|
||||
|
@ -2619,7 +2619,7 @@ reg_process_hint_country_ie(struct wiphy *wiphy,
|
|||
* This doesn't happen yet, not sure we
|
||||
* ever want to support it for this case.
|
||||
*/
|
||||
WARN_ONCE(1, "Unexpected intersection for country IEs");
|
||||
WARN_ONCE(1, "Unexpected intersection for country elements");
|
||||
return REG_REQ_IGNORE;
|
||||
}
|
||||
|
||||
|
@ -2769,6 +2769,21 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
|||
reg_free_request(reg_request);
|
||||
}
|
||||
|
||||
static void notify_self_managed_wiphys(struct regulatory_request *request)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy;
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
wiphy = &rdev->wiphy;
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
|
||||
request->initiator == NL80211_REGDOM_SET_BY_USER &&
|
||||
request->user_reg_hint_type ==
|
||||
NL80211_USER_REG_HINT_CELL_BASE)
|
||||
reg_call_notifier(wiphy, request);
|
||||
}
|
||||
}
|
||||
|
||||
static bool reg_only_self_managed_wiphys(void)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
@ -2820,6 +2835,7 @@ static void reg_process_pending_hints(void)
|
|||
|
||||
spin_unlock(®_requests_lock);
|
||||
|
||||
notify_self_managed_wiphys(reg_request);
|
||||
if (reg_only_self_managed_wiphys()) {
|
||||
reg_free_request(reg_request);
|
||||
return;
|
||||
|
@ -3384,7 +3400,7 @@ bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region)
|
|||
case NL80211_DFS_JP:
|
||||
return true;
|
||||
default:
|
||||
pr_debug("Ignoring uknown DFS master region: %d\n", dfs_region);
|
||||
pr_debug("Ignoring unknown DFS master region: %d\n", dfs_region);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3699,17 +3715,26 @@ EXPORT_SYMBOL(regulatory_set_wiphy_regd_sync_rtnl);
|
|||
|
||||
void wiphy_regulatory_register(struct wiphy *wiphy)
|
||||
{
|
||||
struct regulatory_request *lr;
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
|
||||
/* self-managed devices ignore external hints */
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
/* self-managed devices ignore beacon hints and country IE */
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
|
||||
wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS |
|
||||
REGULATORY_COUNTRY_IE_IGNORE;
|
||||
|
||||
/*
|
||||
* The last request may have been received before this
|
||||
* registration call. Call the driver notifier if
|
||||
* initiator is USER and user type is CELL_BASE.
|
||||
*/
|
||||
if (lr->initiator == NL80211_REGDOM_SET_BY_USER &&
|
||||
lr->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE)
|
||||
reg_call_notifier(wiphy, lr);
|
||||
}
|
||||
|
||||
if (!reg_dev_ignore_cell_hint(wiphy))
|
||||
reg_num_devs_support_basehint++;
|
||||
|
||||
lr = get_last_request();
|
||||
wiphy_update_regulatory(wiphy, lr->initiator);
|
||||
wiphy_all_share_dfs_chan_state(wiphy);
|
||||
}
|
||||
|
|
|
@ -803,8 +803,8 @@ void cfg80211_connect_done(struct net_device *dev,
|
|||
|
||||
ev = kzalloc(sizeof(*ev) + (params->bssid ? ETH_ALEN : 0) +
|
||||
params->req_ie_len + params->resp_ie_len +
|
||||
params->fils_kek_len + params->pmk_len +
|
||||
(params->pmkid ? WLAN_PMKID_LEN : 0), gfp);
|
||||
params->fils.kek_len + params->fils.pmk_len +
|
||||
(params->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
|
||||
if (!ev) {
|
||||
cfg80211_put_bss(wdev->wiphy, params->bss);
|
||||
return;
|
||||
|
@ -831,27 +831,29 @@ void cfg80211_connect_done(struct net_device *dev,
|
|||
params->resp_ie_len);
|
||||
next += params->resp_ie_len;
|
||||
}
|
||||
if (params->fils_kek_len) {
|
||||
ev->cr.fils_kek = next;
|
||||
ev->cr.fils_kek_len = params->fils_kek_len;
|
||||
memcpy((void *)ev->cr.fils_kek, params->fils_kek,
|
||||
params->fils_kek_len);
|
||||
next += params->fils_kek_len;
|
||||
if (params->fils.kek_len) {
|
||||
ev->cr.fils.kek = next;
|
||||
ev->cr.fils.kek_len = params->fils.kek_len;
|
||||
memcpy((void *)ev->cr.fils.kek, params->fils.kek,
|
||||
params->fils.kek_len);
|
||||
next += params->fils.kek_len;
|
||||
}
|
||||
if (params->pmk_len) {
|
||||
ev->cr.pmk = next;
|
||||
ev->cr.pmk_len = params->pmk_len;
|
||||
memcpy((void *)ev->cr.pmk, params->pmk, params->pmk_len);
|
||||
next += params->pmk_len;
|
||||
if (params->fils.pmk_len) {
|
||||
ev->cr.fils.pmk = next;
|
||||
ev->cr.fils.pmk_len = params->fils.pmk_len;
|
||||
memcpy((void *)ev->cr.fils.pmk, params->fils.pmk,
|
||||
params->fils.pmk_len);
|
||||
next += params->fils.pmk_len;
|
||||
}
|
||||
if (params->pmkid) {
|
||||
ev->cr.pmkid = next;
|
||||
memcpy((void *)ev->cr.pmkid, params->pmkid, WLAN_PMKID_LEN);
|
||||
if (params->fils.pmkid) {
|
||||
ev->cr.fils.pmkid = next;
|
||||
memcpy((void *)ev->cr.fils.pmkid, params->fils.pmkid,
|
||||
WLAN_PMKID_LEN);
|
||||
next += WLAN_PMKID_LEN;
|
||||
}
|
||||
ev->cr.update_erp_next_seq_num = params->update_erp_next_seq_num;
|
||||
if (params->update_erp_next_seq_num)
|
||||
ev->cr.fils_erp_next_seq_num = params->fils_erp_next_seq_num;
|
||||
ev->cr.fils.update_erp_next_seq_num = params->fils.update_erp_next_seq_num;
|
||||
if (params->fils.update_erp_next_seq_num)
|
||||
ev->cr.fils.erp_next_seq_num = params->fils.erp_next_seq_num;
|
||||
if (params->bss)
|
||||
cfg80211_hold_bss(bss_from_pub(params->bss));
|
||||
ev->cr.bss = params->bss;
|
||||
|
@ -930,6 +932,7 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
|
|||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
u8 *next;
|
||||
|
||||
if (!info->bss) {
|
||||
info->bss = cfg80211_get_bss(wdev->wiphy, info->channel,
|
||||
|
@ -942,19 +945,52 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
|
|||
if (WARN_ON(!info->bss))
|
||||
return;
|
||||
|
||||
ev = kzalloc(sizeof(*ev) + info->req_ie_len + info->resp_ie_len, gfp);
|
||||
ev = kzalloc(sizeof(*ev) + info->req_ie_len + info->resp_ie_len +
|
||||
info->fils.kek_len + info->fils.pmk_len +
|
||||
(info->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
|
||||
if (!ev) {
|
||||
cfg80211_put_bss(wdev->wiphy, info->bss);
|
||||
return;
|
||||
}
|
||||
|
||||
ev->type = EVENT_ROAMED;
|
||||
ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev);
|
||||
next = ((u8 *)ev) + sizeof(*ev);
|
||||
if (info->req_ie_len) {
|
||||
ev->rm.req_ie = next;
|
||||
ev->rm.req_ie_len = info->req_ie_len;
|
||||
memcpy((void *)ev->rm.req_ie, info->req_ie, info->req_ie_len);
|
||||
ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + info->req_ie_len;
|
||||
next += info->req_ie_len;
|
||||
}
|
||||
if (info->resp_ie_len) {
|
||||
ev->rm.resp_ie = next;
|
||||
ev->rm.resp_ie_len = info->resp_ie_len;
|
||||
memcpy((void *)ev->rm.resp_ie, info->resp_ie, info->resp_ie_len);
|
||||
memcpy((void *)ev->rm.resp_ie, info->resp_ie,
|
||||
info->resp_ie_len);
|
||||
next += info->resp_ie_len;
|
||||
}
|
||||
if (info->fils.kek_len) {
|
||||
ev->rm.fils.kek = next;
|
||||
ev->rm.fils.kek_len = info->fils.kek_len;
|
||||
memcpy((void *)ev->rm.fils.kek, info->fils.kek,
|
||||
info->fils.kek_len);
|
||||
next += info->fils.kek_len;
|
||||
}
|
||||
if (info->fils.pmk_len) {
|
||||
ev->rm.fils.pmk = next;
|
||||
ev->rm.fils.pmk_len = info->fils.pmk_len;
|
||||
memcpy((void *)ev->rm.fils.pmk, info->fils.pmk,
|
||||
info->fils.pmk_len);
|
||||
next += info->fils.pmk_len;
|
||||
}
|
||||
if (info->fils.pmkid) {
|
||||
ev->rm.fils.pmkid = next;
|
||||
memcpy((void *)ev->rm.fils.pmkid, info->fils.pmkid,
|
||||
WLAN_PMKID_LEN);
|
||||
next += WLAN_PMKID_LEN;
|
||||
}
|
||||
ev->rm.fils.update_erp_next_seq_num = info->fils.update_erp_next_seq_num;
|
||||
if (info->fils.update_erp_next_seq_num)
|
||||
ev->rm.fils.erp_next_seq_num = info->fils.erp_next_seq_num;
|
||||
ev->rm.bss = info->bss;
|
||||
|
||||
spin_lock_irqsave(&wdev->event_lock, flags);
|
||||
|
|
|
@ -3243,6 +3243,20 @@ TRACE_EVENT(rdev_set_multicast_to_unicast,
|
|||
WIPHY_PR_ARG, NETDEV_PR_ARG,
|
||||
BOOL_TO_STR(__entry->enabled))
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_get_txq_stats,
|
||||
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
|
||||
TP_ARGS(wiphy, wdev),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
WDEV_ENTRY
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
WDEV_ASSIGN;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
|
||||
);
|
||||
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
|
|
@ -1787,6 +1787,17 @@ bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
|
|||
return false;
|
||||
}
|
||||
|
||||
int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp)
|
||||
{
|
||||
sinfo->pertid = kcalloc(sizeof(*(sinfo->pertid)),
|
||||
IEEE80211_NUM_TIDS + 1, gfp);
|
||||
if (!sinfo->pertid)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_sinfo_alloc_tid_stats);
|
||||
|
||||
/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
|
||||
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
|
||||
const unsigned char rfc1042_header[] __aligned(2) =
|
||||
|
|
Loading…
Reference in New Issue