[v2,3/6] mac80211: Add airtime accounting and scheduling to TXQs
diff mbox series

Message ID 1541805421-27309-4-git-send-email-rmanohar@qti.qualcomm.com
State New
Headers show
Series
  • Move TXQ scheduling and airtime fairness into mac80211
Related show

Commit Message

Rajkumar Manoharan Nov. 9, 2018, 11:16 p.m. UTC
From: Toke Høiland-Jørgensen <toke@toke.dk>

This adds airtime accounting and scheduling to the mac80211 TXQ
scheduler. A new callback, ieee80211_sta_register_airtime(), is added
that drivers can call to report airtime usage for stations.

When airtime information is present, mac80211 will schedule TXQs
(through ieee80211_next_txq()) in a way that enforces airtime fairness
between active stations. This scheduling works the same way as the ath9k
in-driver airtime fairness scheduling. If no airtime usage is reported
by the driver, the scheduler will default to round-robin scheduling.

For drivers that don't control TXQ scheduling in software, a new API
function, ieee80211_txq_may_transmit(), is added which the driver can use
to check if the TXQ is eligible for transmission, or should be throttled to
enforce fairness. Calls to this function must also be enclosed in
ieee80211_txq_schedule_{start,end}() calls to ensure proper locking.

The API ieee80211_txq_may_transmit() also ensures that TXQ list will be
aligned aginst driver's own round-robin scheduler list. i.e it rotates
the TXQ list till it makes the requested node becomes the first entry
in TXQ list. Thus both the TXQ list and driver's list are in sync.

Co-Developed-by: Rajkumar Manoharan <rmanohar@codeaurora.org>
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Rajkumar Manoharan <rmanohar@codeaurora.org>
---
 include/net/mac80211.h     | 59 ++++++++++++++++++++++++++++++
 net/mac80211/cfg.c         |  3 ++
 net/mac80211/debugfs.c     |  3 ++
 net/mac80211/debugfs_sta.c | 50 ++++++++++++++++++++++++--
 net/mac80211/ieee80211_i.h |  2 ++
 net/mac80211/main.c        |  4 +++
 net/mac80211/sta_info.c    | 44 +++++++++++++++++++++--
 net/mac80211/sta_info.h    | 13 +++++++
 net/mac80211/status.c      |  6 ++++
 net/mac80211/tx.c          | 90 +++++++++++++++++++++++++++++++++++++++++++---
 10 files changed, 264 insertions(+), 10 deletions(-)

Comments

kbuild test robot Nov. 10, 2018, 11:57 p.m. UTC | #1
Hi Toke,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mac80211/master]
[also build test WARNING on v4.20-rc1 next-20181109]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Rajkumar-Manoharan/Move-TXQ-scheduling-and-airtime-fairness-into-mac80211/20181111-072032
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git master
config: i386-randconfig-x009-201845 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   In file included from include/linux/bitops.h:5:0,
                    from include/linux/kernel.h:11,
                    from include/linux/list.h:9,
                    from include/linux/module.h:9,
                    from net/mac80211/sta_info.c:13:
   net/mac80211/sta_info.c: In function 'sta_set_sinfo':
   include/linux/bits.h:6:24: warning: left shift count >= width of type [-Wshift-count-overflow]
    #define BIT(nr)   (1UL << (nr))
                           ^
>> net/mac80211/sta_info.c:2212:24: note: in expansion of macro 'BIT'
     if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_DURATION))) {
                           ^~~
   include/linux/bits.h:6:24: warning: left shift count >= width of type [-Wshift-count-overflow]
    #define BIT(nr)   (1UL << (nr))
                           ^
   net/mac80211/sta_info.c:2215:20: note: in expansion of macro 'BIT'
      sinfo->filled |= BIT(NL80211_STA_INFO_RX_DURATION);
                       ^~~
   include/linux/bits.h:6:24: warning: left shift count >= width of type [-Wshift-count-overflow]
    #define BIT(nr)   (1UL << (nr))
                           ^
   net/mac80211/sta_info.c:2218:24: note: in expansion of macro 'BIT'
     if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_DURATION))) {
                           ^~~
   include/linux/bits.h:6:24: warning: left shift count >= width of type [-Wshift-count-overflow]
    #define BIT(nr)   (1UL << (nr))
                           ^
   net/mac80211/sta_info.c:2221:20: note: in expansion of macro 'BIT'
      sinfo->filled |= BIT(NL80211_STA_INFO_TX_DURATION);
                       ^~~
   include/linux/bits.h:6:24: warning: left shift count >= width of type [-Wshift-count-overflow]
    #define BIT(nr)   (1UL << (nr))
                           ^
   net/mac80211/sta_info.c:2224:24: note: in expansion of macro 'BIT'
     if (!(sinfo->filled & BIT(NL80211_STA_INFO_AIRTIME_WEIGHT))) {
                           ^~~
   include/linux/bits.h:6:24: warning: left shift count >= width of type [-Wshift-count-overflow]
    #define BIT(nr)   (1UL << (nr))
                           ^
   net/mac80211/sta_info.c:2226:20: note: in expansion of macro 'BIT'
      sinfo->filled |= BIT(NL80211_STA_INFO_AIRTIME_WEIGHT);
                       ^~~

vim +/BIT +2212 net/mac80211/sta_info.c

  2120	
  2121	void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
  2122			   bool tidstats)
  2123	{
  2124		struct ieee80211_sub_if_data *sdata = sta->sdata;
  2125		struct ieee80211_local *local = sdata->local;
  2126		u32 thr = 0;
  2127		int i, ac, cpu;
  2128		struct ieee80211_sta_rx_stats *last_rxstats;
  2129	
  2130		last_rxstats = sta_get_last_rx_stats(sta);
  2131	
  2132		sinfo->generation = sdata->local->sta_generation;
  2133	
  2134		/* do before driver, so beacon filtering drivers have a
  2135		 * chance to e.g. just add the number of filtered beacons
  2136		 * (or just modify the value entirely, of course)
  2137		 */
  2138		if (sdata->vif.type == NL80211_IFTYPE_STATION)
  2139			sinfo->rx_beacon = sdata->u.mgd.count_beacon_signal;
  2140	
  2141		drv_sta_statistics(local, sdata, &sta->sta, sinfo);
  2142	
  2143		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) |
  2144				 BIT_ULL(NL80211_STA_INFO_STA_FLAGS) |
  2145				 BIT_ULL(NL80211_STA_INFO_BSS_PARAM) |
  2146				 BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME) |
  2147				 BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC);
  2148	
  2149		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
  2150			sinfo->beacon_loss_count = sdata->u.mgd.beacon_loss_count;
  2151			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_LOSS);
  2152		}
  2153	
  2154		sinfo->connected_time = ktime_get_seconds() - sta->last_connected;
  2155		sinfo->inactive_time =
  2156			jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta));
  2157	
  2158		if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
  2159				       BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) {
  2160			sinfo->tx_bytes = 0;
  2161			for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
  2162				sinfo->tx_bytes += sta->tx_stats.bytes[ac];
  2163			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
  2164		}
  2165	
  2166		if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_PACKETS))) {
  2167			sinfo->tx_packets = 0;
  2168			for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
  2169				sinfo->tx_packets += sta->tx_stats.packets[ac];
  2170			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
  2171		}
  2172	
  2173		if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES64) |
  2174				       BIT_ULL(NL80211_STA_INFO_RX_BYTES)))) {
  2175			sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats);
  2176	
  2177			if (sta->pcpu_rx_stats) {
  2178				for_each_possible_cpu(cpu) {
  2179					struct ieee80211_sta_rx_stats *cpurxs;
  2180	
  2181					cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
  2182					sinfo->rx_bytes += sta_get_stats_bytes(cpurxs);
  2183				}
  2184			}
  2185	
  2186			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
  2187		}
  2188	
  2189		if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_PACKETS))) {
  2190			sinfo->rx_packets = sta->rx_stats.packets;
  2191			if (sta->pcpu_rx_stats) {
  2192				for_each_possible_cpu(cpu) {
  2193					struct ieee80211_sta_rx_stats *cpurxs;
  2194	
  2195					cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
  2196					sinfo->rx_packets += cpurxs->packets;
  2197				}
  2198			}
  2199			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
  2200		}
  2201	
  2202		if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_RETRIES))) {
  2203			sinfo->tx_retries = sta->status_stats.retry_count;
  2204			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
  2205		}
  2206	
  2207		if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))) {
  2208			sinfo->tx_failed = sta->status_stats.retry_failed;
  2209			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
  2210		}
  2211	
> 2212		if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_DURATION))) {
  2213			for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
  2214				sinfo->rx_duration += sta->airtime[ac].rx_airtime;
  2215			sinfo->filled |= BIT(NL80211_STA_INFO_RX_DURATION);
  2216		}
  2217	
  2218		if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_DURATION))) {
  2219			for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
  2220				sinfo->tx_duration += sta->airtime[ac].tx_airtime;
  2221			sinfo->filled |= BIT(NL80211_STA_INFO_TX_DURATION);
  2222		}
  2223	
  2224		if (!(sinfo->filled & BIT(NL80211_STA_INFO_AIRTIME_WEIGHT))) {
  2225			sinfo->airtime_weight = sta->airtime_weight;
  2226			sinfo->filled |= BIT(NL80211_STA_INFO_AIRTIME_WEIGHT);
  2227		}
  2228	
  2229		sinfo->rx_dropped_misc = sta->rx_stats.dropped;
  2230		if (sta->pcpu_rx_stats) {
  2231			for_each_possible_cpu(cpu) {
  2232				struct ieee80211_sta_rx_stats *cpurxs;
  2233	
  2234				cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
  2235				sinfo->rx_dropped_misc += cpurxs->dropped;
  2236			}
  2237		}
  2238	
  2239		if (sdata->vif.type == NL80211_IFTYPE_STATION &&
  2240		    !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) {
  2241			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX) |
  2242					 BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG);
  2243			sinfo->rx_beacon_signal_avg = ieee80211_ave_rssi(&sdata->vif);
  2244		}
  2245	
  2246		if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) ||
  2247		    ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) {
  2248			if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL))) {
  2249				sinfo->signal = (s8)last_rxstats->last_signal;
  2250				sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
  2251			}
  2252	
  2253			if (!sta->pcpu_rx_stats &&
  2254			    !(sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG))) {
  2255				sinfo->signal_avg =
  2256					-ewma_signal_read(&sta->rx_stats_avg.signal);
  2257				sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
  2258			}
  2259		}
  2260	
  2261		/* for the average - if pcpu_rx_stats isn't set - rxstats must point to
  2262		 * the sta->rx_stats struct, so the check here is fine with and without
  2263		 * pcpu statistics
  2264		 */
  2265		if (last_rxstats->chains &&
  2266		    !(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL) |
  2267				       BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) {
  2268			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
  2269			if (!sta->pcpu_rx_stats)
  2270				sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG);
  2271	
  2272			sinfo->chains = last_rxstats->chains;
  2273	
  2274			for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
  2275				sinfo->chain_signal[i] =
  2276					last_rxstats->chain_signal_last[i];
  2277				sinfo->chain_signal_avg[i] =
  2278					-ewma_signal_read(&sta->rx_stats_avg.chain_signal[i]);
  2279			}
  2280		}
  2281	
  2282		if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) {
  2283			sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate,
  2284					     &sinfo->txrate);
  2285			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
  2286		}
  2287	
  2288		if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE))) {
  2289			if (sta_set_rate_info_rx(sta, &sinfo->rxrate) == 0)
  2290				sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
  2291		}
  2292	
  2293		if (tidstats && !cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) {
  2294			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
  2295				struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i];
  2296	
  2297				sta_set_tidstats(sta, tidstats, i);
  2298			}
  2299		}
  2300	
  2301		if (ieee80211_vif_is_mesh(&sdata->vif)) {
  2302	#ifdef CONFIG_MAC80211_MESH
  2303			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_LLID) |
  2304					 BIT_ULL(NL80211_STA_INFO_PLID) |
  2305					 BIT_ULL(NL80211_STA_INFO_PLINK_STATE) |
  2306					 BIT_ULL(NL80211_STA_INFO_LOCAL_PM) |
  2307					 BIT_ULL(NL80211_STA_INFO_PEER_PM) |
  2308					 BIT_ULL(NL80211_STA_INFO_NONPEER_PM);
  2309	
  2310			sinfo->llid = sta->mesh->llid;
  2311			sinfo->plid = sta->mesh->plid;
  2312			sinfo->plink_state = sta->mesh->plink_state;
  2313			if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
  2314				sinfo->filled |= BIT_ULL(NL80211_STA_INFO_T_OFFSET);
  2315				sinfo->t_offset = sta->mesh->t_offset;
  2316			}
  2317			sinfo->local_pm = sta->mesh->local_pm;
  2318			sinfo->peer_pm = sta->mesh->peer_pm;
  2319			sinfo->nonpeer_pm = sta->mesh->nonpeer_pm;
  2320	#endif
  2321		}
  2322	
  2323		sinfo->bss_param.flags = 0;
  2324		if (sdata->vif.bss_conf.use_cts_prot)
  2325			sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
  2326		if (sdata->vif.bss_conf.use_short_preamble)
  2327			sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
  2328		if (sdata->vif.bss_conf.use_short_slot)
  2329			sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
  2330		sinfo->bss_param.dtim_period = sdata->vif.bss_conf.dtim_period;
  2331		sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
  2332	
  2333		sinfo->sta_flags.set = 0;
  2334		sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
  2335					BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
  2336					BIT(NL80211_STA_FLAG_WME) |
  2337					BIT(NL80211_STA_FLAG_MFP) |
  2338					BIT(NL80211_STA_FLAG_AUTHENTICATED) |
  2339					BIT(NL80211_STA_FLAG_ASSOCIATED) |
  2340					BIT(NL80211_STA_FLAG_TDLS_PEER);
  2341		if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
  2342			sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
  2343		if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
  2344			sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
  2345		if (sta->sta.wme)
  2346			sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
  2347		if (test_sta_flag(sta, WLAN_STA_MFP))
  2348			sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
  2349		if (test_sta_flag(sta, WLAN_STA_AUTH))
  2350			sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
  2351		if (test_sta_flag(sta, WLAN_STA_ASSOC))
  2352			sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
  2353		if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
  2354			sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
  2355	
  2356		thr = sta_get_expected_throughput(sta);
  2357	
  2358		if (thr != 0) {
  2359			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
  2360			sinfo->expected_throughput = thr;
  2361		}
  2362	
  2363		if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL)) &&
  2364		    sta->status_stats.ack_signal_filled) {
  2365			sinfo->ack_signal = sta->status_stats.last_ack_signal;
  2366			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
  2367		}
  2368	
  2369		if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG)) &&
  2370		    sta->status_stats.ack_signal_filled) {
  2371			sinfo->avg_ack_signal =
  2372				-(s8)ewma_avg_signal_read(
  2373					&sta->status_stats.avg_ack_signal);
  2374			sinfo->filled |=
  2375				BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
  2376		}
  2377	}
  2378	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kbuild test robot Nov. 12, 2018, 11:20 p.m. UTC | #2
Hi Toke,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mac80211/master]
[also build test WARNING on v4.20-rc1]
[cannot apply to next-20181112]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Rajkumar-Manoharan/Move-TXQ-scheduling-and-airtime-fairness-into-mac80211/20181111-072032
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git master
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

   include/net/cfg80211.h:4447: warning: Function parameter or member 'wext.prev_bssid_valid' not described in 'wireless_dev'
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/cfg80211.h:2846: warning: cannot understand function prototype: 'struct cfg80211_ftm_responder_stats '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:2400: warning: Function parameter or member 'radiotap_timestamp.units_pos' not described in 'ieee80211_hw'
   include/net/mac80211.h:2400: warning: Function parameter or member 'radiotap_timestamp.accuracy' not described in 'ieee80211_hw'
>> include/net/mac80211.h:2400: warning: Function parameter or member 'weight_multiplier' not described in 'ieee80211_hw'
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.rates' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.rts_cts_rate_idx' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.use_rts' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.use_cts_prot' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.short_preamble' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.skip_table' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.jiffies' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.vif' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.hw_key' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.flags' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'control.enqueue_time' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'ack' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'ack.cookie' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'status.rates' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'status.ack_signal' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'status.ampdu_ack_len' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'status.ampdu_len' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'status.antenna' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'status.tx_time' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'status.is_valid_ack_signal' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'status.status_driver_data' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'driver_rates' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'pad' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:1007: warning: Function parameter or member 'rate_driver_data' not described in 'ieee80211_tx_info'
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   include/net/mac80211.h:483: warning: cannot understand function prototype: 'struct ieee80211_ftm_responder_params '
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'rx_stats_avg' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'rx_stats_avg.signal' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'rx_stats_avg.chain_signal' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.filtered' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.retry_failed' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.retry_count' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.lost_packets' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.last_tdls_pkt_time' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.msdu_retries' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.msdu_failed' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.last_ack' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.last_ack_signal' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.ack_signal_filled' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'status_stats.avg_ack_signal' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'tx_stats.packets' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'tx_stats.bytes' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'tx_stats.last_rate' not described in 'sta_info'
   net/mac80211/sta_info.h:601: warning: Function parameter or member 'tx_stats.msdu' not described in 'sta_info'
>> net/mac80211/sta_info.h:601: warning: Function parameter or member 'airtime' not described in 'sta_info'
>> net/mac80211/sta_info.h:601: warning: Function parameter or member 'airtime_weight' not described in 'sta_info'
   kernel/rcu/tree.c:685: warning: Excess function parameter 'irq' description in 'rcu_nmi_exit'
   include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_excl.cb' not described in 'dma_buf'
   include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_excl.poll' not described in 'dma_buf'
   include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_excl.active' not described in 'dma_buf'
   include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_shared.cb' not described in 'dma_buf'
   include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_shared.poll' not described in 'dma_buf'
   include/linux/dma-buf.h:304: warning: Function parameter or member 'cb_shared.active' not described in 'dma_buf'
   include/linux/dma-fence-array.h:54: warning: Function parameter or member 'work' not described in 'dma_fence_array'
   include/linux/gpio/driver.h:375: warning: Function parameter or member 'init_valid_mask' not described in 'gpio_chip'
   include/linux/iio/hw-consumer.h:1: warning: no structured comments found
   include/linux/input/sparse-keymap.h:46: warning: Function parameter or member 'sw' not described in 'key_entry'
   drivers/mtd/nand/raw/nand_base.c:603: warning: Excess function parameter 'mtd' description in 'panic_nand_wait'
   drivers/mtd/nand/raw/nand_base.c:603: warning: Excess function parameter 'mtd' description in 'panic_nand_wait'
   include/linux/regulator/driver.h:227: warning: Function parameter or member 'resume' not described in 'regulator_ops'
   arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw0' not described in 'irb'
   arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw1' not described in 'irb'
   arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw2' not described in 'irb'
   arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw3' not described in 'irb'
   arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.eadm' not described in 'irb'
   drivers/slimbus/stream.c:1: warning: no structured comments found
   include/linux/spi/spi.h:177: warning: Function parameter or member 'driver_override' not described in 'spi_device'
   drivers/target/target_core_device.c:1: warning: no structured comments found
   drivers/usb/typec/bus.c:1: warning: no structured comments found
   drivers/usb/typec/class.c:1: warning: no structured comments found
   include/linux/w1.h:281: warning: Function parameter or member 'of_match_table' not described in 'w1_family'
   fs/direct-io.c:257: warning: Excess function parameter 'offset' description in 'dio_complete'
   fs/file_table.c:1: warning: no structured comments found
   fs/libfs.c:477: warning: Excess function parameter 'available' description in 'simple_write_end'
   fs/posix_acl.c:646: warning: Function parameter or member 'inode' not described in 'posix_acl_update_mode'
   fs/posix_acl.c:646: warning: Function parameter or member 'mode_p' not described in 'posix_acl_update_mode'
   fs/posix_acl.c:646: warning: Function parameter or member 'acl' not described in 'posix_acl_update_mode'
   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:183: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_read_lock'
   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:254: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_invalidate_range_start_gfx'
   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:302: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_invalidate_range_start_hsa'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:382: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:383: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:554: warning: Function parameter or member 'adev' not described in 'for_each_amdgpu_vm_pt_leaf'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:554: warning: Function parameter or member 'vm' not described in 'for_each_amdgpu_vm_pt_leaf'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:554: warning: Function parameter or member 'start' not described in 'for_each_amdgpu_vm_pt_leaf'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:554: warning: Function parameter or member 'end' not described in 'for_each_amdgpu_vm_pt_leaf'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:554: warning: Function parameter or member 'cursor' not described in 'for_each_amdgpu_vm_pt_leaf'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:602: warning: Function parameter or member 'adev' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:602: warning: Function parameter or member 'vm' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:602: warning: Function parameter or member 'cursor' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:602: warning: Function parameter or member 'entry' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:847: warning: Function parameter or member 'level' not described in 'amdgpu_vm_bo_param'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1355: warning: Function parameter or member 'params' not described in 'amdgpu_vm_update_func'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1355: warning: Function parameter or member 'bo' not described in 'amdgpu_vm_update_func'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1355: warning: Function parameter or member 'pe' not described in 'amdgpu_vm_update_func'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1355: warning: Function parameter or member 'addr' not described in 'amdgpu_vm_update_func'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1355: warning: Function parameter or member 'count' not described in 'amdgpu_vm_update_func'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1355: warning: Function parameter or member 'incr' not described in 'amdgpu_vm_update_func'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1355: warning: Function parameter or member 'flags' not described in 'amdgpu_vm_update_func'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1522: warning: Function parameter or member 'params' not described in 'amdgpu_vm_update_huge'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1522: warning: Function parameter or member 'bo' not described in 'amdgpu_vm_update_huge'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1522: warning: Function parameter or member 'level' not described in 'amdgpu_vm_update_huge'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1522: warning: Function parameter or member 'pe' not described in 'amdgpu_vm_update_huge'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1522: warning: Function parameter or member 'addr' not described in 'amdgpu_vm_update_huge'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1522: warning: Function parameter or member 'count' not described in 'amdgpu_vm_update_huge'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1522: warning: Function parameter or member 'incr' not described in 'amdgpu_vm_update_huge'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1522: warning: Function parameter or member 'flags' not described in 'amdgpu_vm_update_huge'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:3095: warning: Function parameter or member 'pasid' not described in 'amdgpu_vm_make_compute'
   include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_pin' not described in 'drm_driver'
   include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_unpin' not described in 'drm_driver'
   include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_res_obj' not described in 'drm_driver'
   include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_get_sg_table' not described in 'drm_driver'
   include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_import_sg_table' not described in 'drm_driver'
   include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_vmap' not described in 'drm_driver'
   include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_vunmap' not described in 'drm_driver'
   include/drm/drm_drv.h:609: warning: Function parameter or member 'gem_prime_mmap' not described in 'drm_driver'
   include/drm/drm_mode_config.h:869: warning: Function parameter or member 'quirk_addfb_prefer_xbgr_30bpp' not described in 'drm_mode_config'
   drivers/gpu/drm/drm_fourcc.c:112: warning: Function parameter or member 'dev' not described in 'drm_driver_legacy_fb_format'
   drivers/gpu/drm/drm_fourcc.c:112: warning: Excess function parameter 'native' description in 'drm_driver_legacy_fb_format'
   drivers/gpu/drm/i915/i915_vma.h:49: warning: cannot understand function prototype: 'struct i915_vma '
   drivers/gpu/drm/i915/i915_vma.h:1: warning: no structured comments found
   drivers/gpu/drm/i915/intel_guc_fwif.h:554: warning: cannot understand function prototype: 'struct guc_log_buffer_state '
   drivers/gpu/drm/i915/i915_trace.h:1: warning: no structured comments found
   include/linux/skbuff.h:862: warning: Function parameter or member 'dev_scratch' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'list' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'ip_defrag_offset' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'skb_mstamp_ns' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member '__cloned_offset' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'head_frag' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member '__pkt_type_offset' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'encapsulation' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'encap_hdr_csum' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'csum_valid' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'csum_complete_sw' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'csum_level' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'inner_protocol_type' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'remcsum_offload' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'offload_fwd_mark' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'offload_mr_fwd_mark' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'sender_cpu' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'reserved_tailroom' not described in 'sk_buff'
   include/linux/skbuff.h:862: warning: Function parameter or member 'inner_ipproto' not described in 'sk_buff'
   include/net/sock.h:238: warning: Function parameter or member 'skc_addrpair' not described in 'sock_common'
   include/net/sock.h:238: warning: Function parameter or member 'skc_portpair' not described in 'sock_common'
   include/net/sock.h:238: warning: Function parameter or member 'skc_ipv6only' not described in 'sock_common'
   include/net/sock.h:238: warning: Function parameter or member 'skc_net_refcnt' not described in 'sock_common'

vim +2400 include/net/mac80211.h

1bc0826c8f Johannes Berg          2007-09-18  2242  
7ac1bd6aec Johannes Berg          2007-09-14  2243  /**
7ac1bd6aec Johannes Berg          2007-09-14  2244   * struct ieee80211_hw - hardware information and state
75a5f0ccfd Johannes Berg          2007-09-18  2245   *
75a5f0ccfd Johannes Berg          2007-09-18  2246   * This structure contains the configuration and hardware
75a5f0ccfd Johannes Berg          2007-09-18  2247   * information for an 802.11 PHY.
75a5f0ccfd Johannes Berg          2007-09-18  2248   *
75a5f0ccfd Johannes Berg          2007-09-18  2249   * @wiphy: This points to the &struct wiphy allocated for this
75a5f0ccfd Johannes Berg          2007-09-18  2250   *	802.11 PHY. You must fill in the @perm_addr and @dev
75a5f0ccfd Johannes Berg          2007-09-18  2251   *	members of this structure using SET_IEEE80211_DEV()
8318d78a44 Johannes Berg          2008-01-24  2252   *	and SET_IEEE80211_PERM_ADDR(). Additionally, all supported
8318d78a44 Johannes Berg          2008-01-24  2253   *	bands (with channels, bitrates) are registered here.
75a5f0ccfd Johannes Berg          2007-09-18  2254   *
75a5f0ccfd Johannes Berg          2007-09-18  2255   * @conf: &struct ieee80211_conf, device configuration, don't use.
75a5f0ccfd Johannes Berg          2007-09-18  2256   *
75a5f0ccfd Johannes Berg          2007-09-18  2257   * @priv: pointer to private area that was allocated for driver use
75a5f0ccfd Johannes Berg          2007-09-18  2258   *	along with this structure.
75a5f0ccfd Johannes Berg          2007-09-18  2259   *
75a5f0ccfd Johannes Berg          2007-09-18  2260   * @flags: hardware flags, see &enum ieee80211_hw_flags.
75a5f0ccfd Johannes Berg          2007-09-18  2261   *
75a5f0ccfd Johannes Berg          2007-09-18  2262   * @extra_tx_headroom: headroom to reserve in each transmit skb
75a5f0ccfd Johannes Berg          2007-09-18  2263   *	for use by the driver (e.g. for transmit headers.)
75a5f0ccfd Johannes Berg          2007-09-18  2264   *
70dabeb74e Felix Fietkau          2013-12-14  2265   * @extra_beacon_tailroom: tailroom to reserve in each beacon tx skb.
70dabeb74e Felix Fietkau          2013-12-14  2266   *	Can be used by drivers to add extra IEs.
75a5f0ccfd Johannes Berg          2007-09-18  2267   *
566bfe5a8b Bruno Randolf          2008-05-08  2268   * @max_signal: Maximum value for signal (rssi) in RX information, used
566bfe5a8b Bruno Randolf          2008-05-08  2269   *	only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
75a5f0ccfd Johannes Berg          2007-09-18  2270   *
ea95bba41e Tomas Winkler          2008-07-18  2271   * @max_listen_interval: max listen interval in units of beacon interval
ea95bba41e Tomas Winkler          2008-07-18  2272   *	that HW supports
ea95bba41e Tomas Winkler          2008-07-18  2273   *
75a5f0ccfd Johannes Berg          2007-09-18  2274   * @queues: number of available hardware transmit queues for
e100bb64bf Johannes Berg          2008-04-30  2275   *	data packets. WMM/QoS requires at least four, these
e100bb64bf Johannes Berg          2008-04-30  2276   *	queues need to have configurable access parameters.
e100bb64bf Johannes Berg          2008-04-30  2277   *
830f903866 Johannes Berg          2007-10-28  2278   * @rate_control_algorithm: rate control algorithm for this hardware.
830f903866 Johannes Berg          2007-10-28  2279   *	If unset (NULL), the default algorithm will be used. Must be
830f903866 Johannes Berg          2007-10-28  2280   *	set before calling ieee80211_register_hw().
32bfd35d4b Johannes Berg          2007-12-19  2281   *
32bfd35d4b Johannes Berg          2007-12-19  2282   * @vif_data_size: size (in bytes) of the drv_priv data area
32bfd35d4b Johannes Berg          2007-12-19  2283   *	within &struct ieee80211_vif.
17741cdc26 Johannes Berg          2008-09-11  2284   * @sta_data_size: size (in bytes) of the drv_priv data area
17741cdc26 Johannes Berg          2008-09-11  2285   *	within &struct ieee80211_sta.
d01a1e6586 Michal Kazior          2012-06-26  2286   * @chanctx_data_size: size (in bytes) of the drv_priv data area
d01a1e6586 Michal Kazior          2012-06-26  2287   *	within &struct ieee80211_chanctx_conf.
ba8c3d6f16 Felix Fietkau          2015-03-27  2288   * @txq_data_size: size (in bytes) of the drv_priv data area
ba8c3d6f16 Felix Fietkau          2015-03-27  2289   *	within @struct ieee80211_txq.
870abdf671 Felix Fietkau          2008-10-05  2290   *
78be49ec2a Helmut Schaa           2010-10-02  2291   * @max_rates: maximum number of alternate rate retry stages the hw
78be49ec2a Helmut Schaa           2010-10-02  2292   *	can handle.
78be49ec2a Helmut Schaa           2010-10-02  2293   * @max_report_rates: maximum number of alternate rate retry stages
78be49ec2a Helmut Schaa           2010-10-02  2294   *	the hw can report back.
e6a9854b05 Johannes Berg          2008-10-21  2295   * @max_rate_tries: maximum number of tries for each stage
4e6cbfd09c John W. Linville       2010-07-29  2296   *
df6ba5d80d Luciano Coelho         2011-01-12  2297   * @max_rx_aggregation_subframes: maximum buffer size (number of
df6ba5d80d Luciano Coelho         2011-01-12  2298   *	sub-frames) to be used for A-MPDU block ack receiver
df6ba5d80d Luciano Coelho         2011-01-12  2299   *	aggregation.
df6ba5d80d Luciano Coelho         2011-01-12  2300   *	This is only relevant if the device has restrictions on the
df6ba5d80d Luciano Coelho         2011-01-12  2301   *	number of subframes, if it relies on mac80211 to do reordering
df6ba5d80d Luciano Coelho         2011-01-12  2302   *	it shouldn't be set.
5dd36bc933 Johannes Berg          2011-01-18  2303   *
5dd36bc933 Johannes Berg          2011-01-18  2304   * @max_tx_aggregation_subframes: maximum number of subframes in an
41cbb0f5a2 Luca Coelho            2018-06-09  2305   *	aggregate an HT/HE device will transmit. In HT AddBA we'll
41cbb0f5a2 Luca Coelho            2018-06-09  2306   *	advertise a constant value of 64 as some older APs crash if
41cbb0f5a2 Luca Coelho            2018-06-09  2307   *	the window size is smaller (an example is LinkSys WRT120N
41cbb0f5a2 Luca Coelho            2018-06-09  2308   *	with FW v1.0.07 build 002 Jun 18 2012).
41cbb0f5a2 Luca Coelho            2018-06-09  2309   *	For AddBA to HE capable peers this value will be used.
3a25a8c8b7 Johannes Berg          2012-04-03  2310   *
6e0456b545 Felix Fietkau          2016-03-03  2311   * @max_tx_fragments: maximum number of tx buffers per (A)-MSDU, sum
6e0456b545 Felix Fietkau          2016-03-03  2312   *	of 1 + skb_shinfo(skb)->nr_frags for each skb in the frag_list.
6e0456b545 Felix Fietkau          2016-03-03  2313   *
3a25a8c8b7 Johannes Berg          2012-04-03  2314   * @offchannel_tx_hw_queue: HW queue ID to use for offchannel TX
3a25a8c8b7 Johannes Berg          2012-04-03  2315   *	(if %IEEE80211_HW_QUEUE_CONTROL is set)
ac55d2fe05 Johannes Berg          2012-05-10  2316   *
ac55d2fe05 Johannes Berg          2012-05-10  2317   * @radiotap_mcs_details: lists which MCS information can the HW
ac55d2fe05 Johannes Berg          2012-05-10  2318   *	reports, by default it is set to _MCS, _GI and _BW but doesn't
b4f7f4ad42 Jani Nikula            2016-10-21  2319   *	include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_\* values, only
ac55d2fe05 Johannes Berg          2012-05-10  2320   *	adding _BW is supported today.
72d7872852 Arik Nemtsov           2012-05-10  2321   *
5164892184 Johannes Berg          2012-11-22  2322   * @radiotap_vht_details: lists which VHT MCS information the HW reports,
5164892184 Johannes Berg          2012-11-22  2323   *	the default is _GI | _BANDWIDTH.
b4f7f4ad42 Jani Nikula            2016-10-21  2324   *	Use the %IEEE80211_RADIOTAP_VHT_KNOWN_\* values.
5164892184 Johannes Berg          2012-11-22  2325   *
41cbb0f5a2 Luca Coelho            2018-06-09  2326   * @radiotap_he: HE radiotap validity flags
41cbb0f5a2 Luca Coelho            2018-06-09  2327   *
99ee7cae3b Johannes Berg          2016-08-29  2328   * @radiotap_timestamp: Information for the radiotap timestamp field; if the
99ee7cae3b Johannes Berg          2016-08-29  2329   *	'units_pos' member is set to a non-negative value it must be set to
99ee7cae3b Johannes Berg          2016-08-29  2330   *	a combination of a IEEE80211_RADIOTAP_TIMESTAMP_UNIT_* and a
99ee7cae3b Johannes Berg          2016-08-29  2331   *	IEEE80211_RADIOTAP_TIMESTAMP_SPOS_* value, and then the timestamp
99ee7cae3b Johannes Berg          2016-08-29  2332   *	field will be added and populated from the &struct ieee80211_rx_status
99ee7cae3b Johannes Berg          2016-08-29  2333   *	device_timestamp. If the 'accuracy' member is non-negative, it's put
99ee7cae3b Johannes Berg          2016-08-29  2334   *	into the accuracy radiotap field and the accuracy known flag is set.
99ee7cae3b Johannes Berg          2016-08-29  2335   *
72d7872852 Arik Nemtsov           2012-05-10  2336   * @netdev_features: netdev features to be set in each netdev created
680a0daba7 Johannes Berg          2015-04-13  2337   *	from this HW. Note that not all features are usable with mac80211,
680a0daba7 Johannes Berg          2015-04-13  2338   *	other features will be rejected during HW registration.
219c38674c Alexander Bondar       2013-01-22  2339   *
219c38674c Alexander Bondar       2013-01-22  2340   * @uapsd_queues: This bitmap is included in (re)association frame to indicate
219c38674c Alexander Bondar       2013-01-22  2341   *	for each access category if it is uAPSD trigger-enabled and delivery-
219c38674c Alexander Bondar       2013-01-22  2342   *	enabled. Use IEEE80211_WMM_IE_STA_QOSINFO_AC_* to set this bitmap.
219c38674c Alexander Bondar       2013-01-22  2343   *	Each bit corresponds to different AC. Value '1' in specific bit means
219c38674c Alexander Bondar       2013-01-22  2344   *	that corresponding AC is both trigger- and delivery-enabled. '0' means
219c38674c Alexander Bondar       2013-01-22  2345   *	neither enabled.
219c38674c Alexander Bondar       2013-01-22  2346   *
219c38674c Alexander Bondar       2013-01-22  2347   * @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP may
219c38674c Alexander Bondar       2013-01-22  2348   *	deliver to a WMM STA during any Service Period triggered by the WMM STA.
219c38674c Alexander Bondar       2013-01-22  2349   *	Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values.
2475b1cc0d Max Stepanov           2013-03-24  2350   *
2475b1cc0d Max Stepanov           2013-03-24  2351   * @n_cipher_schemes: a size of an array of cipher schemes definitions.
2475b1cc0d Max Stepanov           2013-03-24  2352   * @cipher_schemes: a pointer to an array of cipher scheme definitions
2475b1cc0d Max Stepanov           2013-03-24  2353   *	supported by HW.
167e33f4f6 Ayala Beker            2016-09-20  2354   * @max_nan_de_entries: maximum number of NAN DE functions supported by the
167e33f4f6 Ayala Beker            2016-09-20  2355   *	device.
70e53669c4 Wen Gong               2018-08-08  2356   *
70e53669c4 Wen Gong               2018-08-08  2357   * @tx_sk_pacing_shift: Pacing shift to set on TCP sockets when frames from
70e53669c4 Wen Gong               2018-08-08  2358   *	them are encountered. The default should typically not be changed,
70e53669c4 Wen Gong               2018-08-08  2359   *	unless the driver has good reasons for needing more buffers.
30e0c99838 Toke Høiland-Jørgensen 2018-11-09  2360   *
30e0c99838 Toke Høiland-Jørgensen 2018-11-09  2361   * @weight_multipler: Driver specific airtime weight multiplier used while
30e0c99838 Toke Høiland-Jørgensen 2018-11-09  2362   *	refilling deficit of each TXQ.
7ac1bd6aec Johannes Berg          2007-09-14  2363   */
f0706e828e Jiri Benc              2007-05-05  2364  struct ieee80211_hw {
f0706e828e Jiri Benc              2007-05-05  2365  	struct ieee80211_conf conf;
75a5f0ccfd Johannes Berg          2007-09-18  2366  	struct wiphy *wiphy;
830f903866 Johannes Berg          2007-10-28  2367  	const char *rate_control_algorithm;
f0706e828e Jiri Benc              2007-05-05  2368  	void *priv;
30686bf7f5 Johannes Berg          2015-06-02  2369  	unsigned long flags[BITS_TO_LONGS(NUM_IEEE80211_HW_FLAGS)];
f0706e828e Jiri Benc              2007-05-05  2370  	unsigned int extra_tx_headroom;
70dabeb74e Felix Fietkau          2013-12-14  2371  	unsigned int extra_beacon_tailroom;
32bfd35d4b Johannes Berg          2007-12-19  2372  	int vif_data_size;
17741cdc26 Johannes Berg          2008-09-11  2373  	int sta_data_size;
d01a1e6586 Michal Kazior          2012-06-26  2374  	int chanctx_data_size;
ba8c3d6f16 Felix Fietkau          2015-03-27  2375  	int txq_data_size;
ea95bba41e Tomas Winkler          2008-07-18  2376  	u16 queues;
ea95bba41e Tomas Winkler          2008-07-18  2377  	u16 max_listen_interval;
f0706e828e Jiri Benc              2007-05-05  2378  	s8 max_signal;
e6a9854b05 Johannes Berg          2008-10-21  2379  	u8 max_rates;
78be49ec2a Helmut Schaa           2010-10-02  2380  	u8 max_report_rates;
e6a9854b05 Johannes Berg          2008-10-21  2381  	u8 max_rate_tries;
41cbb0f5a2 Luca Coelho            2018-06-09  2382  	u16 max_rx_aggregation_subframes;
41cbb0f5a2 Luca Coelho            2018-06-09  2383  	u16 max_tx_aggregation_subframes;
6e0456b545 Felix Fietkau          2016-03-03  2384  	u8 max_tx_fragments;
3a25a8c8b7 Johannes Berg          2012-04-03  2385  	u8 offchannel_tx_hw_queue;
ac55d2fe05 Johannes Berg          2012-05-10  2386  	u8 radiotap_mcs_details;
5164892184 Johannes Berg          2012-11-22  2387  	u16 radiotap_vht_details;
99ee7cae3b Johannes Berg          2016-08-29  2388  	struct {
99ee7cae3b Johannes Berg          2016-08-29  2389  		int units_pos;
99ee7cae3b Johannes Berg          2016-08-29  2390  		s16 accuracy;
99ee7cae3b Johannes Berg          2016-08-29  2391  	} radiotap_timestamp;
72d7872852 Arik Nemtsov           2012-05-10  2392  	netdev_features_t netdev_features;
219c38674c Alexander Bondar       2013-01-22  2393  	u8 uapsd_queues;
219c38674c Alexander Bondar       2013-01-22  2394  	u8 uapsd_max_sp_len;
2475b1cc0d Max Stepanov           2013-03-24  2395  	u8 n_cipher_schemes;
2475b1cc0d Max Stepanov           2013-03-24  2396  	const struct ieee80211_cipher_scheme *cipher_schemes;
167e33f4f6 Ayala Beker            2016-09-20  2397  	u8 max_nan_de_entries;
70e53669c4 Wen Gong               2018-08-08  2398  	u8 tx_sk_pacing_shift;
30e0c99838 Toke Høiland-Jørgensen 2018-11-09  2399  	u8 weight_multiplier;
f0706e828e Jiri Benc              2007-05-05 @2400  };
f0706e828e Jiri Benc              2007-05-05  2401  

:::::: The code at line 2400 was first introduced by commit
:::::: f0706e828e96d0fa4e80c0d25aa98523f6d589a0 [MAC80211]: Add mac80211 wireless stack.

:::::: TO: Jiri Benc <jbenc@suse.cz>
:::::: CC: David S. Miller <davem@davemloft.net>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Patch
diff mbox series

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 18b11c119b7e..c43d615ee9b1 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2357,6 +2357,9 @@  enum ieee80211_hw_flags {
  * @tx_sk_pacing_shift: Pacing shift to set on TCP sockets when frames from
  *	them are encountered. The default should typically not be changed,
  *	unless the driver has good reasons for needing more buffers.
+ *
+ * @weight_multipler: Driver specific airtime weight multiplier used while
+ *	refilling deficit of each TXQ.
  */
 struct ieee80211_hw {
 	struct ieee80211_conf conf;
@@ -2393,6 +2396,7 @@  struct ieee80211_hw {
 	const struct ieee80211_cipher_scheme *cipher_schemes;
 	u8 max_nan_de_entries;
 	u8 tx_sk_pacing_shift;
+	u8 weight_multiplier;
 };
 
 static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw,
@@ -5393,6 +5397,34 @@  void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
 void ieee80211_send_eosp_nullfunc(struct ieee80211_sta *pubsta, int tid);
 
 /**
+ * ieee80211_sta_register_airtime - register airtime usage for a sta/tid
+ *
+ * Register airtime usage for a given sta on a given tid. The driver can call
+ * this function to notify mac80211 that a station used a certain amount of
+ * airtime. This information will be used by the TXQ scheduler to schedule
+ * stations in a way that ensures airtime fairness.
+ *
+ * The reported airtime should as a minimum include all time that is spent
+ * transmitting to the remote station, including overhead and padding, but not
+ * including time spent waiting for a TXOP. If the time is not reported by the
+ * hardware it can in some cases be calculated from the rate and known frame
+ * composition. When possible, the time should include any failed transmission
+ * attempts.
+ *
+ * The driver can either call this function synchronously for every packet or
+ * aggregate, or asynchronously as airtime usage information becomes available.
+ * TX and RX airtime can be reported together, or separately by setting one of
+ * them to 0.
+ *
+ * @pubsta: the station
+ * @tid: the TID to register airtime for
+ * @tx_airtime: airtime used during TX (in usec)
+ * @rx_airtime: airtime used during RX (in usec)
+ */
+void ieee80211_sta_register_airtime(struct ieee80211_sta *pubsta, u8 tid,
+				    u32 tx_airtime, u32 rx_airtime);
+
+/**
  * ieee80211_iter_keys - iterate keys programmed into the device
  * @hw: pointer obtained from ieee80211_alloc_hw()
  * @vif: virtual interface to iterate, may be %NULL for all
@@ -6150,6 +6182,33 @@  struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
 void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac);
 
 /**
+ * ieee80211_txq_may_transmit - check whether TXQ is allowed to transmit
+ *
+ * This function is used to check whether given txq is allowed to transmit by
+ * the airtime scheduler, and can be used by drivers to access the airtime
+ * fairness accounting without going using the scheduling order enfored by
+ * next_txq().
+ *
+ * Returns %true if the airtime scheduler thinks the TXQ should be allowed to
+ * transmit, and %false if it should be throttled. This function can also have
+ * the side effect of rotating the TXQ in the scheduler rotation, which will
+ * eventually bring the deficit to positive and allow the station to transmit
+ * again.
+ *
+ * The API ieee80211_txq_may_transmit() also ensures that TXQ list will be
+ * aligned aginst driver's own round-robin scheduler list. i.e it rotates
+ * the TXQ list till it makes the requested node becomes the first entry
+ * in TXQ list. Thus both the TXQ list and driver's list are in sync. If this
+ * function returns %true, the driver is expected to schedule packets
+ * for transmission, and then return the TXQ through ieee80211_return_txq().
+ *
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @txq: pointer obtained from station or virtual interface
+ */
+bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
+				struct ieee80211_txq *txq);
+
+/**
  * ieee80211_txq_get_depth - get pending frame/byte count of given txq
  *
  * The values are not guaranteed to be coherent with regard to each other, i.e.
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 818aa0060349..57c59e5ceb98 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1447,6 +1447,9 @@  static int sta_apply_parameters(struct ieee80211_local *local,
 	if (ieee80211_vif_is_mesh(&sdata->vif))
 		sta_apply_mesh_params(local, sta, params);
 
+	if (params->airtime_weight)
+		sta->airtime_weight = params->airtime_weight;
+
 	/* set the STA state after all sta info from usermode has been set */
 	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) ||
 	    set & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 3fe541e358f3..81c5fec2eae7 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -383,6 +383,9 @@  void debugfs_hw_add(struct ieee80211_local *local)
 	if (local->ops->wake_tx_queue)
 		DEBUGFS_ADD_MODE(aqm, 0600);
 
+	debugfs_create_u16("airtime_flags", 0600,
+			   phyd, &local->airtime_flags);
+
 	statsd = debugfs_create_dir("statistics", phyd);
 
 	/* if the dir failed, don't put all the other things into the root! */
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index af5185a836e5..446908ab3f5d 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -181,9 +181,9 @@  static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
 			       txqi->tin.tx_bytes,
 			       txqi->tin.tx_packets,
 			       txqi->flags,
-			       txqi->flags & (1<<IEEE80211_TXQ_STOP) ? "STOP" : "RUN",
-			       txqi->flags & (1<<IEEE80211_TXQ_AMPDU) ? " AMPDU" : "",
-			       txqi->flags & (1<<IEEE80211_TXQ_NO_AMSDU) ? " NO-AMSDU" : "");
+			       test_bit(IEEE80211_TXQ_STOP, &txqi->flags) ? "STOP" : "RUN",
+			       test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags) ? " AMPDU" : "",
+			       test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags) ? " NO-AMSDU" : "");
 	}
 
 	rcu_read_unlock();
@@ -195,6 +195,46 @@  static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
 }
 STA_OPS(aqm);
 
+static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,
+				size_t count, loff_t *ppos)
+{
+	struct sta_info *sta = file->private_data;
+	struct ieee80211_local *local = sta->sdata->local;
+	size_t bufsz = 200;
+	char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
+	u64 rx_airtime = 0, tx_airtime = 0;
+	s64 deficit[IEEE80211_NUM_ACS];
+	ssize_t rv;
+	int ac;
+
+	if (!buf)
+		return -ENOMEM;
+
+	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+		spin_lock_bh(&local->active_txq_lock[ac]);
+		rx_airtime += sta->airtime[ac].rx_airtime;
+		tx_airtime += sta->airtime[ac].tx_airtime;
+		deficit[ac] = sta->airtime[ac].deficit;
+		spin_unlock_bh(&local->active_txq_lock[ac]);
+	}
+
+	p += scnprintf(p, bufsz + buf - p,
+		"RX: %llu us\nTX: %llu us\nWeight: %u\n"
+		"Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n",
+		rx_airtime,
+		tx_airtime,
+		sta->airtime_weight,
+		deficit[0],
+		deficit[1],
+		deficit[2],
+		deficit[3]);
+
+	rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+	kfree(buf);
+	return rv;
+}
+STA_OPS(airtime);
+
 static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
 					size_t count, loff_t *ppos)
 {
@@ -906,6 +946,10 @@  void ieee80211_sta_debugfs_add(struct sta_info *sta)
 	if (local->ops->wake_tx_queue)
 		DEBUGFS_ADD(aqm);
 
+	if (wiphy_ext_feature_isset(local->hw.wiphy,
+				    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
+		DEBUGFS_ADD(airtime);
+
 	if (sizeof(sta->driver_buffered_tids) == sizeof(u32))
 		debugfs_create_x32("driver_buffered_tids", 0400,
 				   sta->debugfs_dir,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 33763a2eac81..c5b6ba571288 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1137,6 +1137,8 @@  struct ieee80211_local {
 	struct list_head active_txqs[IEEE80211_NUM_ACS];
 	u16 schedule_round[IEEE80211_NUM_ACS];
 
+	u16 airtime_flags;
+
 	const struct ieee80211_ops *ops;
 
 	/*
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ba64757afea4..3710727fa9c1 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -667,6 +667,7 @@  struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
 		INIT_LIST_HEAD(&local->active_txqs[i]);
 		spin_lock_init(&local->active_txq_lock[i]);
 	}
+	local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
 
 	INIT_LIST_HEAD(&local->chanctx_list);
 	mutex_init(&local->chanctx_mtx);
@@ -1153,6 +1154,9 @@  int ieee80211_register_hw(struct ieee80211_hw *hw)
 	if (!local->hw.max_nan_de_entries)
 		local->hw.max_nan_de_entries = IEEE80211_MAX_NAN_INSTANCE_ID;
 
+	if (!local->hw.weight_multiplier)
+		local->hw.weight_multiplier = 1;
+
 	result = ieee80211_wep_init(local);
 	if (result < 0)
 		wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index c2f5cb7df54f..114277ff3624 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -90,7 +90,6 @@  static void __cleanup_single_sta(struct sta_info *sta)
 	struct tid_ampdu_tx *tid_tx;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 	struct ieee80211_local *local = sdata->local;
-	struct fq *fq = &local->fq;
 	struct ps_data *ps;
 
 	if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
@@ -120,9 +119,7 @@  static void __cleanup_single_sta(struct sta_info *sta)
 
 			txqi = to_txq_info(sta->sta.txq[i]);
 
-			spin_lock_bh(&fq->lock);
 			ieee80211_txq_purge(local, txqi);
-			spin_unlock_bh(&fq->lock);
 		}
 	}
 
@@ -387,9 +384,12 @@  struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 	if (sta_prepare_rate_control(local, sta, gfp))
 		goto free_txq;
 
+	sta->airtime_weight = IEEE80211_DEFAULT_AIRTIME_WEIGHT;
+
 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
 		skb_queue_head_init(&sta->ps_tx_buf[i]);
 		skb_queue_head_init(&sta->tx_filtered[i]);
+		sta->airtime[i].deficit = sta->airtime_weight;
 	}
 
 	for (i = 0; i < IEEE80211_NUM_TIDS; i++)
@@ -1826,6 +1826,27 @@  void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
 }
 EXPORT_SYMBOL(ieee80211_sta_set_buffered);
 
+void ieee80211_sta_register_airtime(struct ieee80211_sta *pubsta, u8 tid,
+				    u32 tx_airtime, u32 rx_airtime)
+{
+	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+	struct ieee80211_local *local = sta->sdata->local;
+	u8 ac = ieee80211_ac_from_tid(tid);
+	u32 airtime = 0;
+
+	if (sta->local->airtime_flags & AIRTIME_USE_TX)
+		airtime += tx_airtime;
+	if (sta->local->airtime_flags & AIRTIME_USE_RX)
+		airtime += rx_airtime;
+
+	spin_lock_bh(&local->active_txq_lock[ac]);
+	sta->airtime[ac].tx_airtime += tx_airtime;
+	sta->airtime[ac].rx_airtime += rx_airtime;
+	sta->airtime[ac].deficit -= airtime;
+	spin_unlock_bh(&local->active_txq_lock[ac]);
+}
+EXPORT_SYMBOL(ieee80211_sta_register_airtime);
+
 int sta_info_move_state(struct sta_info *sta,
 			enum ieee80211_sta_state new_state)
 {
@@ -2188,6 +2209,23 @@  void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
 		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
 	}
 
+	if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_DURATION))) {
+		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+			sinfo->rx_duration += sta->airtime[ac].rx_airtime;
+		sinfo->filled |= BIT(NL80211_STA_INFO_RX_DURATION);
+	}
+
+	if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_DURATION))) {
+		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+			sinfo->tx_duration += sta->airtime[ac].tx_airtime;
+		sinfo->filled |= BIT(NL80211_STA_INFO_TX_DURATION);
+	}
+
+	if (!(sinfo->filled & BIT(NL80211_STA_INFO_AIRTIME_WEIGHT))) {
+		sinfo->airtime_weight = sta->airtime_weight;
+		sinfo->filled |= BIT(NL80211_STA_INFO_AIRTIME_WEIGHT);
+	}
+
 	sinfo->rx_dropped_misc = sta->rx_stats.dropped;
 	if (sta->pcpu_rx_stats) {
 		for_each_possible_cpu(cpu) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 9a04327d71d1..b1b0fd6a2e21 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -127,6 +127,16 @@  enum ieee80211_agg_stop_reason {
 	AGG_STOP_DESTROY_STA,
 };
 
+/* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */
+#define AIRTIME_USE_TX		BIT(0)
+#define AIRTIME_USE_RX		BIT(1)
+
+struct airtime_info {
+	u64 rx_airtime;
+	u64 tx_airtime;
+	s64 deficit;
+};
+
 struct sta_info;
 
 /**
@@ -563,6 +573,9 @@  struct sta_info {
 	} tx_stats;
 	u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
 
+	struct airtime_info airtime[IEEE80211_NUM_ACS];
+	u16 airtime_weight;
+
 	/*
 	 * Aggregation information, locked with lock.
 	 */
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index aa4afbf0abaf..a1f1256448f5 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -818,6 +818,12 @@  static void __ieee80211_tx_status(struct ieee80211_hw *hw,
 			ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
 						acked, info->status.tx_time);
 
+		if (info->status.tx_time &&
+		    wiphy_ext_feature_isset(local->hw.wiphy,
+					    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
+			ieee80211_sta_register_airtime(&sta->sta, tid,
+						       info->status.tx_time, 0);
+
 		if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
 			if (info->flags & IEEE80211_TX_STAT_ACK) {
 				if (sta->status_stats.lost_packets)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 305965283506..dd2354188357 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1488,8 +1488,11 @@  void ieee80211_txq_purge(struct ieee80211_local *local,
 	struct fq *fq = &local->fq;
 	struct fq_tin *tin = &txqi->tin;
 
+	spin_lock_bh(&fq->lock);
 	fq_tin_reset(fq, tin, fq_skb_free_func);
 	ieee80211_purge_tx_queue(&local->hw, &txqi->frags);
+	spin_unlock_bh(&fq->lock);
+
 	spin_lock_bh(&local->active_txq_lock[txqi->txq.ac]);
 	list_del_init(&txqi->schedule_order);
 	spin_unlock_bh(&local->active_txq_lock[txqi->txq.ac]);
@@ -3638,11 +3641,28 @@  struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
 
 	lockdep_assert_held(&local->active_txq_lock[ac]);
 
+ begin:
 	txqi = list_first_entry_or_null(&local->active_txqs[ac],
 					struct txq_info,
 					schedule_order);
+	if (!txqi)
+		return NULL;
+
+	if (txqi->txq.sta) {
+		struct sta_info *sta = container_of(txqi->txq.sta,
+						struct sta_info, sta);
+
+		if (sta->airtime[txqi->txq.ac].deficit < 0) {
+			sta->airtime[txqi->txq.ac].deficit +=
+				sta->airtime_weight;
+			list_move_tail(&txqi->schedule_order,
+				       &local->active_txqs[txqi->txq.ac]);
+			goto begin;
+		}
+	}
+
 
-	if (!txqi || txqi->schedule_round == local->schedule_round[ac])
+	if (txqi->schedule_round == local->schedule_round[ac])
 		return NULL;
 
 	list_del_init(&txqi->schedule_order);
@@ -3660,12 +3680,74 @@  void ieee80211_return_txq(struct ieee80211_hw *hw,
 	lockdep_assert_held(&local->active_txq_lock[txq->ac]);
 
 	if (list_empty(&txqi->schedule_order) &&
-	    (!skb_queue_empty(&txqi->frags) || txqi->tin.backlog_packets))
-		list_add_tail(&txqi->schedule_order,
-			      &local->active_txqs[txq->ac]);
+	    (!skb_queue_empty(&txqi->frags) || txqi->tin.backlog_packets)) {
+		/* If airtime accounting is active, always enqueue STAs at the
+		 * head of the list to ensure that they only get moved to the
+		 * back by the airtime DRR scheduler once they have a negative
+		 * deficit. A station that already has a negative deficit will
+		 * get immediately moved to the back of the list on the next
+		 * call to ieee80211_next_txq().
+		 */
+		if (wiphy_ext_feature_isset(local->hw.wiphy,
+					    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)
+		    && txqi->txq.sta)
+			list_add(&txqi->schedule_order,
+				 &local->active_txqs[txq->ac]);
+		else
+			list_add_tail(&txqi->schedule_order,
+				      &local->active_txqs[txq->ac]);
+	}
 }
 EXPORT_SYMBOL(ieee80211_return_txq);
 
+bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
+				struct ieee80211_txq *txq)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct txq_info *iter, *tmp, *txqi = to_txq_info(txq);
+	struct sta_info *sta;
+	u8 ac = txq->ac;
+
+	lockdep_assert_held(&local->active_txq_lock[ac]);
+
+	if (!txqi->txq.sta)
+		goto out;
+
+	if (list_empty(&txqi->schedule_order))
+		goto out;
+
+	list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac],
+				 schedule_order) {
+		if (iter == txqi)
+			break;
+
+		if (!iter->txq.sta) {
+			list_move_tail(&iter->schedule_order,
+				       &local->active_txqs[ac]);
+			continue;
+		}
+		sta = container_of(iter->txq.sta, struct sta_info, sta);
+		if (sta->airtime[ac].deficit < 0)
+			sta->airtime[ac].deficit += sta->airtime_weight;
+		list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
+	}
+
+	sta = container_of(txqi->txq.sta, struct sta_info, sta);
+	if (sta->airtime[ac].deficit >= 0)
+		goto out;
+
+	sta->airtime[ac].deficit += sta->airtime_weight;
+	list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]);
+
+	return false;
+out:
+	if (!list_empty(&txqi->schedule_order))
+		list_del_init(&txqi->schedule_order);
+
+	return true;
+}
+EXPORT_SYMBOL(ieee80211_txq_may_transmit);
+
 void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
 {
 	struct ieee80211_local *local = hw_to_local(hw);