From patchwork Tue Jan 22 14:20:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 10775543 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 61F101390 for ; Tue, 22 Jan 2019 14:21:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 50D202AB6D for ; Tue, 22 Jan 2019 14:21:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4E93C2AC08; Tue, 22 Jan 2019 14:21:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 18F382AB6D for ; Tue, 22 Jan 2019 14:21:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728714AbfAVOVd (ORCPT ); Tue, 22 Jan 2019 09:21:33 -0500 Received: from mail-ed1-f68.google.com ([209.85.208.68]:36688 "EHLO mail-ed1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728416AbfAVOVd (ORCPT ); Tue, 22 Jan 2019 09:21:33 -0500 Received: by mail-ed1-f68.google.com with SMTP id f23so19446741edb.3 for ; Tue, 22 Jan 2019 06:21:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3IHpxwscK74GPH/OmYTacZuNvfvt+rhFlghjd4c8vPM=; b=I5p+kj8143q6KqITC/FadtqV05YMZnWTZKjKsYcgRfq5fdSRWkjb6mK4RGuxpv26VB cse4J2znLxeWuyvh0BL1RdgW7j/gmnmaKoV6egN2HzUn/eU1CQZUjPBi1xoC+Cn28AhI O1RO4EV6JXY279NuBsUXxaJrSOko9Uopz1HHYWYDC9kSRsNnZHVLNH0DQ56tuIBJuRfe 5RZrPll3yNCQ08afFwsuFhRJpPALnZyUiIlcMeV4UCJ6eMna+IKCFExCGgu+80iSqxN4 lRGD7dk+s4Y/btCRugcMKQMEB96clggb6gbUvJamz8ZA81kJlEBxueSKbou2KP90BDv+ uWHw== X-Gm-Message-State: AJcUukcCHQx/FD1gmUbB7oiFVIGjtddU8a6H8U+1fG+OG1wLecwqs8Gw 1OWUOG4NfIfGp3szvokV0tiDBg== X-Google-Smtp-Source: ALg8bN5nPdEKK/oeg5eB/dxboG3zFhcM4QpFSGhjxptEtLRC+3dfDDkXEJc2faOXxMp/gPj4rHnxFw== X-Received: by 2002:a50:f5af:: with SMTP id u44mr32009323edm.172.1548166891402; Tue, 22 Jan 2019 06:21:31 -0800 (PST) Received: from tohojo-x1-rh.localdomain (borgediget.toke.dk. [85.204.121.218]) by smtp.gmail.com with ESMTPSA id h8sm9462898edb.95.2019.01.22.06.21.30 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 22 Jan 2019 06:21:30 -0800 (PST) Received: by tohojo-x1-rh.localdomain (Postfix, from userid 1000) id 5E7621833C1; Tue, 22 Jan 2019 15:21:29 +0100 (CET) From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: linux-wireless@vger.kernel.org Cc: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= , Rajkumar Manoharan , ath10k@lists.infradead.org, make-wifi-fast@lists.bufferbloat.net Subject: [PATCH v7 1/4] mac80211: Expose ieee80211_schedule_txq() function Date: Tue, 22 Jan 2019 15:20:16 +0100 Message-Id: <20190122142019.21417-2-toke@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190122142019.21417-1-toke@redhat.com> References: <20190122142019.21417-1-toke@redhat.com> MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Since we reworked ieee80211_return_txq() so it assumes that the caller takes care of logging, we need another function that can be called without holding any locks. Introduce ieee80211_schedule_txq() which serves this purpose. Signed-off-by: Toke Høiland-Jørgensen --- include/net/mac80211.h | 13 +++++++++++++ net/mac80211/driver-ops.h | 4 +--- net/mac80211/tx.c | 13 +++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a285c2bfd14e..294a8a36012a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -6209,6 +6209,19 @@ void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac) void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac) __releases(txq_lock); +/** + * ieee80211_schedule_txq - schedule a TXQ for transmission + * + * @hw: pointer as obtained from ieee80211_alloc_hw() + * @txq: pointer obtained from station or virtual interface + * + * Schedules a TXQ for transmission if it is not already scheduled. Takes a + * lock, which means it must *not* be called between + * ieee80211_txq_schedule_start() and ieee80211_txq_schedule_end() + */ +void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq) + __acquires(txq_lock) __releases(txq_lock); + /** * ieee80211_txq_may_transmit - check whether TXQ is allowed to transmit * diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 1aab1734b26f..ba3c07b10cd0 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -1176,9 +1176,7 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local, static inline void schedule_and_wake_txq(struct ieee80211_local *local, struct txq_info *txqi) { - spin_lock_bh(&local->active_txq_lock[txqi->txq.ac]); - ieee80211_return_txq(&local->hw, &txqi->txq); - spin_unlock_bh(&local->active_txq_lock[txqi->txq.ac]); + ieee80211_schedule_txq(&local->hw, &txqi->txq); drv_wake_tx_queue(local, txqi); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f46d8d822f86..17744be84b34 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3703,6 +3703,19 @@ void ieee80211_return_txq(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_return_txq); +void ieee80211_schedule_txq(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) + __acquires(txq_lock) __releases(txq_lock) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct txq_info *txqi = to_txq_info(txq); + + spin_lock_bh(&local->active_txq_lock[txq->ac]); + ieee80211_return_txq(hw, txq); + spin_unlock_bh(&local->active_txq_lock[ac]); +} +EXPORT_SYMBOL(ieee80211_schedule_txq); + bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { From patchwork Tue Jan 22 14:20:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 10775549 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 605D61390 for ; Tue, 22 Jan 2019 14:21:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4AE542AC85 for ; Tue, 22 Jan 2019 14:21:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 48C442AC8B; Tue, 22 Jan 2019 14:21:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BA1DF2AC98 for ; Tue, 22 Jan 2019 14:21:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728719AbfAVOVs (ORCPT ); Tue, 22 Jan 2019 09:21:48 -0500 Received: from mail-ed1-f66.google.com ([209.85.208.66]:41158 "EHLO mail-ed1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728371AbfAVOVs (ORCPT ); Tue, 22 Jan 2019 09:21:48 -0500 Received: by mail-ed1-f66.google.com with SMTP id a20so19423234edc.8 for ; Tue, 22 Jan 2019 06:21:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=mDxRFBKEjkm2O2/VHNqqy0DADQOdF0h3+Cq2fwqIamI=; b=qXcbxe2BR7YC5NFhENnNgXzlIhOYx6M4vmpRt3o7nhMppHSEYAWrdGJ9FCVASuxLX4 jM6lFpfjyJmx2j/1bCpLLbmluM5UAYD3Su6JMqh9m+UhuemdEMjyX7b9dwRlphyW8igV Da8CKgtFwMcWwJoKr8oPkzZHFHreJ797a8kMwgk9/I83BqpM01/ewsIx2cPKJXV4tG4b GIz86MS2FZsH9X7vPbpTsX9vGox4LvQdwkGXfPThKNGWORkLPDnSSVxvt95c4VubcU+C 7NmzBi7Uc5LLabUESR6XoesxD7Y5UW9vZgJHA/Ns7BiBmnpW7yPHnghTpl0VxlYegIdF sm2A== X-Gm-Message-State: AJcUuke14NLKSY9YnS51xDJ+IqW4zhlDDMOQ+zyj01GWXqpop0YxpITV DGPtPrv+8y3DCb11121t5slgTA== X-Google-Smtp-Source: ALg8bN4PCE8pLguUm1J85zcqwBH1bYwWfamguTP3KMC57eSZK3zK5H4S20K1tP4zYfB+3jjaEsYrWA== X-Received: by 2002:a50:f5af:: with SMTP id u44mr32010079edm.172.1548166904220; Tue, 22 Jan 2019 06:21:44 -0800 (PST) Received: from tohojo-x1-rh.localdomain (borgediget.toke.dk. [85.204.121.218]) by smtp.gmail.com with ESMTPSA id b49sm9952411edb.73.2019.01.22.06.21.43 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 22 Jan 2019 06:21:43 -0800 (PST) Received: by tohojo-x1-rh.localdomain (Postfix, from userid 1000) id 0F7661833C1; Tue, 22 Jan 2019 15:21:42 +0100 (CET) From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: linux-wireless@vger.kernel.org Cc: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= , Rajkumar Manoharan , ath10k@lists.infradead.org, make-wifi-fast@lists.bufferbloat.net Subject: [PATCH v6 2/4] ath9k: Switch to mac80211 TXQ scheduling and airtime APIs Date: Tue, 22 Jan 2019 15:20:17 +0100 Message-Id: <20190122142019.21417-3-toke@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190122142019.21417-1-toke@redhat.com> References: <20190122142019.21417-1-toke@redhat.com> MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Toke Høiland-Jørgensen This moves the ath9k driver to use the mac80211 TXQ scheduling and airtime accounting APIs, removing the corresponding state tracking inside the driver. Signed-off-by: Toke Høiland-Jørgensen [rmanohar@codeaurora.org: fixed checkpatch error and warnings] Signed-off-by: Rajkumar Manoharan --- v6: - Use the ieee80211_schedule_txq() function introduced in the previous patch instead of calling ieee80211_return_txq() with no locking. drivers/net/wireless/ath/ath9k/ath9k.h | 14 -- drivers/net/wireless/ath/ath9k/debug.c | 3 - drivers/net/wireless/ath/ath9k/debug.h | 8 - drivers/net/wireless/ath/ath9k/debug_sta.c | 70 ------ drivers/net/wireless/ath/ath9k/init.c | 3 +- drivers/net/wireless/ath/ath9k/recv.c | 9 +- drivers/net/wireless/ath/ath9k/xmit.c | 244 ++++++--------------- 7 files changed, 75 insertions(+), 276 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0fca44e91a71..a412b352182c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -112,8 +112,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, #define ATH_TXFIFO_DEPTH 8 #define ATH_TX_ERROR 0x01 -#define ATH_AIRTIME_QUANTUM 300 /* usec */ - /* Stop tx traffic 1ms before the GO goes away */ #define ATH_P2P_PS_STOP_TIME 1000 @@ -246,10 +244,8 @@ struct ath_atx_tid { s8 bar_index; bool active; bool clear_ps_filter; - bool has_queued; }; -void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid); void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid); struct ath_node { @@ -263,12 +259,9 @@ struct ath_node { bool sleeping; bool no_ps_filter; - s64 airtime_deficit[IEEE80211_NUM_ACS]; - u32 airtime_rx_start; #ifdef CONFIG_ATH9K_STATION_STATISTICS struct ath_rx_rate_stats rx_rate_stats; - struct ath_airtime_stats airtime_stats; #endif u8 key_idx[4]; @@ -986,11 +979,6 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ -#define AIRTIME_USE_TX BIT(0) -#define AIRTIME_USE_RX BIT(1) -#define AIRTIME_USE_NEW_QUEUES BIT(2) -#define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX))) - struct ath_softc { struct ieee80211_hw *hw; struct device *dev; @@ -1034,8 +1022,6 @@ struct ath_softc { short nbcnvifs; unsigned long ps_usecount; - u16 airtime_flags; /* AIRTIME_* */ - struct ath_rx rx; struct ath_tx tx; struct ath_beacon beacon; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 4399e9ad058f..0dfea5d6e949 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1443,9 +1443,6 @@ int ath9k_init_debug(struct ath_hw *ah) #endif debugfs_create_file("tpc", 0600, sc->debug.debugfs_phy, sc, &fops_tpc); - debugfs_create_u16("airtime_flags", 0600, - sc->debug.debugfs_phy, &sc->airtime_flags); - debugfs_create_file("nf_override", 0600, sc->debug.debugfs_phy, sc, &fops_nf_override); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 79607db14387..33826aa13687 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -319,20 +319,12 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause) void ath_debug_rate_stats(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb); -void ath_debug_airtime(struct ath_softc *sc, - struct ath_node *an, - u32 rx, u32 tx); #else static inline void ath_debug_rate_stats(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb) { } -static inline void ath_debug_airtime(struct ath_softc *sc, - struct ath_node *an, - u32 rx, u32 tx) -{ -} #endif /* CONFIG_ATH9K_STATION_STATISTICS */ #endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c index e8fcd3e1c470..d95cabddce33 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c @@ -242,75 +242,6 @@ static const struct file_operations fops_node_recv = { .llseek = default_llseek, }; -void ath_debug_airtime(struct ath_softc *sc, - struct ath_node *an, - u32 rx, - u32 tx) -{ - struct ath_airtime_stats *astats = &an->airtime_stats; - - astats->rx_airtime += rx; - astats->tx_airtime += tx; -} - -static ssize_t read_airtime(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_node *an = file->private_data; - struct ath_airtime_stats *astats; - static const char *qname[4] = { - "VO", "VI", "BE", "BK" - }; - u32 len = 0, size = 256; - char *buf; - size_t retval; - int i; - - buf = kzalloc(size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - astats = &an->airtime_stats; - - len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime); - len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime); - len += scnprintf(buf + len, size - len, "Deficit: "); - for (i = 0; i < 4; i++) - len += scnprintf(buf+len, size - len, "%s: %lld us ", qname[i], an->airtime_deficit[i]); - if (len < size) - buf[len++] = '\n'; - - retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - - return retval; -} - -static ssize_t -write_airtime_reset_stub(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct ath_node *an = file->private_data; - struct ath_airtime_stats *astats; - int i; - - astats = &an->airtime_stats; - astats->rx_airtime = 0; - astats->tx_airtime = 0; - for (i = 0; i < 4; i++) - an->airtime_deficit[i] = ATH_AIRTIME_QUANTUM; - return count; -} - -static const struct file_operations fops_airtime = { - .read = read_airtime, - .write = write_airtime_reset_stub, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - - void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -320,5 +251,4 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, debugfs_create_file("node_aggr", 0444, dir, an, &fops_node_aggr); debugfs_create_file("node_recv", 0444, dir, an, &fops_node_recv); - debugfs_create_file("airtime", 0644, dir, an, &fops_airtime); } diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index c070a9e51ebf..45a31f8a1514 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -676,8 +676,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, /* Will be cleared in ath9k_start() */ set_bit(ATH_OP_INVALID, &common->op_flags); - sc->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX | - AIRTIME_USE_NEW_QUEUES); sc->sc_ah = ah; sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); @@ -1013,6 +1011,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) SET_IEEE80211_PERM_ADDR(hw, common->macaddr); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); } int ath9k_init_device(u16 devid, struct ath_softc *sc, diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 30d1bd832d90..285a62d3019d 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1054,14 +1054,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc, len, rxs->rate_idx, is_sp); } - if (!!(sc->airtime_flags & AIRTIME_USE_RX)) { - spin_lock_bh(&acq->lock); - an->airtime_deficit[acno] -= airtime; - if (an->airtime_deficit[acno] <= 0) - __ath_tx_queue_tid(sc, ATH_AN_2_TID(an, tidno)); - spin_unlock_bh(&acq->lock); - } - ath_debug_airtime(sc, an, airtime, 0); + ieee80211_sta_register_airtime(sta, tidno, 0, airtime); exit: rcu_read_unlock(); } diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f448d5716639..06e0c5a6fab6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -113,44 +113,14 @@ void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq) ath_tx_status(hw, skb); } -void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv; - struct ath_chanctx *ctx = avp->chanctx; - struct ath_acq *acq; - struct list_head *tid_list; - u8 acno = TID_TO_WME_AC(tid->tidno); - - if (!ctx || !list_empty(&tid->list)) - return; - - - acq = &ctx->acq[acno]; - if ((sc->airtime_flags & AIRTIME_USE_NEW_QUEUES) && - tid->an->airtime_deficit[acno] > 0) - tid_list = &acq->acq_new; - else - tid_list = &acq->acq_old; - - list_add_tail(&tid->list, tid_list); -} - void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv; - struct ath_chanctx *ctx = avp->chanctx; - struct ath_acq *acq; + struct ieee80211_txq *queue = + container_of((void *)tid, struct ieee80211_txq, drv_priv); - if (!ctx || !list_empty(&tid->list)) - return; - - acq = &ctx->acq[TID_TO_WME_AC(tid->tidno)]; - spin_lock_bh(&acq->lock); - __ath_tx_queue_tid(sc, tid); - spin_unlock_bh(&acq->lock); + ieee80211_schedule_txq(sc->hw, queue); } - void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue) { struct ath_softc *sc = hw->priv; @@ -163,11 +133,7 @@ void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue) tid->tidno); ath_txq_lock(sc, txq); - - tid->has_queued = true; - ath_tx_queue_tid(sc, tid); ath_txq_schedule(sc, txq); - ath_txq_unlock(sc, txq); } @@ -217,8 +183,8 @@ ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb) return ATH_AN_2_TID(an, tidno); } -static struct sk_buff * -ath_tid_pull(struct ath_atx_tid *tid) +static int +ath_tid_pull(struct ath_atx_tid *tid, struct sk_buff **skbuf) { struct ieee80211_txq *txq = container_of((void*)tid, struct ieee80211_txq, drv_priv); struct ath_softc *sc = tid->an->sc; @@ -229,20 +195,16 @@ ath_tid_pull(struct ath_atx_tid *tid) }; struct sk_buff *skb; struct ath_frame_info *fi; - int q; - - if (!tid->has_queued) - return NULL; + int q, ret; skb = ieee80211_tx_dequeue(hw, txq); - if (!skb) { - tid->has_queued = false; - return NULL; - } + if (!skb) + return -ENOENT; - if (ath_tx_prepare(hw, skb, &txctl)) { + ret = ath_tx_prepare(hw, skb, &txctl); + if (ret) { ieee80211_free_txskb(hw, skb); - return NULL; + return ret; } q = skb_get_queue_mapping(skb); @@ -252,24 +214,19 @@ ath_tid_pull(struct ath_atx_tid *tid) ++tid->txq->pending_frames; } - return skb; -} - - -static bool ath_tid_has_buffered(struct ath_atx_tid *tid) -{ - return !skb_queue_empty(&tid->retry_q) || tid->has_queued; + *skbuf = skb; + return 0; } -static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid) +static int ath_tid_dequeue(struct ath_atx_tid *tid, + struct sk_buff **skb) { - struct sk_buff *skb; - - skb = __skb_dequeue(&tid->retry_q); - if (!skb) - skb = ath_tid_pull(tid); + int ret = 0; + *skb = __skb_dequeue(&tid->retry_q); + if (!*skb) + ret = ath_tid_pull(tid, skb); - return skb; + return ret; } static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) @@ -365,11 +322,12 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, struct list_head bf_head; struct ath_tx_status ts; struct ath_frame_info *fi; + int ret; memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); - while ((skb = ath_tid_dequeue(tid))) { + while ((ret = ath_tid_dequeue(tid, &skb)) == 0) { fi = get_frame_info(skb); bf = fi->bf; @@ -681,7 +639,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, skb_queue_splice_tail(&bf_pending, &tid->retry_q); if (!an->sleeping) { ath_tx_queue_tid(sc, tid); - if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY)) tid->clear_ps_filter = true; } @@ -708,11 +665,11 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf) return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); } -static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an, - struct ath_atx_tid *tid, struct ath_buf *bf, +static void ath_tx_count_airtime(struct ath_softc *sc, + struct ieee80211_sta *sta, + struct ath_buf *bf, struct ath_tx_status *ts) { - struct ath_txq *txq = tid->txq; u32 airtime = 0; int i; @@ -722,17 +679,7 @@ static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an, airtime += rate_dur * bf->rates[i].count; } - if (sc->airtime_flags & AIRTIME_USE_TX) { - int q = txq->mac80211_qnum; - struct ath_acq *acq = &sc->cur_chan->acq[q]; - - spin_lock_bh(&acq->lock); - an->airtime_deficit[q] -= airtime; - if (an->airtime_deficit[q] <= 0) - __ath_tx_queue_tid(sc, tid); - spin_unlock_bh(&acq->lock); - } - ath_debug_airtime(sc, an, 0, airtime); + ieee80211_sta_register_airtime(sta, ts->tid, airtime, 0); } static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, @@ -762,7 +709,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, if (sta) { struct ath_node *an = (struct ath_node *)sta->drv_priv; tid = ath_get_skb_tid(sc, an, bf->bf_mpdu); - ath_tx_count_airtime(sc, an, tid, bf, ts); + ath_tx_count_airtime(sc, sta, bf, ts); if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY)) tid->clear_ps_filter = true; } @@ -947,20 +894,21 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, return ndelim; } -static struct ath_buf * +static int ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid) + struct ath_atx_tid *tid, struct ath_buf **buf) { struct ieee80211_tx_info *tx_info; struct ath_frame_info *fi; - struct sk_buff *skb, *first_skb = NULL; struct ath_buf *bf; + struct sk_buff *skb, *first_skb = NULL; u16 seqno; + int ret; while (1) { - skb = ath_tid_dequeue(tid); - if (!skb) - break; + ret = ath_tid_dequeue(tid, &skb); + if (ret < 0) + return ret; fi = get_frame_info(skb); bf = fi->bf; @@ -992,7 +940,7 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { bf->bf_state.bf_type = 0; - return bf; + break; } bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; @@ -1011,7 +959,7 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, first_skb = skb; continue; } - break; + return -EINPROGRESS; } if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) { @@ -1028,10 +976,11 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, if (bf_isampdu(bf)) ath_tx_addto_baw(sc, tid, bf); - return bf; + break; } - return NULL; + *buf = bf; + return 0; } static int @@ -1041,7 +990,7 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, { #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) struct ath_buf *bf = bf_first, *bf_prev = NULL; - int nframes = 0, ndelim; + int nframes = 0, ndelim, ret; u16 aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw = tid->baw_size / 2; struct ieee80211_tx_info *tx_info; @@ -1093,7 +1042,9 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, bf_prev = bf; - bf = ath_tx_get_tid_subframe(sc, txq, tid); + ret = ath_tx_get_tid_subframe(sc, txq, tid, &bf); + if (ret < 0) + break; } goto finish; stop: @@ -1490,7 +1441,7 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf_first) { struct ath_buf *bf = bf_first, *bf_prev = NULL; - int nframes = 0; + int nframes = 0, ret; do { struct ieee80211_tx_info *tx_info; @@ -1504,8 +1455,8 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, if (nframes >= 2) break; - bf = ath_tx_get_tid_subframe(sc, txq, tid); - if (!bf) + ret = ath_tx_get_tid_subframe(sc, txq, tid, &bf); + if (ret < 0) break; tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); @@ -1518,30 +1469,27 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, } while (1); } -static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid) +static int ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid) { - struct ath_buf *bf; + struct ath_buf *bf = NULL; struct ieee80211_tx_info *tx_info; struct list_head bf_q; - int aggr_len = 0; + int aggr_len = 0, ret; bool aggr; - if (!ath_tid_has_buffered(tid)) - return false; - INIT_LIST_HEAD(&bf_q); - bf = ath_tx_get_tid_subframe(sc, txq, tid); - if (!bf) - return false; + ret = ath_tx_get_tid_subframe(sc, txq, tid, &bf); + if (ret < 0) + return ret; tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) || (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) { __skb_queue_tail(&tid->retry_q, bf->bf_mpdu); - return false; + return -EBUSY; } ath_set_rates(tid->an->vif, tid->an->sta, bf); @@ -1551,7 +1499,7 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_form_burst(sc, txq, tid, &bf_q, bf); if (list_empty(&bf_q)) - return false; + return -EAGAIN; if (tid->clear_ps_filter || tid->an->no_ps_filter) { tid->clear_ps_filter = false; @@ -1560,7 +1508,7 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_fill_desc(sc, bf, txq, aggr_len); ath_tx_txqaddbuf(sc, txq, &bf_q, false); - return true; + return 0; } int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, @@ -1623,28 +1571,16 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_atx_tid *tid; - struct ath_txq *txq; int tidno; ath_dbg(common, XMIT, "%s called\n", __func__); for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { tid = ath_node_to_tid(an, tidno); - txq = tid->txq; - - ath_txq_lock(sc, txq); - - if (list_empty(&tid->list)) { - ath_txq_unlock(sc, txq); - continue; - } if (!skb_queue_empty(&tid->retry_q)) ieee80211_sta_set_buffered(sta, tid->tidno, true); - list_del_init(&tid->list); - - ath_txq_unlock(sc, txq); } } @@ -1663,11 +1599,12 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) ath_txq_lock(sc, txq); tid->clear_ps_filter = true; - if (ath_tid_has_buffered(tid)) { + if (!skb_queue_empty(&tid->retry_q)) { ath_tx_queue_tid(sc, tid); ath_txq_schedule(sc, txq); } ath_txq_unlock_complete(sc, txq); + } } @@ -1698,9 +1635,9 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, struct ath_txq *txq = sc->tx.uapsdq; struct ieee80211_tx_info *info; struct list_head bf_q; - struct ath_buf *bf_tail = NULL, *bf; + struct ath_buf *bf_tail = NULL, *bf = NULL; int sent = 0; - int i; + int i, ret; INIT_LIST_HEAD(&bf_q); for (i = 0; tids && nframes; i++, tids >>= 1) { @@ -1713,8 +1650,9 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, ath_txq_lock(sc, tid->txq); while (nframes > 0) { - bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid); - if (!bf) + ret = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, + tid, &bf); + if (ret < 0) break; ath9k_set_moredata(sc, bf, true); @@ -1980,11 +1918,11 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) */ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) { + struct ieee80211_hw *hw = sc->hw; struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ieee80211_txq *queue; struct ath_atx_tid *tid; - struct list_head *tid_list; - struct ath_acq *acq; - bool active = AIRTIME_ACTIVE(sc->airtime_flags); + int ret; if (txq->mac80211_qnum < 0) return; @@ -1992,58 +1930,26 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) return; + ieee80211_txq_schedule_start(hw, txq->mac80211_qnum); spin_lock_bh(&sc->chan_lock); rcu_read_lock(); - acq = &sc->cur_chan->acq[txq->mac80211_qnum]; if (sc->cur_chan->stopped) goto out; -begin: - tid_list = &acq->acq_new; - if (list_empty(tid_list)) { - tid_list = &acq->acq_old; - if (list_empty(tid_list)) - goto out; - } - tid = list_first_entry(tid_list, struct ath_atx_tid, list); - - if (active && tid->an->airtime_deficit[txq->mac80211_qnum] <= 0) { - spin_lock_bh(&acq->lock); - tid->an->airtime_deficit[txq->mac80211_qnum] += ATH_AIRTIME_QUANTUM; - list_move_tail(&tid->list, &acq->acq_old); - spin_unlock_bh(&acq->lock); - goto begin; - } - - if (!ath_tid_has_buffered(tid)) { - spin_lock_bh(&acq->lock); - if ((tid_list == &acq->acq_new) && !list_empty(&acq->acq_old)) - list_move_tail(&tid->list, &acq->acq_old); - else { - list_del_init(&tid->list); - } - spin_unlock_bh(&acq->lock); - goto begin; - } + while ((queue = ieee80211_next_txq(hw, txq->mac80211_qnum))) { + tid = (struct ath_atx_tid *)queue->drv_priv; + ret = ath_tx_sched_aggr(sc, txq, tid); + ath_dbg(common, QUEUE, "ath_tx_sched_aggr returned %d\n", ret); - /* - * If we succeed in scheduling something, immediately restart to make - * sure we keep the HW busy. - */ - if(ath_tx_sched_aggr(sc, txq, tid)) { - if (!active) { - spin_lock_bh(&acq->lock); - list_move_tail(&tid->list, &acq->acq_old); - spin_unlock_bh(&acq->lock); - } - goto begin; + ieee80211_return_txq(hw, queue); } out: rcu_read_unlock(); spin_unlock_bh(&sc->chan_lock); + ieee80211_txq_schedule_end(hw, txq->mac80211_qnum); } void ath_txq_schedule_all(struct ath_softc *sc) @@ -2887,9 +2793,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) struct ath_atx_tid *tid; int tidno, acno; - for (acno = 0; acno < IEEE80211_NUM_ACS; acno++) - an->airtime_deficit[acno] = ATH_AIRTIME_QUANTUM; - for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { tid = ath_node_to_tid(an, tidno); tid->an = an; @@ -2899,7 +2802,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) tid->baw_head = tid->baw_tail = 0; tid->active = false; tid->clear_ps_filter = true; - tid->has_queued = false; __skb_queue_head_init(&tid->retry_q); INIT_LIST_HEAD(&tid->list); acno = TID_TO_WME_AC(tidno); From patchwork Tue Jan 22 14:20:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 10775547 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 934F31390 for ; Tue, 22 Jan 2019 14:21:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7E9B42AC98 for ; Tue, 22 Jan 2019 14:21:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 70A142AAEF; Tue, 22 Jan 2019 14:21:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7A56A2AC5A for ; Tue, 22 Jan 2019 14:21:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728718AbfAVOVr (ORCPT ); Tue, 22 Jan 2019 09:21:47 -0500 Received: from mail-ed1-f65.google.com ([209.85.208.65]:34598 "EHLO mail-ed1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728700AbfAVOVr (ORCPT ); Tue, 22 Jan 2019 09:21:47 -0500 Received: by mail-ed1-f65.google.com with SMTP id b3so19533610ede.1 for ; Tue, 22 Jan 2019 06:21:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9R3PaquB9Qt50JGBV1TVFQDcbyAxdTHfOAtR5/CPZH4=; b=JCb3XVxzXTjfFQ59WOjQ/2BMlRoBi/mRM1iofdfYfz72Oc114AlruP7iLDtm+ILc/0 4PGFD/f9J8ArNI4GHeWLbpEQFjrctwLM5mskT7cQO48BVITKTZ0KocQaM44bluSx1z0M mNwQKHIFVtZcM4bx95ZlIhIEqnuVKIVDETmEb93NtDow+1fOZTBtMrWfLJOwZ7yjp4jk aR5ob0v6MLLv22MQf7V8TX2zP9VaL2S7x1C0awx27CPN2/H5UeWd2wgfSPOxCkfo7P/y dhysvhKDv9KXIHK3DHND4FOsvoX96led/XmtfeJzKMr1qQea5h8yui5C4IgO49XVKvO2 JFSw== X-Gm-Message-State: AJcUukcvdHRmSScWqPnz9wZ5ECvnn5ZgHEazSGr/exi2hBLecND+vMrN uAF7Gki67ZZ0yOOUqi9m0n59VQ== X-Google-Smtp-Source: ALg8bN63j8+eMW1Hi2vZd98GLsLO+w5knX5CFVsTQda1v336dxt00QOxae0A8u9H4eAoSgnFEbbduw== X-Received: by 2002:a50:a246:: with SMTP id 64mr31490100edl.43.1548166904994; Tue, 22 Jan 2019 06:21:44 -0800 (PST) Received: from tohojo-x1-rh.localdomain (borgediget.toke.dk. [85.204.121.218]) by smtp.gmail.com with ESMTPSA id f35sm10069885edd.80.2019.01.22.06.21.43 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 22 Jan 2019 06:21:44 -0800 (PST) Received: by tohojo-x1-rh.localdomain (Postfix, from userid 1000) id 694861833DF; Tue, 22 Jan 2019 15:21:43 +0100 (CET) From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: linux-wireless@vger.kernel.org Cc: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= , Rajkumar Manoharan , ath10k@lists.infradead.org, make-wifi-fast@lists.bufferbloat.net, Venkateswara Naralasetty Subject: [PATCH v6 3/4] ath10k: migrate to mac80211 txq scheduling Date: Tue, 22 Jan 2019 15:20:18 +0100 Message-Id: <20190122142019.21417-4-toke@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190122142019.21417-1-toke@redhat.com> References: <20190122142019.21417-1-toke@redhat.com> MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Toke Høiland-Jørgensen ath10k maintains common txqs list for all stations. This txq management can be removed by migrating to mac80211 txq APIs and let mac80211 handle txqs reordering based on reported airtime. By doing this, txq fairness maintained in ath10k i.e processing N frames per txq is removed. By adapting to mac80211 APIs, ath10k will support mac80211 based airtime fairness algorithm. Tested on QCA4019 with firmware version 10.4-3.2.1.1-00015 Tested on QCA9984 with firmware version 10.4-3.9.0.1-00005 Tested-by: Venkateswara Naralasetty Co-developed-by: Rajkumar Manoharan Signed-off-by: Rajkumar Manoharan Signed-off-by: Toke Høiland-Jørgensen --- drivers/net/wireless/ath/ath10k/core.c | 2 - drivers/net/wireless/ath/ath10k/core.h | 6 +- drivers/net/wireless/ath/ath10k/htc.h | 1 - drivers/net/wireless/ath/ath10k/htt_rx.c | 8 ++ drivers/net/wireless/ath/ath10k/mac.c | 98 +++++++++++------------- 5 files changed, 54 insertions(+), 61 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 399b501f3c3c..c7327900316e 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -3098,9 +3098,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, mutex_init(&ar->conf_mutex); spin_lock_init(&ar->data_lock); - spin_lock_init(&ar->txqs_lock); - INIT_LIST_HEAD(&ar->txqs); INIT_LIST_HEAD(&ar->peers); init_waitqueue_head(&ar->peer_mapping_wq); init_waitqueue_head(&ar->htt.empty_tx_wq); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 46e9c8c97a4d..28cecf7375f8 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -90,6 +90,9 @@ /* The magic used by QCA spec */ #define ATH10K_SMBIOS_BDF_EXT_MAGIC "BDF_" +/* Default Airtime weight multipler (Tuned for multiclient performance) */ +#define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4 + struct ath10k; static inline const char *ath10k_bus_str(enum ath10k_bus bus) @@ -1068,10 +1071,7 @@ struct ath10k { /* protects shared structure data */ spinlock_t data_lock; - /* protects: ar->txqs, artxq->list */ - spinlock_t txqs_lock; - struct list_head txqs; struct list_head arvifs; struct list_head peers; struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS]; diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index 51fda6c23f69..cb30add7dd33 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -51,7 +51,6 @@ struct ath10k; */ #define HTC_HOST_MAX_MSG_PER_RX_BUNDLE 8 -#define HTC_HOST_MAX_MSG_PER_TX_BUNDLE 16 enum ath10k_htc_tx_flags { ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01, diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index f42bac204ef8..dc9895f2eb9d 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2596,6 +2596,7 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) u8 tid; int ret; int i; + bool may_tx; ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind\n"); @@ -2668,8 +2669,13 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) num_msdus = 0; num_bytes = 0; + ieee80211_txq_schedule_start(hw, txq->ac); + may_tx = ieee80211_txq_may_transmit(hw, txq); while (num_msdus < max_num_msdus && num_bytes < max_num_bytes) { + if (!may_tx) + break; + ret = ath10k_mac_tx_push_txq(hw, txq); if (ret < 0) break; @@ -2677,6 +2683,8 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) num_msdus++; num_bytes += ret; } + ieee80211_return_txq(hw, txq); + ieee80211_txq_schedule_end(hw, txq->ac); record->num_msdus = cpu_to_le16(num_msdus); record->num_bytes = cpu_to_le32(num_bytes); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 49758490eaba..cf7fdf72e990 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3890,7 +3890,6 @@ static void ath10k_mac_txq_init(struct ieee80211_txq *txq) static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) { - struct ath10k_txq *artxq; struct ath10k_skb_cb *cb; struct sk_buff *msdu; int msdu_id; @@ -3898,12 +3897,6 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) if (!txq) return; - artxq = (void *)txq->drv_priv; - spin_lock_bh(&ar->txqs_lock); - if (!list_empty(&artxq->list)) - list_del_init(&artxq->list); - spin_unlock_bh(&ar->txqs_lock); - spin_lock_bh(&ar->htt.tx_lock); idr_for_each_entry(&ar->htt.pending_tx, msdu, msdu_id) { cb = ATH10K_SKB_CB(msdu); @@ -3943,7 +3936,6 @@ static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw, struct ath10k_txq *artxq = (void *)txq->drv_priv; /* No need to get locks */ - if (ar->htt.tx_q_state.mode == HTT_TX_MODE_SWITCH_PUSH) return true; @@ -4030,48 +4022,45 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, return skb_len; } -void ath10k_mac_tx_push_pending(struct ath10k *ar) +static int ath10k_mac_schedule_txq(struct ieee80211_hw *hw, u32 ac) { - struct ieee80211_hw *hw = ar->hw; struct ieee80211_txq *txq; - struct ath10k_txq *artxq; - struct ath10k_txq *last; - int ret; - int max; - - if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2)) - return; - - spin_lock_bh(&ar->txqs_lock); - rcu_read_lock(); - - last = list_last_entry(&ar->txqs, struct ath10k_txq, list); - while (!list_empty(&ar->txqs)) { - artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list); - txq = container_of((void *)artxq, struct ieee80211_txq, - drv_priv); + int ret = 0; - /* Prevent aggressive sta/tid taking over tx queue */ - max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE; - ret = 0; - while (ath10k_mac_tx_can_push(hw, txq) && max--) { + ieee80211_txq_schedule_start(hw, ac); + while ((txq = ieee80211_next_txq(hw, ac))) { + while (ath10k_mac_tx_can_push(hw, txq)) { ret = ath10k_mac_tx_push_txq(hw, txq); if (ret < 0) break; } + ieee80211_return_txq(hw, txq); + ath10k_htt_tx_txq_update(hw, txq); + if (ret == -EBUSY) + break; + } + ieee80211_txq_schedule_end(hw, ac); + + return ret; +} - list_del_init(&artxq->list); - if (ret != -ENOENT) - list_add_tail(&artxq->list, &ar->txqs); +void ath10k_mac_tx_push_pending(struct ath10k *ar) +{ + struct ieee80211_hw *hw = ar->hw; + u32 ac; - ath10k_htt_tx_txq_update(hw, txq); + if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH) + return; - if (artxq == last || (ret < 0 && ret != -ENOENT)) + if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2)) + return; + + rcu_read_lock(); + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + if (ath10k_mac_schedule_txq(hw, ac) == -EBUSY) break; } - rcu_read_unlock(); - spin_unlock_bh(&ar->txqs_lock); } EXPORT_SYMBOL(ath10k_mac_tx_push_pending); @@ -4310,31 +4299,28 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { struct ath10k *ar = hw->priv; - struct ath10k_txq *artxq = (void *)txq->drv_priv; - struct ieee80211_txq *f_txq; - struct ath10k_txq *f_artxq; - int ret = 0; - int max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE; + int ret; + u8 ac; - spin_lock_bh(&ar->txqs_lock); - if (list_empty(&artxq->list)) - list_add_tail(&artxq->list, &ar->txqs); + ath10k_htt_tx_txq_update(hw, txq); + if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH) + return; - f_artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list); - f_txq = container_of((void *)f_artxq, struct ieee80211_txq, drv_priv); - list_del_init(&f_artxq->list); + ac = txq->ac; + ieee80211_txq_schedule_start(hw, ac); + txq = ieee80211_next_txq(hw, ac); + if (!txq) + goto out; - while (ath10k_mac_tx_can_push(hw, f_txq) && max--) { - ret = ath10k_mac_tx_push_txq(hw, f_txq); + while (ath10k_mac_tx_can_push(hw, txq)) { + ret = ath10k_mac_tx_push_txq(hw, txq); if (ret < 0) break; } - if (ret != -ENOENT) - list_add_tail(&f_artxq->list, &ar->txqs); - spin_unlock_bh(&ar->txqs_lock); - - ath10k_htt_tx_txq_update(hw, f_txq); + ieee80211_return_txq(hw, txq); ath10k_htt_tx_txq_update(hw, txq); +out: + ieee80211_txq_schedule_end(hw, ac); } /* Must not be called with conf_mutex held as workers can use that also. */ @@ -8726,6 +8712,8 @@ int ath10k_mac_register(struct ath10k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; + ret = ieee80211_register_hw(ar->hw); if (ret) { ath10k_err(ar, "failed to register ieee80211: %d\n", ret); From patchwork Tue Jan 22 14:20:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 10775551 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B0DF9139A for ; Tue, 22 Jan 2019 14:21:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A01A92AC6E for ; Tue, 22 Jan 2019 14:21:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9E4822AB14; Tue, 22 Jan 2019 14:21:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D4FEF2AC6E for ; Tue, 22 Jan 2019 14:21:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728722AbfAVOVu (ORCPT ); Tue, 22 Jan 2019 09:21:50 -0500 Received: from mail-ed1-f66.google.com ([209.85.208.66]:33005 "EHLO mail-ed1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728416AbfAVOVs (ORCPT ); Tue, 22 Jan 2019 09:21:48 -0500 Received: by mail-ed1-f66.google.com with SMTP id p6so19494211eds.0 for ; Tue, 22 Jan 2019 06:21:47 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ArfIx3KMdm0G25ep2c9RDAISYwufk1Ha00yFX5Qx9YY=; b=eWmirDnYygtNPdXyOj3b0PkjRzwXUQL3kS6hLlXa9qU5qNECmzwEoib3F25Rf2uKA1 d/W80IczY6ASIjsPrxfm91Lsi2QkD8fFISq3uelpalBrxu72MnmMTp0LpinqdJ37ZeRc qKYECtVpw3jY5L5o/LBuZGxNbExVrj/eGdTNFgJXLS7Oxq7vFRuLyyC4okAFC1IT9DFs GaXZuIj3mvNUDT9tTx0DgplU3s9hDzWeb9vnd4e3Y8OTWdOcJgwl20ez/7qOpg1iLzkU X0WZP0e6Zc+t5jYTijCrYvzYk3phMJdcHwRntWdkUp4+zfn7zlqSt0RHiG+NeXQMQgxw KEbQ== X-Gm-Message-State: AJcUukfstlll8UydE6tpgm+Hrwu+YcwRt6TbVMPBR6xYZcLQOqGjSZVf XGUEaUX/HqItaxBOOjAyIlN3Rw== X-Google-Smtp-Source: ALg8bN5lQqjT75vbrrHo71ow+/HoGISqcdOC4wgNSPnAe5wj7DySxNU90iWIJZIKrN8wEe5n2McwZg== X-Received: by 2002:a50:91a8:: with SMTP id g37mr30690307eda.216.1548166906373; Tue, 22 Jan 2019 06:21:46 -0800 (PST) Received: from tohojo-x1-rh.localdomain ([2a00:7660:6da:1:2262:af2:1f58:2146]) by smtp.gmail.com with ESMTPSA id v12-v6sm5150968ejk.58.2019.01.22.06.21.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 22 Jan 2019 06:21:45 -0800 (PST) Received: by tohojo-x1-rh.localdomain (Postfix, from userid 1000) id 2CF6C1833E0; Tue, 22 Jan 2019 15:21:44 +0100 (CET) From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: linux-wireless@vger.kernel.org Cc: Kan Yan , Rajkumar Manoharan , ath10k@lists.infradead.org, make-wifi-fast@lists.bufferbloat.net, =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= Subject: [PATCH v6 4/4] ath10k: reporting estimated tx airtime for fairness Date: Tue, 22 Jan 2019 15:20:19 +0100 Message-Id: <20190122142019.21417-5-toke@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190122142019.21417-1-toke@redhat.com> References: <20190122142019.21417-1-toke@redhat.com> MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Kan Yan Transmit airtime will be estimated from last tx rate used. Firmware report tx rate by peer stats. Airtime is computed on tx path and the same will be reported to mac80211 upon tx completion. This change is based on Kan's orginal commit in Chromium tree ("CHROMIUM: ath10k: Implementing airtime fairness based TX scheduler") ref: https://chromium-review.googlesource.com/588190 Tested on QCA4019 with firmware version 10.4-3.2.1.1-00015 Tested on QCA9984 with firmware version 10.4-3.9.0.1-00005 Signed-off-by: Kan Yan [rmanohar@codeaurora.org: ported only the airtime computation] Signed-off-by: Rajkumar Manoharan [toke@redhat.com: Rebase to mac80211-next, add test note] Signed-off-by: Toke Høiland-Jørgensen --- Rajkumar / Kan: Please check that I didn't mess anything up while rebasing this onto the current mac80211-next branch! drivers/net/wireless/ath/ath10k/core.h | 2 + drivers/net/wireless/ath/ath10k/htt_rx.c | 1 + drivers/net/wireless/ath/ath10k/mac.c | 57 ++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/txrx.c | 4 ++ 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 28cecf7375f8..4528a6e47b8d 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -126,6 +126,7 @@ struct ath10k_skb_cb { u8 flags; u8 eid; u16 msdu_id; + u16 airtime_est; struct ieee80211_vif *vif; struct ieee80211_txq *txq; } __packed; @@ -498,6 +499,7 @@ struct ath10k_sta { u16 peer_id; struct rate_info txrate; struct ieee80211_tx_info tx_info; + u32 last_tx_bitrate; struct work_struct update_wk; u64 rx_duration; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index dc9895f2eb9d..6a93b57900ae 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -3078,6 +3078,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, arsta->txrate.nss = txrate.nss; arsta->txrate.bw = ath10k_bw_to_mac80211_bw(txrate.bw); + arsta->last_tx_bitrate = cfg80211_calculate_bitrate(&arsta->txrate); if (sgi) arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index cf7fdf72e990..b13dcb4533cb 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3544,7 +3544,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, struct ieee80211_vif *vif, struct ieee80211_txq *txq, - struct sk_buff *skb) + struct sk_buff *skb, u16 airtime) { struct ieee80211_hdr *hdr = (void *)skb->data; struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb); @@ -3561,6 +3561,7 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, cb->vif = vif; cb->txq = txq; + cb->airtime_est = airtime; } bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) @@ -3948,6 +3949,49 @@ static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw, return false; } +/* Return estimated airtime in microsecond, which is calculated using last + * reported TX rate. This is just a rough estimation because host driver has no + * knowledge of the actual transmit rate, retries or aggregation. If actual + * airtime can be reported by firmware, then delta between estimated and actual + * airtime can be adjusted from deficit. + */ +#define IEEE80211_ATF_OVERHEAD 100 /* IFS + some slot time */ +#define IEEE80211_ATF_OVERHEAD_IFS 16 /* IFS only */ +static u16 ath10k_mac_update_airtime(struct ath10k *ar, + struct ieee80211_txq *txq, + struct sk_buff *skb) +{ + struct ath10k_sta *arsta; + u32 pktlen; + u16 airtime = 0; + + if (!txq || !txq->sta) + return airtime; + + spin_lock_bh(&ar->data_lock); + arsta = (struct ath10k_sta *)txq->sta->drv_priv; + + pktlen = skb->len + 38; /* Assume MAC header 30, SNAP 8 for most case */ + if (arsta->last_tx_bitrate) { + /* airtime in us, last_tx_bitrate in 100kbps */ + airtime = (pktlen * 8 * (1000 / 100)) + / arsta->last_tx_bitrate; + /* overhead for media access time and IFS */ + airtime += IEEE80211_ATF_OVERHEAD_IFS; + } else { + /* This is mostly for throttle excessive BC/MC frames, and the + * airtime/rate doesn't need be exact. Airtime of BC/MC frames + * in 2G get some discount, which helps prevent very low rate + * frames from being blocked for too long. + */ + airtime = (pktlen * 8 * (1000 / 100)) / 60; /* 6M */ + airtime += IEEE80211_ATF_OVERHEAD; + } + spin_unlock_bh(&ar->data_lock); + + return airtime; +} + int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { @@ -3963,6 +4007,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, size_t skb_len; bool is_mgmt, is_presp; int ret; + u16 airtime; spin_lock_bh(&ar->htt.tx_lock); ret = ath10k_htt_tx_inc_pending(htt); @@ -3980,7 +4025,8 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, return -ENOENT; } - ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb); + airtime = ath10k_mac_update_airtime(ar, txq, skb); + ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime); skb_len = skb->len; txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); @@ -4247,8 +4293,10 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, bool is_mgmt; bool is_presp; int ret; + u16 airtime; - ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb); + airtime = ath10k_mac_update_airtime(ar, txq, skb); + ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); @@ -8603,6 +8651,9 @@ int ath10k_mac_register(struct ath10k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); + if (ath10k_peer_stats_enabled(ar)) + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); /* * on LL hardware queues are managed entirely by the FW * so we only advertise to mac we can do the queues thing diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 23606b6972d0..8e7c416cd330 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -95,6 +95,10 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); + if (txq && txq->sta) + ieee80211_sta_register_airtime(txq->sta, txq->tid, + skb_cb->airtime_est, 0); + if (ar->dev_type != ATH10K_DEV_TYPE_HL) dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);