Advertisement
Guest User

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

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