Guest User

700-Add-Airtime-Queue-Limits-Master-5f68333952.patch

a guest
Nov 27th, 2019
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 41.01 KB | None | 0 0
  1. From patchwork Tue Nov 19 06:06:07 2019
  2. Content-Type: text/plain; charset="utf-8"
  3. MIME-Version: 1.0
  4. Content-Transfer-Encoding: 8bit
  5. X-Patchwork-Submitter: Kan Yan <[email protected]>
  6. X-Patchwork-Id: 11250877
  7. X-Patchwork-Delegate: [email protected]
  8. Return-Path: <[email protected]>
  9. Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
  10.  [172.30.200.123])
  11.     by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 97F14930
  12.     for <[email protected]>;
  13.  Tue, 19 Nov 2019 06:06:25 +0000 (UTC)
  14. Received: from vger.kernel.org (vger.kernel.org [209.132.180.67])
  15.     by mail.kernel.org (Postfix) with ESMTP id 7734720672
  16.     for <[email protected]>;
  17.  Tue, 19 Nov 2019 06:06:25 +0000 (UTC)
  18. Authentication-Results: mail.kernel.org;
  19.     dkim=pass (2048-bit key) header.d=google.com [email protected]
  20.  header.b="jzcfBOXO"
  21. Received: ([email protected]) by vger.kernel.org via listexpand
  22.         id S1728994AbfKSGGY (ORCPT
  23.         <rfc822;[email protected]>);
  24.         Tue, 19 Nov 2019 01:06:24 -0500
  25. Received: from mail-pg1-f202.google.com ([209.85.215.202]:54341 "EHLO
  26.         mail-pg1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
  27.         with ESMTP id S1728017AbfKSGGX (ORCPT
  28.         <rfc822;[email protected]>);
  29.         Tue, 19 Nov 2019 01:06:23 -0500
  30. Received: by mail-pg1-f202.google.com with SMTP id t28so14933858pgl.21
  31.         for <[email protected]>;
  32.  Mon, 18 Nov 2019 22:06:21 -0800 (PST)
  33. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
  34.         d=google.com; s=20161025;
  35.         h=date:in-reply-to:message-id:mime-version:references:subject:from:to
  36.          :cc:content-transfer-encoding;
  37.         bh=SUJ++x/TlhzzyCi0jS7LtcmTW7wMb85gdnxub2e66+4=;
  38.         b=jzcfBOXOxGybpn7TTyB80D1IkGi0bBq0gVKYBPTYxT3//xKRGogjWxHWfnUxLuQ6YF
  39.          NUAibcBr6n7a2nLtzBvI1I/He3pN/eVNDKWeJqYZbYsd1e0gXsJXnTZ0pqpCzOi8f+3o
  40.          fFHs+UGbTbQ3XIFzivdY7soT8yuSQwMlDXDRNYyktpg4/qepd+pTOYIpPIz4/S2UEkDh
  41.          7xOgJBp13PkQ34TvIckWDeiQdHqoNlPAUBEhFycLMS2E01YXo096G8e6p3or2T3fLjfG
  42.          4gmAFDtJPjGPuiFOViOrxXCIWg84AeT4iBVFhGsqhaFHxdRAYzggxqLkRclxkfxv4Rnq
  43.          IEBA==
  44. X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
  45.         d=1e100.net; s=20161025;
  46.         h=x-gm-message-state:date:in-reply-to:message-id:mime-version
  47.          :references:subject:from:to:cc:content-transfer-encoding;
  48.         bh=SUJ++x/TlhzzyCi0jS7LtcmTW7wMb85gdnxub2e66+4=;
  49.         b=VdCLKYUgoukaLMEzApy7mDNUHyPknx1Lb7ZnJAK73AYoCU01rksYh3bwvliY1XNu8h
  50.          wt+j/Xeo8FtKmTgdX2P57B/AD6Tb3M1mfUeexgRfBDnIYzTmME8d2UvlahaTpvApDeW1
  51.          HIFgNGvnCrRWwYjb1JM91P+ZbhZd8SJ53XZTmbjN+4ajLrF6scspfsbzMrm3yJqcDWEQ
  52.          3I4+inXgaTcykB2cwKV+VcIok5yp6KDftvVvjdhcV3aQAiCrxBBBCLGrjViuQ9vUTeqQ
  53.          3zJva+XTOxoCvlcDDoOrf0oAifty38zQcqyj87xXdQzYHxIGUkWh9I8cCGI1coUDGztW
  54.          FWlw==
  55. X-Gm-Message-State: APjAAAUcfgy++sF4qvWYNEreAdurouFwF+fC1HjEXImvjP+1pjuviFB5
  56.         kuA45Vu28r8izcB5dd96kWaZM19V
  57. X-Google-Smtp-Source:
  58.  APXvYqzNV134LcY9JhSizYZkLWNChU1nezzOzXKtuUuyFIXvORQzS+wTNUd+ckq/gOiolRVK8ppuCq/Q
  59. X-Received: by 2002:a63:495b:: with SMTP id y27mr3614518pgk.438.1574143580296;
  60.  Mon, 18 Nov 2019 22:06:20 -0800 (PST)
  61. Date: Mon, 18 Nov 2019 22:06:07 -0800
  62. In-Reply-To: <20191119060610.76681-1[email protected]>
  63. Message-Id: <20191119060610.76681-2[email protected]>
  64. Mime-Version: 1.0
  65. References: <20191119060610.76681-1[email protected]>
  66. X-Mailer: git-send-email 2.24.0.432.g9d3f5f5b63-goog
  67. Subject: [PATCH v11 1/4] mac80211: Add new sta_info getter by sta/vif addrs
  68. From: Kan Yan <[email protected]>
  69. Precedence: bulk
  70. List-ID: <linux-wireless.vger.kernel.org>
  71. X-Mailing-List: [email protected]
  72.  
  73. From: Toke Høiland-Jørgensen <[email protected]>
  74.  
  75. In ieee80211_tx_status() we don't have an sdata struct when looking up the
  76. destination sta. Instead, we just do a lookup by the vif addr that is the
  77. source of the packet being completed. Factor this out into a new sta_info
  78. getter helper, since we need to use it for accounting AQL as well.
  79.  
  80. Signed-off-by: Toke Høiland-Jørgensen <[email protected]>
  81. ---
  82. net/mac80211/sta_info.c | 20 ++++++++++++++++++++
  83.  net/mac80211/sta_info.h |  3 +++
  84.  net/mac80211/status.c   | 10 ++--------
  85.  3 files changed, 25 insertions(+), 8 deletions(-)
  86.  
  87. --- a/net/mac80211/sta_info.c
  88. +++ b/net/mac80211/sta_info.c
  89. @@ -210,6 +210,20 @@ struct sta_info *sta_info_get_bss(struct
  90.     return NULL;
  91.  }
  92.  
  93. +struct sta_info *sta_info_get_by_addrs(struct ieee80211_local *local,
  94. +                      const u8 *sta_addr, const u8 *vif_addr)
  95. +{
  96. +   struct rhlist_head *tmp;
  97. +   struct sta_info *sta;
  98. +
  99. +   for_each_sta_info(local, sta_addr, sta, tmp) {
  100. +       if (ether_addr_equal(vif_addr, sta->sdata->vif.addr))
  101. +           return sta;
  102. +   }
  103. +
  104. +   return NULL;
  105. +}
  106. +
  107.  struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
  108.                      int idx)
  109.  {
  110. @@ -397,6 +411,9 @@ struct sta_info *sta_info_alloc(struct i
  111.         skb_queue_head_init(&sta->ps_tx_buf[i]);
  112.         skb_queue_head_init(&sta->tx_filtered[i]);
  113.         sta->airtime[i].deficit = sta->airtime_weight;
  114. +       atomic_set(&sta->airtime[i].aql_tx_pending, 0);
  115. +       sta->airtime[i].aql_limit_low = local->aql_txq_limit_low[i];
  116. +       sta->airtime[i].aql_limit_high = local->aql_txq_limit_high[i];
  117.     }
  118.  
  119.     for (i = 0; i < IEEE80211_NUM_TIDS; i++)
  120. @@ -1894,6 +1911,41 @@ void ieee80211_sta_register_airtime(stru
  121.  }
  122.  EXPORT_SYMBOL(ieee80211_sta_register_airtime);
  123.  
  124. +void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
  125. +                     struct sta_info *sta, u8 ac,
  126. +                     u16 tx_airtime, bool tx_completed)
  127. +{
  128. +   int tx_pending;
  129. +
  130. +   if (!tx_completed) {
  131. +       if (sta)
  132. +           atomic_add(tx_airtime,
  133. +                  &sta->airtime[ac].aql_tx_pending);
  134. +
  135. +       atomic_add(tx_airtime, &local->aql_total_pending_airtime);
  136. +       return;
  137. +   }
  138. +
  139. +   if (sta) {
  140. +       tx_pending = atomic_sub_return(tx_airtime,
  141. +                          &sta->airtime[ac].aql_tx_pending);
  142. +       if (WARN_ONCE(tx_pending < 0,
  143. +                 "STA %pM AC %d txq pending airtime underflow: %u, %u",
  144. +                 sta->addr, ac, tx_pending, tx_airtime))
  145. +           atomic_cmpxchg(&sta->airtime[ac].aql_tx_pending,
  146. +                      tx_pending, 0);
  147. +   }
  148. +
  149. +   tx_pending = atomic_sub_return(tx_airtime,
  150. +                      &local->aql_total_pending_airtime);
  151. +   if (WARN_ONCE(tx_pending < 0,
  152. +             "Device %s AC %d pending airtime underflow: %u, %u",
  153. +             wiphy_name(local->hw.wiphy), ac, tx_pending,
  154. +             tx_airtime))
  155. +       atomic_cmpxchg(&local->aql_total_pending_airtime,
  156. +                  tx_pending, 0);
  157. +}
  158. +
  159.  int sta_info_move_state(struct sta_info *sta,
  160.             enum ieee80211_sta_state new_state)
  161.  {
  162. --- a/net/mac80211/sta_info.h
  163. +++ b/net/mac80211/sta_info.h
  164. @@ -127,13 +127,21 @@ enum ieee80211_agg_stop_reason {
  165.  /* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */
  166.  #define AIRTIME_USE_TX     BIT(0)
  167.  #define AIRTIME_USE_RX     BIT(1)
  168. +#define AIRTIME_USE_AQL        BIT(2)
  169.  
  170.  struct airtime_info {
  171.     u64 rx_airtime;
  172.     u64 tx_airtime;
  173.     s64 deficit;
  174. +   atomic_t aql_tx_pending; /* Estimated airtime for frames pending */
  175. +   u32 aql_limit_low;
  176. +   u32 aql_limit_high;
  177.  };
  178.  
  179. +void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
  180. +                     struct sta_info *sta, u8 ac,
  181. +                     u16 tx_airtime, bool tx_completed);
  182. +
  183.  struct sta_info;
  184.  
  185.  /**
  186. @@ -725,6 +733,10 @@ struct sta_info *sta_info_get(struct iee
  187.  struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
  188.                   const u8 *addr);
  189.  
  190. +/* user must hold sta_mtx or be in RCU critical section */
  191. +struct sta_info *sta_info_get_by_addrs(struct ieee80211_local *local,
  192. +                      const u8 *sta_addr, const u8 *vif_addr);
  193. +
  194.  #define for_each_sta_info(local, _addr, _sta, _tmp)            \
  195.     rhl_for_each_entry_rcu(_sta, _tmp,              \
  196.                    sta_info_hash_lookup(local, _addr), hash_node)
  197. --- a/net/mac80211/status.c
  198. +++ b/net/mac80211/status.c
  199. @@ -670,12 +670,26 @@ static void ieee80211_report_used_skb(st
  200.                       struct sk_buff *skb, bool dropped)
  201.  {
  202.     struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  203. +   u16 tx_time_est = ieee80211_info_get_tx_time_est(info);
  204.     struct ieee80211_hdr *hdr = (void *)skb->data;
  205.     bool acked = info->flags & IEEE80211_TX_STAT_ACK;
  206.  
  207.     if (dropped)
  208.         acked = false;
  209.  
  210. +   if (tx_time_est) {
  211. +       struct sta_info *sta;
  212. +
  213. +       rcu_read_lock();
  214. +
  215. +       sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2);
  216. +       ieee80211_sta_update_pending_airtime(local, sta,
  217. +                            skb_get_queue_mapping(skb),
  218. +                            tx_time_est,
  219. +                            true);
  220. +       rcu_read_unlock();
  221. +   }
  222. +
  223.     if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) {
  224.         struct ieee80211_sub_if_data *sdata;
  225.  
  226. @@ -884,6 +898,7 @@ static void __ieee80211_tx_status(struct
  227.     struct ieee80211_bar *bar;
  228.     int shift = 0;
  229.     int tid = IEEE80211_NUM_TIDS;
  230. +   u16 tx_time_est;
  231.  
  232.     rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
  233.  
  234. @@ -993,6 +1008,17 @@ static void __ieee80211_tx_status(struct
  235.             ieee80211_sta_register_airtime(&sta->sta, tid,
  236.                                info->status.tx_time, 0);
  237.  
  238. +       if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
  239. +           /* Do this here to avoid the expensive lookup of the sta
  240. +            * in ieee80211_report_used_skb().
  241. +            */
  242. +           ieee80211_sta_update_pending_airtime(local, sta,
  243. +                                skb_get_queue_mapping(skb),
  244. +                                tx_time_est,
  245. +                                true);
  246. +           ieee80211_info_set_tx_time_est(info, 0);
  247. +       }
  248. +
  249.         if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
  250.             if (info->flags & IEEE80211_TX_STAT_ACK) {
  251.                 if (sta->status_stats.lost_packets)
  252. @@ -1080,19 +1106,13 @@ void ieee80211_tx_status(struct ieee8021
  253.         .skb = skb,
  254.         .info = IEEE80211_SKB_CB(skb),
  255.     };
  256. -   struct rhlist_head *tmp;
  257.     struct sta_info *sta;
  258.  
  259.     rcu_read_lock();
  260.  
  261. -   for_each_sta_info(local, hdr->addr1, sta, tmp) {
  262. -       /* skip wrong virtual interface */
  263. -       if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
  264. -           continue;
  265. -
  266. +   sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2);
  267. +   if (sta)
  268.         status.sta = &sta->sta;
  269. -       break;
  270. -   }
  271.  
  272.     __ieee80211_tx_status(hw, &status);
  273.     rcu_read_unlock();
  274. --- a/include/net/mac80211.h
  275. +++ b/include/net/mac80211.h
  276. @@ -1073,6 +1073,22 @@ struct ieee80211_tx_status {
  277.     struct rate_info *rate;
  278.  };
  279.  
  280. +static inline u16
  281. +ieee80211_info_set_tx_time_est(struct ieee80211_tx_info *info, u16 tx_time_est)
  282. +{
  283. +   /* We only have 10 bits in tx_time_est, so store airtime
  284. +    * in increments of 4us and clamp the maximum to 2**12-1
  285. +    */
  286. +   info->tx_time_est = min_t(u16, tx_time_est, 4095) >> 2;
  287. +   return info->tx_time_est << 2;
  288. +}
  289. +
  290. +static inline u16
  291. +ieee80211_info_get_tx_time_est(struct ieee80211_tx_info *info)
  292. +{
  293. +   return info->tx_time_est << 2;
  294. +}
  295. +
  296.  /**
  297.   * struct ieee80211_scan_ies - descriptors for different blocks of IEs
  298.   *
  299. @@ -5559,6 +5575,18 @@ void ieee80211_sta_register_airtime(stru
  300.                     u32 tx_airtime, u32 rx_airtime);
  301.  
  302.  /**
  303. + * ieee80211_txq_airtime_check - check if a txq can send frame to device
  304. + *
  305. + * @hw: pointer obtained from ieee80211_alloc_hw()
  306. + * @txq: pointer obtained from station or virtual interface
  307. + *
  308. + * Return true if the AQL's airtime limit has not been reached and the txq can
  309. + * continue to send more packets to the device. Otherwise return false.
  310. + */
  311. +bool
  312. +ieee80211_txq_airtime_check(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
  313. +
  314. +/**
  315.   * ieee80211_iter_keys - iterate keys programmed into the device
  316.   * @hw: pointer obtained from ieee80211_alloc_hw()
  317.   * @vif: virtual interface to iterate, may be %NULL for all
  318. @@ -6417,4 +6445,33 @@ void ieee80211_nan_func_match(struct iee
  319.                   struct cfg80211_nan_match_params *match,
  320.                   gfp_t gfp);
  321.  
  322. +/**
  323. + * ieee80211_calc_rx_airtime - calculate estimated transmission airtime for RX.
  324. + *
  325. + * This function calculates the estimated airtime usage of a frame based on the
  326. + * rate information in the RX status struct and the frame length.
  327. + *
  328. + * @hw: pointer as obtained from ieee80211_alloc_hw()
  329. + * @status: &struct ieee80211_rx_status containing the transmission rate
  330. + *          information.
  331. + * @len: frame length in bytes
  332. + */
  333. +u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
  334. +                 struct ieee80211_rx_status *status,
  335. +                 int len);
  336. +
  337. +/**
  338. + * ieee80211_calc_tx_airtime - calculate estimated transmission airtime for TX.
  339. + *
  340. + * This function calculates the estimated airtime usage of a frame based on the
  341. + * rate information in the TX info struct and the frame length.
  342. + *
  343. + * @hw: pointer as obtained from ieee80211_alloc_hw()
  344. + * @info: &struct ieee80211_tx_info of the frame.
  345. + * @len: frame length in bytes
  346. + */
  347. +u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
  348. +                 struct ieee80211_tx_info *info,
  349. +                 int len);
  350. +
  351.  #endif /* MAC80211_H */
  352. --- a/net/mac80211/Makefile
  353. +++ b/net/mac80211/Makefile
  354. @@ -31,7 +31,8 @@ mac80211-y := \
  355.     chan.o \
  356.     trace.o mlme.o \
  357.     tdls.o \
  358. -   ocb.o
  359. +   ocb.o \
  360. +   airtime.o
  361.  
  362.  mac80211-$(CPTCFG_MAC80211_LEDS) += led.o
  363.  mac80211-$(CPTCFG_MAC80211_DEBUGFS) += \
  364. --- /dev/null
  365. +++ b/net/mac80211/airtime.c
  366. @@ -0,0 +1,597 @@
  367. +// SPDX-License-Identifier: ISC
  368. +/*
  369. + * Copyright (C) 2019 Felix Fietkau <[email protected]>
  370. + */
  371. +
  372. +#include <net/mac80211.h>
  373. +#include "ieee80211_i.h"
  374. +#include "sta_info.h"
  375. +
  376. +#define AVG_PKT_SIZE   1024
  377. +
  378. +/* Number of bits for an average sized packet */
  379. +#define MCS_NBITS (AVG_PKT_SIZE << 3)
  380. +
  381. +/* Number of kilo-symbols (symbols * 1024) for a packet with (bps) bits per
  382. + * symbol. We use k-symbols to avoid rounding in the _TIME macros below.
  383. + */
  384. +#define MCS_N_KSYMS(bps) DIV_ROUND_UP(MCS_NBITS << 10, (bps))
  385. +
  386. +/* Transmission time (in 1024 * usec) for a packet containing (ksyms) * 1024
  387. + * symbols.
  388. + */
  389. +#define MCS_SYMBOL_TIME(sgi, ksyms)                    \
  390. +   (sgi ?                              \
  391. +     ((ksyms) * 4 * 18) / 20 :     /* 3.6 us per sym */    \
  392. +     ((ksyms) * 4)         /* 4.0 us per sym */    \
  393. +   )
  394. +
  395. +/* Transmit duration for the raw data part of an average sized packet */
  396. +#define MCS_DURATION(streams, sgi, bps) \
  397. +   ((u32)MCS_SYMBOL_TIME(sgi, MCS_N_KSYMS((streams) * (bps))))
  398. +
  399. +#define MCS_DURATION_S(shift, streams, sgi, bps)       \
  400. +   ((u16)((MCS_DURATION(streams, sgi, bps) >> shift)))
  401. +
  402. +/* These should match the values in enum nl80211_he_gi */
  403. +#define HE_GI_08 0
  404. +#define HE_GI_16 1
  405. +#define HE_GI_32 2
  406. +
  407. +/* Transmission time (1024 usec) for a packet containing (ksyms) * k-symbols */
  408. +#define HE_SYMBOL_TIME(gi, ksyms)                  \
  409. +   (gi == HE_GI_08 ?                       \
  410. +    ((ksyms) * 16 * 17) / 20 :     /* 13.6 us per sym */   \
  411. +    (gi == HE_GI_16 ?                      \
  412. +     ((ksyms) * 16 * 18) / 20 :        /* 14.4 us per sym */   \
  413. +     ((ksyms) * 16)            /* 16.0 us per sym */   \
  414. +    ))
  415. +
  416. +/* Transmit duration for the raw data part of an average sized packet */
  417. +#define HE_DURATION(streams, gi, bps) \
  418. +   ((u32)HE_SYMBOL_TIME(gi, MCS_N_KSYMS((streams) * (bps))))
  419. +
  420. +#define HE_DURATION_S(shift, streams, gi, bps)     \
  421. +   (HE_DURATION(streams, gi, bps) >> shift)
  422. +
  423. +#define BW_20          0
  424. +#define BW_40          1
  425. +#define BW_80          2
  426. +#define BW_160         3
  427. +
  428. +/*
  429. + * Define group sort order: HT40 -> SGI -> #streams
  430. + */
  431. +#define IEEE80211_MAX_STREAMS      4
  432. +#define IEEE80211_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */
  433. +#define IEEE80211_VHT_STREAM_GROUPS    8 /* BW(=4) * SGI(=2) */
  434. +
  435. +#define IEEE80211_HE_MAX_STREAMS   8
  436. +#define IEEE80211_HE_STREAM_GROUPS 12 /* BW(=4) * GI(=3) */
  437. +
  438. +#define IEEE80211_HT_GROUPS_NB (IEEE80211_MAX_STREAMS *    \
  439. +                IEEE80211_HT_STREAM_GROUPS)
  440. +#define IEEE80211_VHT_GROUPS_NB    (IEEE80211_MAX_STREAMS *    \
  441. +                    IEEE80211_VHT_STREAM_GROUPS)
  442. +#define IEEE80211_HE_GROUPS_NB (IEEE80211_HE_MAX_STREAMS * \
  443. +                IEEE80211_HE_STREAM_GROUPS)
  444. +#define IEEE80211_GROUPS_NB    (IEEE80211_HT_GROUPS_NB +   \
  445. +                IEEE80211_VHT_GROUPS_NB +  \
  446. +                IEEE80211_HE_GROUPS_NB)
  447. +
  448. +#define IEEE80211_HT_GROUP_0   0
  449. +#define IEEE80211_VHT_GROUP_0  (IEEE80211_HT_GROUP_0 + IEEE80211_HT_GROUPS_NB)
  450. +#define IEEE80211_HE_GROUP_0   (IEEE80211_VHT_GROUP_0 + IEEE80211_VHT_GROUPS_NB)
  451. +
  452. +#define MCS_GROUP_RATES        12
  453. +
  454. +#define HT_GROUP_IDX(_streams, _sgi, _ht40)    \
  455. +   IEEE80211_HT_GROUP_0 +          \
  456. +   IEEE80211_MAX_STREAMS * 2 * _ht40 + \
  457. +   IEEE80211_MAX_STREAMS * _sgi +      \
  458. +   _streams - 1
  459. +
  460. +#define _MAX(a, b) (((a)>(b))?(a):(b))
  461. +
  462. +#define GROUP_SHIFT(duration)                      \
  463. +   _MAX(0, 16 - __builtin_clz(duration))
  464. +
  465. +/* MCS rate information for an MCS group */
  466. +#define __MCS_GROUP(_streams, _sgi, _ht40, _s)             \
  467. +   [HT_GROUP_IDX(_streams, _sgi, _ht40)] = {           \
  468. +   .shift = _s,                            \
  469. +   .duration = {                           \
  470. +       MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 54 : 26),    \
  471. +       MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 108 : 52),   \
  472. +       MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 162 : 78),   \
  473. +       MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 216 : 104),  \
  474. +       MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 324 : 156),  \
  475. +       MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 432 : 208),  \
  476. +       MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 486 : 234),  \
  477. +       MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 540 : 260)   \
  478. +   }                               \
  479. +}
  480. +
  481. +#define MCS_GROUP_SHIFT(_streams, _sgi, _ht40)             \
  482. +   GROUP_SHIFT(MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26))
  483. +
  484. +#define MCS_GROUP(_streams, _sgi, _ht40)               \
  485. +   __MCS_GROUP(_streams, _sgi, _ht40,              \
  486. +           MCS_GROUP_SHIFT(_streams, _sgi, _ht40))
  487. +
  488. +#define VHT_GROUP_IDX(_streams, _sgi, _bw)             \
  489. +   (IEEE80211_VHT_GROUP_0 +                    \
  490. +    IEEE80211_MAX_STREAMS * 2 * (_bw) +                \
  491. +    IEEE80211_MAX_STREAMS * (_sgi) +               \
  492. +    (_streams) - 1)
  493. +
  494. +#define BW2VBPS(_bw, r4, r3, r2, r1)                   \
  495. +   (_bw == BW_160 ? r4 : _bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
  496. +
  497. +#define __VHT_GROUP(_streams, _sgi, _bw, _s)               \
  498. +   [VHT_GROUP_IDX(_streams, _sgi, _bw)] = {            \
  499. +   .shift = _s,                            \
  500. +   .duration = {                           \
  501. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  502. +                  BW2VBPS(_bw,  234,  117,  54,  26)), \
  503. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  504. +                  BW2VBPS(_bw,  468,  234, 108,  52)), \
  505. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  506. +                  BW2VBPS(_bw,  702,  351, 162,  78)), \
  507. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  508. +                  BW2VBPS(_bw,  936,  468, 216, 104)), \
  509. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  510. +                  BW2VBPS(_bw, 1404,  702, 324, 156)), \
  511. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  512. +                  BW2VBPS(_bw, 1872,  936, 432, 208)), \
  513. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  514. +                  BW2VBPS(_bw, 2106, 1053, 486, 234)), \
  515. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  516. +                  BW2VBPS(_bw, 2340, 1170, 540, 260)), \
  517. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  518. +                  BW2VBPS(_bw, 2808, 1404, 648, 312)), \
  519. +       MCS_DURATION_S(_s, _streams, _sgi,          \
  520. +                  BW2VBPS(_bw, 3120, 1560, 720, 346))  \
  521. +        }                              \
  522. +}
  523. +
  524. +#define VHT_GROUP_SHIFT(_streams, _sgi, _bw)               \
  525. +   GROUP_SHIFT(MCS_DURATION(_streams, _sgi,            \
  526. +                BW2VBPS(_bw, 243, 117,  54,  26)))
  527. +
  528. +#define VHT_GROUP(_streams, _sgi, _bw)                 \
  529. +   __VHT_GROUP(_streams, _sgi, _bw,                \
  530. +           VHT_GROUP_SHIFT(_streams, _sgi, _bw))
  531. +
  532. +
  533. +#define HE_GROUP_IDX(_streams, _gi, _bw)               \
  534. +   (IEEE80211_HE_GROUP_0 +                 \
  535. +    IEEE80211_HE_MAX_STREAMS * 2 * (_bw) +         \
  536. +    IEEE80211_HE_MAX_STREAMS * (_gi) +             \
  537. +    (_streams) - 1)
  538. +
  539. +#define __HE_GROUP(_streams, _gi, _bw, _s)             \
  540. +   [HE_GROUP_IDX(_streams, _gi, _bw)] = {          \
  541. +   .shift = _s,                            \
  542. +   .duration = {                           \
  543. +       HE_DURATION_S(_s, _streams, _gi,            \
  544. +                 BW2VBPS(_bw,   979,  489,  230,  115)),   \
  545. +       HE_DURATION_S(_s, _streams, _gi,            \
  546. +                 BW2VBPS(_bw,  1958,  979,  475,  230)),   \
  547. +       HE_DURATION_S(_s, _streams, _gi,            \
  548. +                 BW2VBPS(_bw,  2937, 1468,  705,  345)),   \
  549. +       HE_DURATION_S(_s, _streams, _gi,            \
  550. +                 BW2VBPS(_bw,  3916, 1958,  936,  475)),   \
  551. +       HE_DURATION_S(_s, _streams, _gi,            \
  552. +                 BW2VBPS(_bw,  5875, 2937, 1411,  705)),   \
  553. +       HE_DURATION_S(_s, _streams, _gi,            \
  554. +                 BW2VBPS(_bw,  7833, 3916, 1872,  936)),   \
  555. +       HE_DURATION_S(_s, _streams, _gi,            \
  556. +                 BW2VBPS(_bw,  8827, 4406, 2102, 1051)),   \
  557. +       HE_DURATION_S(_s, _streams, _gi,            \
  558. +                 BW2VBPS(_bw,  9806, 4896, 2347, 1166)),   \
  559. +       HE_DURATION_S(_s, _streams, _gi,            \
  560. +                 BW2VBPS(_bw, 11764, 5875, 2808, 1411)),   \
  561. +       HE_DURATION_S(_s, _streams, _gi,            \
  562. +                 BW2VBPS(_bw, 13060, 6523, 3124, 1555)),   \
  563. +       HE_DURATION_S(_s, _streams, _gi,            \
  564. +                 BW2VBPS(_bw, 14702, 7344, 3513, 1756)),   \
  565. +       HE_DURATION_S(_s, _streams, _gi,            \
  566. +                 BW2VBPS(_bw, 16329, 8164, 3902, 1944))    \
  567. +        }                              \
  568. +}
  569. +
  570. +#define HE_GROUP_SHIFT(_streams, _gi, _bw)             \
  571. +   GROUP_SHIFT(HE_DURATION(_streams, _gi,          \
  572. +               BW2VBPS(_bw,   979,  489,  230,  115)))
  573. +
  574. +#define HE_GROUP(_streams, _gi, _bw)                   \
  575. +   __HE_GROUP(_streams, _gi, _bw,              \
  576. +          HE_GROUP_SHIFT(_streams, _gi, _bw))
  577. +struct mcs_group {
  578. +   u8 shift;
  579. +   u16 duration[MCS_GROUP_RATES];
  580. +};
  581. +
  582. +static const struct mcs_group airtime_mcs_groups[] = {
  583. +   MCS_GROUP(1, 0, BW_20),
  584. +   MCS_GROUP(2, 0, BW_20),
  585. +   MCS_GROUP(3, 0, BW_20),
  586. +   MCS_GROUP(4, 0, BW_20),
  587. +
  588. +   MCS_GROUP(1, 1, BW_20),
  589. +   MCS_GROUP(2, 1, BW_20),
  590. +   MCS_GROUP(3, 1, BW_20),
  591. +   MCS_GROUP(4, 1, BW_20),
  592. +
  593. +   MCS_GROUP(1, 0, BW_40),
  594. +   MCS_GROUP(2, 0, BW_40),
  595. +   MCS_GROUP(3, 0, BW_40),
  596. +   MCS_GROUP(4, 0, BW_40),
  597. +
  598. +   MCS_GROUP(1, 1, BW_40),
  599. +   MCS_GROUP(2, 1, BW_40),
  600. +   MCS_GROUP(3, 1, BW_40),
  601. +   MCS_GROUP(4, 1, BW_40),
  602. +
  603. +   VHT_GROUP(1, 0, BW_20),
  604. +   VHT_GROUP(2, 0, BW_20),
  605. +   VHT_GROUP(3, 0, BW_20),
  606. +   VHT_GROUP(4, 0, BW_20),
  607. +
  608. +   VHT_GROUP(1, 1, BW_20),
  609. +   VHT_GROUP(2, 1, BW_20),
  610. +   VHT_GROUP(3, 1, BW_20),
  611. +   VHT_GROUP(4, 1, BW_20),
  612. +
  613. +   VHT_GROUP(1, 0, BW_40),
  614. +   VHT_GROUP(2, 0, BW_40),
  615. +   VHT_GROUP(3, 0, BW_40),
  616. +   VHT_GROUP(4, 0, BW_40),
  617. +
  618. +   VHT_GROUP(1, 1, BW_40),
  619. +   VHT_GROUP(2, 1, BW_40),
  620. +   VHT_GROUP(3, 1, BW_40),
  621. +   VHT_GROUP(4, 1, BW_40),
  622. +
  623. +   VHT_GROUP(1, 0, BW_80),
  624. +   VHT_GROUP(2, 0, BW_80),
  625. +   VHT_GROUP(3, 0, BW_80),
  626. +   VHT_GROUP(4, 0, BW_80),
  627. +
  628. +   VHT_GROUP(1, 1, BW_80),
  629. +   VHT_GROUP(2, 1, BW_80),
  630. +   VHT_GROUP(3, 1, BW_80),
  631. +   VHT_GROUP(4, 1, BW_80),
  632. +
  633. +   VHT_GROUP(1, 0, BW_160),
  634. +   VHT_GROUP(2, 0, BW_160),
  635. +   VHT_GROUP(3, 0, BW_160),
  636. +   VHT_GROUP(4, 0, BW_160),
  637. +
  638. +   VHT_GROUP(1, 1, BW_160),
  639. +   VHT_GROUP(2, 1, BW_160),
  640. +   VHT_GROUP(3, 1, BW_160),
  641. +   VHT_GROUP(4, 1, BW_160),
  642. +
  643. +   HE_GROUP(1, HE_GI_08, BW_20),
  644. +   HE_GROUP(2, HE_GI_08, BW_20),
  645. +   HE_GROUP(3, HE_GI_08, BW_20),
  646. +   HE_GROUP(4, HE_GI_08, BW_20),
  647. +   HE_GROUP(5, HE_GI_08, BW_20),
  648. +   HE_GROUP(6, HE_GI_08, BW_20),
  649. +   HE_GROUP(7, HE_GI_08, BW_20),
  650. +   HE_GROUP(8, HE_GI_08, BW_20),
  651. +
  652. +   HE_GROUP(1, HE_GI_16, BW_20),
  653. +   HE_GROUP(2, HE_GI_16, BW_20),
  654. +   HE_GROUP(3, HE_GI_16, BW_20),
  655. +   HE_GROUP(4, HE_GI_16, BW_20),
  656. +   HE_GROUP(5, HE_GI_16, BW_20),
  657. +   HE_GROUP(6, HE_GI_16, BW_20),
  658. +   HE_GROUP(7, HE_GI_16, BW_20),
  659. +   HE_GROUP(8, HE_GI_16, BW_20),
  660. +
  661. +   HE_GROUP(1, HE_GI_32, BW_20),
  662. +   HE_GROUP(2, HE_GI_32, BW_20),
  663. +   HE_GROUP(3, HE_GI_32, BW_20),
  664. +   HE_GROUP(4, HE_GI_32, BW_20),
  665. +   HE_GROUP(5, HE_GI_32, BW_20),
  666. +   HE_GROUP(6, HE_GI_32, BW_20),
  667. +   HE_GROUP(7, HE_GI_32, BW_20),
  668. +   HE_GROUP(8, HE_GI_32, BW_20),
  669. +
  670. +   HE_GROUP(1, HE_GI_08, BW_40),
  671. +   HE_GROUP(2, HE_GI_08, BW_40),
  672. +   HE_GROUP(3, HE_GI_08, BW_40),
  673. +   HE_GROUP(4, HE_GI_08, BW_40),
  674. +   HE_GROUP(5, HE_GI_08, BW_40),
  675. +   HE_GROUP(6, HE_GI_08, BW_40),
  676. +   HE_GROUP(7, HE_GI_08, BW_40),
  677. +   HE_GROUP(8, HE_GI_08, BW_40),
  678. +
  679. +   HE_GROUP(1, HE_GI_16, BW_40),
  680. +   HE_GROUP(2, HE_GI_16, BW_40),
  681. +   HE_GROUP(3, HE_GI_16, BW_40),
  682. +   HE_GROUP(4, HE_GI_16, BW_40),
  683. +   HE_GROUP(5, HE_GI_16, BW_40),
  684. +   HE_GROUP(6, HE_GI_16, BW_40),
  685. +   HE_GROUP(7, HE_GI_16, BW_40),
  686. +   HE_GROUP(8, HE_GI_16, BW_40),
  687. +
  688. +   HE_GROUP(1, HE_GI_32, BW_40),
  689. +   HE_GROUP(2, HE_GI_32, BW_40),
  690. +   HE_GROUP(3, HE_GI_32, BW_40),
  691. +   HE_GROUP(4, HE_GI_32, BW_40),
  692. +   HE_GROUP(5, HE_GI_32, BW_40),
  693. +   HE_GROUP(6, HE_GI_32, BW_40),
  694. +   HE_GROUP(7, HE_GI_32, BW_40),
  695. +   HE_GROUP(8, HE_GI_32, BW_40),
  696. +
  697. +   HE_GROUP(1, HE_GI_08, BW_80),
  698. +   HE_GROUP(2, HE_GI_08, BW_80),
  699. +   HE_GROUP(3, HE_GI_08, BW_80),
  700. +   HE_GROUP(4, HE_GI_08, BW_80),
  701. +   HE_GROUP(5, HE_GI_08, BW_80),
  702. +   HE_GROUP(6, HE_GI_08, BW_80),
  703. +   HE_GROUP(7, HE_GI_08, BW_80),
  704. +   HE_GROUP(8, HE_GI_08, BW_80),
  705. +
  706. +   HE_GROUP(1, HE_GI_16, BW_80),
  707. +   HE_GROUP(2, HE_GI_16, BW_80),
  708. +   HE_GROUP(3, HE_GI_16, BW_80),
  709. +   HE_GROUP(4, HE_GI_16, BW_80),
  710. +   HE_GROUP(5, HE_GI_16, BW_80),
  711. +   HE_GROUP(6, HE_GI_16, BW_80),
  712. +   HE_GROUP(7, HE_GI_16, BW_80),
  713. +   HE_GROUP(8, HE_GI_16, BW_80),
  714. +
  715. +   HE_GROUP(1, HE_GI_32, BW_80),
  716. +   HE_GROUP(2, HE_GI_32, BW_80),
  717. +   HE_GROUP(3, HE_GI_32, BW_80),
  718. +   HE_GROUP(4, HE_GI_32, BW_80),
  719. +   HE_GROUP(5, HE_GI_32, BW_80),
  720. +   HE_GROUP(6, HE_GI_32, BW_80),
  721. +   HE_GROUP(7, HE_GI_32, BW_80),
  722. +   HE_GROUP(8, HE_GI_32, BW_80),
  723. +
  724. +   HE_GROUP(1, HE_GI_08, BW_160),
  725. +   HE_GROUP(2, HE_GI_08, BW_160),
  726. +   HE_GROUP(3, HE_GI_08, BW_160),
  727. +   HE_GROUP(4, HE_GI_08, BW_160),
  728. +   HE_GROUP(5, HE_GI_08, BW_160),
  729. +   HE_GROUP(6, HE_GI_08, BW_160),
  730. +   HE_GROUP(7, HE_GI_08, BW_160),
  731. +   HE_GROUP(8, HE_GI_08, BW_160),
  732. +
  733. +   HE_GROUP(1, HE_GI_16, BW_160),
  734. +   HE_GROUP(2, HE_GI_16, BW_160),
  735. +   HE_GROUP(3, HE_GI_16, BW_160),
  736. +   HE_GROUP(4, HE_GI_16, BW_160),
  737. +   HE_GROUP(5, HE_GI_16, BW_160),
  738. +   HE_GROUP(6, HE_GI_16, BW_160),
  739. +   HE_GROUP(7, HE_GI_16, BW_160),
  740. +   HE_GROUP(8, HE_GI_16, BW_160),
  741. +
  742. +   HE_GROUP(1, HE_GI_32, BW_160),
  743. +   HE_GROUP(2, HE_GI_32, BW_160),
  744. +   HE_GROUP(3, HE_GI_32, BW_160),
  745. +   HE_GROUP(4, HE_GI_32, BW_160),
  746. +   HE_GROUP(5, HE_GI_32, BW_160),
  747. +   HE_GROUP(6, HE_GI_32, BW_160),
  748. +   HE_GROUP(7, HE_GI_32, BW_160),
  749. +   HE_GROUP(8, HE_GI_32, BW_160),
  750. +};
  751. +
  752. +static u32
  753. +ieee80211_calc_legacy_rate_duration(u16 bitrate, bool short_pre,
  754. +                   bool cck, int len)
  755. +{
  756. +   u32 duration;
  757. +
  758. +   if (cck) {
  759. +       duration = 144 + 48; /* preamble + PLCP */
  760. +       if (short_pre)
  761. +           duration >>= 1;
  762. +
  763. +       duration += 10; /* SIFS */
  764. +   } else {
  765. +       duration = 20 + 16; /* premable + SIFS */
  766. +   }
  767. +
  768. +   len <<= 3;
  769. +   duration += (len * 10) / bitrate;
  770. +
  771. +   return duration;
  772. +}
  773. +
  774. +u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
  775. +                 struct ieee80211_rx_status *status,
  776. +                 int len)
  777. +{
  778. +   struct ieee80211_supported_band *sband;
  779. +   const struct ieee80211_rate *rate;
  780. +   bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI;
  781. +   bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE;
  782. +   int bw, streams;
  783. +   int group, idx;
  784. +   u32 duration;
  785. +   bool cck;
  786. +
  787. +   switch (status->bw) {
  788. +   case RATE_INFO_BW_20:
  789. +       bw = BW_20;
  790. +       break;
  791. +   case RATE_INFO_BW_40:
  792. +       bw = BW_40;
  793. +       break;
  794. +   case RATE_INFO_BW_80:
  795. +       bw = BW_80;
  796. +       break;
  797. +   case RATE_INFO_BW_160:
  798. +       bw = BW_160;
  799. +       break;
  800. +   default:
  801. +       WARN_ON_ONCE(1);
  802. +       return 0;
  803. +   }
  804. +
  805. +   switch (status->encoding) {
  806. +   case RX_ENC_LEGACY:
  807. +       if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ))
  808. +           return 0;
  809. +
  810. +       sband = hw->wiphy->bands[status->band];
  811. +       if (!sband || status->rate_idx > sband->n_bitrates)
  812. +           return 0;
  813. +
  814. +       rate = &sband->bitrates[status->rate_idx];
  815. +       cck = rate->flags & IEEE80211_RATE_MANDATORY_B;
  816. +
  817. +       return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp,
  818. +                              cck, len);
  819. +
  820. +   case RX_ENC_VHT:
  821. +       streams = status->nss;
  822. +       idx = status->rate_idx;
  823. +       group = VHT_GROUP_IDX(streams, sgi, bw);
  824. +       break;
  825. +   case RX_ENC_HT:
  826. +       streams = ((status->rate_idx >> 3) & 3) + 1;
  827. +       idx = status->rate_idx & 7;
  828. +       group = HT_GROUP_IDX(streams, sgi, bw);
  829. +       break;
  830. +   case RX_ENC_HE:
  831. +       streams = status->nss;
  832. +       idx = status->rate_idx;
  833. +       group = HE_GROUP_IDX(streams, status->he_gi, bw);
  834. +       break;
  835. +   default:
  836. +       WARN_ON_ONCE(1);
  837. +       return 0;
  838. +   }
  839. +
  840. +   if (WARN_ON_ONCE((status->encoding != RX_ENC_HE && streams > 4) ||
  841. +            (status->encoding == RX_ENC_HE && streams > 8)))
  842. +       return 0;
  843. +
  844. +   duration = airtime_mcs_groups[group].duration[idx];
  845. +   duration <<= airtime_mcs_groups[group].shift;
  846. +   duration *= len;
  847. +   duration /= AVG_PKT_SIZE;
  848. +   duration /= 1024;
  849. +
  850. +   duration += 36 + (streams << 2);
  851. +
  852. +   return duration;
  853. +}
  854. +EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime);
  855. +
  856. +static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
  857. +                     struct ieee80211_tx_rate *rate,
  858. +                     u8 band, int len)
  859. +{
  860. +   struct ieee80211_rx_status stat = {
  861. +       .band = band,
  862. +   };
  863. +
  864. +   if (rate->idx < 0 || !rate->count)
  865. +       return 0;
  866. +
  867. +   if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
  868. +       stat.bw = RATE_INFO_BW_80;
  869. +   else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
  870. +       stat.bw = RATE_INFO_BW_40;
  871. +   else
  872. +       stat.bw = RATE_INFO_BW_20;
  873. +
  874. +   stat.enc_flags = 0;
  875. +   if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
  876. +       stat.enc_flags |= RX_ENC_FLAG_SHORTPRE;
  877. +   if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
  878. +       stat.enc_flags |= RX_ENC_FLAG_SHORT_GI;
  879. +
  880. +   stat.rate_idx = rate->idx;
  881. +   if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
  882. +       stat.encoding = RX_ENC_VHT;
  883. +       stat.rate_idx = ieee80211_rate_get_vht_mcs(rate);
  884. +       stat.nss = ieee80211_rate_get_vht_nss(rate);
  885. +   } else if (rate->flags & IEEE80211_TX_RC_MCS) {
  886. +       stat.encoding = RX_ENC_HT;
  887. +   } else {
  888. +       stat.encoding = RX_ENC_LEGACY;
  889. +   }
  890. +
  891. +   return ieee80211_calc_rx_airtime(hw, &stat, len);
  892. +}
  893. +
  894. +u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
  895. +                 struct ieee80211_tx_info *info,
  896. +                 int len)
  897. +{
  898. +   u32 duration = 0;
  899. +   int i;
  900. +
  901. +   for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) {
  902. +       struct ieee80211_tx_rate *rate = &info->status.rates[i];
  903. +       u32 cur_duration;
  904. +
  905. +       cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate,
  906. +                                 info->band, len);
  907. +       if (!cur_duration)
  908. +           break;
  909. +
  910. +       duration += cur_duration * rate->count;
  911. +   }
  912. +
  913. +   return duration;
  914. +}
  915. +EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airtime);
  916. +
  917. +u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
  918. +                      struct ieee80211_vif *vif,
  919. +                      struct ieee80211_sta *pubsta,
  920. +                      int len)
  921. +{
  922. +   struct ieee80211_supported_band *sband;
  923. +   struct ieee80211_chanctx_conf *conf;
  924. +   int rateidx, shift = 0;
  925. +   bool cck, short_pream;
  926. +   u32 basic_rates;
  927. +   u8 band = 0;
  928. +   u16 rate;
  929. +
  930. +   len += 38; /* Ethernet header length */
  931. +
  932. +   conf = rcu_dereference(vif->chanctx_conf);
  933. +   if (conf) {
  934. +       band = conf->def.chan->band;
  935. +       shift = ieee80211_chandef_get_shift(&conf->def);
  936. +   }
  937. +
  938. +   if (pubsta) {
  939. +       struct sta_info *sta = container_of(pubsta, struct sta_info,
  940. +                           sta);
  941. +
  942. +       return ieee80211_calc_tx_airtime_rate(hw,
  943. +                             &sta->tx_stats.last_rate,
  944. +                             band, len);
  945. +   }
  946. +
  947. +   if (!conf)
  948. +       return 0;
  949. +
  950. +   /* No station to get latest rate from, so calculate the worst-case
  951. +    * duration using the lowest configured basic rate.
  952. +    */
  953. +   sband = hw->wiphy->bands[band];
  954. +
  955. +   basic_rates = vif->bss_conf.basic_rates;
  956. +   short_pream = vif->bss_conf.use_short_preamble;
  957. +
  958. +   rateidx = basic_rates ? ffs(basic_rates) - 1 : 0;
  959. +   rate = sband->bitrates[rateidx].bitrate << shift;
  960. +   cck = sband->bitrates[rateidx].flags & IEEE80211_RATE_MANDATORY_B;
  961. +
  962. +   return ieee80211_calc_legacy_rate_duration(rate, short_pream, cck, len);
  963. +}
  964. --- a/net/mac80211/ieee80211_i.h
  965. +++ b/net/mac80211/ieee80211_i.h
  966. @@ -1142,6 +1142,10 @@ struct ieee80211_local {
  967.     u16 schedule_round[IEEE80211_NUM_ACS];
  968.  
  969.     u16 airtime_flags;
  970. +   u32 aql_txq_limit_low[IEEE80211_NUM_ACS];
  971. +   u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
  972. +   u32 aql_threshold;
  973. +   atomic_t aql_total_pending_airtime;
  974.  
  975.     const struct ieee80211_ops *ops;
  976.  
  977. @@ -2254,6 +2258,10 @@ const char *ieee80211_get_reason_code_st
  978.  
  979.  extern const struct ethtool_ops ieee80211_ethtool_ops;
  980.  
  981. +u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
  982. +                      struct ieee80211_vif *vif,
  983. +                      struct ieee80211_sta *pubsta,
  984. +                      int len);
  985.  #ifdef CPTCFG_MAC80211_NOINLINE
  986.  #define debug_noinline noinline
  987.  #else
  988. --- a/include/net/cfg80211.h
  989. +++ b/include/net/cfg80211.h
  990. @@ -2603,6 +2603,13 @@ enum wiphy_params_flags {
  991.  
  992.  #define IEEE80211_DEFAULT_AIRTIME_WEIGHT   256
  993.  
  994. +/* The per TXQ device queue limit in airtime */
  995. +#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L  5000
  996. +#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H  12000
  997. +
  998. +/* The per interface airtime threshold to switch to lower queue limit */
  999. +#define IEEE80211_AQL_THRESHOLD            24000
  1000. +
  1001.  /**
  1002.   * struct cfg80211_pmksa - PMK Security Association
  1003.   *
  1004. --- a/net/mac80211/debugfs.c
  1005. +++ b/net/mac80211/debugfs.c
  1006. @@ -148,6 +148,87 @@ static const struct file_operations aqm_
  1007.     .llseek = default_llseek,
  1008.  };
  1009.  
  1010. +static ssize_t aql_txq_limit_read(struct file *file,
  1011. +                 char __user *user_buf,
  1012. +                 size_t count,
  1013. +                 loff_t *ppos)
  1014. +{
  1015. +   struct ieee80211_local *local = file->private_data;
  1016. +   char buf[400];
  1017. +   int len = 0;
  1018. +
  1019. +   len = scnprintf(buf, sizeof(buf),
  1020. +           "AC AQL limit low   AQL limit high\n"
  1021. +           "VO %u      %u\n"
  1022. +           "VI %u      %u\n"
  1023. +           "BE %u      %u\n"
  1024. +           "BK %u      %u\n",
  1025. +           local->aql_txq_limit_low[IEEE80211_AC_VO],
  1026. +           local->aql_txq_limit_high[IEEE80211_AC_VO],
  1027. +           local->aql_txq_limit_low[IEEE80211_AC_VI],
  1028. +           local->aql_txq_limit_high[IEEE80211_AC_VI],
  1029. +           local->aql_txq_limit_low[IEEE80211_AC_BE],
  1030. +           local->aql_txq_limit_high[IEEE80211_AC_BE],
  1031. +           local->aql_txq_limit_low[IEEE80211_AC_BK],
  1032. +           local->aql_txq_limit_high[IEEE80211_AC_BK]);
  1033. +   return simple_read_from_buffer(user_buf, count, ppos,
  1034. +                      buf, len);
  1035. +}
  1036. +
  1037. +static ssize_t aql_txq_limit_write(struct file *file,
  1038. +                  const char __user *user_buf,
  1039. +                  size_t count,
  1040. +                  loff_t *ppos)
  1041. +{
  1042. +   struct ieee80211_local *local = file->private_data;
  1043. +   char buf[100];
  1044. +   size_t len;
  1045. +   u32 ac, q_limit_low, q_limit_high, q_limit_low_old, q_limit_high_old;
  1046. +   struct sta_info *sta;
  1047. +
  1048. +   if (count > sizeof(buf))
  1049. +       return -EINVAL;
  1050. +
  1051. +   if (copy_from_user(buf, user_buf, count))
  1052. +       return -EFAULT;
  1053. +
  1054. +   buf[sizeof(buf) - 1] = 0;
  1055. +   len = strlen(buf);
  1056. +   if (len > 0 && buf[len - 1] == '\n')
  1057. +       buf[len - 1] = 0;
  1058. +
  1059. +   if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
  1060. +       return -EINVAL;
  1061. +
  1062. +   if (ac >= IEEE80211_NUM_ACS)
  1063. +       return -EINVAL;
  1064. +
  1065. +   q_limit_low_old = local->aql_txq_limit_low[ac];
  1066. +   q_limit_high_old = local->aql_txq_limit_high[ac];
  1067. +
  1068. +   local->aql_txq_limit_low[ac] = q_limit_low;
  1069. +   local->aql_txq_limit_high[ac] = q_limit_high;
  1070. +
  1071. +   mutex_lock(&local->sta_mtx);
  1072. +   list_for_each_entry(sta, &local->sta_list, list) {
  1073. +       /* If a sta has customized queue limits, keep it */
  1074. +       if (sta->airtime[ac].aql_limit_low == q_limit_low_old &&
  1075. +           sta->airtime[ac].aql_limit_high == q_limit_high_old) {
  1076. +           sta->airtime[ac].aql_limit_low = q_limit_low;
  1077. +           sta->airtime[ac].aql_limit_high = q_limit_high;
  1078. +       }
  1079. +   }
  1080. +   mutex_unlock(&local->sta_mtx);
  1081. +   return count;
  1082. +}
  1083. +
  1084. +static const struct file_operations aql_txq_limit_ops = {
  1085. +   .write = aql_txq_limit_write,
  1086. +   .read = aql_txq_limit_read,
  1087. +   .open = simple_open,
  1088. +   .llseek = default_llseek,
  1089. +};
  1090. +
  1091.  static ssize_t force_tx_status_read(struct file *file,
  1092.                     char __user *user_buf,
  1093.                     size_t count,
  1094. @@ -441,6 +522,10 @@ void debugfs_hw_add(struct ieee80211_loc
  1095.     debugfs_create_u16("airtime_flags", 0600,
  1096.                phyd, &local->airtime_flags);
  1097.  
  1098. +   DEBUGFS_ADD(aql_txq_limit);
  1099. +   debugfs_create_u32("aql_threshold", 0600,
  1100. +              phyd, &local->aql_threshold);
  1101. +
  1102.     statsd = debugfs_create_dir("statistics", phyd);
  1103.  
  1104.     /* if the dir failed, don't put all the other things into the root! */
  1105. --- a/net/mac80211/debugfs_sta.c
  1106. +++ b/net/mac80211/debugfs_sta.c
  1107. @@ -197,10 +197,12 @@ static ssize_t sta_airtime_read(struct f
  1108.  {
  1109.     struct sta_info *sta = file->private_data;
  1110.     struct ieee80211_local *local = sta->sdata->local;
  1111. -   size_t bufsz = 200;
  1112. +   size_t bufsz = 400;
  1113.     char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
  1114.     u64 rx_airtime = 0, tx_airtime = 0;
  1115.     s64 deficit[IEEE80211_NUM_ACS];
  1116. +   u32 q_depth[IEEE80211_NUM_ACS];
  1117. +   u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
  1118.     ssize_t rv;
  1119.     int ac;
  1120.  
  1121. @@ -212,19 +214,22 @@ static ssize_t sta_airtime_read(struct f
  1122.         rx_airtime += sta->airtime[ac].rx_airtime;
  1123.         tx_airtime += sta->airtime[ac].tx_airtime;
  1124.         deficit[ac] = sta->airtime[ac].deficit;
  1125. +       q_limit_l[ac] = sta->airtime[ac].aql_limit_low;
  1126. +       q_limit_h[ac] = sta->airtime[ac].aql_limit_high;
  1127.         spin_unlock_bh(&local->active_txq_lock[ac]);
  1128. +       q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending);
  1129.     }
  1130.  
  1131.     p += scnprintf(p, bufsz + buf - p,
  1132.         "RX: %llu us\nTX: %llu us\nWeight: %u\n"
  1133. -       "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n",
  1134. -       rx_airtime,
  1135. -       tx_airtime,
  1136. -       sta->airtime_weight,
  1137. -       deficit[0],
  1138. -       deficit[1],
  1139. -       deficit[2],
  1140. -       deficit[3]);
  1141. +       "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n"
  1142. +       "Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n"
  1143. +       "Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n",
  1144. +       rx_airtime, tx_airtime, sta->airtime_weight,
  1145. +       deficit[0], deficit[1], deficit[2], deficit[3],
  1146. +       q_depth[0], q_depth[1], q_depth[2], q_depth[3],
  1147. +       q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1],
  1148. +       q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]),
  1149.  
  1150.     rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
  1151.     kfree(buf);
  1152. @@ -236,7 +241,25 @@ static ssize_t sta_airtime_write(struct
  1153.  {
  1154.     struct sta_info *sta = file->private_data;
  1155.     struct ieee80211_local *local = sta->sdata->local;
  1156. -   int ac;
  1157. +   u32 ac, q_limit_l, q_limit_h;
  1158. +   char _buf[100] = {}, *buf = _buf;
  1159. +
  1160. +   if (count > sizeof(_buf))
  1161. +       return -EINVAL;
  1162. +
  1163. +   if (copy_from_user(buf, userbuf, count))
  1164. +       return -EFAULT;
  1165. +
  1166. +   buf[sizeof(_buf) - 1] = '\0';
  1167. +   if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
  1168. +       != 3)
  1169. +       return -EINVAL;
  1170. +
  1171. +   if (ac >= IEEE80211_NUM_ACS)
  1172. +       return -EINVAL;
  1173. +
  1174. +   sta->airtime[ac].aql_limit_low = q_limit_l;
  1175. +   sta->airtime[ac].aql_limit_high = q_limit_h;
  1176.  
  1177.     for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
  1178.         spin_lock_bh(&local->active_txq_lock[ac]);
  1179. --- a/net/mac80211/main.c
  1180. +++ b/net/mac80211/main.c
  1181. @@ -676,8 +676,16 @@ struct ieee80211_hw *ieee80211_alloc_hw_
  1182.     for (i = 0; i < IEEE80211_NUM_ACS; i++) {
  1183.         INIT_LIST_HEAD(&local->active_txqs[i]);
  1184.         spin_lock_init(&local->active_txq_lock[i]);
  1185. +       local->aql_txq_limit_low[i] = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L;
  1186. +       local->aql_txq_limit_high[i] =
  1187. +           IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
  1188.     }
  1189. -   local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
  1190. +
  1191. +   local->airtime_flags = AIRTIME_USE_TX |
  1192. +                  AIRTIME_USE_RX |
  1193. +                  AIRTIME_USE_AQL;
  1194. +   local->aql_threshold = IEEE80211_AQL_THRESHOLD;
  1195. +   atomic_set(&local->aql_total_pending_airtime, 0);
  1196.  
  1197.     INIT_LIST_HEAD(&local->chanctx_list);
  1198.     mutex_init(&local->chanctx_mtx);
  1199. --- a/net/mac80211/tx.c
  1200. +++ b/net/mac80211/tx.c
  1201. @@ -3535,6 +3535,9 @@ struct sk_buff *ieee80211_tx_dequeue(str
  1202.  
  1203.     WARN_ON_ONCE(softirq_count() == 0);
  1204.  
  1205. +   if (!ieee80211_txq_airtime_check(hw, txq))
  1206. +       return NULL;
  1207. +
  1208.  begin:
  1209.     spin_lock_bh(&fq->lock);
  1210.  
  1211. @@ -3645,6 +3648,21 @@ begin:
  1212.     }
  1213.  
  1214.     IEEE80211_SKB_CB(skb)->control.vif = vif;
  1215. +
  1216. +   if (local->airtime_flags & AIRTIME_USE_AQL) {
  1217. +       u32 airtime;
  1218. +
  1219. +       airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
  1220. +                                skb->len);
  1221. +       if (airtime) {
  1222. +           airtime = ieee80211_info_set_tx_time_est(info, airtime);
  1223. +           ieee80211_sta_update_pending_airtime(local, tx.sta,
  1224. +                                txq->ac,
  1225. +                                airtime,
  1226. +                                false);
  1227. +       }
  1228. +   }
  1229. +
  1230.     return skb;
  1231.  
  1232.  out:
  1233. @@ -3658,7 +3676,8 @@ struct ieee80211_txq *ieee80211_next_txq
  1234.  {
  1235.     struct ieee80211_local *local = hw_to_local(hw);
  1236.     struct ieee80211_txq *ret = NULL;
  1237. -   struct txq_info *txqi = NULL;
  1238. +   struct txq_info *txqi = NULL, *head = NULL;
  1239. +   bool found_eligible_txq = false;
  1240.  
  1241.     spin_lock_bh(&local->active_txq_lock[ac]);
  1242.  
  1243. @@ -3669,13 +3688,30 @@ struct ieee80211_txq *ieee80211_next_txq
  1244.     if (!txqi)
  1245.         goto out;
  1246.  
  1247. +   if (txqi == head) {
  1248. +       if (!found_eligible_txq)
  1249. +           goto out;
  1250. +       else
  1251. +           found_eligible_txq = false;
  1252. +   }
  1253. +
  1254. +   if (!head)
  1255. +       head = txqi;
  1256. +
  1257.     if (txqi->txq.sta) {
  1258.         struct sta_info *sta = container_of(txqi->txq.sta,
  1259. -                       struct sta_info, sta);
  1260. +                           struct sta_info, sta);
  1261. +       bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
  1262. +       s64 deficit = sta->airtime[txqi->txq.ac].deficit;
  1263.  
  1264. -       if (sta->airtime[txqi->txq.ac].deficit < 0) {
  1265. +       if (aql_check)
  1266. +           found_eligible_txq = true;
  1267. +
  1268. +       if (deficit < 0)
  1269.             sta->airtime[txqi->txq.ac].deficit +=
  1270.                 sta->airtime_weight;
  1271. +
  1272. +       if (deficit < 0 || !aql_check) {
  1273.             list_move_tail(&txqi->schedule_order,
  1274.                        &local->active_txqs[txqi->txq.ac]);
  1275.             goto begin;
  1276. @@ -3729,6 +3765,33 @@ void __ieee80211_schedule_txq(struct iee
  1277.  }
  1278.  EXPORT_SYMBOL(__ieee80211_schedule_txq);
  1279.  
  1280. +bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
  1281. +                struct ieee80211_txq *txq)
  1282. +{
  1283. +   struct sta_info *sta;
  1284. +   struct ieee80211_local *local = hw_to_local(hw);
  1285. +
  1286. +   if (!(local->airtime_flags & AIRTIME_USE_AQL))
  1287. +       return true;
  1288. +
  1289. +   if (!txq->sta)
  1290. +       return true;
  1291. +
  1292. +   sta = container_of(txq->sta, struct sta_info, sta);
  1293. +   if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
  1294. +       sta->airtime[txq->ac].aql_limit_low)
  1295. +       return true;
  1296. +
  1297. +   if (atomic_read(&local->aql_total_pending_airtime) <
  1298. +       local->aql_threshold &&
  1299. +       atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
  1300. +       sta->airtime[txq->ac].aql_limit_high)
  1301. +       return true;
  1302. +
  1303. +   return false;
  1304. +}
  1305. +EXPORT_SYMBOL(ieee80211_txq_airtime_check);
  1306. +
  1307.  bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
  1308.                 struct ieee80211_txq *txq)
  1309.  {
Advertisement
Add Comment
Please, Sign In to add comment