From patchwork Fri Dec 13 15:38:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Crispin X-Patchwork-Id: 11291641 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 40D3614BD for ; Fri, 13 Dec 2019 22:23:38 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 271C02077B for ; Fri, 13 Dec 2019 22:23:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="GDdC5b2a" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 271C02077B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=phrozen.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=ath11k-bounces+patchwork-ath11k=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=ATdTvAWyD2Mu3aDA/itH6gOGuY/kYmCVhmLPTougWkM=; b=GDdC5b2aztq0It oMU2meb2P7201T4x6wJ3JtFtiGeFKNnyj5m4jBAoqFL6FU5TbxmtNS025SBhUFkwCKu6/7Y0qmzuP 7mkZI7OAvR6tPehAAUG/GEbgI+mLjiQegUqfwWnLD4qY6u3Y0bKDc+re/t1HAx+gCxqRI4gjEueKa EoXUni1IR+Q8sm9QYvcX52VbdNrIXapvr/0MYPcLNJVt7s2Tbnl9S34Dxi2y2Ls2RzbQy5X3P7JMK Ioj1eR1RlKVii/Ipb/w0aXqGZg0wo7z7mhcCjOXQF13MRYI4om6z49hLM1zDrJwxu9BM0Qix3PHUM 1dMQsVqm31Ck6NUpD5iw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ifn1s-0004Al-Vh; Fri, 13 Dec 2019 15:38:57 +0000 Received: from nbd.name ([2a01:4f8:221:3d45::2]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ifn1l-00042C-OQ for ath11k@lists.infradead.org; Fri, 13 Dec 2019 15:38:53 +0000 Received: from pd95fd344.dip0.t-ipconnect.de ([217.95.211.68] helo=bertha.fritz.box) by ds12 with esmtpa (Exim 4.89) (envelope-from ) id 1ifn1h-0005pC-6q; Fri, 13 Dec 2019 16:38:45 +0100 From: John Crispin To: Kalle Valo Subject: [PATCH V3 8/9] ath11k: optimise ath11k_dp_tx_completion_handler Date: Fri, 13 Dec 2019 16:38:38 +0100 Message-Id: <20191213153839.12372-9-john@phrozen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191213153839.12372-1-john@phrozen.org> References: <20191213153839.12372-1-john@phrozen.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191213_073849_966223_23EA76C6 X-CRM114-Status: GOOD ( 14.41 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-BeenThere: ath11k@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-wireless@vger.kernel.org, ath11k@lists.infradead.org, John Crispin Sender: "ath11k" Errors-To: ath11k-bounces+patchwork-ath11k=patchwork.kernel.org@lists.infradead.org the current code does 4 memcpys for each completion frame. 1) duplicate the desc 2 + 3) inside kfifo insertion 4) kfifo remove The code simply drops the kfifo and uses a trivial ring buffer. This requires a single memcpy for insertion. There is no removal needed as we can simply use the inserted data for processing. As the code runs inside the NAPI context it is atomic and there is no need for most of the locking. Signed-off-by: John Crispin --- drivers/net/wireless/ath/ath11k/dp.c | 16 ++++----- drivers/net/wireless/ath/ath11k/dp.h | 11 +++---- drivers/net/wireless/ath/ath11k/dp_tx.c | 41 +++++++++--------------- drivers/net/wireless/ath/ath11k/hal_tx.c | 13 -------- drivers/net/wireless/ath/ath11k/hal_tx.h | 2 -- 5 files changed, 27 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c index b966a16a930f..b112825a52ed 100644 --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c @@ -3,7 +3,6 @@ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */ -#include #include "core.h" #include "dp_tx.h" #include "hal_tx.h" @@ -828,10 +827,7 @@ void ath11k_dp_free(struct ath11k_base *ab) ath11k_dp_tx_pending_cleanup, ab); idr_destroy(&dp->tx_ring[i].txbuf_idr); spin_unlock_bh(&dp->tx_ring[i].tx_idr_lock); - - spin_lock_bh(&dp->tx_ring[i].tx_status_lock); - kfifo_free(&dp->tx_ring[i].tx_status_fifo); - spin_unlock_bh(&dp->tx_ring[i].tx_status_lock); + kfree(dp->tx_ring[i].tx_status); } /* Deinit any SOC level resource */ @@ -871,17 +867,17 @@ int ath11k_dp_alloc(struct ath11k_base *ab) if (ret) goto fail_link_desc_cleanup; - size = roundup_pow_of_two(DP_TX_COMP_RING_SIZE); + size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE; for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) { idr_init(&dp->tx_ring[i].txbuf_idr); spin_lock_init(&dp->tx_ring[i].tx_idr_lock); dp->tx_ring[i].tcl_data_ring_id = i; - spin_lock_init(&dp->tx_ring[i].tx_status_lock); - ret = kfifo_alloc(&dp->tx_ring[i].tx_status_fifo, size, - GFP_KERNEL); - if (ret) + dp->tx_ring[i].tx_status_head = 0; + dp->tx_ring[i].tx_status_tail = DP_TX_COMP_RING_SIZE - 1; + dp->tx_ring[i].tx_status = kmalloc(size, GFP_KERNEL); + if (!dp->tx_ring[i].tx_status) goto fail_cmn_srng_cleanup; } diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h index f7e53509ae07..2f0980f2c762 100644 --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h @@ -6,7 +6,6 @@ #ifndef ATH11K_DP_H #define ATH11K_DP_H -#include #include "hal_rx.h" struct ath11k_base; @@ -58,6 +57,8 @@ struct dp_rxdma_ring { int bufs_max; }; +#define ATH11K_TX_COMPL_NEXT(x) (((x) + 1) % DP_TX_COMP_RING_SIZE) + struct dp_tx_ring { u8 tcl_data_ring_id; struct dp_srng tcl_data_ring; @@ -65,11 +66,9 @@ struct dp_tx_ring { struct idr txbuf_idr; /* Protects txbuf_idr and num_pending */ spinlock_t tx_idr_lock; - DECLARE_KFIFO_PTR(tx_status_fifo, struct hal_wbm_release_ring); - /* lock to protect tx_status_fifo because tx_status_fifo can be - * accessed concurrently. - */ - spinlock_t tx_status_lock; + struct hal_wbm_release_ring *tx_status; + int tx_status_head; + int tx_status_tail; }; struct ath11k_pdev_mon_stats { diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 28ebc414533e..5d6403cf99ab 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -79,7 +79,6 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, struct hal_srng *tcl_ring; struct ieee80211_hdr *hdr = (void *)skb->data; struct dp_tx_ring *tx_ring; - u8 cached_desc[HAL_TCL_DESC_LEN]; void *hal_tcl_desc; u8 pool_id; u8 hal_ring_id; @@ -167,8 +166,6 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, skb_cb->vif = arvif->vif; skb_cb->ar = ar; - ath11k_hal_tx_cmd_desc_setup(ab, cached_desc, &ti); - hal_ring_id = tx_ring->tcl_data_ring.ring_id; tcl_ring = &ab->hal.srng_list[hal_ring_id]; @@ -188,7 +185,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, goto fail_unmap_dma; } - ath11k_hal_tx_desc_sync(cached_desc, hal_tcl_desc); + ath11k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc + + sizeof(struct hal_tlv_hdr), &ti); ath11k_hal_srng_access_end(ab, tcl_ring); @@ -432,47 +430,44 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id) int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id; struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id]; struct sk_buff *msdu; - struct hal_wbm_release_ring tx_status; struct hal_tx_status ts; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; u32 *desc; u32 msdu_id; u8 mac_id; - spin_lock_bh(&status_ring->lock); - ath11k_hal_srng_access_begin(ab, status_ring); - spin_lock_bh(&tx_ring->tx_status_lock); - while (!kfifo_is_full(&tx_ring->tx_status_fifo) && + while ((ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head) != tx_ring->tx_status_tail) && (desc = ath11k_hal_srng_dst_get_next_entry(ab, status_ring))) { - ath11k_hal_tx_status_desc_sync((void *)desc, - (void *)&tx_status); - kfifo_put(&tx_ring->tx_status_fifo, tx_status); + memcpy(&tx_ring->tx_status[tx_ring->tx_status_head], + desc, sizeof(struct hal_wbm_release_ring)); + tx_ring->tx_status_head = + ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head); } if ((ath11k_hal_srng_dst_peek(ab, status_ring) != NULL) && - kfifo_is_full(&tx_ring->tx_status_fifo)) { + (ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head) == tx_ring->tx_status_tail)) { /* TODO: Process pending tx_status messages when kfifo_is_full() */ ath11k_warn(ab, "Unable to process some of the tx_status ring desc because status_fifo is full\n"); } - spin_unlock_bh(&tx_ring->tx_status_lock); - ath11k_hal_srng_access_end(ab, status_ring); - spin_unlock_bh(&status_ring->lock); - spin_lock_bh(&tx_ring->tx_status_lock); - while (kfifo_get(&tx_ring->tx_status_fifo, &tx_status)) { - memset(&ts, 0, sizeof(ts)); - ath11k_hal_tx_status_parse(ab, &tx_status, &ts); + while (ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_tail) != tx_ring->tx_status_head) { + struct hal_wbm_release_ring *tx_status; + + tx_ring->tx_status_tail = + ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_tail); + tx_status = &tx_ring->tx_status[tx_ring->tx_status_tail]; + ath11k_hal_tx_status_parse(ab, tx_status, &ts); mac_id = FIELD_GET(DP_TX_DESC_ID_MAC_ID, ts.desc_id); msdu_id = FIELD_GET(DP_TX_DESC_ID_MSDU_ID, ts.desc_id); if (ts.buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) { ath11k_dp_tx_process_htt_tx_complete(ab, - (void *)&tx_status, + (void *)tx_status, mac_id, msdu_id, tx_ring); continue; @@ -494,12 +489,8 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id) if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); - /* TODO: Locking optimization so that tx_completion for an msdu - * is not called with tx_status_lock acquired - */ ath11k_dp_tx_complete_msdu(ar, msdu, &ts); } - spin_unlock_bh(&tx_ring->tx_status_lock); } int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid, diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.c b/drivers/net/wireless/ath/ath11k/hal_tx.c index c2a3a9d2e534..e8710bbbbc3a 100644 --- a/drivers/net/wireless/ath/ath11k/hal_tx.c +++ b/drivers/net/wireless/ath/ath11k/hal_tx.c @@ -74,19 +74,6 @@ void ath11k_hal_tx_cmd_desc_setup(struct ath11k_base *ab, void *cmd, tcl_cmd->info4 = 0; } -/* Commit the descriptor to hardware */ -void ath11k_hal_tx_desc_sync(void *tx_desc_cached, void *hw_desc) -{ - memcpy(hw_desc + sizeof(struct hal_tlv_hdr), tx_desc_cached, - sizeof(struct hal_tcl_data_cmd)); -} - -/* Get the descriptor status from hardware */ -void ath11k_hal_tx_status_desc_sync(void *hw_desc, void *local_desc) -{ - memcpy(local_desc, hw_desc, HAL_TX_STATUS_DESC_LEN); -} - void ath11k_hal_tx_status_parse(struct ath11k_base *ab, struct hal_wbm_release_ring *desc, struct hal_tx_status *ts) diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.h b/drivers/net/wireless/ath/ath11k/hal_tx.h index cf99e2b31f9f..5fe89b729a6e 100644 --- a/drivers/net/wireless/ath/ath11k/hal_tx.h +++ b/drivers/net/wireless/ath/ath11k/hal_tx.h @@ -61,11 +61,9 @@ struct hal_tx_status { void ath11k_hal_tx_cmd_desc_setup(struct ath11k_base *ab, void *cmd, struct hal_tx_info *ti); -void ath11k_hal_tx_desc_sync(void *tx_desc_cached, void *hw_desc); void ath11k_hal_tx_status_parse(struct ath11k_base *ab, struct hal_wbm_release_ring *desc, struct hal_tx_status *ts); -void ath11k_hal_tx_status_desc_sync(void *hw_desc, void *local_desc); void ath11k_hal_tx_set_dscp_tid_map(struct ath11k_base *ab, int id); int ath11k_hal_reo_cmd_send(struct ath11k_base *ab, struct hal_srng *srng, enum hal_reo_cmd_type type,