From patchwork Thu Sep 21 10:43:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 726340 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 40955E7D0AB for ; Thu, 21 Sep 2023 20:57:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231635AbjIUU57 (ORCPT ); Thu, 21 Sep 2023 16:57:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37698 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232277AbjIUU5h (ORCPT ); Thu, 21 Sep 2023 16:57:37 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 40A9F7EA27 for ; Thu, 21 Sep 2023 10:37:37 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5F458C3279D; Thu, 21 Sep 2023 10:43:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695293028; bh=6cIXfOe0K6ze7eTH40ZzlFmMUg+Xi64dGsArrarMuzA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gSMzYtZ712Ol+/dvMxb39eaHDRpAg6hsDvcn58xe2C668qhN30wmwvOxD9NxLcI9w 2YuODyh1ZSerpwRf+kTG302uTb/9RobpEpxIUOSovYGEItNz5k0HngUf+0/WmejG8I NF34AIAbdBuw6WoIV9UJrJsmp0FD/mOMfDOXeYYRZvCHq+4Jlwp/IECZ1LqSOLT+s4 nNmm/hUG0cRt3MzF5prSr4Rrq4UANFeGWuF49NtM4Fb/nW+EvRplXW9D3j7VeYy0rK eeuOFYWlQe8Fz9lpvGwpDoxAf6hPopPIRCZfZeNtlkLHhJHse02QgKjIR559/waMzn /OmsJabX1NhHQ== 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 1/9] wifi: mt76: mmio: move mt76_mmio_wed_{init,release}_rx_buf in common code Date: Thu, 21 Sep 2023 12:43:30 +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 fede40cf86b7..7e43a800d378 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 Thu Sep 21 10:43:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 725211 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 E87F8E7D0A4 for ; Thu, 21 Sep 2023 18:11:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229840AbjIUSLY (ORCPT ); Thu, 21 Sep 2023 14:11:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46970 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229477AbjIUSK5 (ORCPT ); Thu, 21 Sep 2023 14:10:57 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0CDB77EA2C for ; Thu, 21 Sep 2023 10:37:37 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 50175C3279E; Thu, 21 Sep 2023 10:43:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695293032; bh=gmjVO4FL9gCwcCHrtMsFLoevWHLxvLUnEpLKtPNe+N8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ghuPj6C7CPWggcrruNXNss0ayqffz+kO+EEqXQMqicNDY7RLDtkYRMM2ZCnrzz0Cr 32cT/Unj8KQTZ0v3hsn7wLHqfVxGmpmM+Jyy13FctISwnlPZYhl0FhnmEMfKr0yYVA CTWKmAqxZFLRlBhOB3VhitSpYDzTRIc90/U9HHAm962bU4Ct35N5gr9PMTANBvkuwY ItdxG2NTGHyRFP5NVFtTGlWwn7WMuJ772zpsFtHS3dJ7wS0519B5VHGaVPAWlY/LHd 53vXzObPEXtazSeI41BYu+7sxd0flGVPDs3M7iNg7dpqNozye02KJ9+uQg8KwfDwNW htNxhQxuDZB+Q== 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 2/9] wifi: mt76: move mt76_mmio_wed_offload_{enable,disable} in common code Date: Thu, 21 Sep 2023 12:43:31 +0200 Message-ID: <895f948a654aeaaedf11a0e0c12935a55f816c40.1695292502.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 7e43a800d378..82e33a1b36ab 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 Thu Sep 21 10:43:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 726328 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 72478E7D0B0 for ; Thu, 21 Sep 2023 22:15:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232195AbjIUWQC (ORCPT ); Thu, 21 Sep 2023 18:16:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53628 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231817AbjIUWP0 (ORCPT ); Thu, 21 Sep 2023 18:15:26 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DF1357EA2A for ; Thu, 21 Sep 2023 10:37:37 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1843DC3279F; Thu, 21 Sep 2023 10:43:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695293036; bh=JmPRwGD8tXRsnlGbou9Rh78/vsK7nzRrY8wYaA8z1qg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KwutYm2orkJo8R5BbNM2OY0xhq6wxrn98m10MKv7lyRbBGyTO38s7sLJ29bIUkNpN fMIi9jnrUpfr0KopuniSf+rGImmiURVbQVYPGvoI31MYfg33Cw7rDfT/V5uP0xKr3Q /FSiWvJlrJFnXm+XVGfYr/LyQnRyvaH4zQ5WMRhPcV8Ygdu40UPtJyVqs8OCS43mmb h3rg0dTDZ/roYAV+fN1KHSH+PH8Kg9kKKMwDojaEm0uYoLcFTbHDJosAM/Q2LzJ57D UuvBhZ18XMjQ0lM6tx9RBCHnZTF12b6rn/qQf91EZSbLFMEq+wLfTDSsDj3d8z3/5Z ulMxDFtw5Kq3g== 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 3/9] wifi: mt76: move mt76_net_setup_tc in common code Date: Thu, 21 Sep 2023 12:43:32 +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/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 82e33a1b36ab..e8e9d9bc3730 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 Thu Sep 21 10:43:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 725202 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 BCC6CE7D0B0 for ; Thu, 21 Sep 2023 21:05:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230237AbjIUVFq (ORCPT ); Thu, 21 Sep 2023 17:05:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46250 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232897AbjIUVFI (ORCPT ); Thu, 21 Sep 2023 17:05:08 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D93D47EA29 for ; Thu, 21 Sep 2023 10:37:37 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A4F19C36AE6; Thu, 21 Sep 2023 10:43:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695293040; bh=1K/xpj89LnsSxSnZRLe9XnU/8MgULN5QpqENtjkZBsk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OEkujMmgiC0A+uad+mha2O9eGGryG5/hjeM3Xy5afVELxgwF716aE7wL0nNJOBLSf FE1cl5SkI7I52ISHYB8P7UhXuVY25tlprAm9OGlKN6fhEtat20h5J8sF+WYF71Cc0G pNsaq8T9uj9P0nZ/8ZCwkbEuR8MEa8A0l4WwTqdBc5us34rQ/TnDY7a6sOqJQqYRUs UE1lJRt6PTFekJ0y3O09+pDMrTC7J8U6EkOdBdOqAb4AGG2zsZX2A21/oeLaRjh3zc qr8Wje4DDh7qfv5GtPc5vL0epYHn0oGBitRkB+jN/UFsP8OTxyX0L/ebe+w5XO/Rk8 aVE6UyB+bdpKw== 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 4/9] wifi: mt76: introduce mt76_queue_is_wed_tx_free utility routine Date: Thu, 21 Sep 2023 12:43:33 +0200 Message-ID: <833b5d797b2da35fd42e59b0a8b193cf379d5d43.1695292502.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/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 643e18ebb5ee..f62b6af4316b 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; @@ -773,7 +773,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); } @@ -816,7 +816,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 e8e9d9bc3730..4ce3a0def8fb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1555,6 +1555,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 Thu Sep 21 10:43:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 726339 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 CB972E7D0AA for ; Thu, 21 Sep 2023 21:02:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232346AbjIUVDA (ORCPT ); Thu, 21 Sep 2023 17:03:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232307AbjIUVCn (ORCPT ); Thu, 21 Sep 2023 17:02:43 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AE63B7EA39 for ; Thu, 21 Sep 2023 10:37:38 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6DEC4C36AEE; Thu, 21 Sep 2023 10:44:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695293043; bh=DYVOEi5xVZo8aLe1A7iq0Anonq1a7Z/3pm3PIcGtfq8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FUe3CNsZ8U8QVPMdObNYUvIgJagin7e3Lvhrx8h05FmvbDfD908wrmhf8NxxeOLJF Q9Up/ff5GdoJzcQ029+rFBD9Fke/vwAccb7Ig0x22T61n8NLiTD2QLJ+ySZP4cjHEL x0BOf+LzreaSo558PUlhJalpjlGGik1wVicsPl1eLFDkaL4+1M4nbfl0lGkNvFObcA Z9DOPMAN36hzzAoDLhst28oZBbkaaoYoViD96heEQyp3ZWiF2HOleAJAs7BlKmbvlM OgB+PF6LAWqSxFjO1e5DNDou3PNmLFmzh+6KTL8u9A5CzvaO9IdB3F6kvWZwHyEVio p6MpuBfqMBN0w== 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 5/9] wifi: mt76: introduce wed pointer in mt76_queue Date: Thu, 21 Sep 2023 12:43:34 +0200 Message-ID: <35d29fc66f8e737f6daa7f40747aaae3b0e19d9c.1695292502.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 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 f62b6af4316b..80f46d988dc9 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; @@ -817,7 +818,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; } @@ -827,7 +828,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 4ce3a0def8fb..61b8d082cd0c 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 e4bb22b84159..c87dcb6a7c41 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -400,7 +400,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 Thu Sep 21 10:43:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 725201 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 1531AE7D0AF for ; Thu, 21 Sep 2023 21:10:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231267AbjIUVLA (ORCPT ); Thu, 21 Sep 2023 17:11:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232947AbjIUVFN (ORCPT ); Thu, 21 Sep 2023 17:05:13 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9B017EA3B for ; Thu, 21 Sep 2023 10:37:38 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3A1C5C36AF1; Thu, 21 Sep 2023 10:44:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695293047; bh=IPe5TSQAv2UTclbOLSu6Yjl5/f+ADH5J1nd/VG0Qoco=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HIWE7Dl2M/tiP0mXI7MYPKuxD5eDoaHESu03PQoqbwLfCXgSXsn6zNUpKvCG0PNRU rQPH86vs2oC9hNjjI5AJqK7A0R0RUPmYmnhgz5R+BEBOBzRKhA6pGWvOI8vaoSpqsV uK3aX2RKkfoyjNjxz4DaB4n/RKcKDW0wUb3FsMTPoFlv2Gf49kB+c5caN/t+5BhJAa Y6yO8LMg5txm+km/W+jmjggUCLZjsvcAfTWUuqe18KDILvllBanEubAEGkW1UYZg9o 7CaUFHrhsX79Xmv+bkkfmskREGAE+TuKjrLQJIqVQmCdjR8Z9MUKsKpx+2d1oS4MtW yvONxdSqZzJfQ== 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 6/9] wifi: mt76: increase MT_QFLAG_WED_TYPE size Date: Thu, 21 Sep 2023 12:43:35 +0200 Message-ID: <75d8f3f75ef86fdf37feeb4ce1c6d5c6d2f2a741.1695292502.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 61b8d082cd0c..b49a0ed5d23f 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 Thu Sep 21 10:43:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 726336 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 046D3E7D0AB for ; Thu, 21 Sep 2023 21:06:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232489AbjIUVG7 (ORCPT ); Thu, 21 Sep 2023 17:06:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50576 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233220AbjIUVFf (ORCPT ); Thu, 21 Sep 2023 17:05:35 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EC8027EA3C for ; Thu, 21 Sep 2023 10:37:38 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C6EBEC4AF6A; Thu, 21 Sep 2023 10:44:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695293051; bh=l02fRn1cjw8MNL4Bmi3pQolmlL1u1cE89BPLDFGcIoQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a/fiTNvXdjd4QixjQOFpE06gHg2hPit+Atgk5iviGGVv2in49FDoR27q3WS4Z5YKl kojKQDhhIVNNQ89FwONhAnhUUfnjsfJCnLbsuiXVmkdhc2xigBJ8ebqluXV/i1WMzY RljgwlYE7TN+jjCsGwW6kFb+h0nL/bzVHts7x7LQw/yOsivAhc5zDllzsX4paBtNAC Komq1DD6WxeBDEvkpQbUoM6ub+UmSsM/RH58cBPgSVgjxaDA/Bpn1NVBks5yzwRinB Vuw2stieicwOuxRljaabY17bucUEBk1cRiHDyBRa6BIcJHvELHkW2SmfbZPYCBjfpG Cwah5WUUGy4tA== 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 7/9] wifi: mt76: mt7996: add wed tx support Date: Thu, 21 Sep 2023 12:43:36 +0200 Message-ID: <2e594401fc56d9759d7a62d56254aebad879e81e.1695292502.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 | 72 ++++++-- .../net/wireless/mediatek/mt76/mt7996/regs.h | 5 + 10 files changed, 396 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 80f46d988dc9..d615d5b1ad42 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -986,10 +986,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 b49a0ed5d23f..02aceaded9fa 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 c87dcb6a7c41..de87493f8a7a 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; @@ -351,6 +353,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; @@ -362,8 +365,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) @@ -396,12 +401,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; @@ -414,6 +419,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: @@ -885,7 +897,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 c43839a20508..2ab93241e3d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1005,6 +1005,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, __le32 *txwi) { @@ -1383,6 +1406,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; @@ -1857,7 +1886,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 a2ab668a3b0f..ae4f0ce757e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -1368,6 +1368,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, @@ -1412,4 +1450,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 7354e5cf8e67..470a54139831 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 */ @@ -335,7 +336,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..92869ca1f363 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c @@ -125,15 +125,26 @@ 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; - irq = pdev->irq; - ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler, + if (!ret) { + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + goto free_device; + } + ret = devm_request_irq(mdev->dev, pdev->irq, mt7996_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) - goto free_irq_vector; + goto free_wed_or_irq_vector; + + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler, + IRQF_SHARED, KBUILD_MODNAME "-wed", dev); + if (ret) + goto free_irq; + } mt76_wr(dev, MT_INT_MASK_CSR, 0); /* master switch of PCIe tnterrupt enable */ @@ -143,16 +154,30 @@ 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, &irq); if (ret < 0) - goto free_hif2; + goto free_irq; + + 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; - ret = devm_request_irq(mdev->dev, dev->hif2->irq, - mt7996_irq_handler, IRQF_SHARED, - KBUILD_MODNAME "-hif", dev); + dev->hif2->irq = hif2_dev->irq; + } + + ret = devm_request_irq(mdev->dev, hif2_dev->irq, mt7996_irq_handler, + IRQF_SHARED, KBUILD_MODNAME "-hif", dev); if (ret) - goto free_hif2_irq_vector; + goto free_hif2; + + if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) { + ret = devm_request_irq(mdev->dev, irq, + mt7996_irq_handler, IRQF_SHARED, + KBUILD_MODNAME "-wed-hif", dev); + if (ret) + goto free_hif2_irq_vector; + } mt76_wr(dev, MT_INT1_MASK_CSR, 0); /* master switch of PCIe tnterrupt enable */ @@ -168,15 +193,28 @@ static int mt7996_pci_probe(struct pci_dev *pdev, free_hif2_irq: if (dev->hif2) devm_free_irq(mdev->dev, dev->hif2->irq, dev); + if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) + devm_free_irq(mdev->dev, dev->mt76.mmio.wed_hif2.irq, dev); free_hif2_irq_vector: - if (dev->hif2) - pci_free_irq_vectors(hif2_dev); + 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); + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + devm_free_irq(mdev->dev, dev->mt76.mmio.wed.irq, dev); +free_irq: + devm_free_irq(mdev->dev, pdev->irq, dev); +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 57022906216c..04d6dc56c049 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -323,6 +323,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) @@ -367,6 +368,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) @@ -412,6 +416,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 Thu Sep 21 10:43:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 726335 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 85CDAE7D0B2 for ; Thu, 21 Sep 2023 21:10:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231504AbjIUVLB (ORCPT ); Thu, 21 Sep 2023 17:11:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37564 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230410AbjIUU7h (ORCPT ); Thu, 21 Sep 2023 16:59:37 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C8B784F01 for ; Thu, 21 Sep 2023 10:37:39 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AC16FC36AF0; Thu, 21 Sep 2023 10:44:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695293055; bh=G3gltqhihnma9XLcjHfxtduXPoh5CUvLQuM3489vSHw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MQ2ycQaFtgGAdDrF20v1nzk8A59rgJ0XnVBuFF/1pBzAxwG0HJp9w81t1l5DjwcC0 kzFKWVi7/H7nQEjC4WaC+SH7OgwoD1VuecAy6vDZ3GFSAehhDiG1Pt1Y3dDVRh7bOb sriX1oZezAz+wp8E66hwAvc+H0bFFcOQUoOeqN9vE/iP8uMx3fhgztQGt20tUtws4/ hNGKae0eDy0uDQ4hyfGQhL44VBJAZqDKVbnrboHncV7pSFpsjbajtimUgFmJd2fwCV XvfYB770y5h/FLRk04dAZSfyXrl5b/cFnZVW3zqiLsZGfU+IkL/e7nxboNUU0PvDkY rRIgIO73N7cTQ== 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 8/9] wifi: mt76: dma: introduce __mt76_dma_queue_reset utility routine Date: Thu, 21 Sep 2023 12:43:37 +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 d615d5b1ad42..15923e1540d4 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 Thu Sep 21 10:43:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 726338 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 D7F59E7D0AA for ; Thu, 21 Sep 2023 21:04:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232495AbjIUVEI (ORCPT ); Thu, 21 Sep 2023 17:04:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35690 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230197AbjIUVDc (ORCPT ); Thu, 21 Sep 2023 17:03:32 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BB27184F0A for ; Thu, 21 Sep 2023 10:37:40 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7D388C4AF6B; Thu, 21 Sep 2023 10:44:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695293059; bh=brhvxX8rxgGrtJ970/RHm2LI5ZOg6nIGl1PPh3bD1SU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hxzgF0VyfGWdQ3i5FVSizpMVIfdKjvkxH8RToTkALuaGXLGqXDebvgUfca7EAThX9 KQRRM/MiNk+JWdMFYjfW1OJ2IcJL0C65lqTPvNRjNCxTwS0tQunPx44H4JEc77Qu16 x4EMDx1rQvLSaOB+mzi/MyVvnvKFn1Gw+Bu93cVU1t2zRm6MM7RLqp+0b6fG3B44lh PUnpeKXzk++9Y3RLRLoyjxpL1oVP6xy5fFiuS5EZSNuFBbYlUwBCEuuS0S2prO+tQI nfdjMW8fp5wy4Z2QmY+091axfBmCpyYXla6INyDbyfHKDt/sx7uE5iJOWEw4KWRHQW EiOLeSJx1j8Lg== 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 9/9] wifi: mt76: mt7996: add wed rx support Date: Thu, 21 Sep 2023 12:43:38 +0200 Message-ID: <9ba57d99ed64a3a4a8b030f26d0b8945479a5a8f.1695292502.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: 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 | 148 +++++++++---- drivers/net/wireless/mediatek/mt76/dma.h | 12 ++ drivers/net/wireless/mediatek/mt76/mt76.h | 58 ++++- .../net/wireless/mediatek/mt76/mt7996/dma.c | 198 ++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7996/init.c | 127 ++++++++++- .../net/wireless/mediatek/mt76/mt7996/mac.c | 41 +++- .../net/wireless/mediatek/mt76/mt7996/mcu.c | 13 +- .../net/wireless/mediatek/mt76/mt7996/mmio.c | 60 ++++-- .../wireless/mediatek/mt76/mt7996/mt7996.h | 55 +++++ .../net/wireless/mediatek/mt76/mt7996/regs.h | 60 +++++- 10 files changed, 687 insertions(+), 85 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 15923e1540d4..dd20271fc637 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,10 +416,14 @@ 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; + void *buf = e->buf; + u32 ctrl; + + 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); } @@ -412,6 +431,12 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, if (info) *info = le32_to_cpu(desc->info); + if (drop) { + *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP)); + if (ctrl & MT_DMA_CTL_VER_MASK) + *drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL); + } + if (mt76_queue_is_wed_rx(q)) { u32 buf1 = le32_to_cpu(desc->buf1); u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1); @@ -429,23 +454,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 +477,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 +638,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 +656,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 +666,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 +677,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 +705,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 +716,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 +764,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 +797,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; } @@ -756,7 +824,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); if (q->rx_head) { @@ -771,13 +840,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); @@ -989,6 +1061,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..22b79d58093b 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.h +++ b/drivers/net/wireless/mediatek/mt76/dma.h @@ -25,6 +25,13 @@ #define MT_DMA_PPE_ENTRY GENMASK(30, 16) #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_HDR_LEN 4 #define MT_RX_INFO_LEN 4 #define MT_FCE_INFO_LEN 4 @@ -37,6 +44,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, diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 02aceaded9fa..1013a6ff16b2 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; @@ -1574,10 +1596,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 * @@ -1617,10 +1661,14 @@ static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked) static inline int mt76_token_get(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi) { - int token; + int token, start = 0; + + if (mtk_wed_device_active(&dev->mmio.wed)) + start = dev->mmio.wed.wlan.nbuf; spin_lock_bh(&dev->token_lock); - token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC); + token = idr_alloc(&dev->token, *ptxwi, start, start + dev->token_size, + GFP_ATOMIC); spin_unlock_bh(&dev->token_lock); return token; 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 de87493f8a7a..878e3856583a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -315,8 +315,13 @@ 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) { + 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, @@ -470,6 +475,120 @@ 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 int mt7996_init_hardware(struct mt7996_dev *dev) { int ret, idx; @@ -491,6 +610,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; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 2ab93241e3d7..4fecef94b317 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 && @@ -1428,7 +1459,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 12bf4e5038b5..3ff70c6d4c17 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -912,7 +912,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) { @@ -921,7 +921,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); @@ -935,8 +935,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); } @@ -951,8 +952,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, @@ -962,8 +962,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 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 470a54139831..c541eaa4a4e6 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 { @@ -148,6 +174,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; @@ -227,6 +262,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 04d6dc56c049..854390dcd86e 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) @@ -391,6 +423,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) @@ -418,6 +451,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)]) @@ -425,20 +466,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)