OSDN Git Service

Merge remote-tracking branch 'net-next/master' into mac80211-next
authorJohannes Berg <johannes.berg@intel.com>
Wed, 23 May 2018 09:05:26 +0000 (11:05 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 23 May 2018 09:05:59 +0000 (11:05 +0200)
Bring in net-next which had pulled in net, so I have the changes
from mac80211 and can apply a patch that would otherwise conflict.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
20 files changed:
drivers/net/wireless/mac80211_hwsim.c
include/net/cfg80211.h
include/net/mac80211.h
include/uapi/linux/nl80211.h
net/mac80211/cfg.c
net/mac80211/ethtool.c
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/status.c
net/mac80211/tx.c
net/mac80211/util.c
net/wireless/nl80211.c
net/wireless/rdev-ops.h
net/wireless/reg.c
net/wireless/trace.h
net/wireless/util.c

index 4a017a0..c26469b 100644 (file)
@@ -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);
index 250dac3..df33c27 100644 (file)
@@ -1080,6 +1080,37 @@ struct sta_bss_parameters {
 };
 
 /**
+ * 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
  *     indicate the relevant values in this struct are filled
@@ -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)
@@ -2201,6 +2238,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 +2249,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 +3004,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 +3308,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 +3856,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 +3994,10 @@ struct wiphy {
 
        u8 nan_supported_bands;
 
+       u32 txq_limit;
+       u32 txq_memory_limit;
+       u32 txq_quantum;
+
        char priv[0] __aligned(NETDEV_ALIGN);
 };
 
@@ -5648,6 +5706,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
index b2f3a0c..604d738 100644 (file)
@@ -4450,6 +4450,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.
  *
index 9c36301..83ed1dd 100644 (file)
@@ -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
@@ -2225,6 +2226,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 +2670,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 +2998,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 +3039,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 +3057,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,6 +3068,7 @@ 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,
@@ -3055,6 +3076,44 @@ enum nl80211_tid_stats {
 };
 
 /**
+ * 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
  *
  * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active
@@ -3144,6 +3203,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
  * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
@@ -3192,6 +3274,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 +3305,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 +5126,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 +5163,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,
index 85dbaa8..bdf6fa7 100644 (file)
@@ -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,
 };
index 9cc986d..690c142 100644 (file)
@@ -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);
                }
index c78036a..26a7ba3 100644 (file)
@@ -301,26 +301,27 @@ 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.
         */
-       mutex_lock(&sta->ampdu_mlme.mtx);
-       for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
-               struct tid_ampdu_tx *tid_tx =
-                       rcu_dereference_protected_tid_tx(sta, i);
+       if(reason == AGG_STOP_DESTROY_STA) {
+               cancel_work_sync(&sta->ampdu_mlme.work);
 
-               if (!tid_tx)
-                       continue;
+               mutex_lock(&sta->ampdu_mlme.mtx);
+               for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
+                       struct tid_ampdu_tx *tid_tx =
+                               rcu_dereference_protected_tid_tx(sta, i);
 
-               if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state))
-                       ieee80211_stop_tx_ba_cb(sta, i, tid_tx);
+                       if (!tid_tx)
+                               continue;
+
+                       if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state))
+                               ieee80211_stop_tx_ba_cb(sta, i, tid_tx);
+               }
+               mutex_unlock(&sta->ampdu_mlme.mtx);
        }
-       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,
index 6372dbd..d1978aa 100644 (file)
@@ -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,
index 9ea17af..4d2e797 100644 (file)
@@ -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);
index 03102af..0a38cc1 100644 (file)
@@ -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;
 }
 
index 655c3d8..6428f1a 100644 (file)
@@ -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,11 +2234,12 @@ 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);
-       for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
-               struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i];
+       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);
+                       sta_set_tidstats(sta, tidstats, i);
+               }
        }
 
        if (ieee80211_vif_is_mesh(&sdata->vif)) {
@@ -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)
index f64eb86..81b35f6 100644 (file)
@@ -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);
 
index 743e89c..9a6d720 100644 (file)
@@ -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);
                }
        }
 
index 05a265c..44b5dfe 100644 (file)
@@ -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 @@ unlock:
 }
 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);
index 11f9cfc..2d82c88 100644 (file)
@@ -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;
index a052693..a3dcea2 100644 (file)
@@ -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,
@@ -14321,7 +14491,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 +14500,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 +14628,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) {
index 87479a5..364f5d6 100644 (file)
@@ -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);
index ac3e12c..e55099b 100644 (file)
@@ -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 @@ out_free:
        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(&reg_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);
 }
index 55fb279..2b417a2 100644 (file)
@@ -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
index d112e9a..b5bb1c3 100644 (file)
@@ -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) =