From patchwork Fri Mar 25 09:39:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 8669281 Return-Path: X-Original-To: patchwork-ath10k@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B37F7C0553 for ; Fri, 25 Mar 2016 09:38:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9BE8020382 for ; Fri, 25 Mar 2016 09:38:14 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 875622037E for ; Fri, 25 Mar 2016 09:38:13 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ajOBr-00062g-BZ; Fri, 25 Mar 2016 09:37:59 +0000 Received: from mail-lb0-x230.google.com ([2a00:1450:4010:c04::230]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ajOBD-0005gz-Dh for ath10k@lists.infradead.org; Fri, 25 Mar 2016 09:37:23 +0000 Received: by mail-lb0-x230.google.com with SMTP id bc4so45761849lbc.2 for ; Fri, 25 Mar 2016 02:36:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tieto.com; s=google; h=from:to:cc:subject:date:message-id; bh=jWpX5GkBvyR1JOPMFDrDPXHLIoaQCMZrkbmdkUsU/20=; b=mjlHUib+6HaVzPvLAFOC/uums7xh8oBi3u4TENZh0BOaOshjP8WW1UTHX+5Hv3gfYP IkXt+rgAs886rXyxdNQWbaPh6NVjXhl4lv4Dy1XJGCFBqe35naEOXQU494mktNzgeBlt 81VlLtYFGaPk44k5Ilu0B1TGS4FR9FahgPgFc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=jWpX5GkBvyR1JOPMFDrDPXHLIoaQCMZrkbmdkUsU/20=; b=Kd/6nSHxAdBgPhirGLJqTNjlSsd3L8hJK3oF4IVlE7A6rWiYFt5vBUERf5vDMI8afI PCYoVuOTfyvRipYUWiWqxGr/e9Tmn13BVNO0L7V5XLzxK+AvYhAuo4/EfVHHwNfCHOD5 YTAsd8ns+xg9cN4szt/bWQ9l4Rva3ag4olxWcHmzyaphZlHNRytNXWGM7cK1Ya/nwW3E lSOLu+UTGsMx88mcoJhxmvkHOdW0QPcyqp42w8aDrwbYyMhHThISNaRNVB4a2KOP9adK 8O/7ByzTd5tfwvRzTgh6CXChJLRNhA2EW3cGzy0cq2isQn2bU4e4gw1+KKR+38UOHqON OiLA== X-Gm-Message-State: AD7BkJJUtPAAgXzP+PGTt11sVDur03SMtTEGJWyDJBlIWeaR3i7dEqG/CLynZB93AdvrEgdWvx8w62HKYh82ArK28QhRrxGXq9aLXLM41iigILYnzU+YbTzNF7xNaGBTS5fdd2vO8nPmJmoBLDp6LkRc3ZD6Zrf4RBmserm/oNm2CPMPNvN6ZhmA69uMP0fm4A== X-Received: by 10.112.202.136 with SMTP id ki8mr5247056lbc.10.1458898615913; Fri, 25 Mar 2016 02:36:55 -0700 (PDT) Received: from localhost.localdomain ([91.198.246.10]) by smtp.gmail.com with ESMTPSA id ke9sm1842985lbc.28.2016.03.25.02.36.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 25 Mar 2016 02:36:55 -0700 (PDT) From: Michal Kazior To: ath10k@lists.infradead.org Subject: [RFC] ath10k: implement dql for htt tx Date: Fri, 25 Mar 2016 10:39:03 +0100 Message-Id: <1458898743-21118-1-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 2.1.4 X-DomainID: tieto.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160325_023719_982410_A89FFA25 X-CRM114-Status: GOOD ( 17.81 ) X-Spam-Score: -2.7 (--) X-BeenThere: ath10k@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: make-wifi-fast@lists.bufferbloat.net, linux-wireless@vger.kernel.org, dave.taht@gmail.com, codel@lists.bufferbloat.net, Michal Kazior MIME-Version: 1.0 Sender: "ath10k" Errors-To: ath10k-bounces+patchwork-ath10k=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This implements a very naive dynamic queue limits on the flat HTT Tx. In some of my tests (using flent) it seems to reduce induced latency by orders of magnitude (e.g. when enforcing 6mbps tx rates 2500ms -> 150ms). But at the same time it introduces TCP throughput buildup over time (instead of immediate bump to max). More importantly I didn't observe it to make things much worse (yet). Signed-off-by: Michal Kazior --- I'm not sure yet if it's worth to consider this patch for merging per se. My motivation was to have something to prove mac80211 fq works and to see if DQL can learn the proper queue limit in face of wireless rate control at all. I'll do a follow up post with flent test results and some notes. drivers/net/wireless/ath/ath10k/core.h | 2 ++ drivers/net/wireless/ath/ath10k/htt_rx.c | 12 ++++++++---- drivers/net/wireless/ath/ath10k/htt_tx.c | 8 +++++++- drivers/net/wireless/ath/ath10k/mac.c | 26 ++++++++++++++++++++------ drivers/net/wireless/ath/ath10k/txrx.c | 6 +++++- drivers/net/wireless/ath/ath10k/txrx.h | 3 ++- 6 files changed, 44 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index b6c157ef705a..d8eebcd2b0b0 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -630,6 +630,8 @@ struct ath10k { struct device *dev; u8 mac_addr[ETH_ALEN]; + struct dql dql; + enum ath10k_hw_rev hw_rev; u16 dev_id; u32 chip_id; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 2da8ccf3da05..38bc8bf46b67 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1679,7 +1679,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, } static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar, - struct sk_buff *skb) + struct sk_buff *skb, + unsigned int *completed) { struct ath10k_htt *htt = &ar->htt; struct htt_resp *resp = (struct htt_resp *)skb->data; @@ -1712,7 +1713,7 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar, for (i = 0; i < resp->data_tx_completion.num_msdus; i++) { msdu_id = resp->data_tx_completion.msdus[i]; tx_done.msdu_id = __le16_to_cpu(msdu_id); - ath10k_txrx_tx_unref(htt, &tx_done); + ath10k_txrx_tx_unref(htt, &tx_done, completed); } } @@ -2354,7 +2355,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; } - status = ath10k_txrx_tx_unref(htt, &tx_done); + status = ath10k_txrx_tx_unref(htt, &tx_done, NULL); if (!status) { spin_lock_bh(&htt->tx_lock); ath10k_htt_tx_mgmt_dec_pending(htt); @@ -2482,6 +2483,7 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) struct htt_resp *resp; struct sk_buff *skb; unsigned long flags; + unsigned int completed = 0; __skb_queue_head_init(&tx_q); __skb_queue_head_init(&rx_q); @@ -2505,10 +2507,12 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags); while ((skb = __skb_dequeue(&tx_q))) { - ath10k_htt_rx_frm_tx_compl(htt->ar, skb); + ath10k_htt_rx_frm_tx_compl(htt->ar, skb, &completed); dev_kfree_skb_any(skb); } + dql_completed(&htt->ar->dql, completed); + while ((skb = __skb_dequeue(&tx_ind_q))) { ath10k_htt_rx_tx_fetch_ind(ar, skb); dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index b2ae122381ca..2b7f7802f9f1 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -367,7 +367,7 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx) tx_done.discard = 1; tx_done.msdu_id = msdu_id; - ath10k_txrx_tx_unref(htt, &tx_done); + ath10k_txrx_tx_unref(htt, &tx_done, NULL); return 0; } @@ -378,6 +378,7 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); idr_destroy(&htt->pending_tx); + dql_reset(&htt->ar->dql); if (htt->txbuf.vaddr) { size = htt->max_num_pending_tx * @@ -839,6 +840,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, u16 freq = 0; u32 frags_paddr = 0; u32 txbuf_paddr; + size_t skb_len; struct htt_msdu_ext_desc *ext_desc = NULL; spin_lock_bh(&htt->tx_lock); @@ -1000,12 +1002,16 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, sg_items[1].paddr = skb_cb->paddr; sg_items[1].len = prefetch_len; + skb_len = msdu->len; + res = ath10k_hif_tx_sg(htt->ar, htt->ar->htc.endpoint[htt->eid].ul_pipe_id, sg_items, ARRAY_SIZE(sg_items)); if (res) goto err_unmap_msdu; + dql_queued(&ar->dql, skb_len); + return 0; err_unmap_msdu: diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ed00853ea9cc..c848049ffdf3 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3755,23 +3755,35 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar) struct ieee80211_hw *hw = ar->hw; struct ieee80211_txq *txq; struct ath10k_txq *artxq; - struct ath10k_txq *last; int ret; int max; spin_lock_bh(&ar->txqs_lock); rcu_read_lock(); - last = list_last_entry(&ar->txqs, struct ath10k_txq, list); - while (!list_empty(&ar->txqs)) { + for (;;) { + if (list_empty(&ar->txqs)) + break; + + if (dql_avail(&ar->dql) < 0) + break; + artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list); txq = container_of((void *)artxq, struct ieee80211_txq, drv_priv); - /* Prevent aggressive sta/tid taking over tx queue */ max = 16; ret = 0; - while (ath10k_mac_tx_can_push(hw, txq) && max--) { + for (;;) { + if (!max--) + break; + + if (!ath10k_mac_tx_can_push(hw, txq)) + break; + + if (dql_avail(&ar->dql) < 0) + break; + ret = ath10k_mac_tx_push_txq(hw, txq); if (ret < 0) break; @@ -3783,7 +3795,7 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar) ath10k_htt_tx_txq_update(hw, txq); - if (artxq == last || (ret < 0 && ret != -ENOENT)) + if (ret < 0 && ret != -ENOENT) break; } @@ -4331,6 +4343,8 @@ static int ath10k_start(struct ieee80211_hw *hw) mutex_lock(&ar->conf_mutex); + dql_init(&ar->dql, HZ); + switch (ar->state) { case ATH10K_STATE_OFF: ar->state = ATH10K_STATE_ON; diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 48e26cdfe9a5..122c8edf10a1 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -50,7 +50,8 @@ out: } int ath10k_txrx_tx_unref(struct ath10k_htt *htt, - const struct htt_tx_done *tx_done) + const struct htt_tx_done *tx_done, + unsigned int *completed) { struct ath10k *ar = htt->ar; struct device *dev = ar->dev; @@ -87,6 +88,9 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, if (txq) artxq->num_fw_queued--; + if (completed) + *completed += msdu->len; + ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); ath10k_htt_tx_dec_pending(htt); if (htt->num_pending_tx == 0) diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h index e7ea1ae1c438..3a655270bcc5 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.h +++ b/drivers/net/wireless/ath/ath10k/txrx.h @@ -20,7 +20,8 @@ #include "htt.h" int ath10k_txrx_tx_unref(struct ath10k_htt *htt, - const struct htt_tx_done *tx_done); + const struct htt_tx_done *tx_done, + unsigned int *completed); struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, const u8 *addr);