From patchwork Fri Oct 20 10:30:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430484 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B7358C004C0 for ; Fri, 20 Oct 2023 10:31:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376866AbjJTKb2 (ORCPT ); Fri, 20 Oct 2023 06:31:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49000 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376857AbjJTKb1 (ORCPT ); Fri, 20 Oct 2023 06:31:27 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1B600D5A for ; Fri, 20 Oct 2023 03:31:25 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4D5B4C433C9; Fri, 20 Oct 2023 10:31:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797884; bh=oXyUA0uN5v3peBVNB2eKJz/PM1Cdu9sHgmbRhC84ez8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YG2JKbVr98w6Pm28h1MiXdltGalSzK9Y2YNleWMdDBAdj0gdaw7HC8JJmIqWGW7DS Ch4FirVN/Dea37UYp/naiXYSke+YEoHhnfVwbZnajTXQjZNF1cdEp5SCat+i5HJ2ai ER7iiihEL97XNVu5j9XAgySMD8dzeoJ3BIobRkGBYDGJRkDJV3QzZ4dOwZo3D4rtAg b82hbJWlniOxOWfX11P6g70VAU40gdDr3Vp0W0EiHJFTSkLlVAkWUvyyhSWceLrRmz pCceRjwjN96KJHKQI1kY6/B2ykCbg9aKiJZTdwiBJOBrSYbnf8awcvzPEgyOpGY3gt y04lkdtEQSVjQ== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 01/13] wifi: mt76: mmio: move mt76_mmio_wed_{init,release}_rx_buf in common code Date: Fri, 20 Oct 2023 12:30:48 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Move mt76_mmio_wed_init_rx_buf and mt76_mmio_wed_release_rx_buf routines in common code. This is a preliminary patch to introduce WED support for mt7996 Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/mmio.c | 75 ++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 5 ++ .../net/wireless/mediatek/mt76/mt7915/mmio.c | 78 +------------------ 3 files changed, 82 insertions(+), 76 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index 86e3d2ac4d0d..350650a0fce2 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -4,6 +4,7 @@ */ #include "mt76.h" +#include "dma.h" #include "trace.h" static u32 mt76_mmio_rr(struct mt76_dev *dev, u32 offset) @@ -84,6 +85,80 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, } EXPORT_SYMBOL_GPL(mt76_set_irq_mask); +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + int i; + + for (i = 0; i < dev->rx_token_size; i++) { + struct mt76_txwi_cache *t; + + t = mt76_rx_token_release(dev, i); + if (!t || !t->ptr) + continue; + + mt76_put_page_pool_buf(t->ptr, false); + t->ptr = NULL; + + mt76_put_rxwi(dev, t); + } + + mt76_free_pending_rxwi(dev); +} +EXPORT_SYMBOL_GPL(mt76_mmio_wed_release_rx_buf); + +u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc; + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + int i, len = SKB_WITH_OVERHEAD(q->buf_size); + struct mt76_txwi_cache *t = NULL; + + for (i = 0; i < size; i++) { + enum dma_data_direction dir; + dma_addr_t addr; + u32 offset; + int token; + void *buf; + + t = mt76_get_rxwi(dev); + if (!t) + goto unmap; + + buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); + if (!buf) + goto unmap; + + addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset; + dir = page_pool_get_dma_dir(q->page_pool); + dma_sync_single_for_device(dev->dma_dev, addr, len, dir); + + desc->buf0 = cpu_to_le32(addr); + token = mt76_rx_token_consume(dev, buf, t, addr); + if (token < 0) { + mt76_put_page_pool_buf(buf, false); + goto unmap; + } + + desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN, + token)); + desc++; + } + + return 0; + +unmap: + if (t) + mt76_put_rxwi(dev, t); + mt76_mmio_wed_release_rx_buf(wed); + + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(mt76_mmio_wed_init_rx_buf); +#endif /*CONFIG_NET_MEDIATEK_SOC_WED */ + void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) { static const struct mt76_bus_ops mt76_mmio_ops = { diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index ea828ba0b83a..11212b6153ab 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1057,6 +1057,11 @@ static inline u16 mt76_rev(struct mt76_dev *dev) return dev->rev & 0xffff; } +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size); +void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed); +#endif /*CONFIG_NET_MEDIATEK_SOC_WED */ + #define mt76xx_chip(dev) mt76_chip(&((dev)->mt76)) #define mt76xx_rev(dev) mt76_rev(&((dev)->mt76)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index e7d8e03f826f..1621a8150798 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -567,80 +567,6 @@ static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed) spin_unlock_bh(&dev->mt76.token_lock); } -static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) -{ - struct mt7915_dev *dev; - int i; - - dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); - for (i = 0; i < dev->mt76.rx_token_size; i++) { - struct mt76_txwi_cache *t; - - t = mt76_rx_token_release(&dev->mt76, i); - if (!t || !t->ptr) - continue; - - mt76_put_page_pool_buf(t->ptr, false); - t->ptr = NULL; - - mt76_put_rxwi(&dev->mt76, t); - } - - mt76_free_pending_rxwi(&dev->mt76); -} - -static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) -{ - struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc; - struct mt76_txwi_cache *t = NULL; - struct mt7915_dev *dev; - struct mt76_queue *q; - int i, len; - - dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); - q = &dev->mt76.q_rx[MT_RXQ_MAIN]; - len = SKB_WITH_OVERHEAD(q->buf_size); - - for (i = 0; i < size; i++) { - enum dma_data_direction dir; - dma_addr_t addr; - u32 offset; - int token; - void *buf; - - t = mt76_get_rxwi(&dev->mt76); - if (!t) - goto unmap; - - buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); - if (!buf) - goto unmap; - - addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset; - dir = page_pool_get_dma_dir(q->page_pool); - dma_sync_single_for_device(dev->mt76.dma_dev, addr, len, dir); - - desc->buf0 = cpu_to_le32(addr); - token = mt76_rx_token_consume(&dev->mt76, buf, t, addr); - if (token < 0) { - mt76_put_page_pool_buf(buf, false); - goto unmap; - } - - desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN, - token)); - desc++; - } - - return 0; - -unmap: - if (t) - mt76_put_rxwi(&dev->mt76, t); - mt7915_mmio_wed_release_rx_buf(wed); - return -ENOMEM; -} - static void mt7915_mmio_wed_update_rx_stats(struct mtk_wed_device *wed, struct mtk_wed_wo_rx_stats *stats) { @@ -780,8 +706,8 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, wed->wlan.init_buf = mt7915_wed_init_buf; wed->wlan.offload_enable = mt7915_mmio_wed_offload_enable; wed->wlan.offload_disable = mt7915_mmio_wed_offload_disable; - wed->wlan.init_rx_buf = mt7915_mmio_wed_init_rx_buf; - wed->wlan.release_rx_buf = mt7915_mmio_wed_release_rx_buf; + wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf; + wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf; wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats; wed->wlan.reset = mt7915_mmio_wed_reset; wed->wlan.reset_complete = mt7915_mmio_wed_reset_complete; From patchwork Fri Oct 20 10:30:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430485 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16100CDB474 for ; Fri, 20 Oct 2023 10:31:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376845AbjJTKbb (ORCPT ); Fri, 20 Oct 2023 06:31:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58452 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376802AbjJTKba (ORCPT ); Fri, 20 Oct 2023 06:31:30 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DDD63D46 for ; Fri, 20 Oct 2023 03:31:28 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32CD3C433C7; Fri, 20 Oct 2023 10:31:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797888; bh=3vLyqqYT010XU7aySBEjTffX1ERMPpYj/d//AMHvRpY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vFYTeVIg5LTrp56iIypXkDq5Y1qb9d1v+J20ycEgGVT0joZbi53R/K7Rb4nfARJxe d6MjDDcpZk7wwC76/W5qCGXcZgctRV9h9OsKFvH1vP/rL2L+VD7eWXfjYX1i5QaFfi U42OFgB8vY1Z70FnoDm0Hh3iEYpcafACca5TIlYVwrmrkAQuo8vG+vppopZgOiH90V f7tGn8BMv11oSjrT4GzxySogMK0mg726k4N+s+okHGz6BA+SrAz0MDi124fideg2R/ 0n/GSbl+1xXFYgMA1eDiLhGs8TbOeNWPEGaIcw9TZD6eOL3zSw/z9cejUZTysFjVXR tnbvk8yRdUi7w== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 02/13] wifi: mt76: move mt76_mmio_wed_offload_{enable,disable} in common code Date: Fri, 20 Oct 2023 12:30:49 +0200 Message-ID: <6924f13aba360ff415acd68cb5a39b3048d06d6f.1697797423.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org mt76_mmio_wed_offload_enable and mt76_mmio_wed_offload_disable routines will be reused by mt7996 driver for wed support. Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/mmio.c | 22 ++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++ .../net/wireless/mediatek/mt76/mt7915/mmio.c | 29 ++----------------- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index 350650a0fce2..c34624978a14 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -157,6 +157,28 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) return -ENOMEM; } EXPORT_SYMBOL_GPL(mt76_mmio_wed_init_rx_buf); + +int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + + spin_lock_bh(&dev->token_lock); + dev->token_size = wed->wlan.token_start; + spin_unlock_bh(&dev->token_lock); + + return !wait_event_timeout(dev->tx_wait, !dev->wed_token_count, HZ); +} +EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_enable); + +void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + + spin_lock_bh(&dev->token_lock); + dev->token_size = dev->drv->token_size; + spin_unlock_bh(&dev->token_lock); +} +EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_disable); #endif /*CONFIG_NET_MEDIATEK_SOC_WED */ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 11212b6153ab..2e9f208ae8f8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1060,6 +1060,8 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #ifdef CONFIG_NET_MEDIATEK_SOC_WED u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size); void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed); +int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed); +void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed); #endif /*CONFIG_NET_MEDIATEK_SOC_WED */ #define mt76xx_chip(dev) mt76_chip(&((dev)->mt76)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 1621a8150798..85cb3fed9505 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -542,31 +542,6 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) } #ifdef CONFIG_NET_MEDIATEK_SOC_WED -static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed) -{ - struct mt7915_dev *dev; - - dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); - - spin_lock_bh(&dev->mt76.token_lock); - dev->mt76.token_size = wed->wlan.token_start; - spin_unlock_bh(&dev->mt76.token_lock); - - return !wait_event_timeout(dev->mt76.tx_wait, - !dev->mt76.wed_token_count, HZ); -} - -static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed) -{ - struct mt7915_dev *dev; - - dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); - - spin_lock_bh(&dev->mt76.token_lock); - dev->mt76.token_size = MT7915_TOKEN_SIZE; - spin_unlock_bh(&dev->mt76.token_lock); -} - static void mt7915_mmio_wed_update_rx_stats(struct mtk_wed_device *wed, struct mtk_wed_wo_rx_stats *stats) { @@ -704,8 +679,8 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, } wed->wlan.init_buf = mt7915_wed_init_buf; - wed->wlan.offload_enable = mt7915_mmio_wed_offload_enable; - wed->wlan.offload_disable = mt7915_mmio_wed_offload_disable; + wed->wlan.offload_enable = mt76_mmio_wed_offload_enable; + wed->wlan.offload_disable = mt76_mmio_wed_offload_disable; wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf; wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf; wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats; From patchwork Fri Oct 20 10:30:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430486 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0CC22C001DF for ; Fri, 20 Oct 2023 10:31:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376824AbjJTKbg (ORCPT ); Fri, 20 Oct 2023 06:31:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41894 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376802AbjJTKbe (ORCPT ); Fri, 20 Oct 2023 06:31:34 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0332E1BF for ; Fri, 20 Oct 2023 03:31:33 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 400A0C433C8; Fri, 20 Oct 2023 10:31:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797892; bh=N114NVR2yH2worVoQ2OyetWtwUD+J/sPtCWEuQnFtbM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BNebuQge7I8SDIsHFKAimevChhqM+b3WXaJL4n0Gw6ujdwdLy75mBekWRxl8y5Vzb ZKV9roiGrTwFgEAixt/IHjRHeY6YNPGEs5YbFdIz4jCcrwknatfkH648+KdzyGzptc mOyGG65i+DL35wcDNIoPty/Xhhr9OCcUn66oYZ/B3kbnzT1BPy6w18XVWk8vQrDf8P TbssYCXipQDlQCc9BYN6NC69HB1J3cKtnVQyTfdQow9N7qTSlVBzjHvVGpLi7ZarxW FbaoPNifXWBZQ539d5EwBikOPrtauC3RUstgpAoJbUb5Quejs+uFy8QdCct7GElNO/ 4SLGif3RlUiOQ== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 03/13] wifi: mt76: move mt76_net_setup_tc in common code Date: Fri, 20 Oct 2023 12:30:50 +0200 Message-ID: <8510d01c6ab2c067777a593700a17a6af414c404.1697797423.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org This is a preliminary patch to introduce WED support for mt7996 Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/mac80211.c | 16 ++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt7915/main.c | 16 +--------------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index cb76053973aa..15c4ca664b3a 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -1842,3 +1842,19 @@ enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy) return MT_DFS_STATE_ACTIVE; } EXPORT_SYMBOL_GPL(mt76_phy_dfs_state); + +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct net_device *netdev, enum tc_setup_type type, + void *type_data) +{ + struct mt76_phy *phy = hw->priv; + struct mtk_wed_device *wed = &phy->dev->mmio.wed; + + if (!mtk_wed_device_active(wed)) + return -EOPNOTSUPP; + + return mtk_wed_device_setup_tc(wed, netdev, type, type_data); +} +EXPORT_SYMBOL_GPL(mt76_net_setup_tc); +#endif /* CONFIG_NET_MEDIATEK_SOC_WED */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 2e9f208ae8f8..141f2e80c165 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1047,6 +1047,12 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs); void mt76_pci_disable_aspm(struct pci_dev *pdev); +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct net_device *netdev, enum tc_setup_type type, + void *type_data); +#endif /*CONFIG_NET_MEDIATEK_SOC_WED */ + static inline u16 mt76_chip(struct mt76_dev *dev) { return dev->rev >> 16; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index a3fd54cc1911..ba34c8e19aab 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -1653,20 +1653,6 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, return 0; } - -static int -mt7915_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct net_device *netdev, enum tc_setup_type type, - void *type_data) -{ - struct mt7915_dev *dev = mt7915_hw_dev(hw); - struct mtk_wed_device *wed = &dev->mt76.mmio.wed; - - if (!mtk_wed_device_active(wed)) - return -EOPNOTSUPP; - - return mtk_wed_device_setup_tc(wed, netdev, type, type_data); -} #endif const struct ieee80211_ops mt7915_ops = { @@ -1721,6 +1707,6 @@ const struct ieee80211_ops mt7915_ops = { .set_radar_background = mt7915_set_radar_background, #ifdef CONFIG_NET_MEDIATEK_SOC_WED .net_fill_forward_path = mt7915_net_fill_forward_path, - .net_setup_tc = mt7915_net_setup_tc, + .net_setup_tc = mt76_net_setup_tc, #endif }; From patchwork Fri Oct 20 10:30:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430487 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BAE5AC004C0 for ; Fri, 20 Oct 2023 10:31:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376854AbjJTKbj (ORCPT ); Fri, 20 Oct 2023 06:31:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33926 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376746AbjJTKbi (ORCPT ); Fri, 20 Oct 2023 06:31:38 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A9E49D52 for ; Fri, 20 Oct 2023 03:31:36 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id ECDA6C433C8; Fri, 20 Oct 2023 10:31:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797896; bh=5DSCe8D4qsVY/zWY9E6Zp8QX+LyLbr3uDvpEyNMTcvI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Q9PKR+31UyvyKQ3BzqQm7LNmuG3mfe3cpDBkDg8PPUmKnsmgJCtiOdUbXyXIB943s tFn3snP8HclINaH4mAx0v6TQZkIdbopEL+fahNq2rXQ8LcuufbRljfpcDqoH/XtUK0 TLJnwqS88gZx9Tgc89xitfDpZnKYV7qUcxu1Og1gM1d9L4qt5UzUD8OVLjpzHW+O4J 32x9XFqf90ybN3O2qkRHN2X1eI+abGEe0euwEHu6xAGtwIlvaPUIiz+4FtVer5Ciw6 jVmx5ICnOqemcqs/DLHoWUjuipf6Y878Xs/dVihYgQwozvE7k4p9UmLloiPSQ0edRi Q3avO2C8ib1EQ== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 04/13] wifi: mt76: introduce mt76_queue_is_wed_tx_free utility routine Date: Fri, 20 Oct 2023 12:30:51 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org This is a preliminary patch to introduce WED support for mt7996 Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/dma.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt76.h | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt7915/dma.c | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 5f31d4d6a640..f1cb78450d99 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -724,7 +724,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, if (ret) return ret; - if (q->flags != MT_WED_Q_TXFREE) + if (!mt76_queue_is_wed_tx_free(q)) mt76_dma_queue_reset(dev, q); return 0; @@ -775,7 +775,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) /* reset WED rx queues */ mt76_dma_wed_setup(dev, q, true); - if (q->flags != MT_WED_Q_TXFREE) { + if (!mt76_queue_is_wed_tx_free(q)) { mt76_dma_sync_idx(dev, q); mt76_dma_rx_fill(dev, q, false); } @@ -818,7 +818,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) bool more; if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) && - q->flags == MT_WED_Q_TXFREE) { + mt76_queue_is_wed_tx_free(q)) { dma_idx = Q_READ(dev, q, dma_idx); check_ddone = true; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 141f2e80c165..16982fd53716 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1560,6 +1560,12 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, struct mt76_power_limits *dest, s8 target_power); +static inline bool mt76_queue_is_wed_tx_free(struct mt76_queue *q) +{ + return (q->flags & MT_QFLAG_WED) && + FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE; +} + static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q) { return (q->flags & MT_QFLAG_WED) && diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index 59a44d79aaed..96b2c3802ac1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -643,7 +643,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force) mt76_queue_reset(dev, dev->mt76.q_mcu[i]); mt76_for_each_q_rx(&dev->mt76, i) { - if (dev->mt76.q_rx[i].flags == MT_WED_Q_TXFREE) + if (mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i])) continue; mt76_queue_reset(dev, &dev->mt76.q_rx[i]); From patchwork Fri Oct 20 10:30:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430488 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2CA3FCDB474 for ; Fri, 20 Oct 2023 10:31:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376858AbjJTKbp (ORCPT ); Fri, 20 Oct 2023 06:31:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34004 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376874AbjJTKbo (ORCPT ); Fri, 20 Oct 2023 06:31:44 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4F916D46 for ; Fri, 20 Oct 2023 03:31:40 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7C722C433C7; Fri, 20 Oct 2023 10:31:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797899; bh=O/D2oNT24XkeEV/8SV9pVpLyeci0UtUBeFPuPWRlylI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=u/j1ybAj8HU3ou9YnE0LMy+UM0ik63SxlpU+5VcSRhDHlZIzPkncLk933FyfIhtX1 X73PWwicDq138bD4VUMYQU75yNH3T64t9LO5CeytHRuqnWzUQK186rrbP+eMObzOYz kh8mfjar/ePEtkJ5trQ9XGAzNHqzHftajijhJNzupI0HKn2YGTft9M+zO4Ji3XAFO6 SvRDrn6OqolxSST1MvYsehmyDjpagE9HvlCpyORXs4rkUGLLT+lBGEh87slhXQ1PsU BCWJPqyjH2cc1b32Z7pouYQIe3MPA+L8RueqdQaSc6ZSNyfr09LRS7Pu8PUnqHnjHt +nsLVMPhIikMA== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 05/13] wifi: mt76: introduce wed pointer in mt76_queue Date: Fri, 20 Oct 2023 12:30:52 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Introduce mtk_wed_device pointer in mt76_queue structure in order to configure WED chip. Get rid of dev parameter in Q_READ and Q_WRITE macros. Introduce wed parameter to the following routine signatures: - mt76_init_queue - mt76_init_tx_queue This is a preliminary patch to introduce WED support for mt7996 since mt7996 runs two separate WED chips. Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/dma.c | 49 ++++++++++--------- drivers/net/wireless/mediatek/mt76/mac80211.c | 3 +- drivers/net/wireless/mediatek/mt76/mt76.h | 10 ++-- .../net/wireless/mediatek/mt76/mt7603/dma.c | 9 ++-- .../net/wireless/mediatek/mt76/mt7615/dma.c | 6 +-- .../net/wireless/mediatek/mt76/mt76_connac.h | 3 +- .../wireless/mediatek/mt76/mt76_connac_mac.c | 5 +- .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 5 +- .../net/wireless/mediatek/mt76/mt7915/dma.c | 16 ++++-- .../net/wireless/mediatek/mt76/mt7921/pci.c | 2 +- .../net/wireless/mediatek/mt76/mt7925/pci.c | 2 +- .../net/wireless/mediatek/mt76/mt7996/dma.c | 2 +- .../net/wireless/mediatek/mt76/mt7996/init.c | 3 +- 13 files changed, 65 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index f1cb78450d99..d779ec57b95e 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -9,11 +9,11 @@ #if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) -#define Q_READ(_dev, _q, _field) ({ \ +#define Q_READ(_q, _field) ({ \ u32 _offset = offsetof(struct mt76_queue_regs, _field); \ u32 _val; \ if ((_q)->flags & MT_QFLAG_WED) \ - _val = mtk_wed_device_reg_read(&(_dev)->mmio.wed, \ + _val = mtk_wed_device_reg_read((_q)->wed, \ ((_q)->wed_regs + \ _offset)); \ else \ @@ -21,10 +21,10 @@ _val; \ }) -#define Q_WRITE(_dev, _q, _field, _val) do { \ +#define Q_WRITE(_q, _field, _val) do { \ u32 _offset = offsetof(struct mt76_queue_regs, _field); \ if ((_q)->flags & MT_QFLAG_WED) \ - mtk_wed_device_reg_write(&(_dev)->mmio.wed, \ + mtk_wed_device_reg_write((_q)->wed, \ ((_q)->wed_regs + _offset), \ _val); \ else \ @@ -33,8 +33,8 @@ #else -#define Q_READ(_dev, _q, _field) readl(&(_q)->regs->_field) -#define Q_WRITE(_dev, _q, _field, _val) writel(_val, &(_q)->regs->_field) +#define Q_READ(_q, _field) readl(&(_q)->regs->_field) +#define Q_WRITE(_q, _field, _val) writel(_val, &(_q)->regs->_field) #endif @@ -188,9 +188,9 @@ EXPORT_SYMBOL_GPL(mt76_free_pending_rxwi); static void mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) { - Q_WRITE(dev, q, desc_base, q->desc_dma); - Q_WRITE(dev, q, ring_size, q->ndesc); - q->head = Q_READ(dev, q, dma_idx); + Q_WRITE(q, desc_base, q->desc_dma); + Q_WRITE(q, ring_size, q->ndesc); + q->head = Q_READ(q, dma_idx); q->tail = q->head; } @@ -206,8 +206,8 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) for (i = 0; i < q->ndesc; i++) q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); - Q_WRITE(dev, q, cpu_idx, 0); - Q_WRITE(dev, q, dma_idx, 0); + Q_WRITE(q, cpu_idx, 0); + Q_WRITE(q, dma_idx, 0); mt76_dma_sync_idx(dev, q); } @@ -343,7 +343,7 @@ static void mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) { wmb(); - Q_WRITE(dev, q, cpu_idx, q->head); + Q_WRITE(q, cpu_idx, q->head); } static void @@ -359,7 +359,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush) if (flush) last = -1; else - last = Q_READ(dev, q, dma_idx); + last = Q_READ(q, dma_idx); while (q->queued > 0 && q->tail != last) { mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry); @@ -371,7 +371,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush) } if (!flush && q->tail == last) - last = Q_READ(dev, q, dma_idx); + last = Q_READ(q, dma_idx); } spin_unlock_bh(&q->cleanup_lock); @@ -641,7 +641,6 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) { #ifdef CONFIG_NET_MEDIATEK_SOC_WED - struct mtk_wed_device *wed = &dev->mmio.wed; int ret, type, ring; u8 flags; @@ -649,7 +648,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) return -EINVAL; flags = q->flags; - if (!mtk_wed_device_active(wed)) + if (!q->wed || !mtk_wed_device_active(q->wed)) q->flags &= ~MT_QFLAG_WED; if (!(q->flags & MT_QFLAG_WED)) @@ -660,9 +659,10 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) switch (type) { case MT76_WED_Q_TX: - ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs, reset); + ret = mtk_wed_device_tx_ring_setup(q->wed, ring, q->regs, + reset); if (!ret) - q->wed_regs = wed->tx_ring[ring].reg_base; + q->wed_regs = q->wed->tx_ring[ring].reg_base; break; case MT76_WED_Q_TXFREE: /* WED txfree queue needs ring to be initialized before setup */ @@ -671,14 +671,15 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) mt76_dma_rx_fill(dev, q, false); q->flags = flags; - ret = mtk_wed_device_txfree_ring_setup(wed, q->regs); + ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs); if (!ret) - q->wed_regs = wed->txfree_ring.reg_base; + q->wed_regs = q->wed->txfree_ring.reg_base; break; case MT76_WED_Q_RX: - ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, reset); + ret = mtk_wed_device_rx_ring_setup(q->wed, ring, q->regs, + reset); if (!ret) - q->wed_regs = wed->rx_ring[ring].reg_base; + q->wed_regs = q->wed->rx_ring[ring].reg_base; break; default: ret = -EINVAL; @@ -819,7 +820,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) && mt76_queue_is_wed_tx_free(q)) { - dma_idx = Q_READ(dev, q, dma_idx); + dma_idx = Q_READ(q, dma_idx); check_ddone = true; } @@ -829,7 +830,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) if (check_ddone) { if (q->tail == dma_idx) - dma_idx = Q_READ(dev, q, dma_idx); + dma_idx = Q_READ(q, dma_idx); if (q->tail == dma_idx) break; diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 15c4ca664b3a..6ee7be6eaab8 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -1725,7 +1725,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna); struct mt76_queue * mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, - int ring_base, u32 flags) + int ring_base, void *wed, u32 flags) { struct mt76_queue *hwq; int err; @@ -1735,6 +1735,7 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, return ERR_PTR(-ENOMEM); hwq->flags = flags; + hwq->wed = wed; err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base); if (err < 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 16982fd53716..8fa0440f1686 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -199,6 +199,7 @@ struct mt76_queue { u8 hw_idx; u8 flags; + struct mtk_wed_device *wed; u32 wed_regs; dma_addr_t desc_dma; @@ -1119,15 +1120,16 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len); struct mt76_queue * mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, - int ring_base, u32 flags); + int ring_base, void *wed, u32 flags); u16 mt76_calculate_default_rate(struct mt76_phy *phy, struct ieee80211_vif *vif, int rateidx); static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx, - int n_desc, int ring_base, u32 flags) + int n_desc, int ring_base, void *wed, + u32 flags) { struct mt76_queue *q; - q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base, flags); + q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base, wed, flags); if (IS_ERR(q)) return PTR_ERR(q); @@ -1141,7 +1143,7 @@ static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx, { struct mt76_queue *q; - q = mt76_init_queue(dev, qid, idx, n_desc, ring_base, 0); + q = mt76_init_queue(dev, qid, idx, n_desc, ring_base, NULL, 0); if (IS_ERR(q)) return PTR_ERR(q); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 03ba11a61c90..7a2f5d38562b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -173,13 +173,14 @@ int mt7603_dma_init(struct mt7603_dev *dev) for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], - MT7603_TX_RING_SIZE, MT_TX_RING_BASE, 0); + MT7603_TX_RING_SIZE, MT_TX_RING_BASE, + NULL, 0); if (ret) return ret; } ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, - MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, 0); + MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, NULL, 0); if (ret) return ret; @@ -189,12 +190,12 @@ int mt7603_dma_init(struct mt7603_dev *dev) return ret; ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN, - MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0); + MT_MCU_RING_SIZE, MT_TX_RING_BASE, NULL, 0); if (ret) return ret; ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC, - MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0); + MT_MCU_RING_SIZE, MT_TX_RING_BASE, NULL, 0); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 0ce01ccc5dce..e7135b2f1742 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -26,14 +26,14 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev) for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], MT7615_TX_RING_SIZE / 2, - MT_TX_RING_BASE, 0); + MT_TX_RING_BASE, NULL, 0); if (ret) return ret; } ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE, - MT_TX_RING_BASE, 0); + MT_TX_RING_BASE, NULL, 0); if (ret) return ret; @@ -55,7 +55,7 @@ mt7615_init_tx_queues(struct mt7615_dev *dev) return mt7622_init_tx_queues_multi(dev); ret = mt76_connac_init_tx_queues(&dev->mphy, 0, MT7615_TX_RING_SIZE, - MT_TX_RING_BASE, 0); + MT_TX_RING_BASE, NULL, 0); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index 1f29d8cd900c..e5ebde19af8f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -391,7 +391,8 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm) void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss); int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc, - int ring_base, u32 flags); + int ring_base, void *wed, u32 flags); + void mt76_connac_write_hw_txp(struct mt76_dev *dev, struct mt76_tx_info *tx_info, void *txp_ptr, u32 id); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index 93402d2c2538..c7914643e9c0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -256,11 +256,12 @@ void mt76_connac_txp_skb_unmap(struct mt76_dev *dev, EXPORT_SYMBOL_GPL(mt76_connac_txp_skb_unmap); int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc, - int ring_base, u32 flags) + int ring_base, void *wed, u32 flags) { int i, err; - err = mt76_init_tx_queue(phy, 0, idx, n_desc, ring_base, flags); + err = mt76_init_tx_queue(phy, 0, idx, n_desc, ring_base, + wed, flags); if (err < 0) return err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 9b5e3fb7b0df..e5ad635d3c56 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -199,13 +199,14 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) for (i = 0; i < IEEE80211_NUM_ACS; i++) { ret = mt76_init_tx_queue(&dev->mphy, i, mt76_ac_to_hwq(i), MT76x02_TX_RING_SIZE, - MT_TX_RING_BASE, 0); + MT_TX_RING_BASE, NULL, 0); if (ret) return ret; } ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, - MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE, 0); + MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE, + NULL, 0); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index 96b2c3802ac1..1bceeb5227b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -9,18 +9,20 @@ static int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base) { struct mt7915_dev *dev = phy->dev; + struct mtk_wed_device *wed = NULL; - if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) { + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { if (is_mt798x(&dev->mt76)) ring_base += MT_TXQ_ID(0) * MT_RING_SIZE; else ring_base = MT_WED_TX_RING_BASE; idx -= MT_TXQ_ID(0); + wed = &dev->mt76.mmio.wed; } return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc, ring_base, - MT_WED_Q_TX(idx)); + wed, MT_WED_Q_TX(idx)); } static int mt7915_poll_tx(struct napi_struct *napi, int budget) @@ -492,7 +494,8 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) if (mtk_wed_device_active(&mdev->mmio.wed) && is_mt7915(mdev)) { wa_rx_base = MT_WED_RX_RING_BASE; wa_rx_idx = MT7915_RXQ_MCU_WA; - dev->mt76.q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE; + mdev->q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE; + mdev->q_rx[MT_RXQ_MCU_WA].wed = &mdev->mmio.wed; } else { wa_rx_base = MT_RXQ_RING_BASE(MT_RXQ_MCU_WA); wa_rx_idx = MT_RXQ_ID(MT_RXQ_MCU_WA); @@ -507,9 +510,10 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) if (!dev->phy.mt76->band_idx) { if (mtk_wed_device_active(&mdev->mmio.wed) && mtk_wed_get_rx_capa(&mdev->mmio.wed)) { - dev->mt76.q_rx[MT_RXQ_MAIN].flags = + mdev->q_rx[MT_RXQ_MAIN].flags = MT_WED_Q_RX(MT7915_RXQ_BAND0); dev->mt76.rx_token_size += MT7915_RX_RING_SIZE; + mdev->q_rx[MT_RXQ_MAIN].wed = &mdev->mmio.wed; } ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], @@ -528,6 +532,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) if (mtk_wed_device_active(&mdev->mmio.wed)) { mdev->q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE; + mdev->q_rx[MT_RXQ_MAIN_WA].wed = &mdev->mmio.wed; if (is_mt7916(mdev)) { wa_rx_base = MT_WED_RX_RING_BASE; wa_rx_idx = MT7915_RXQ_MCU_WA; @@ -544,9 +549,10 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) if (dev->dbdc_support || dev->phy.mt76->band_idx) { if (mtk_wed_device_active(&mdev->mmio.wed) && mtk_wed_get_rx_capa(&mdev->mmio.wed)) { - dev->mt76.q_rx[MT_RXQ_BAND1].flags = + mdev->q_rx[MT_RXQ_BAND1].flags = MT_WED_Q_RX(MT7915_RXQ_BAND1); dev->mt76.rx_token_size += MT7915_RX_RING_SIZE; + mdev->q_rx[MT_RXQ_BAND1].wed = &mdev->mmio.wed; } /* rx data queue for band1 */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index f04e7095e181..6f83c4c5fce2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -171,7 +171,7 @@ static int mt7921_dma_init(struct mt792x_dev *dev) /* init tx queue */ ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0, MT7921_TX_RING_SIZE, - MT_TX_RING_BASE, 0); + MT_TX_RING_BASE, NULL, 0); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c index 08ef75e24e1c..734f31ee40d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c @@ -218,7 +218,7 @@ static int mt7925_dma_init(struct mt792x_dev *dev) /* init tx queue */ ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7925_TXQ_BAND0, MT7925_TX_RING_SIZE, - MT_TX_RING_BASE, 0); + MT_TX_RING_BASE, NULL, 0); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c index 586e247a1e06..b33346360075 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c @@ -268,7 +268,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT_TXQ_ID(dev->mphy.band_idx), MT7996_TX_RING_SIZE, - MT_TXQ_RING_BASE(0), 0); + MT_TXQ_RING_BASE(0), NULL, 0); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 55cb1770fa34..b09ae6cc6eb4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -405,7 +405,8 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, ret = mt76_connac_init_tx_queues(phy->mt76, MT_TXQ_ID(band), MT7996_TX_RING_SIZE, - MT_TXQ_RING_BASE(band) + hif1_ofs, 0); + MT_TXQ_RING_BASE(band) + hif1_ofs, + NULL, 0); if (ret) goto error; From patchwork Fri Oct 20 10:30:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430489 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0A00ECDB47E for ; Fri, 20 Oct 2023 10:31:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376871AbjJTKbq (ORCPT ); Fri, 20 Oct 2023 06:31:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34018 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376855AbjJTKbp (ORCPT ); Fri, 20 Oct 2023 06:31:45 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BDF3BD5B for ; Fri, 20 Oct 2023 03:31:43 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 10B88C433C9; Fri, 20 Oct 2023 10:31:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797903; bh=kov4yMSQdmfTBSDB3yLwqivPB51jrQoms4p5iBEYCZY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tueI1HPIHRdUV1YnpRIvUnP/LrYAoyS3hwXUGiHJgVS5TYIDjL+jn8zOl6wyBMkpr I2/68S53afgAbBVd5UmzZcp5JJCk/vzavkXgE2voaqBSYpSw1MSEJFrPhTP9XXjrW8 kGHgxBGTIR2N7GphdL2L4JwVtkR5oS50eypaRSHvBTWxt0gOtOmzp9g2WUh/piZeGU YUdit2ey8t56qUQZcBFY1Dsv2cgLWjt/t2iTqB8IaN3uOnDmrqL9F7RW+w18/liEOx AjAUO/pSo+r2ePJehEq/UDai4vxAZZLSCUQGgyr+ExgDtwGzZ806zZQuSyLH1uE+pZ 3UdhGbxMkLvVg== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 06/13] wifi: mt76: increase MT_QFLAG_WED_TYPE size Date: Fri, 20 Oct 2023 12:30:53 +0200 Message-ID: <8dca673261ac27abfd7f471663abfb45c442803e.1697797423.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org This is a preliminary patch to introduce WED support for mt7996 Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8fa0440f1686..fa33ecfbf72d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -29,8 +29,8 @@ #define MT76_TOKEN_FREE_THR 64 #define MT_QFLAG_WED_RING GENMASK(1, 0) -#define MT_QFLAG_WED_TYPE GENMASK(3, 2) -#define MT_QFLAG_WED BIT(4) +#define MT_QFLAG_WED_TYPE GENMASK(4, 2) +#define MT_QFLAG_WED BIT(5) #define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \ FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \ From patchwork Fri Oct 20 10:30:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430491 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CDE85CDB474 for ; Fri, 20 Oct 2023 10:31:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376874AbjJTKbx (ORCPT ); Fri, 20 Oct 2023 06:31:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41240 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376855AbjJTKbv (ORCPT ); Fri, 20 Oct 2023 06:31:51 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 91B5ED46 for ; Fri, 20 Oct 2023 03:31:47 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A7348C433C8; Fri, 20 Oct 2023 10:31:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797907; bh=T6qzb2yXI4dbQOR9ul/7XHJh87gJghJL+h5cFHHLxio=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CsIvGi7nonWtscoVmTYlEJDU/edlmEKuDimloQGshjQrTjMFii6gFCUtLVBtRWKaZ GBoKV4dNpM+h99FO2cNw3nhvNGznFhJYwxds6GOIVBKC01JTOgrywWgfaalZEQrRi5 A4IiynaPCPzdcQ31GI1GbapsBHzdI/j0OA0hEIT5gItHvUncgp5DI5AekCaC2AwMGy Kc8R8pa2iXM1NPIdZ6+jzaUqDapF6gfTqDxq12Qd7AucJCTX2GB68QwWiFgP9Yld8K 4Hnn0KVluVDQc8MU5BWMT/k7SWu9xL1eTYzB7V5wxjy2ZR3SbJIQA81gpC4ZpJx+Og c94ulKUbNPN6g== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 07/13] wifi: mt76: mt7996: add wed tx support Date: Fri, 20 Oct 2023 12:30:54 +0200 Message-ID: <3acb1c6d71291e141f8de83c2ca1a88131e81054.1697797423.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Sujuan Chen Similar to MT7915, enable Wireless Ethernet Ditpatcher for MT7996 to offload traffic received from the LAN nic and transmitted on the WLAN one Co-developed-by: Lorenzo Bianconi Signed-off-by: Lorenzo Bianconi Signed-off-by: Sujuan Chen --- drivers/net/wireless/mediatek/mt76/dma.c | 9 +- drivers/net/wireless/mediatek/mt76/mt76.h | 11 ++ .../net/wireless/mediatek/mt76/mt7996/dma.c | 76 ++++++-- .../net/wireless/mediatek/mt76/mt7996/init.c | 30 ++- .../net/wireless/mediatek/mt76/mt7996/mac.c | 31 +++- .../net/wireless/mediatek/mt76/mt7996/main.c | 42 +++++ .../net/wireless/mediatek/mt76/mt7996/mmio.c | 172 ++++++++++++++++-- .../wireless/mediatek/mt76/mt7996/mt7996.h | 12 +- .../net/wireless/mediatek/mt76/mt7996/pci.c | 61 +++++-- .../net/wireless/mediatek/mt76/mt7996/regs.h | 5 + 10 files changed, 383 insertions(+), 66 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index d779ec57b95e..64027572a5e6 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -988,10 +988,13 @@ void mt76_dma_cleanup(struct mt76_dev *dev) page_pool_destroy(q->page_pool); } - mt76_free_pending_txwi(dev); - mt76_free_pending_rxwi(dev); - if (mtk_wed_device_active(&dev->mmio.wed)) mtk_wed_device_detach(&dev->mmio.wed); + + if (mtk_wed_device_active(&dev->mmio.wed_hif2)) + mtk_wed_device_detach(&dev->mmio.wed_hif2); + + mt76_free_pending_txwi(dev); + mt76_free_pending_rxwi(dev); } EXPORT_SYMBOL_GPL(mt76_dma_cleanup); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index fa33ecfbf72d..6fbcdfa187be 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -107,6 +107,16 @@ enum mt76_rxq_id { MT_RXQ_MAIN_WA, MT_RXQ_BAND2, MT_RXQ_BAND2_WA, + MT_RXQ_RRO_BAND0, + MT_RXQ_RRO_BAND1, + MT_RXQ_RRO_BAND2, + MT_RXQ_MSDU_PAGE_BAND0, + MT_RXQ_MSDU_PAGE_BAND1, + MT_RXQ_MSDU_PAGE_BAND2, + MT_RXQ_TXFREE_BAND0, + MT_RXQ_TXFREE_BAND1, + MT_RXQ_TXFREE_BAND2, + MT_RXQ_RRO_IND, __MT_RXQ_MAX }; @@ -604,6 +614,7 @@ struct mt76_mmio { u32 irqmask; struct mtk_wed_device wed; + struct mtk_wed_device wed_hif2; struct completion wed_reset; struct completion wed_reset_complete; }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c index b33346360075..72912f376bc9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c @@ -7,6 +7,26 @@ #include "../dma.h" #include "mac.h" +int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx, int n_desc, + int ring_base, struct mtk_wed_device *wed) +{ + struct mt7996_dev *dev = phy->dev; + u32 flags = 0; + + if (mtk_wed_device_active(wed)) { + ring_base += MT_TXQ_ID(0) * MT_RING_SIZE; + idx -= MT_TXQ_ID(0); + + if (phy->mt76->band_idx == MT_BAND2) + flags = MT_WED_Q_TX(0); + else + flags = MT_WED_Q_TX(idx); + } + + return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc, + ring_base, wed, flags); +} + static int mt7996_poll_tx(struct napi_struct *napi, int budget) { struct mt7996_dev *dev; @@ -128,7 +148,7 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset) } } -void mt7996_dma_start(struct mt7996_dev *dev, bool reset) +void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) { u32 hif1_ofs = 0; u32 irq_mask; @@ -153,11 +173,7 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset) } /* enable interrupts for TX/RX rings */ - irq_mask = MT_INT_MCU_CMD; - if (reset) - goto done; - - irq_mask = MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU; + irq_mask = MT_INT_MCU_CMD | MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU; if (!dev->mphy.band_idx) irq_mask |= MT_INT_BAND0_RX_DONE; @@ -168,7 +184,16 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset) if (dev->tbtc_support) irq_mask |= MT_INT_BAND2_RX_DONE; -done: + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) { + u32 wed_irq_mask = irq_mask; + + wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; + mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask); + mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask); + } + + irq_mask = reset ? MT_INT_MCU_CMD : irq_mask; + mt7996_irq_enable(dev, irq_mask); mt7996_irq_disable(dev, 0); } @@ -243,15 +268,16 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset) */ mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL, MT_WFDMA0_RX_INT_SEL_RING3); - - /* TODO: redirect rx ring6 interrupt to pcie0 for wed function */ } - mt7996_dma_start(dev, reset); + mt7996_dma_start(dev, reset, true); } int mt7996_dma_init(struct mt7996_dev *dev) { + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2; + u32 rx_base; u32 hif1_ofs = 0; int ret; @@ -265,10 +291,11 @@ int mt7996_dma_init(struct mt7996_dev *dev) mt7996_dma_disable(dev, true); /* init tx queue */ - ret = mt76_connac_init_tx_queues(dev->phy.mt76, - MT_TXQ_ID(dev->mphy.band_idx), - MT7996_TX_RING_SIZE, - MT_TXQ_RING_BASE(0), NULL, 0); + ret = mt7996_init_tx_queues(&dev->phy, + MT_TXQ_ID(dev->mphy.band_idx), + MT7996_TX_RING_SIZE, + MT_TXQ_RING_BASE(0), + wed); if (ret) return ret; @@ -315,6 +342,11 @@ int mt7996_dma_init(struct mt7996_dev *dev) return ret; /* rx data queue for band0 and band1 */ + if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) { + dev->mt76.q_rx[MT_RXQ_MAIN].flags = MT_WED_Q_RX(0); + dev->mt76.q_rx[MT_RXQ_MAIN].wed = wed; + } + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], MT_RXQ_ID(MT_RXQ_MAIN), MT7996_RX_RING_SIZE, @@ -324,6 +356,11 @@ int mt7996_dma_init(struct mt7996_dev *dev) return ret; /* tx free notify event from WA for band0 */ + if (mtk_wed_device_active(wed)) { + dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE; + dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed; + } + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA], MT_RXQ_ID(MT_RXQ_MAIN_WA), MT7996_RX_MCU_RING_SIZE, @@ -334,17 +371,26 @@ int mt7996_dma_init(struct mt7996_dev *dev) if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) { /* rx data queue for band2 */ + rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs; + if (mtk_wed_device_active(wed)) + rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2); + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2], MT_RXQ_ID(MT_RXQ_BAND2), MT7996_RX_RING_SIZE, MT_RX_BUF_SIZE, - MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs); + rx_base); if (ret) return ret; /* tx free notify event from WA for band2 * use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1 */ + if (mtk_wed_device_active(wed_hif2)) { + dev->mt76.q_rx[MT_RXQ_BAND2_WA].flags = MT_WED_Q_TXFREE; + dev->mt76.q_rx[MT_RXQ_BAND2_WA].wed = wed_hif2; + } + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2_WA], MT_RXQ_ID(MT_RXQ_BAND2_WA), MT7996_RX_MCU_RING_SIZE, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index b09ae6cc6eb4..e19c8fb71609 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -156,7 +156,7 @@ mt7996_regd_notifier(struct wiphy *wiphy, } static void -mt7996_init_wiphy(struct ieee80211_hw *hw) +mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) { struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt76_dev *mdev = &phy->dev->mt76; @@ -168,6 +168,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) hw->max_rx_aggregation_subframes = max_subframes; hw->max_tx_aggregation_subframes = max_subframes; hw->netdev_features = NETIF_F_RXCSUM; + if (mtk_wed_device_active(wed)) + hw->netdev_features |= NETIF_F_HW_TC; hw->radiotap_timestamp.units_pos = IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; @@ -356,6 +358,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, struct mt76_phy *mphy; u32 mac_ofs, hif1_ofs = 0; int ret; + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; if (band != MT_BAND1 && band != MT_BAND2) return 0; @@ -367,8 +370,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, if (phy) return 0; - if (band == MT_BAND2 && dev->hif2) + if (band == MT_BAND2 && dev->hif2) { hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + wed = &dev->mt76.mmio.wed_hif2; + } mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7996_ops, band); if (!mphy) @@ -401,12 +406,12 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, mt76_eeprom_override(mphy); /* init wiphy according to mphy and phy */ - mt7996_init_wiphy(mphy->hw); - ret = mt76_connac_init_tx_queues(phy->mt76, - MT_TXQ_ID(band), - MT7996_TX_RING_SIZE, - MT_TXQ_RING_BASE(band) + hif1_ofs, - NULL, 0); + mt7996_init_wiphy(mphy->hw, wed); + ret = mt7996_init_tx_queues(mphy->priv, + MT_TXQ_ID(band), + MT7996_TX_RING_SIZE, + MT_TXQ_RING_BASE(band) + hif1_ofs, + wed); if (ret) goto error; @@ -419,6 +424,13 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, if (ret) goto error; + if (wed == &dev->mt76.mmio.wed_hif2 && mtk_wed_device_active(wed)) { + u32 irq_mask = dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2; + + mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask); + mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, irq_mask); + } + return 0; error: @@ -890,7 +902,7 @@ int mt7996_register_device(struct mt7996_dev *dev) if (ret) return ret; - mt7996_init_wiphy(hw); + mt7996_init_wiphy(hw, &dev->mt76.mmio.wed); ret = mt76_register_device(&dev->mt76, true, mt76_rates, ARRAY_SIZE(mt76_rates)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 04540833485f..fd0f48d7cb91 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -996,6 +996,29 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return 0; } +u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id) +{ + struct mt76_connac_fw_txp *txp = ptr + MT_TXD_SIZE; + __le32 *txwi = ptr; + u32 val; + + memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp)); + + val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) | + FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT); + txwi[0] = cpu_to_le32(val); + + val = BIT(31) | + FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3); + txwi[1] = cpu_to_le32(val); + + txp->token = cpu_to_le16(token_id); + txp->nbuf = 1; + txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp)); + + return MT_TXD_SIZE + sizeof(*txp); +} + static void mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb) { @@ -1403,6 +1426,12 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, switch (type) { case PKT_TYPE_TXRX_NOTIFY: + if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2) && + q == MT_RXQ_TXFREE_BAND2) { + dev_kfree_skb(skb); + break; + } + mt7996_mac_tx_free(dev, skb->data, skb->len); napi_consume_skb(skb, 1); break; @@ -1877,7 +1906,7 @@ void mt7996_mac_reset_work(struct work_struct *work) mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); /* enable DMA Tx/Tx and interrupt */ - mt7996_dma_start(dev, false); + mt7996_dma_start(dev, false, false); clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 09c7a28a3d51..f074616c7007 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -1388,6 +1388,44 @@ mt7996_set_radar_background(struct ieee80211_hw *hw, return ret; } +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +static int +mt7996_net_fill_forward_path(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct net_device_path_ctx *ctx, + struct net_device_path *path) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct mt7996_phy *phy = mt7996_hw_phy(hw); + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + + if (phy != &dev->phy && phy->mt76->band_idx == MT_BAND2) + wed = &dev->mt76.mmio.wed_hif2; + + if (!mtk_wed_device_active(wed)) + return -ENODEV; + + if (msta->wcid.idx > MT7996_WTBL_STA) + return -EIO; + + path->type = DEV_PATH_MTK_WDMA; + path->dev = ctx->dev; + path->mtk_wdma.wdma_idx = wed->wdma_idx; + path->mtk_wdma.bss = mvif->mt76.idx; + path->mtk_wdma.queue = 0; + path->mtk_wdma.wcid = msta->wcid.idx; + + path->mtk_wdma.amsdu = mtk_wed_is_amsdu_supported(wed); + ctx->dev = NULL; + + return 0; +} + +#endif + const struct ieee80211_ops mt7996_ops = { .tx = mt7996_tx, .start = mt7996_start, @@ -1432,4 +1470,8 @@ const struct ieee80211_ops mt7996_ops = { .sta_add_debugfs = mt7996_sta_add_debugfs, #endif .set_radar_background = mt7996_set_radar_background, +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + .net_fill_forward_path = mt7996_net_fill_forward_path, + .net_setup_tc = mt76_net_setup_tc, +#endif }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index 3a591a7b47ae..ae029ae9969d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -10,6 +10,10 @@ #include "mt7996.h" #include "mac.h" #include "../trace.h" +#include "../dma.h" + +static bool wed_enable; +module_param(wed_enable, bool, 0644); static const struct __base mt7996_reg_base[] = { [WF_AGG_BASE] = { { 0x820e2000, 0x820f2000, 0x830e2000 } }, @@ -191,6 +195,106 @@ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) return dev->bus_ops->rmw(mdev, __mt7996_reg_addr(dev, offset), mask, val); } +int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, + bool hif2, int *irq) +{ +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + struct pci_dev *pci_dev = pdev_ptr; + u32 hif1_ofs = 0; + int ret; + + if (!wed_enable) + return 0; + + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + + if (hif2) + wed = &dev->mt76.mmio.wed_hif2; + + wed->wlan.pci_dev = pci_dev; + wed->wlan.bus_type = MTK_WED_BUS_PCIE; + + wed->wlan.base = devm_ioremap(dev->mt76.dev, + pci_resource_start(pci_dev, 0), + pci_resource_len(pci_dev, 0)); + wed->wlan.phy_base = pci_resource_start(pci_dev, 0); + + if (hif2) { + wed->wlan.wpdma_int = wed->wlan.phy_base + + MT_INT_PCIE1_SOURCE_CSR_EXT; + wed->wlan.wpdma_mask = wed->wlan.phy_base + + MT_INT_PCIE1_MASK_CSR; + wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs + + MT_TXQ_RING_BASE(0) + + MT7996_TXQ_BAND2 * MT_RING_SIZE; + wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs + + MT_RXQ_RING_BASE(0) + + MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE; + wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1; + + wed->wlan.id = 0x7991; + wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1; + } else { + wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR; + wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR; + wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) + + MT7996_TXQ_BAND0 * MT_RING_SIZE; + + wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + MT_WFDMA0_GLO_CFG; + + wed->wlan.wpdma_rx = wed->wlan.phy_base + + MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) + + MT7996_RXQ_BAND0 * MT_RING_SIZE; + + wed->wlan.rx_nbuf = 65536; + wed->wlan.rx_npkt = dev->hif2 ? 32768 : 24576; + wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE); + + wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1; + wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1; + + wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1; + wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1; + wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1; + wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) + + MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE; + } + + wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE; + wed->wlan.token_start = MT7996_TOKEN_SIZE - wed->wlan.nbuf; + + wed->wlan.amsdu_max_subframes = 8; + wed->wlan.amsdu_max_len = 1536; + + wed->wlan.init_buf = mt7996_wed_init_buf; + wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf; + wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf; + wed->wlan.offload_enable = mt76_mmio_wed_offload_enable; + wed->wlan.offload_disable = mt76_mmio_wed_offload_disable; + + dev->mt76.rx_token_size += wed->wlan.rx_npkt; + + if (mtk_wed_device_attach(wed)) + return 0; + + *irq = wed->irq; + dev->mt76.dma_dev = wed->dev; + + ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + ret = dma_set_coherent_mask(wed->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + return 1; +#else + return 0; +#endif +} + static int mt7996_mmio_init(struct mt76_dev *mdev, void __iomem *mem_base, u32 device_id) @@ -241,8 +345,17 @@ void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg, mdev->mmio.irqmask |= set; if (write_reg) { - mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask); - mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask); + if (mtk_wed_device_active(&mdev->mmio.wed)) { + mtk_wed_device_irq_set_mask(&mdev->mmio.wed, + mdev->mmio.irqmask); + if (mtk_wed_device_active(&mdev->mmio.wed_hif2)) { + mtk_wed_device_irq_set_mask(&mdev->mmio.wed_hif2, + mdev->mmio.irqmask); + } + } else { + mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask); + mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask); + } } spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags); @@ -260,22 +373,36 @@ static void mt7996_rx_poll_complete(struct mt76_dev *mdev, static void mt7996_irq_tasklet(struct tasklet_struct *t) { struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet); + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2; u32 i, intr, mask, intr1; - mt76_wr(dev, MT_INT_MASK_CSR, 0); - if (dev->hif2) - mt76_wr(dev, MT_INT1_MASK_CSR, 0); - - intr = mt76_rr(dev, MT_INT_SOURCE_CSR); - intr &= dev->mt76.mmio.irqmask; - mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - - if (dev->hif2) { - intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR); - intr1 &= dev->mt76.mmio.irqmask; - mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1); + if (dev->hif2 && mtk_wed_device_active(wed_hif2)) { + mtk_wed_device_irq_set_mask(wed_hif2, 0); + intr1 = mtk_wed_device_irq_get(wed_hif2, + dev->mt76.mmio.irqmask); + if (intr1 & MT_INT_RX_TXFREE_EXT) + napi_schedule(&dev->mt76.napi[MT_RXQ_TXFREE_BAND2]); + } - intr |= intr1; + if (mtk_wed_device_active(wed)) { + mtk_wed_device_irq_set_mask(wed, 0); + intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask); + intr |= (intr1 & ~MT_INT_RX_TXFREE_EXT); + } else { + mt76_wr(dev, MT_INT_MASK_CSR, 0); + if (dev->hif2) + mt76_wr(dev, MT_INT1_MASK_CSR, 0); + + intr = mt76_rr(dev, MT_INT_SOURCE_CSR); + intr &= dev->mt76.mmio.irqmask; + mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + if (dev->hif2) { + intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR); + intr1 &= dev->mt76.mmio.irqmask; + mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1); + intr |= intr1; + } } trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); @@ -307,10 +434,19 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t) irqreturn_t mt7996_irq_handler(int irq, void *dev_instance) { struct mt7996_dev *dev = dev_instance; + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; - mt76_wr(dev, MT_INT_MASK_CSR, 0); - if (dev->hif2) - mt76_wr(dev, MT_INT1_MASK_CSR, 0); + if (mtk_wed_device_active(wed)) + mtk_wed_device_irq_set_mask(wed, 0); + else + mt76_wr(dev, MT_INT_MASK_CSR, 0); + + if (dev->hif2) { + if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) + mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed_hif2, 0); + else + mt76_wr(dev, MT_INT1_MASK_CSR, 0); + } if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index e53cf6a3704c..ccb6c5763956 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -37,6 +37,7 @@ #define MT7996_EEPROM_SIZE 7680 #define MT7996_EEPROM_BLOCK_SIZE 16 #define MT7996_TOKEN_SIZE 16384 +#define MT7996_HW_TOKEN_SIZE 8192 #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ @@ -334,7 +335,9 @@ int mt7996_dma_init(struct mt7996_dev *dev); void mt7996_dma_reset(struct mt7996_dev *dev, bool force); void mt7996_dma_prefetch(struct mt7996_dev *dev); void mt7996_dma_cleanup(struct mt7996_dev *dev); -void mt7996_dma_start(struct mt7996_dev *dev, bool reset); +void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset); +int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx, + int n_desc, int ring_base, struct mtk_wed_device *wed); void mt7996_init_txpower(struct mt7996_dev *dev, struct ieee80211_supported_band *sband); int mt7996_txbf_init(struct mt7996_dev *dev); @@ -495,5 +498,12 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev, void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir); #endif +int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, + bool hif2, int *irq); +u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id); + +#ifdef CONFIG_MTK_DEBUG +int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir); +#endif #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c index c5301050ff8b..93ecc9a8dde0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c @@ -92,10 +92,10 @@ static int mt7996_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct pci_dev *hif2_dev; + struct mt7996_hif *hif2; struct mt7996_dev *dev; + int irq, hif2_irq, ret; struct mt76_dev *mdev; - struct mt7996_hif *hif2; - int irq, ret; ret = pcim_enable_device(pdev); if (ret) @@ -125,15 +125,22 @@ static int mt7996_pci_probe(struct pci_dev *pdev, mt7996_wfsys_reset(dev); hif2 = mt7996_pci_init_hif2(pdev); - ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + ret = mt7996_mmio_wed_init(dev, pdev, false, &irq); if (ret < 0) - goto free_device; + goto free_wed_or_irq_vector; + + if (!ret) { + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + goto free_device; + + irq = pdev->irq; + } - irq = pdev->irq; ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) - goto free_irq_vector; + goto free_wed_or_irq_vector; mt76_wr(dev, MT_INT_MASK_CSR, 0); /* master switch of PCIe tnterrupt enable */ @@ -143,16 +150,25 @@ static int mt7996_pci_probe(struct pci_dev *pdev, hif2_dev = container_of(hif2->dev, struct pci_dev, dev); dev->hif2 = hif2; - ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, PCI_IRQ_ALL_TYPES); + ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &hif2_irq); if (ret < 0) - goto free_hif2; + goto free_hif2_wed_irq_vector; + + if (!ret) { + ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, + PCI_IRQ_ALL_TYPES); + if (ret < 0) + goto free_hif2; + + dev->hif2->irq = hif2_dev->irq; + hif2_irq = dev->hif2->irq; + } - dev->hif2->irq = hif2_dev->irq; - ret = devm_request_irq(mdev->dev, dev->hif2->irq, - mt7996_irq_handler, IRQF_SHARED, - KBUILD_MODNAME "-hif", dev); + ret = devm_request_irq(mdev->dev, hif2_irq, mt7996_irq_handler, + IRQF_SHARED, KBUILD_MODNAME "-hif", + dev); if (ret) - goto free_hif2_irq_vector; + goto free_hif2_wed_irq_vector; mt76_wr(dev, MT_INT1_MASK_CSR, 0); /* master switch of PCIe tnterrupt enable */ @@ -167,16 +183,23 @@ static int mt7996_pci_probe(struct pci_dev *pdev, free_hif2_irq: if (dev->hif2) - devm_free_irq(mdev->dev, dev->hif2->irq, dev); -free_hif2_irq_vector: - if (dev->hif2) - pci_free_irq_vectors(hif2_dev); + devm_free_irq(mdev->dev, hif2_irq, dev); +free_hif2_wed_irq_vector: + if (dev->hif2) { + if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) + mtk_wed_device_detach(&dev->mt76.mmio.wed_hif2); + else + pci_free_irq_vectors(hif2_dev); + } free_hif2: if (dev->hif2) put_device(dev->hif2->dev); devm_free_irq(mdev->dev, irq, dev); -free_irq_vector: - pci_free_irq_vectors(pdev); +free_wed_or_irq_vector: + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + mtk_wed_device_detach(&dev->mt76.mmio.wed); + else + pci_free_irq_vectors(pdev); free_device: mt76_free_device(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 0086a7866657..b7d78adce11a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -330,6 +330,7 @@ enum base_rev { #define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154) #define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3) +#define MT_WFDMA0_RX_INT_SEL_RING6 BIT(6) #define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4) @@ -374,6 +375,9 @@ enum base_rev { #define MT_WFDMA0_PCIE1_BASE 0xd8000 #define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs)) +#define MT_INT_PCIE1_SOURCE_CSR_EXT MT_WFDMA0_PCIE1(0x118) +#define MT_INT_PCIE1_MASK_CSR MT_WFDMA0_PCIE1(0x11c) + #define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c) #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0) #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1) @@ -419,6 +423,7 @@ enum base_rev { #define MT_INT_RX_TXFREE_MAIN BIT(17) #define MT_INT_RX_TXFREE_TRI BIT(15) #define MT_INT_MCU_CMD BIT(29) +#define MT_INT_RX_TXFREE_EXT BIT(26) #define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)]) #define MT_INT_TX_MCU(q) (dev->q_int_mask[(q)]) From patchwork Fri Oct 20 10:30:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430490 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28D03CDB47E for ; Fri, 20 Oct 2023 10:31:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376855AbjJTKby (ORCPT ); Fri, 20 Oct 2023 06:31:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41260 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376881AbjJTKbx (ORCPT ); Fri, 20 Oct 2023 06:31:53 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4976BD46 for ; Fri, 20 Oct 2023 03:31:51 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 90FB6C433C9; Fri, 20 Oct 2023 10:31:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797910; bh=YdZwi7PiVHPeDTOb8qJp4IGfc6Ab3P3P06xqpebgMOw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PeQkqlkrKwhwOuMrgCDVdmzEk+/EMUkWdzasJzPNwzOLhONHsD9j0cg8Ok+8aTif8 VwOytIPt52bPYtiif3eSVk2M0ZKEV0C9GFUAx1/SsatBdciHWBkyzdlnyI9W7UYqpX wpkhsl0iz02v7lK48mTGU9hs+gXKgciY4AFpuiLUtLrV/49qzQTYVVBOIsBhQlikJK zR45lGIKYQ3aZfFoCtzG6ZtvQSdZIdYxt7/NJ69bbcFnAXutjkPfUtSMQUdOXBwDbq iewNOmRoD49nxi4BFlKSNpudzUzb0EXTVyEBGUpjz66WL6WEP3k1Hz0xMJaEba9kL/ OpnQSwS9REJig== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 08/13] wifi: mt76: dma: introduce __mt76_dma_queue_reset utility routine Date: Fri, 20 Oct 2023 12:30:55 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org This is a preliminary patch to introduce WED support for mt7996 Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/dma.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 64027572a5e6..7b622e966f58 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -195,7 +195,8 @@ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) } static void -mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) +__mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, + bool reset_idx) { int i; @@ -206,11 +207,19 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) for (i = 0; i < q->ndesc; i++) q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); - Q_WRITE(q, cpu_idx, 0); - Q_WRITE(q, dma_idx, 0); + if (reset_idx) { + Q_WRITE(q, cpu_idx, 0); + Q_WRITE(q, dma_idx, 0); + } mt76_dma_sync_idx(dev, q); } +static void +mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) +{ + __mt76_dma_queue_reset(dev, q, true); +} + static int mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf *buf, void *data) From patchwork Fri Oct 20 10:30:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430492 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E149CCDB474 for ; Fri, 20 Oct 2023 10:32:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376894AbjJTKb7 (ORCPT ); Fri, 20 Oct 2023 06:31:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51680 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376881AbjJTKb5 (ORCPT ); Fri, 20 Oct 2023 06:31:57 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 270BC114 for ; Fri, 20 Oct 2023 03:31:55 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63496C433C9; Fri, 20 Oct 2023 10:31:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797914; bh=XCjwwQVr6jl38xcwubSN4H5Ycb70YzrZh+Ybb+/Y1fY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=e8VdptcAIDN9x/prleh6Rk2Ttdbj4QJRD9eBGNi6A/Pi35CQcDpjmd+X6hFAbyFTU zj+Al4BIWY4XrzSvtoT4Z5znf3RZpMgtt2jRNfjarVvj4l2tYxh3NtznliUz1R/9CD 66MRXari/71VjAulC8t7Mc4J3Ro5uPYBO8oDNqXgV2L2q/l9IzzYAeqjE4z+bx+eeH j84ETkqttgSRDAlo9j4MEeweEvkCzQdD1T1Zij9qy+cE9Ty5A9jiJR5ZpDZDln0yV1 4GaO785XjOhnfhkSPGpCHT02uRwfgBCkP7PWyxh3022QG68ErcGo9FvjIenC+eZ6NB I3Bqxgg8x1/mg== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 09/13] wifi: mt76: mt7996: use u16 for val field in mt7996_mcu_set_rro signature Date: Fri, 20 Oct 2023 12:30:56 +0200 Message-ID: <78b1ae679ad5555ce94cc28a0b7ef950ae7b24c8.1697797423.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org This is a preliminary patch to introduce WED rx support for mt7996 driver. Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index bf917beb9439..3ecdc09323c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -4019,7 +4019,7 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev) &req, sizeof(req), false); } -int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val) +int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val) { struct { u8 __rsv1[4]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index ccb6c5763956..d4425c133ced 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -397,7 +397,7 @@ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef); int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set); int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans); -int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val); +int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val); int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3); int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl); int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level); From patchwork Fri Oct 20 10:30:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430518 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3AF66CDB47E for ; Fri, 20 Oct 2023 10:32:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376895AbjJTKcG (ORCPT ); Fri, 20 Oct 2023 06:32:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51900 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376890AbjJTKcE (ORCPT ); Fri, 20 Oct 2023 06:32:04 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 04B5E1BF for ; Fri, 20 Oct 2023 03:31:59 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1FCD5C433C7; Fri, 20 Oct 2023 10:31:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797918; bh=J1vGMucYQJ1BGDm0LGAOPPxBW2VDlf6dnZrtz5jMgJQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=k+vUxT6Vk0F8/2eEYo6eovYh2fc+PBN4SMjpF3vjyY7//DfI6NzAceAjWCcgRXep9 km+5CGo5saphcUAGOcpoBGZDdjKBatsCfRFAk1UHBQNnEqiN/OUjIT1Blh3qg+8FZ4 DzjWcNDKwgLLXwLUTJzOtcfa93WkN0t3Oim7QcxxErmZUu45hIHob7VNOjd8jXQLss 3LhVnMUpaLofYyWfPiM3p9TZOy2+/izf0IJADEy3V3v4KVTuE0kjW7C4826codyPz+ IY8zifkebPGXJWrQ7d3JHgTjU4/RB+XmluX8uypjy6kNaEszvJF1bNAEoqp0pdrIyG ZkXCLd/9hKV5Q== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 10/13] wifi: mt76: mt7996: add wed rx support Date: Fri, 20 Oct 2023 12:30:57 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Bo Jiao Similar to MT7915, enable Wireless Ethernet Ditpatcher for MT7996 to offload traffic received from the WLAN nic and transmitted on the LAN one Co-developed-by: Lorenzo Bianconi Signed-off-by: Lorenzo Bianconi Co-developed-by: Sujuan Chen Signed-off-by: Sujuan Chen Signed-off-by: Bo Jiao --- drivers/net/wireless/mediatek/mt76/dma.c | 149 +++++++++---- drivers/net/wireless/mediatek/mt76/dma.h | 43 ++++ drivers/net/wireless/mediatek/mt76/mt76.h | 50 ++++- .../net/wireless/mediatek/mt76/mt7996/dma.c | 198 ++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7996/init.c | 175 +++++++++++++++- .../net/wireless/mediatek/mt76/mt7996/mac.c | 41 +++- .../net/wireless/mediatek/mt76/mt7996/mcu.c | 24 ++- .../net/wireless/mediatek/mt76/mt7996/mcu.h | 2 + .../net/wireless/mediatek/mt76/mt7996/mmio.c | 60 ++++-- .../wireless/mediatek/mt76/mt7996/mt7996.h | 55 +++++ .../net/wireless/mediatek/mt76/mt7996/regs.h | 62 +++++- 11 files changed, 772 insertions(+), 87 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 7b622e966f58..e60012a1896b 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -189,7 +189,10 @@ static void mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) { Q_WRITE(q, desc_base, q->desc_dma); - Q_WRITE(q, ring_size, q->ndesc); + if (q->flags & MT_QFLAG_WED_RRO_EN) + Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc); + else + Q_WRITE(q, ring_size, q->ndesc); q->head = Q_READ(q, dma_idx); q->tail = q->head; } @@ -198,14 +201,16 @@ static void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, bool reset_idx) { - int i; - if (!q || !q->ndesc) return; - /* clear descriptors */ - for (i = 0; i < q->ndesc; i++) - q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); + if (!mt76_queue_is_wed_rro_ind(q)) { + int i; + + /* clear descriptors */ + for (i = 0; i < q->ndesc; i++) + q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); + } if (reset_idx) { Q_WRITE(q, cpu_idx, 0); @@ -224,13 +229,22 @@ static int mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf *buf, void *data) { - struct mt76_desc *desc = &q->desc[q->head]; struct mt76_queue_entry *entry = &q->entry[q->head]; struct mt76_txwi_cache *txwi = NULL; + struct mt76_desc *desc; u32 buf1 = 0, ctrl; int idx = q->head; int rx_token; + if (mt76_queue_is_wed_rro_ind(q)) { + struct mt76_wed_rro_desc *rro_desc; + + rro_desc = (struct mt76_wed_rro_desc *)q->desc; + data = &rro_desc[q->head]; + goto done; + } + + desc = &q->desc[q->head]; ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len); if (mt76_queue_is_wed_rx(q)) { @@ -253,6 +267,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q, WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); WRITE_ONCE(desc->info, 0); +done: entry->dma_addr[0] = buf->addr; entry->dma_len[0] = buf->len; entry->txwi = txwi; @@ -401,19 +416,26 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, { struct mt76_queue_entry *e = &q->entry[idx]; struct mt76_desc *desc = &q->desc[idx]; - void *buf; + u32 ctrl, desc_info, buf1; + void *buf = e->buf; + + if (mt76_queue_is_wed_rro_ind(q)) + goto done; + ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); if (len) { - u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); *len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl); *more = !(ctrl & MT_DMA_CTL_LAST_SEC0); } + desc_info = le32_to_cpu(desc->info); if (info) - *info = le32_to_cpu(desc->info); + *info = desc_info; + + buf1 = le32_to_cpu(desc->buf1); + mt76_dma_should_drop_buf(drop, ctrl, buf1, desc_info); if (mt76_queue_is_wed_rx(q)) { - u32 buf1 = le32_to_cpu(desc->buf1); u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1); struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token); @@ -429,23 +451,16 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, t->ptr = NULL; mt76_put_rxwi(dev, t); - - if (drop) { - u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); - - *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | - MT_DMA_CTL_DROP)); - + if (drop) *drop |= !!(buf1 & MT_DMA_CTL_WO_DROP); - } } else { - buf = e->buf; - e->buf = NULL; dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0], SKB_WITH_OVERHEAD(q->buf_size), page_pool_get_dma_dir(q->page_pool)); } +done: + e->buf = NULL; return buf; } @@ -459,11 +474,16 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, if (!q->queued) return NULL; - if (flush) - q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE); - else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE))) + if (mt76_queue_is_wed_rro_data(q)) return NULL; + if (!mt76_queue_is_wed_rro_ind(q)) { + if (flush) + q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE); + else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE))) + return NULL; + } + q->tail = (q->tail + 1) % q->ndesc; q->queued--; @@ -615,11 +635,14 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, spin_lock_bh(&q->lock); while (q->queued < q->ndesc - 1) { + struct mt76_queue_buf qbuf = {}; enum dma_data_direction dir; - struct mt76_queue_buf qbuf; dma_addr_t addr; int offset; - void *buf; + void *buf = NULL; + + if (mt76_queue_is_wed_rro_ind(q)) + goto done; buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); if (!buf) @@ -630,6 +653,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, dma_sync_single_for_device(dev->dma_dev, addr, len, dir); qbuf.addr = addr + q->buf_offset; +done: qbuf.len = len - q->buf_offset; qbuf.skip_unmap = false; if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) { @@ -639,7 +663,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, frames++; } - if (frames) + if (frames || mt76_queue_is_wed_rx(q)) mt76_dma_kick_queue(dev, q); spin_unlock_bh(&q->lock); @@ -650,8 +674,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) { #ifdef CONFIG_NET_MEDIATEK_SOC_WED - int ret, type, ring; - u8 flags; + int ret = 0, type, ring; + u16 flags; if (!q || !q->ndesc) return -EINVAL; @@ -678,7 +702,6 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) q->flags = 0; mt76_dma_queue_reset(dev, q); mt76_dma_rx_fill(dev, q, false); - q->flags = flags; ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs); if (!ret) @@ -690,9 +713,31 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) if (!ret) q->wed_regs = q->wed->rx_ring[ring].reg_base; break; + case MT76_WED_RRO_Q_DATA: + q->flags &= ~MT_QFLAG_WED; + __mt76_dma_queue_reset(dev, q, false); + mtk_wed_device_rro_rx_ring_setup(q->wed, ring, q->regs); + q->head = q->ndesc - 1; + q->queued = q->head; + break; + case MT76_WED_RRO_Q_MSDU_PG: + q->flags &= ~MT_QFLAG_WED; + __mt76_dma_queue_reset(dev, q, false); + mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs); + q->head = q->ndesc - 1; + q->queued = q->head; + break; + case MT76_WED_RRO_Q_IND: + q->flags &= ~MT_QFLAG_WED; + mt76_dma_queue_reset(dev, q); + mt76_dma_rx_fill(dev, q, false); + mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs); + break; default: ret = -EINVAL; + break; } + q->flags = flags; return ret; #else @@ -716,11 +761,26 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, q->buf_size = bufsize; q->hw_idx = idx; - size = q->ndesc * sizeof(struct mt76_desc); - q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL); + size = mt76_queue_is_wed_rro_ind(q) ? sizeof(struct mt76_wed_rro_desc) + : sizeof(struct mt76_desc); + q->desc = dmam_alloc_coherent(dev->dma_dev, q->ndesc * size, + &q->desc_dma, GFP_KERNEL); if (!q->desc) return -ENOMEM; + if (mt76_queue_is_wed_rro_ind(q)) { + struct mt76_wed_rro_desc *rro_desc; + int i; + + rro_desc = (struct mt76_wed_rro_desc *)q->desc; + for (i = 0; i < q->ndesc; i++) { + struct mt76_wed_rro_ind *cmd; + + cmd = (struct mt76_wed_rro_ind *)&rro_desc[i]; + cmd->magic_cnt = MT_DMA_WED_IND_CMD_CNT - 1; + } + } + size = q->ndesc * sizeof(*q->entry); q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL); if (!q->entry) @@ -734,8 +794,13 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, if (ret) return ret; - if (!mt76_queue_is_wed_tx_free(q)) - mt76_dma_queue_reset(dev, q); + if (mtk_wed_device_active(&dev->mmio.wed)) { + if ((mtk_wed_get_rx_capa(&dev->mmio.wed) && mt76_queue_is_wed_rro(q)) || + mt76_queue_is_wed_tx_free(q)) + return 0; + } + + mt76_dma_queue_reset(dev, q); return 0; } @@ -757,7 +822,8 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) if (!buf) break; - mt76_put_page_pool_buf(buf, false); + if (!mt76_queue_is_wed_rro(q)) + mt76_put_page_pool_buf(buf, false); } while (1); spin_lock_bh(&q->lock); @@ -773,13 +839,16 @@ static void mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) { struct mt76_queue *q = &dev->q_rx[qid]; - int i; if (!q->ndesc) return; - for (i = 0; i < q->ndesc; i++) - q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); + if (!mt76_queue_is_wed_rro_ind(q)) { + int i; + + for (i = 0; i < q->ndesc; i++) + q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); + } mt76_dma_rx_cleanup(dev, q); @@ -991,6 +1060,10 @@ void mt76_dma_cleanup(struct mt76_dev *dev) mt76_for_each_q_rx(dev, i) { struct mt76_queue *q = &dev->q_rx[i]; + if (mtk_wed_device_active(&dev->mmio.wed) && + mt76_queue_is_wed_rro(q)) + continue; + netif_napi_del(&dev->napi[i]); mt76_dma_rx_cleanup(dev, q); diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h index 1b090d78cd05..e549e678b69f 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.h +++ b/drivers/net/wireless/mediatek/mt76/dma.h @@ -23,8 +23,17 @@ #define MT_DMA_PPE_CPU_REASON GENMASK(15, 11) #define MT_DMA_PPE_ENTRY GENMASK(30, 16) +#define MT_DMA_INFO_DMA_FRAG BIT(9) #define MT_DMA_INFO_PPE_VLD BIT(31) +#define MT_DMA_CTL_PN_CHK_FAIL BIT(13) +#define MT_DMA_CTL_VER_MASK BIT(7) + +#define MT_DMA_RRO_EN BIT(13) + +#define MT_DMA_WED_IND_CMD_CNT 8 +#define MT_DMA_WED_IND_REASON GENMASK(15, 12) + #define MT_DMA_HDR_LEN 4 #define MT_RX_INFO_LEN 4 #define MT_FCE_INFO_LEN 4 @@ -37,6 +46,11 @@ struct mt76_desc { __le32 info; } __packed __aligned(4); +struct mt76_wed_rro_desc { + __le32 buf0; + __le32 buf1; +} __packed __aligned(4); + enum mt76_qsel { MT_QSEL_MGMT, MT_QSEL_HCCA, @@ -54,9 +68,38 @@ enum mt76_mcu_evt_type { EVT_EVENT_DFS_DETECT_RSP, }; +enum mt76_dma_wed_ind_reason { + MT_DMA_WED_IND_REASON_NORMAL, + MT_DMA_WED_IND_REASON_REPEAT, + MT_DMA_WED_IND_REASON_OLDPKT, +}; + int mt76_dma_rx_poll(struct napi_struct *napi, int budget); void mt76_dma_attach(struct mt76_dev *dev); void mt76_dma_cleanup(struct mt76_dev *dev); int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset); +static inline void +mt76_dma_should_drop_buf(bool *drop, u32 ctrl, u32 buf1, u32 info) +{ + if (!drop) + return; + + *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP)); + if (!(ctrl & MT_DMA_CTL_VER_MASK)) + return; + + switch (FIELD_GET(MT_DMA_WED_IND_REASON, buf1)) { + case MT_DMA_WED_IND_REASON_REPEAT: + *drop = true; + break; + case MT_DMA_WED_IND_REASON_OLDPKT: + *drop = !(info & MT_DMA_INFO_DMA_FRAG); + break; + default: + *drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL); + break; + } +} + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 6fbcdfa187be..f015c94b3c68 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -31,13 +31,20 @@ #define MT_QFLAG_WED_RING GENMASK(1, 0) #define MT_QFLAG_WED_TYPE GENMASK(4, 2) #define MT_QFLAG_WED BIT(5) +#define MT_QFLAG_WED_RRO BIT(6) +#define MT_QFLAG_WED_RRO_EN BIT(7) #define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \ FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \ FIELD_PREP(MT_QFLAG_WED_RING, _n)) +#define __MT_WED_RRO_Q(_type, _n) (MT_QFLAG_WED_RRO | __MT_WED_Q(_type, _n)) + #define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n) #define MT_WED_Q_RX(_n) __MT_WED_Q(MT76_WED_Q_RX, _n) #define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0) +#define MT_WED_RRO_Q_DATA(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_DATA, _n) +#define MT_WED_RRO_Q_MSDU_PG(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_MSDU_PG, _n) +#define MT_WED_RRO_Q_IND __MT_WED_RRO_Q(MT76_WED_RRO_Q_IND, 0) struct mt76_dev; struct mt76_phy; @@ -59,6 +66,9 @@ enum mt76_wed_type { MT76_WED_Q_TX, MT76_WED_Q_TXFREE, MT76_WED_Q_RX, + MT76_WED_RRO_Q_DATA, + MT76_WED_RRO_Q_MSDU_PG, + MT76_WED_RRO_Q_IND, }; struct mt76_bus_ops { @@ -194,6 +204,7 @@ struct mt76_queue { spinlock_t lock; spinlock_t cleanup_lock; struct mt76_queue_entry *entry; + struct mt76_rro_desc *rro_desc; struct mt76_desc *desc; u16 first; @@ -207,7 +218,7 @@ struct mt76_queue { u8 buf_offset; u8 hw_idx; - u8 flags; + u16 flags; struct mtk_wed_device *wed; u32 wed_regs; @@ -364,6 +375,17 @@ struct mt76_txq { bool aggr; }; +struct mt76_wed_rro_ind { + u32 se_id : 12; + u32 rsv : 4; + u32 start_sn : 12; + u32 ind_reason : 4; + u32 ind_cnt : 13; + u32 win_sz : 3; + u32 rsv2 : 13; + u32 magic_cnt : 3; +}; + struct mt76_txwi_cache { struct list_head list; dma_addr_t dma_addr; @@ -1579,10 +1601,32 @@ static inline bool mt76_queue_is_wed_tx_free(struct mt76_queue *q) FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE; } +static inline bool mt76_queue_is_wed_rro(struct mt76_queue *q) +{ + return q->flags & MT_QFLAG_WED_RRO; +} + +static inline bool mt76_queue_is_wed_rro_ind(struct mt76_queue *q) +{ + return mt76_queue_is_wed_rro(q) && + FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_IND; +} + +static inline bool mt76_queue_is_wed_rro_data(struct mt76_queue *q) +{ + return mt76_queue_is_wed_rro(q) && + (FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_DATA || + FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_MSDU_PG); +} + static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q) { - return (q->flags & MT_QFLAG_WED) && - FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX; + if (!(q->flags & MT_QFLAG_WED)) + return false; + + return FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX || + mt76_queue_is_wed_rro_ind(q) || mt76_queue_is_wed_rro_data(q); + } struct mt76_txwi_cache * diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c index 72912f376bc9..2221d22ccffb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c @@ -65,6 +65,29 @@ static void mt7996_dma_config(struct mt7996_dev *dev) RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2); RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI); + if (dev->has_rro) { + /* band0 */ + RXQ_CONFIG(MT_RXQ_RRO_BAND0, WFDMA0, MT_INT_RX_DONE_RRO_BAND0, + MT7996_RXQ_RRO_BAND0); + RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND0, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND0, + MT7996_RXQ_MSDU_PG_BAND0); + RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0, MT_INT_RX_TXFREE_MAIN, + MT7996_RXQ_TXFREE0); + /* band1 */ + RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND1, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND1, + MT7996_RXQ_MSDU_PG_BAND1); + /* band2 */ + RXQ_CONFIG(MT_RXQ_RRO_BAND2, WFDMA0, MT_INT_RX_DONE_RRO_BAND2, + MT7996_RXQ_RRO_BAND2); + RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND2, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND2, + MT7996_RXQ_MSDU_PG_BAND2); + RXQ_CONFIG(MT_RXQ_TXFREE_BAND2, WFDMA0, MT_INT_RX_TXFREE_TRI, + MT7996_RXQ_TXFREE2); + + RXQ_CONFIG(MT_RXQ_RRO_IND, WFDMA0, MT_INT_RX_DONE_RRO_IND, + MT7996_RXQ_RRO_IND); + } + /* data tx queue */ TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0); TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1); @@ -93,6 +116,24 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs) mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x1a0, 0x10)); mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x2a0, 0x10)); + if (dev->has_rro) { + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs, + PREFETCH(0x3a0, 0x10)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs, + PREFETCH(0x4a0, 0x10)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs, + PREFETCH(0x5a0, 0x4)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs, + PREFETCH(0x5e0, 0x4)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs, + PREFETCH(0x620, 0x4)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND0) + ofs, + PREFETCH(0x660, 0x4)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND2) + ofs, + PREFETCH(0x6a0, 0x4)); + } +#undef PREFETCH + mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1 + ofs, WF_WFDMA0_GLO_CFG_EXT1_CALC_MODE); } @@ -150,6 +191,7 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset) void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) { + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; u32 hif1_ofs = 0; u32 irq_mask; @@ -158,11 +200,16 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) /* enable WFDMA Tx/Rx */ if (!reset) { - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO); + else + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); if (dev->hif2) mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, @@ -184,12 +231,12 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) if (dev->tbtc_support) irq_mask |= MT_INT_BAND2_RX_DONE; - if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) { + if (mtk_wed_device_active(wed) && wed_reset) { u32 wed_irq_mask = irq_mask; wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask); - mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask); + mtk_wed_device_start(wed, wed_irq_mask); } irq_mask = reset ? MT_INT_MCU_CMD : irq_mask; @@ -266,13 +313,85 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset) /* fix hardware limitation, pcie1's rx ring3 is not available * so, redirect pcie0 rx ring3 interrupt to pcie1 */ - mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL, - MT_WFDMA0_RX_INT_SEL_RING3); + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && + dev->has_rro) + mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs, + MT_WFDMA0_RX_INT_SEL_RING6); + else + mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL, + MT_WFDMA0_RX_INT_SEL_RING3); } mt7996_dma_start(dev, reset, true); } +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +int mt7996_dma_rro_init(struct mt7996_dev *dev) +{ + struct mt76_dev *mdev = &dev->mt76; + u32 irq_mask; + int ret; + + /* ind cmd */ + mdev->q_rx[MT_RXQ_RRO_IND].flags = MT_WED_RRO_Q_IND; + mdev->q_rx[MT_RXQ_RRO_IND].wed = &mdev->mmio.wed; + ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_RRO_IND], + MT_RXQ_ID(MT_RXQ_RRO_IND), + MT7996_RX_RING_SIZE, + 0, MT_RXQ_RRO_IND_RING_BASE); + if (ret) + return ret; + + /* rx msdu page queue for band0 */ + mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags = + MT_WED_RRO_Q_MSDU_PG(0) | MT_QFLAG_WED_RRO_EN; + mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].wed = &mdev->mmio.wed; + ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0], + MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0), + MT7996_RX_RING_SIZE, + MT7996_RX_MSDU_PAGE_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0)); + if (ret) + return ret; + + if (dev->dbdc_support) { + /* rx msdu page queue for band1 */ + mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags = + MT_WED_RRO_Q_MSDU_PG(1) | MT_QFLAG_WED_RRO_EN; + mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].wed = &mdev->mmio.wed; + ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1], + MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1), + MT7996_RX_RING_SIZE, + MT7996_RX_MSDU_PAGE_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1)); + if (ret) + return ret; + } + + if (dev->tbtc_support) { + /* rx msdu page queue for band2 */ + mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags = + MT_WED_RRO_Q_MSDU_PG(2) | MT_QFLAG_WED_RRO_EN; + mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].wed = &mdev->mmio.wed; + ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2], + MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2), + MT7996_RX_RING_SIZE, + MT7996_RX_MSDU_PAGE_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2)); + if (ret) + return ret; + } + + irq_mask = mdev->mmio.irqmask | MT_INT_RRO_RX_DONE | + MT_INT_TX_DONE_BAND2; + mt76_wr(dev, MT_INT_MASK_CSR, irq_mask); + mtk_wed_device_start_hw_rro(&mdev->mmio.wed, irq_mask, false); + mt7996_irq_enable(dev, irq_mask); + + return 0; +} +#endif /* CONFIG_NET_MEDIATEK_SOC_WED */ + int mt7996_dma_init(struct mt7996_dev *dev) { struct mtk_wed_device *wed = &dev->mt76.mmio.wed; @@ -356,7 +475,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) return ret; /* tx free notify event from WA for band0 */ - if (mtk_wed_device_active(wed)) { + if (mtk_wed_device_active(wed) && !dev->has_rro) { dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE; dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed; } @@ -372,9 +491,6 @@ int mt7996_dma_init(struct mt7996_dev *dev) if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) { /* rx data queue for band2 */ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs; - if (mtk_wed_device_active(wed)) - rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2); - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2], MT_RXQ_ID(MT_RXQ_BAND2), MT7996_RX_RING_SIZE, @@ -386,7 +502,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) /* tx free notify event from WA for band2 * use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1 */ - if (mtk_wed_device_active(wed_hif2)) { + if (mtk_wed_device_active(wed_hif2) && !dev->has_rro) { dev->mt76.q_rx[MT_RXQ_BAND2_WA].flags = MT_WED_Q_TXFREE; dev->mt76.q_rx[MT_RXQ_BAND2_WA].wed = wed_hif2; } @@ -400,6 +516,60 @@ int mt7996_dma_init(struct mt7996_dev *dev) return ret; } + if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) && + dev->has_rro) { + /* rx rro data queue for band0 */ + dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags = + MT_WED_RRO_Q_DATA(0) | MT_QFLAG_WED_RRO_EN; + dev->mt76.q_rx[MT_RXQ_RRO_BAND0].wed = wed; + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0], + MT_RXQ_ID(MT_RXQ_RRO_BAND0), + MT7996_RX_RING_SIZE, + MT7996_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0)); + if (ret) + return ret; + + /* tx free notify event from WA for band0 */ + dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE; + dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].wed = wed; + + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0], + MT_RXQ_ID(MT_RXQ_TXFREE_BAND0), + MT7996_RX_MCU_RING_SIZE, + MT7996_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0)); + if (ret) + return ret; + + if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) { + /* rx rro data queue for band2 */ + dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags = + MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN; + dev->mt76.q_rx[MT_RXQ_RRO_BAND2].wed = wed; + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2], + MT_RXQ_ID(MT_RXQ_RRO_BAND2), + MT7996_RX_RING_SIZE, + MT7996_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs); + if (ret) + return ret; + + /* tx free notify event from MAC for band2 */ + if (mtk_wed_device_active(wed_hif2)) { + dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].flags = MT_WED_Q_TXFREE; + dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].wed = wed_hif2; + } + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2], + MT_RXQ_ID(MT_RXQ_TXFREE_BAND2), + MT7996_RX_MCU_RING_SIZE, + MT7996_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND2) + hif1_ofs); + if (ret) + return ret; + } + } + ret = mt76_init_queues(dev, mt76_dma_rx_poll); if (ret < 0) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index e19c8fb71609..a1adbc65ae00 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -320,8 +320,17 @@ void mt7996_mac_init(struct mt7996_dev *dev) /* rro module init */ mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2); - mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3); - mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1); + if (dev->has_rro) { + u16 timeout; + + timeout = mt76_rr(dev, MT_HW_REV) == MT_HW_REV1 ? 512 : 128; + mt7996_mcu_set_rro(dev, UNI_RRO_SET_FLUSH_TIMEOUT, timeout); + mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 1); + mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 0); + } else { + mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3); + mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1); + } mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), MCU_WA_PARAM_HW_PATH_HIF_VER, @@ -475,6 +484,163 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev) msleep(20); } +static int mt7996_wed_rro_init(struct mt7996_dev *dev) +{ +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + u32 reg = MT_RRO_ADDR_ELEM_SEG_ADDR0; + struct mt7996_wed_rro_addr *addr; + void *ptr; + int i; + + if (!dev->has_rro) + return 0; + + if (!mtk_wed_device_active(wed)) + return 0; + + for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) { + ptr = dmam_alloc_coherent(dev->mt76.dma_dev, + MT7996_RRO_BA_BITMAP_CR_SIZE, + &dev->wed_rro.ba_bitmap[i].phy_addr, + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + dev->wed_rro.ba_bitmap[i].ptr = ptr; + } + + for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) { + int j; + + ptr = dmam_alloc_coherent(dev->mt76.dma_dev, + MT7996_RRO_WINDOW_MAX_SIZE * sizeof(*addr), + &dev->wed_rro.addr_elem[i].phy_addr, + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + dev->wed_rro.addr_elem[i].ptr = ptr; + memset(dev->wed_rro.addr_elem[i].ptr, 0, + MT7996_RRO_WINDOW_MAX_SIZE * sizeof(*addr)); + + addr = dev->wed_rro.addr_elem[i].ptr; + for (j = 0; j < MT7996_RRO_WINDOW_MAX_SIZE; j++) { + addr->signature = 0xff; + addr++; + } + + wed->wlan.ind_cmd.addr_elem_phys[i] = + dev->wed_rro.addr_elem[i].phy_addr; + } + + ptr = dmam_alloc_coherent(dev->mt76.dma_dev, + MT7996_RRO_WINDOW_MAX_LEN * sizeof(*addr), + &dev->wed_rro.session.phy_addr, + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + dev->wed_rro.session.ptr = ptr; + addr = dev->wed_rro.session.ptr; + for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) { + addr->signature = 0xff; + addr++; + } + + /* rro hw init */ + /* TODO: remove line after WM has set */ + mt76_clear(dev, WF_RRO_AXI_MST_CFG, WF_RRO_AXI_MST_CFG_DIDX_OK); + + /* setup BA bitmap cache address */ + mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0, + dev->wed_rro.ba_bitmap[0].phy_addr); + mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0); + mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0, + dev->wed_rro.ba_bitmap[1].phy_addr); + mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0); + + /* setup Address element address */ + for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) { + mt76_wr(dev, reg, dev->wed_rro.addr_elem[i].phy_addr >> 4); + reg += 4; + } + + /* setup Address element address - separate address segment mode */ + mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1, + MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE); + + wed->wlan.ind_cmd.win_size = ffs(MT7996_RRO_WINDOW_MAX_LEN) - 6; + wed->wlan.ind_cmd.particular_sid = MT7996_RRO_MAX_SESSION; + wed->wlan.ind_cmd.particular_se_phys = dev->wed_rro.session.phy_addr; + wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_LEN; + wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL; + + mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00); + mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1, + MT_RRO_IND_CMD_SIGNATURE_BASE1_EN); + + /* particular session configure */ + /* use max session idx + 1 as particular session id */ + mt76_wr(dev, MT_RRO_PARTICULAR_CFG0, dev->wed_rro.session.phy_addr); + mt76_wr(dev, MT_RRO_PARTICULAR_CFG1, + MT_RRO_PARTICULAR_CONFG_EN | + FIELD_PREP(MT_RRO_PARTICULAR_SID, MT7996_RRO_MAX_SESSION)); + + /* interrupt enable */ + mt76_wr(dev, MT_RRO_HOST_INT_ENA, + MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA); + + /* rro ind cmd queue init */ + return mt7996_dma_rro_init(dev); +#else + return 0; +#endif +} + +static void mt7996_wed_rro_free(struct mt7996_dev *dev) +{ +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + int i; + + if (!dev->has_rro) + return; + + if (!mtk_wed_device_active(&dev->mt76.mmio.wed)) + return; + + for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) { + if (!dev->wed_rro.ba_bitmap[i].ptr) + continue; + + dmam_free_coherent(dev->mt76.dma_dev, + MT7996_RRO_BA_BITMAP_CR_SIZE, + dev->wed_rro.ba_bitmap[i].ptr, + dev->wed_rro.ba_bitmap[i].phy_addr); + } + + for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) { + if (!dev->wed_rro.addr_elem[i].ptr) + continue; + + dmam_free_coherent(dev->mt76.dma_dev, + MT7996_RRO_WINDOW_MAX_SIZE * + sizeof(struct mt7996_wed_rro_addr), + dev->wed_rro.addr_elem[i].ptr, + dev->wed_rro.addr_elem[i].phy_addr); + } + + if (!dev->wed_rro.session.ptr) + return; + + dmam_free_coherent(dev->mt76.dma_dev, + MT7996_RRO_WINDOW_MAX_LEN * + sizeof(struct mt7996_wed_rro_addr), + dev->wed_rro.session.ptr, + dev->wed_rro.session.phy_addr); +#endif +} + static int mt7996_init_hardware(struct mt7996_dev *dev) { int ret, idx; @@ -496,6 +662,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev) if (ret) return ret; + ret = mt7996_wed_rro_init(dev); + if (ret) + return ret; + ret = mt7996_eeprom_init(dev); if (ret < 0) return ret; @@ -934,6 +1104,7 @@ void mt7996_unregister_device(struct mt7996_dev *dev) mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1); mt7996_coredump_unregister(dev); mt76_unregister_device(&dev->mt76); + mt7996_wed_rro_free(dev); mt7996_mcu_exit(dev); mt7996_tx_token_put(dev); mt7996_dma_cleanup(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index fd0f48d7cb91..c79e1b4588b4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -449,8 +449,36 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev, return 0; } +static void +mt7996_wed_check_ppe(struct mt7996_dev *dev, struct mt76_queue *q, + struct mt7996_sta *msta, struct sk_buff *skb, + u32 info) +{ + struct ieee80211_vif *vif; + struct wireless_dev *wdev; + + if (!msta || !msta->vif) + return; + + if (!mt76_queue_is_wed_rx(q)) + return; + + if (!(info & MT_DMA_INFO_PPE_VLD)) + return; + + vif = container_of((void *)msta->vif, struct ieee80211_vif, + drv_priv); + wdev = ieee80211_vif_to_wdev(vif); + skb->dev = wdev->netdev; + + mtk_wed_device_ppe_check(&dev->mt76.mmio.wed, skb, + FIELD_GET(MT_DMA_PPE_CPU_REASON, info), + FIELD_GET(MT_DMA_PPE_ENTRY, info)); +} + static int -mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) +mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, + struct sk_buff *skb, u32 *info) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct mt76_phy *mphy = &dev->mt76.phy; @@ -475,7 +503,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) u16 seq_ctrl = 0; __le16 fc = 0; int idx; + u8 hw_aggr = false; + struct mt7996_sta *msta = NULL; + hw_aggr = status->aggr; memset(status, 0, sizeof(*status)); band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1); @@ -502,8 +533,6 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) status->wcid = mt7996_rx_get_wcid(dev, idx, unicast); if (status->wcid) { - struct mt7996_sta *msta; - msta = container_of(status->wcid, struct mt7996_sta, wcid); spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->wcid.poll_list)) @@ -708,12 +737,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) } } else { status->flag |= RX_FLAG_8023; + mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb, + *info); } if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); - if (!status->wcid || !ieee80211_is_data_qos(fc)) + if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr) return 0; status->aggr = unicast && @@ -1448,7 +1479,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, dev_kfree_skb(skb); break; case PKT_TYPE_NORMAL: - if (!mt7996_mac_fill_rx(dev, skb)) { + if (!mt7996_mac_fill_rx(dev, q, skb, info)) { mt76_rx(&dev->mt76, q, skb); return; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 3ecdc09323c5..5369f0a7800c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -963,7 +963,7 @@ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif) } static int -mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, +mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif *mvif, struct ieee80211_ampdu_params *params, bool enable, bool tx) { @@ -972,7 +972,7 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, struct sk_buff *skb; struct tlv *tlv; - skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid, + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, mvif, wcid, MT7996_STA_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -986,8 +986,9 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, ba->ba_en = enable << params->tid; ba->amsdu = params->amsdu; ba->tid = params->tid; + ba->ba_rdd_rro = !tx && enable && dev->has_rro; - return mt76_mcu_skb_send_msg(dev, skb, + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); } @@ -1002,8 +1003,7 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev, if (enable && !params->amsdu) msta->wcid.amsdu = false; - return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, - enable, true); + return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, true); } int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev, @@ -1013,8 +1013,7 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev, struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv; struct mt7996_vif *mvif = msta->vif; - return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, - enable, false); + return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, false); } static void @@ -4023,10 +4022,8 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val) { struct { u8 __rsv1[4]; - __le16 tag; __le16 len; - union { struct { u8 type; @@ -4041,6 +4038,11 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val) u8 path; u8 __rsv2[3]; } __packed txfree_path; + struct { + __le16 flush_one; + __le16 flush_all; + u8 __rsv2[4]; + } __packed timeout; }; } __packed req = { .tag = cpu_to_le16(tag), @@ -4057,6 +4059,10 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val) case UNI_RRO_SET_TXFREE_PATH: req.txfree_path.path = val; break; + case UNI_RRO_SET_FLUSH_TIMEOUT: + req.timeout.flush_one = cpu_to_le16(val); + req.timeout.flush_all = cpu_to_le16(2 * val); + break; default: return -EINVAL; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index a88f6af323da..a4715b8e005b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h @@ -669,6 +669,8 @@ enum { UNI_RRO_GET_BA_SESSION_TABLE, UNI_RRO_SET_BYPASS_MODE, UNI_RRO_SET_TXFREE_PATH, + UNI_RRO_DEL_BA_SESSION, + UNI_RRO_SET_FLUSH_TIMEOUT }; enum{ diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index ae029ae9969d..c7b6d4bd2ded 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -207,6 +207,8 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, if (!wed_enable) return 0; + dev->has_rro = true; + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); if (hif2) @@ -228,14 +230,27 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs + MT_TXQ_RING_BASE(0) + MT7996_TXQ_BAND2 * MT_RING_SIZE; - wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs + - MT_RXQ_RING_BASE(0) + - MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE; - wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1; + if (dev->has_rro) { + wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs + + MT_RXQ_RING_BASE(0) + + MT7996_RXQ_TXFREE2 * MT_RING_SIZE; + wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1; + } else { + wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs + + MT_RXQ_RING_BASE(0) + + MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE; + wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1; + } + + wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG; + wed->wlan.wpdma_rx = wed->wlan.phy_base + hif1_ofs + + MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) + + MT7996_RXQ_BAND0 * MT_RING_SIZE; wed->wlan.id = 0x7991; wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1; } else { + wed->wlan.hw_rro = dev->has_rro; /* default on */ wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR; wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR; wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) + @@ -247,6 +262,16 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) + MT7996_RXQ_BAND0 * MT_RING_SIZE; + wed->wlan.wpdma_rx_rro[0] = wed->wlan.phy_base + + MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND0) + + MT7996_RXQ_RRO_BAND0 * MT_RING_SIZE; + wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs + + MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) + + MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE; + wed->wlan.wpdma_rx_pg = wed->wlan.phy_base + + MT_RXQ_RING_BASE(MT7996_RXQ_MSDU_PG_BAND0) + + MT7996_RXQ_MSDU_PG_BAND0 * MT_RING_SIZE; + wed->wlan.rx_nbuf = 65536; wed->wlan.rx_npkt = dev->hif2 ? 32768 : 24576; wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE); @@ -254,11 +279,25 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1; wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1; + wed->wlan.rro_rx_tbit[0] = ffs(MT_INT_RX_DONE_RRO_BAND0) - 1; + wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1; + + wed->wlan.rx_pg_tbit[0] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND0) - 1; + wed->wlan.rx_pg_tbit[1] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND1) - 1; + wed->wlan.rx_pg_tbit[2] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND2) - 1; + wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1; wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1; - wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1; - wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) + - MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE; + if (dev->has_rro) { + wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) + + MT7996_RXQ_TXFREE0 * MT_RING_SIZE; + wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1; + } else { + wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1; + wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) + + MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE; + } + dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt; } wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE; @@ -273,8 +312,6 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.offload_enable = mt76_mmio_wed_offload_enable; wed->wlan.offload_disable = mt76_mmio_wed_offload_disable; - dev->mt76.rx_token_size += wed->wlan.rx_npkt; - if (mtk_wed_device_attach(wed)) return 0; @@ -434,10 +471,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t) irqreturn_t mt7996_irq_handler(int irq, void *dev_instance) { struct mt7996_dev *dev = dev_instance; - struct mtk_wed_device *wed = &dev->mt76.mmio.wed; - if (mtk_wed_device_active(wed)) - mtk_wed_device_irq_set_mask(wed, 0); + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed, 0); else mt76_wr(dev, MT_INT_MASK_CSR, 0); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index d4425c133ced..f7b6945b7acc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -50,6 +50,22 @@ #define MT7996_BASIC_RATES_TBL 11 #define MT7996_BEACON_RATES_TBL 25 +#define MT7996_RRO_MAX_SESSION 1024 +#define MT7996_RRO_WINDOW_MAX_LEN 1024 +#define MT7996_RRO_ADDR_ELEM_LEN 128 +#define MT7996_RRO_BA_BITMAP_LEN 2 +#define MT7996_RRO_BA_BITMAP_CR_SIZE ((MT7996_RRO_MAX_SESSION * 128) / \ + MT7996_RRO_BA_BITMAP_LEN) +#define MT7996_RRO_BA_BITMAP_SESSION_SIZE (MT7996_RRO_MAX_SESSION / \ + MT7996_RRO_ADDR_ELEM_LEN) +#define MT7996_RRO_WINDOW_MAX_SIZE (MT7996_RRO_WINDOW_MAX_LEN * \ + MT7996_RRO_BA_BITMAP_SESSION_SIZE) + +#define MT7996_RX_BUF_SIZE (1800 + \ + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) +#define MT7996_RX_MSDU_PAGE_SIZE (128 + \ + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) + struct mt7996_vif; struct mt7996_sta; struct mt7996_dfs_pulse; @@ -79,6 +95,16 @@ enum mt7996_rxq_id { MT7996_RXQ_BAND0 = 4, MT7996_RXQ_BAND1 = 4,/* unused */ MT7996_RXQ_BAND2 = 5, + MT7996_RXQ_RRO_BAND0 = 8, + MT7996_RXQ_RRO_BAND1 = 8,/* unused */ + MT7996_RXQ_RRO_BAND2 = 6, + MT7996_RXQ_MSDU_PG_BAND0 = 10, + MT7996_RXQ_MSDU_PG_BAND1 = 11, + MT7996_RXQ_MSDU_PG_BAND2 = 12, + MT7996_RXQ_TXFREE0 = 9, + MT7996_RXQ_TXFREE1 = 9, + MT7996_RXQ_TXFREE2 = 7, + MT7996_RXQ_RRO_IND = 0, }; struct mt7996_twt_flow { @@ -147,6 +173,15 @@ struct mt7996_hif { int irq; }; +struct mt7996_wed_rro_addr { + u32 head_low; + u32 head_high : 4; + u32 count: 11; + u32 oor: 1; + u32 rsv : 8; + u32 signature : 8; +}; + struct mt7996_phy { struct mt76_phy *mt76; struct mt7996_dev *dev; @@ -226,6 +261,22 @@ struct mt7996_dev { bool tbtc_support:1; bool flash_mode:1; bool has_eht:1; + bool has_rro:1; + + struct { + struct { + void *ptr; + dma_addr_t phy_addr; + } ba_bitmap[MT7996_RRO_BA_BITMAP_LEN]; + struct { + void *ptr; + dma_addr_t phy_addr; + } addr_elem[MT7996_RRO_ADDR_ELEM_LEN]; + struct { + void *ptr; + dma_addr_t phy_addr; + } session; + } wed_rro; bool ibf; u8 fw_debug_wm; @@ -506,4 +557,8 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id); int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir); #endif +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +int mt7996_dma_rro_init(struct mt7996_dev *dev); +#endif /* CONFIG_NET_MEDIATEK_SOC_WED */ + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index b7d78adce11a..7cefe8985590 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -39,6 +39,38 @@ enum base_rev { #define __BASE(_id, _band) (dev->reg.base[(_id)].band_base[(_band)]) +/* RRO TOP */ +#define MT_RRO_TOP_BASE 0xA000 +#define MT_RRO_TOP(ofs) (MT_RRO_TOP_BASE + (ofs)) + +#define MT_RRO_BA_BITMAP_BASE0 MT_RRO_TOP(0x8) +#define MT_RRO_BA_BITMAP_BASE1 MT_RRO_TOP(0xC) +#define WF_RRO_AXI_MST_CFG MT_RRO_TOP(0xB8) +#define WF_RRO_AXI_MST_CFG_DIDX_OK BIT(12) +#define MT_RRO_ADDR_ARRAY_BASE1 MT_RRO_TOP(0x34) +#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE BIT(31) + +#define MT_RRO_IND_CMD_SIGNATURE_BASE0 MT_RRO_TOP(0x38) +#define MT_RRO_IND_CMD_SIGNATURE_BASE1 MT_RRO_TOP(0x3C) +#define MT_RRO_IND_CMD_0_CTRL0 MT_RRO_TOP(0x40) +#define MT_RRO_IND_CMD_SIGNATURE_BASE1_EN BIT(31) + +#define MT_RRO_PARTICULAR_CFG0 MT_RRO_TOP(0x5C) +#define MT_RRO_PARTICULAR_CFG1 MT_RRO_TOP(0x60) +#define MT_RRO_PARTICULAR_CONFG_EN BIT(31) +#define MT_RRO_PARTICULAR_SID GENMASK(30, 16) + +#define MT_RRO_BA_BITMAP_BASE_EXT0 MT_RRO_TOP(0x70) +#define MT_RRO_BA_BITMAP_BASE_EXT1 MT_RRO_TOP(0x74) +#define MT_RRO_HOST_INT_ENA MT_RRO_TOP(0x204) +#define MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA BIT(0) + +#define MT_RRO_ADDR_ELEM_SEG_ADDR0 MT_RRO_TOP(0x400) + +#define MT_RRO_ACK_SN_CTRL MT_RRO_TOP(0x50) +#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16) +#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0) + #define MT_MCU_INT_EVENT 0x2108 #define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0) #define MT_MCU_INT_EVENT_DMA_INIT BIT(1) @@ -398,6 +430,7 @@ enum base_rev { #define MT_MCUQ_RING_BASE(q) (MT_Q_BASE(q) + 0x300) #define MT_TXQ_RING_BASE(q) (MT_Q_BASE(__TXQ(q)) + 0x300) #define MT_RXQ_RING_BASE(q) (MT_Q_BASE(__RXQ(q)) + 0x500) +#define MT_RXQ_RRO_IND_RING_BASE MT_RRO_TOP(0x40) #define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \ MT_MCUQ_ID(q) * 0x4) @@ -425,6 +458,14 @@ enum base_rev { #define MT_INT_MCU_CMD BIT(29) #define MT_INT_RX_TXFREE_EXT BIT(26) +#define MT_INT_RX_DONE_RRO_BAND0 BIT(16) +#define MT_INT_RX_DONE_RRO_BAND1 BIT(16) +#define MT_INT_RX_DONE_RRO_BAND2 BIT(14) +#define MT_INT_RX_DONE_RRO_IND BIT(11) +#define MT_INT_RX_DONE_MSDU_PG_BAND0 BIT(18) +#define MT_INT_RX_DONE_MSDU_PG_BAND1 BIT(19) +#define MT_INT_RX_DONE_MSDU_PG_BAND2 BIT(23) + #define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)]) #define MT_INT_TX_MCU(q) (dev->q_int_mask[(q)]) @@ -432,20 +473,31 @@ enum base_rev { MT_INT_RX(MT_RXQ_MCU_WA)) #define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \ - MT_INT_RX(MT_RXQ_MAIN_WA)) + MT_INT_RX(MT_RXQ_MAIN_WA) | \ + MT_INT_RX(MT_RXQ_TXFREE_BAND0)) #define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \ MT_INT_RX(MT_RXQ_BAND1_WA) | \ - MT_INT_RX(MT_RXQ_MAIN_WA)) + MT_INT_RX(MT_RXQ_MAIN_WA) | \ + MT_INT_RX(MT_RXQ_TXFREE_BAND0)) #define MT_INT_BAND2_RX_DONE (MT_INT_RX(MT_RXQ_BAND2) | \ MT_INT_RX(MT_RXQ_BAND2_WA) | \ - MT_INT_RX(MT_RXQ_MAIN_WA)) + MT_INT_RX(MT_RXQ_MAIN_WA) | \ + MT_INT_RX(MT_RXQ_TXFREE_BAND0)) + +#define MT_INT_RRO_RX_DONE (MT_INT_RX(MT_RXQ_RRO_BAND0) | \ + MT_INT_RX(MT_RXQ_RRO_BAND1) | \ + MT_INT_RX(MT_RXQ_RRO_BAND2) | \ + MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND0) | \ + MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND1) | \ + MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2)) #define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \ MT_INT_BAND0_RX_DONE | \ MT_INT_BAND1_RX_DONE | \ - MT_INT_BAND2_RX_DONE) + MT_INT_BAND2_RX_DONE | \ + MT_INT_RRO_RX_DONE) #define MT_INT_TX_DONE_FWDL BIT(26) #define MT_INT_TX_DONE_MCU_WM BIT(27) @@ -558,6 +610,8 @@ enum base_rev { #define MT_TOP_MISC_FW_STATE GENMASK(2, 0) #define MT_HW_REV 0x70010204 +#define MT_HW_REV1 0x8a00 + #define MT_WF_SUBSYS_RST 0x70028600 /* PCIE MAC */ From patchwork Fri Oct 20 10:30:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430520 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36959C004C0 for ; Fri, 20 Oct 2023 10:32:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376890AbjJTKcH (ORCPT ); Fri, 20 Oct 2023 06:32:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51900 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376891AbjJTKcE (ORCPT ); Fri, 20 Oct 2023 06:32:04 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D31A1D5D for ; Fri, 20 Oct 2023 03:32:02 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1132BC433C9; Fri, 20 Oct 2023 10:32:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797922; bh=iCDbtoqp4JDm0LxlvrH53ccqWCzQRCqkN4LJ47GsAos=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KmNVVUSticFMQFchd+1r6NubLiXUcT9vK5ytmxJHPKrdIUFBwujIkJBQqZ0yi+Qo8 4hXm5+JnISVOwC7QGtSjKRxc8EUpPvB5nP5yTFfh406Ynqj7QT2v5BDmDzmUB8r4O7 PtsmZ0ZGxUkIV1OiZtOgEAU0YKUrqrkUKpWDi6QOudUjR10yGn8H0yohraxzlSSAFT RGpWPVwwNUVwTqCBw72nu4Sv5AVbAXj/LhZfqo2PUsyeUJ1ISHjxX2v2TtQmyTnCXj FUD2BIBXvy7RbJoGxTcNoFGm0FOTr4KJ+28i6QqWU071cgQgYX0JHwV7+1JLYbVrJE nx/uxoMhqkzRA== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 11/13] mt76: move wed reset common code in mt76 module Date: Fri, 20 Oct 2023 12:30:58 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Move WED reset code shared between mt7915 and mt7996 in common module. This is a preliminary patch to introduce WED reset support for mt7996. Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/dma.c | 14 ++++++++++ drivers/net/wireless/mediatek/mt76/dma.h | 9 ++++++ drivers/net/wireless/mediatek/mt76/mmio.c | 8 ++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7915/dma.c | 28 ++----------------- .../net/wireless/mediatek/mt76/mt7915/mmio.c | 9 +----- 6 files changed, 36 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index e60012a1896b..71f07deeeaab 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -1036,6 +1036,20 @@ void mt76_dma_attach(struct mt76_dev *dev) } EXPORT_SYMBOL_GPL(mt76_dma_attach); +void mt76_dma_wed_reset(struct mt76_dev *dev) +{ + struct mt76_mmio *mmio = &dev->mmio; + + if (!test_bit(MT76_STATE_WED_RESET, &dev->phy.state)) + return; + + complete(&mmio->wed_reset); + + if (!wait_for_completion_timeout(&mmio->wed_reset_complete, 3 * HZ)) + dev_err(dev->dev, "wed reset complete timeout\n"); +} +EXPORT_SYMBOL_GPL(mt76_dma_wed_reset); + void mt76_dma_cleanup(struct mt76_dev *dev) { int i; diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h index e549e678b69f..c60dfb817227 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.h +++ b/drivers/net/wireless/mediatek/mt76/dma.h @@ -78,6 +78,15 @@ int mt76_dma_rx_poll(struct napi_struct *napi, int budget); void mt76_dma_attach(struct mt76_dev *dev); void mt76_dma_cleanup(struct mt76_dev *dev); int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset); +void mt76_dma_wed_reset(struct mt76_dev *dev); + +static inline void +mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q) +{ + dev->queue_ops->reset_q(dev, q); + if (mtk_wed_device_active(&dev->mmio.wed)) + mt76_dma_wed_setup(dev, q, true); +} static inline void mt76_dma_should_drop_buf(bool *drop, u32 ctrl, u32 buf1, u32 info) diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index c34624978a14..4a006409a373 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -179,6 +179,14 @@ void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed) spin_unlock_bh(&dev->token_lock); } EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_disable); + +void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + + complete(&dev->mmio.wed_reset_complete); +} +EXPORT_SYMBOL_GPL(mt76_mmio_wed_reset_complete); #endif /*CONFIG_NET_MEDIATEK_SOC_WED */ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index f015c94b3c68..482a280b7c25 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1102,6 +1102,7 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size); void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed); int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed); void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed); +void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed); #endif /*CONFIG_NET_MEDIATEK_SOC_WED */ #define mt76xx_chip(dev) mt76_chip(&((dev)->mt76)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index 1bceeb5227b1..c91a1c54027f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -587,28 +587,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) return 0; } -static void mt7915_dma_wed_reset(struct mt7915_dev *dev) -{ - struct mt76_dev *mdev = &dev->mt76; - - if (!test_bit(MT76_STATE_WED_RESET, &dev->mphy.state)) - return; - - complete(&mdev->mmio.wed_reset); - - if (!wait_for_completion_timeout(&dev->mt76.mmio.wed_reset_complete, - 3 * HZ)) - dev_err(dev->mt76.dev, "wed reset complete timeout\n"); -} - -static void -mt7915_dma_reset_tx_queue(struct mt7915_dev *dev, struct mt76_queue *q) -{ - mt76_queue_reset(dev, q); - if (mtk_wed_device_active(&dev->mt76.mmio.wed)) - mt76_dma_wed_setup(&dev->mt76, q, true); -} - int mt7915_dma_reset(struct mt7915_dev *dev, bool force) { struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1]; @@ -636,13 +614,13 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force) mtk_wed_device_dma_reset(wed); mt7915_dma_disable(dev, force); - mt7915_dma_wed_reset(dev); + mt76_dma_wed_reset(&dev->mt76); /* reset hw queues */ for (i = 0; i < __MT_TXQ_MAX; i++) { - mt7915_dma_reset_tx_queue(dev, dev->mphy.q_tx[i]); + mt76_dma_reset_tx_queue(&dev->mt76, dev->mphy.q_tx[i]); if (mphy_ext) - mt7915_dma_reset_tx_queue(dev, mphy_ext->q_tx[i]); + mt76_dma_reset_tx_queue(&dev->mt76, mphy_ext->q_tx[i]); } for (i = 0; i < __MT_MCUQ_MAX; i++) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 85cb3fed9505..c404c90b58a6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -595,13 +595,6 @@ static int mt7915_mmio_wed_reset(struct mtk_wed_device *wed) return ret; } - -static void mt7915_mmio_wed_reset_complete(struct mtk_wed_device *wed) -{ - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); - - complete(&dev->mmio.wed_reset_complete); -} #endif int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, @@ -685,7 +678,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf; wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats; wed->wlan.reset = mt7915_mmio_wed_reset; - wed->wlan.reset_complete = mt7915_mmio_wed_reset_complete; + wed->wlan.reset_complete = mt76_mmio_wed_reset_complete; dev->mt76.rx_token_size = wed->wlan.rx_npkt; From patchwork Fri Oct 20 10:30:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430519 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C1366C07480 for ; Fri, 20 Oct 2023 10:32:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376893AbjJTKcJ (ORCPT ); Fri, 20 Oct 2023 06:32:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58516 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376891AbjJTKcI (ORCPT ); Fri, 20 Oct 2023 06:32:08 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 56CE3D65 for ; Fri, 20 Oct 2023 03:32:06 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9AFCBC433C7; Fri, 20 Oct 2023 10:32:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797926; bh=Ak0QFvH77MLGFgfI6JsaCzO9S99tDGkLifJGZt947IY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lhuiGIhUzxgukmusaP2XNBwoL70Kpo6w9uu9yZNhoabUY3PtmldJLzk+lFcyjmveb ZhP/jt50p/XxFPFmi6ynS0pVaAotoQMBekuJBNGi5v63p+bS5BBFEAd1eTf5xJyeSU UlxGQnBEtTzVMfzUCMxeb5+fsHNq7KgtEgS8X9fZr1sVxSlZcZ4jEQqkRCRR4r5e5p HgJ5t6BuspgVYtEHlRASznZiDw8XXoqOQgEVCTNIvvsu0RbTu9gnB1pWb+D42XXd2d DH3BzZ5iXHTdTZsYpt4eQcprAH0leAz8bHF8zLwdLJ9l6I1maYs/sJT4lJYuPnjCwy Y68uaYnoqbHDg== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 12/13] mt76: mt7996: add wed reset support Date: Fri, 20 Oct 2023 12:30:59 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Introduce the capability to reset mt7996 chipset if requested by wed driver. Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/dma.c | 14 ++++-- .../net/wireless/mediatek/mt76/mt7996/dma.c | 18 +++++-- .../net/wireless/mediatek/mt76/mt7996/mac.c | 47 ++++++++++++++++++- .../net/wireless/mediatek/mt76/mt7996/mmio.c | 37 +++++++++++++++ .../net/wireless/mediatek/mt76/mt7996/regs.h | 7 ++- 5 files changed, 114 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 71f07deeeaab..d0067b8dbbc8 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -854,10 +854,16 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) /* reset WED rx queues */ mt76_dma_wed_setup(dev, q, true); - if (!mt76_queue_is_wed_tx_free(q)) { - mt76_dma_sync_idx(dev, q); - mt76_dma_rx_fill(dev, q, false); - } + + if (mt76_queue_is_wed_tx_free(q)) + return; + + if (mtk_wed_device_active(&dev->mmio.wed) && + mt76_queue_is_wed_rro(q)) + return; + + mt76_dma_sync_idx(dev, q); + mt76_dma_rx_fill(dev, q, false); } static void diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c index 2221d22ccffb..8bc08d993085 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c @@ -621,21 +621,33 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force) if (force) mt7996_wfsys_reset(dev); + if (dev->hif2 && mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) + mtk_wed_device_dma_reset(&dev->mt76.mmio.wed_hif2); + + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + mtk_wed_device_dma_reset(&dev->mt76.mmio.wed); + mt7996_dma_disable(dev, force); + mt76_dma_wed_reset(&dev->mt76); /* reset hw queues */ for (i = 0; i < __MT_TXQ_MAX; i++) { - mt76_queue_reset(dev, dev->mphy.q_tx[i]); + mt76_dma_reset_tx_queue(&dev->mt76, dev->mphy.q_tx[i]); if (phy2) - mt76_queue_reset(dev, phy2->q_tx[i]); + mt76_dma_reset_tx_queue(&dev->mt76, phy2->q_tx[i]); if (phy3) - mt76_queue_reset(dev, phy3->q_tx[i]); + mt76_dma_reset_tx_queue(&dev->mt76, phy3->q_tx[i]); } for (i = 0; i < __MT_MCUQ_MAX; i++) mt76_queue_reset(dev, dev->mt76.q_mcu[i]); mt76_for_each_q_rx(&dev->mt76, i) { + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + if (mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]) || + mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i])) + continue; + mt76_queue_reset(dev, &dev->mt76.q_rx[i]); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index c79e1b4588b4..236a88b50e97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1712,6 +1712,10 @@ mt7996_mac_restart(struct mt7996_dev *dev) /* disable all tx/rx napi */ mt76_worker_disable(&dev->mt76.tx_worker); mt76_for_each_q_rx(mdev, i) { + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && + mt76_queue_is_wed_rro(&mdev->q_rx[i])) + continue; + if (mdev->q_rx[i].ndesc) napi_disable(&dev->mt76.napi[i]); } @@ -1725,6 +1729,10 @@ mt7996_mac_restart(struct mt7996_dev *dev) local_bh_disable(); mt76_for_each_q_rx(mdev, i) { + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && + mt76_queue_is_wed_rro(&mdev->q_rx[i])) + continue; + if (mdev->q_rx[i].ndesc) { napi_enable(&dev->mt76.napi[i]); napi_schedule(&dev->mt76.napi[i]); @@ -1896,6 +1904,13 @@ void mt7996_mac_reset_work(struct work_struct *work) dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.", wiphy_name(dev->mt76.hw->wiphy)); + + if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) + mtk_wed_device_stop(&dev->mt76.mmio.wed_hif2); + + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + mtk_wed_device_stop(&dev->mt76.mmio.wed); + ieee80211_stop_queues(mt76_hw(dev)); if (phy2) ieee80211_stop_queues(phy2->mt76->hw); @@ -1915,8 +1930,13 @@ void mt7996_mac_reset_work(struct work_struct *work) cancel_delayed_work_sync(&phy3->mt76->mac_work); } mt76_worker_disable(&dev->mt76.tx_worker); - mt76_for_each_q_rx(&dev->mt76, i) + mt76_for_each_q_rx(&dev->mt76, i) { + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && + mt76_queue_is_wed_rro(&dev->mt76.q_rx[i])) + continue; + napi_disable(&dev->mt76.napi[i]); + } napi_disable(&dev->mt76.tx_napi); mutex_lock(&dev->mt76.mutex); @@ -1939,6 +1959,27 @@ void mt7996_mac_reset_work(struct work_struct *work) /* enable DMA Tx/Tx and interrupt */ mt7996_dma_start(dev, false, false); + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + u32 wed_irq_mask = MT_INT_RRO_RX_DONE | MT_INT_TX_DONE_BAND2 | + dev->mt76.mmio.irqmask; + + if (mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) + wed_irq_mask &= ~MT_INT_RX_DONE_RRO_IND; + + mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask); + + mtk_wed_device_start_hw_rro(&dev->mt76.mmio.wed, wed_irq_mask, + true); + mt7996_irq_enable(dev, wed_irq_mask); + mt7996_irq_disable(dev, 0); + } + + if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) { + mt76_wr(dev, MT_INT_PCIE1_MASK_CSR, MT_INT_TX_RX_DONE_EXT); + mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, + MT_INT_TX_RX_DONE_EXT); + } + clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); if (phy2) @@ -1948,6 +1989,10 @@ void mt7996_mac_reset_work(struct work_struct *work) local_bh_disable(); mt76_for_each_q_rx(&dev->mt76, i) { + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && + mt76_queue_is_wed_rro(&dev->mt76.q_rx[i])) + continue; + napi_enable(&dev->mt76.napi[i]); napi_schedule(&dev->mt76.napi[i]); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index c7b6d4bd2ded..739d7f53d347 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -6,9 +6,11 @@ #include #include #include +#include #include "mt7996.h" #include "mac.h" +#include "mcu.h" #include "../trace.h" #include "../dma.h" @@ -195,6 +197,37 @@ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) return dev->bus_ops->rmw(mdev, __mt7996_reg_addr(dev, offset), mask, val); } +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed) +{ + struct mt76_dev *mdev = container_of(wed, struct mt76_dev, mmio.wed); + struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); + struct mt76_phy *mphy = &dev->mphy; + int ret; + + ASSERT_RTNL(); + + if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state)) + return -EBUSY; + + ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1, + mphy->band_idx); + if (ret) + goto out; + + rtnl_unlock(); + if (!wait_for_completion_timeout(&mdev->mmio.wed_reset, 20 * HZ)) { + dev_err(mdev->dev, "wed reset timeout\n"); + ret = -ETIMEDOUT; + } + rtnl_lock(); +out: + clear_bit(MT76_STATE_WED_RESET, &mphy->state); + + return ret; +} +#endif + int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, bool hif2, int *irq) { @@ -311,6 +344,10 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf; wed->wlan.offload_enable = mt76_mmio_wed_offload_enable; wed->wlan.offload_disable = mt76_mmio_wed_offload_disable; + if (!hif2) { + wed->wlan.reset = mt7996_mmio_wed_reset; + wed->wlan.reset_complete = mt76_mmio_wed_reset_complete; + } if (mtk_wed_device_attach(wed)) return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 7cefe8985590..49eb583399c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -455,8 +455,9 @@ enum base_rev { #define MT_INT_RX_DONE_WA_TRI BIT(3) #define MT_INT_RX_TXFREE_MAIN BIT(17) #define MT_INT_RX_TXFREE_TRI BIT(15) -#define MT_INT_MCU_CMD BIT(29) +#define MT_INT_RX_DONE_BAND2_EXT BIT(23) #define MT_INT_RX_TXFREE_EXT BIT(26) +#define MT_INT_MCU_CMD BIT(29) #define MT_INT_RX_DONE_RRO_BAND0 BIT(16) #define MT_INT_RX_DONE_RRO_BAND1 BIT(16) @@ -506,6 +507,10 @@ enum base_rev { #define MT_INT_TX_DONE_BAND1 BIT(31) #define MT_INT_TX_DONE_BAND2 BIT(15) +#define MT_INT_TX_RX_DONE_EXT (MT_INT_TX_DONE_BAND2 | \ + MT_INT_RX_DONE_BAND2_EXT | \ + MT_INT_RX_TXFREE_EXT) + #define MT_INT_TX_DONE_MCU (MT_INT_TX_MCU(MT_MCUQ_WA) | \ MT_INT_TX_MCU(MT_MCUQ_WM) | \ MT_INT_TX_MCU(MT_MCUQ_FWDL)) From patchwork Fri Oct 20 10:31:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 13430521 X-Patchwork-Delegate: nbd@nbd.name Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 10194CDB474 for ; Fri, 20 Oct 2023 10:32:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376901AbjJTKcM (ORCPT ); Fri, 20 Oct 2023 06:32:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58586 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376891AbjJTKcM (ORCPT ); Fri, 20 Oct 2023 06:32:12 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CEA5CD60 for ; Fri, 20 Oct 2023 03:32:09 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 25C17C433C8; Fri, 20 Oct 2023 10:32:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1697797929; bh=wvRbHHAfmjeCx/FVVRZGvK+V2crX0gO3730CFi4KY+Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=C9WUbvbB18BbhwGx73/AG+X4/k0y3nIC4SEDAM/RFXyc9Ey842sr4ogs1y8AkA1a5 da3Zz+2bAL9X9L7+YZJNmRjgG5kYACb6QA8nyOYEnLwBkJ8yFrpY8I8vmrXt67g6p8 InSakJcZLHWK21U+utaNlxmFVjuGA4Fk0ZSDbZ4ulcznyHQkEdMkwrwjcWMC5GzkFd KsBcL4g1TUIld9/fzXu1wq0FEl4bmI0UA3NDOeGiLv3QixmfEkNiiChyu7HZfC3iEo fh/3FatjLk5aIJMfRtc2cgvQ+nn0aTpoae9lMs51i3eut6e0VoON/oYhkl7VX7HupL AQxj9POzcv9bQ== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org, ryder.lee@mediatek.com, evelyn.tsai@mediatek.com, shayne.chen@mediatek.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, linux-mediatek@lists.infradead.org Subject: [PATCH v3 13/13] wifi: mt76: mt7996: add wed rro delete session garbage collector Date: Fri, 20 Oct 2023 12:31:00 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Introduce the capability to clear WED rro session configured in the hw according to the event reported by the MCU firmware Co-developed-by: Sujuan Chen Signed-off-by: Sujuan Chen Co-developed-by: Bo Jiao Signed-off-by: Bo Jiao Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../wireless/mediatek/mt76/mt76_connac_mcu.h | 1 + .../net/wireless/mediatek/mt76/mt7996/init.c | 52 +++++++++++ .../net/wireless/mediatek/mt76/mt7996/mac.c | 3 + .../net/wireless/mediatek/mt76/mt7996/mcu.c | 89 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7996/mcu.h | 35 ++++++++ .../wireless/mediatek/mt76/mt7996/mt7996.h | 10 +++ .../net/wireless/mediatek/mt76/mt7996/regs.h | 6 ++ 8 files changed, 197 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 482a280b7c25..f88192c402e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -404,6 +404,7 @@ struct mt76_rx_tid { spinlock_t lock; struct delayed_work reorder_work; + u16 id; u16 head; u16 size; u16 nframes; diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 0563b1b22f48..97822f7d46cc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -1022,6 +1022,7 @@ enum { MCU_UNI_EVENT_ROC = 0x27, MCU_UNI_EVENT_TX_DONE = 0x2d, MCU_UNI_EVENT_NIC_CAPAB = 0x43, + MCU_UNI_EVENT_WED_RRO = 0x57, MCU_UNI_EVENT_PER_STA_INFO = 0x6d, MCU_UNI_EVENT_ALL_STA_INFO = 0x6e, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index a1adbc65ae00..5af85ddfdc36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -641,6 +641,54 @@ static void mt7996_wed_rro_free(struct mt7996_dev *dev) #endif } +static void mt7996_wed_rro_work(struct work_struct *work) +{ +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + struct mt7996_dev *dev; + LIST_HEAD(list); + + dev = (struct mt7996_dev *)container_of(work, struct mt7996_dev, + wed_rro.work); + + spin_lock_bh(&dev->wed_rro.lock); + list_splice_init(&dev->wed_rro.poll_list, &list); + spin_unlock_bh(&dev->wed_rro.lock); + + while (!list_empty(&list)) { + struct mt7996_wed_rro_session_id *e; + int i; + + e = list_first_entry(&list, struct mt7996_wed_rro_session_id, + list); + list_del_init(&e->list); + + for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) { + void *ptr = dev->wed_rro.session.ptr; + struct mt7996_wed_rro_addr *elem; + u32 idx, elem_id = i; + + if (e->id == MT7996_RRO_MAX_SESSION) + goto reset; + + idx = e->id / MT7996_RRO_BA_BITMAP_SESSION_SIZE; + if (idx >= ARRAY_SIZE(dev->wed_rro.addr_elem)) + goto out; + + ptr = dev->wed_rro.addr_elem[idx].ptr; + elem_id += + (e->id % MT7996_RRO_BA_BITMAP_SESSION_SIZE) * + MT7996_RRO_WINDOW_MAX_LEN; +reset: + elem = ptr + elem_id * sizeof(*elem); + elem->signature = 0xff; + } + mt7996_mcu_wed_rro_reset_sessions(dev, e->id); +out: + kfree(e); + } +#endif +} + static int mt7996_init_hardware(struct mt7996_dev *dev) { int ret, idx; @@ -648,6 +696,9 @@ static int mt7996_init_hardware(struct mt7996_dev *dev) mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); INIT_WORK(&dev->init_work, mt7996_init_work); + INIT_WORK(&dev->wed_rro.work, mt7996_wed_rro_work); + INIT_LIST_HEAD(&dev->wed_rro.poll_list); + spin_lock_init(&dev->wed_rro.lock); dev->dbdc_support = true; dev->tbtc_support = true; @@ -1100,6 +1151,7 @@ int mt7996_register_device(struct mt7996_dev *dev) void mt7996_unregister_device(struct mt7996_dev *dev) { + cancel_work_sync(&dev->wed_rro.work); mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2); mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1); mt7996_coredump_unregister(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 236a88b50e97..7e896af29404 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1822,6 +1822,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev) if (phy3) ieee80211_stop_queues(phy3->mt76->hw); + cancel_work_sync(&dev->wed_rro.work); cancel_delayed_work_sync(&dev->mphy.mac_work); if (phy2) cancel_delayed_work_sync(&phy2->mt76->mac_work); @@ -1920,6 +1921,8 @@ void mt7996_mac_reset_work(struct work_struct *work) set_bit(MT76_RESET, &dev->mphy.state); set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); + + cancel_work_sync(&dev->wed_rro.work); cancel_delayed_work_sync(&dev->mphy.mac_work); if (phy2) { set_bit(MT76_RESET, &phy2->mt76->state); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 5369f0a7800c..61de5e041627 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -526,6 +526,73 @@ mt7996_mcu_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb) dev_kfree_skb(skb); } +static void +mt7996_mcu_wed_rro_event(struct mt7996_dev *dev, struct sk_buff *skb) +{ + struct mt7996_mcu_wed_rro_event *event = (void *)skb->data; + + if (!dev->has_rro) + return; + + skb_pull(skb, sizeof(struct mt7996_mcu_rxd) + 4); + + switch (event->tag) { + case UNI_WED_RRO_BA_SESSION_STATUS: { + struct mt7996_mcu_wed_rro_ba_event *e; + + while (skb->len >= sizeof(*e)) { + struct mt76_rx_tid *tid; + struct mt76_wcid *wcid; + u16 idx; + + e = (void *)skb->data; + idx = le16_to_cpu(e->wlan_id); + if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + break; + + wcid = rcu_dereference(dev->mt76.wcid[idx]); + if (!wcid || !wcid->sta) + break; + + if (e->tid >= ARRAY_SIZE(wcid->aggr)) + break; + + tid = rcu_dereference(wcid->aggr[e->tid]); + if (!tid) + break; + + tid->id = le16_to_cpu(e->id); + skb_pull(skb, sizeof(*e)); + } + break; + } + case UNI_WED_RRO_BA_SESSION_DELETE: { + struct mt7996_mcu_wed_rro_ba_delete_event *e; + + while (skb->len >= sizeof(*e)) { + struct mt7996_wed_rro_session_id *session; + + e = (void *)skb->data; + session = kzalloc(sizeof(*session), GFP_ATOMIC); + if (!session) + break; + + session->id = le16_to_cpu(e->session_id); + + spin_lock_bh(&dev->wed_rro.lock); + list_add_tail(&session->list, &dev->wed_rro.poll_list); + spin_unlock_bh(&dev->wed_rro.lock); + + ieee80211_queue_work(mt76_hw(dev), &dev->wed_rro.work); + skb_pull(skb, sizeof(*e)); + } + break; + } + default: + break; + } +} + static void mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb) { @@ -544,6 +611,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb) case MCU_UNI_EVENT_ALL_STA_INFO: mt7996_mcu_rx_all_sta_info_event(dev, skb); break; + case MCU_UNI_EVENT_WED_RRO: + mt7996_mcu_wed_rro_event(dev, skb); + break; default: break; } @@ -4087,3 +4157,22 @@ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag) return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO), &req, sizeof(req), false); } + +int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id) +{ + struct { + u8 __rsv[4]; + + __le16 tag; + __le16 len; + __le16 session_id; + u8 pad[4]; + } __packed req = { + .tag = cpu_to_le16(UNI_RRO_DEL_BA_SESSION), + .len = cpu_to_le16(sizeof(req) - 4), + .session_id = cpu_to_le16(id), + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req, + sizeof(req), true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index a4715b8e005b..e32a78d6622b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h @@ -179,6 +179,41 @@ struct mt7996_mcu_all_sta_info_event { }; } __packed; +struct mt7996_mcu_wed_rro_event { + struct mt7996_mcu_rxd rxd; + + u8 __rsv1[4]; + + __le16 tag; + __le16 len; +} __packed; + +struct mt7996_mcu_wed_rro_ba_event { + __le16 tag; + __le16 len; + + __le16 wlan_id; + u8 tid; + u8 __rsv1; + __le32 status; + __le16 id; + u8 __rsv2[2]; +} __packed; + +struct mt7996_mcu_wed_rro_ba_delete_event { + __le16 tag; + __le16 len; + + __le16 session_id; + u8 __rsv2[2]; +} __packed; + +enum { + UNI_WED_RRO_BA_SESSION_STATUS, + UNI_WED_RRO_BA_SESSION_TBL, + UNI_WED_RRO_BA_SESSION_DELETE, +}; + enum mt7996_chan_mib_offs { UNI_MIB_OBSS_AIRTIME = 26, UNI_MIB_NON_WIFI_TIME = 27, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index f7b6945b7acc..e7818b2b253f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -182,6 +182,11 @@ struct mt7996_wed_rro_addr { u32 signature : 8; }; +struct mt7996_wed_rro_session_id { + struct list_head list; + u16 id; +}; + struct mt7996_phy { struct mt76_phy *mt76; struct mt7996_dev *dev; @@ -276,6 +281,10 @@ struct mt7996_dev { void *ptr; dma_addr_t phy_addr; } session; + + struct work_struct work; + struct list_head poll_list; + spinlock_t lock; } wed_rro; bool ibf; @@ -456,6 +465,7 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev); void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb); void mt7996_mcu_exit(struct mt7996_dev *dev); int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag); +int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id); static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 49eb583399c5..e9edba830aff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -71,6 +71,12 @@ enum base_rev { #define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16) #define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0) +#define MT_RRO_DBG_RD_CTRL MT_RRO_TOP(0xe0) +#define MT_RRO_DBG_RD_ADDR GENMASK(15, 0) +#define MT_RRO_DBG_RD_EXEC BIT(31) + +#define MT_RRO_DBG_RDAT_DW(_n) MT_RRO_TOP(0xf0 + (_n) * 0x4) + #define MT_MCU_INT_EVENT 0x2108 #define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0) #define MT_MCU_INT_EVENT_DMA_INIT BIT(1)