wifi: mt7996: add wed support
Subsystems (2)
Lorenzo Bianconi
maintainerv3 cover wifi: mt7996: add wed support
Similar to MT7915, introduce Wireless Ethernet Dispatcher (WED) support for MT7996 driver to offload transmitted/received traffic.
Changes since v2:
- fix compilation errors if wed is not enabled
- add RRO garbage collector patch to the series
Changes since v1:
- add wed reset support
- unmap rro buffer on module unload
- check ind reason to check if the rx buffer must be discarded
Bo Jiao (1):
wifi: mt76: mt7996: add wed rx support
Lorenzo Bianconi (11):
wifi: mt76: mmio: move mt76_mmio_wed_{init,release}_rx_buf in common
code
wifi: mt76: move mt76_mmio_wed_offload_{enable,disable} in common code
wifi: mt76: move mt76_net_setup_tc in common code
wifi: mt76: introduce mt76_queue_is_wed_tx_free utility routine
wifi: mt76: introduce wed pointer in mt76_queue
wifi: mt76: increase MT_QFLAG_WED_TYPE size
wifi: mt76: dma: introduce __mt76_dma_queue_reset utility routine
wifi: mt76: mt7996: use u16 for val field in mt7996_mcu_set_rro
signature
mt76: move wed reset common code in mt76 module
mt76: mt7996: add wed reset support
wifi: mt76: mt7996: add wed rro delete session garbage collector
Sujuan Chen (1):
wifi: mt76: mt7996: add wed tx support
drivers/net/wireless/mediatek/mt76/dma.c | 246 +++++++++++----- drivers/net/wireless/mediatek/mt76/dma.h | 52 ++++ drivers/net/wireless/mediatek/mt76/mac80211.c | 19 +- drivers/net/wireless/mediatek/mt76/mmio.c | 105 +++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 96 +++++- .../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 +- .../wireless/mediatek/mt76/mt76_connac_mcu.h | 1 + .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 5 +- .../net/wireless/mediatek/mt76/mt7915/dma.c | 46 +-- .../net/wireless/mediatek/mt76/mt7915/main.c | 16 +- .../net/wireless/mediatek/mt76/mt7915/mmio.c | 116 +------- .../net/wireless/mediatek/mt76/mt7921/pci.c | 2 +- .../net/wireless/mediatek/mt76/mt7925/pci.c | 2 +- .../net/wireless/mediatek/mt76/mt7996/dma.c | 276 ++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7996/init.c | 256 +++++++++++++++- .../net/wireless/mediatek/mt76/mt7996/mac.c | 122 +++++++- .../net/wireless/mediatek/mt76/mt7996/main.c | 42 +++ .../net/wireless/mediatek/mt76/mt7996/mcu.c | 115 +++++++- .../net/wireless/mediatek/mt76/mt7996/mcu.h | 37 +++ .../net/wireless/mediatek/mt76/mt7996/mmio.c | 245 ++++++++++++++-- .../wireless/mediatek/mt76/mt7996/mt7996.h | 79 ++++- .../net/wireless/mediatek/mt76/mt7996/pci.c | 61 ++-- .../net/wireless/mediatek/mt76/mt7996/regs.h | 78 ++++- 26 files changed, 1695 insertions(+), 345 deletions(-)
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 1/13 wifi: mt76: mmio: move mt76_mmio_wed_{init,release}_rx_buf in common code
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
--- 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(-)
drivers/net/wireless/mediatek/mt76/mmio.c +75 -0
@@ -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 = {
drivers/net/wireless/mediatek/mt76/mt76.h +5 -0
@@ -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))
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +2 -76
90 lines not on this page · raw message
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 2/13 wifi: mt76: move mt76_mmio_wed_offload_{enable,disable} in common code
In reply to Lorenzo Bianconimt76_mmio_wed_offload_enable and mt76_mmio_wed_offload_disable routines will be reused by mt7996 driver for wed support.
--- 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(-)
drivers/net/wireless/mediatek/mt76/mmio.c +22 -0
@@ -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)
drivers/net/wireless/mediatek/mt76/mt76.h +2 -0
@@ -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))
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +2 -27
@@ -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;
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 3/13 wifi: mt76: move mt76_net_setup_tc in common code
In reply to Lorenzo BianconiThis is a preliminary patch to introduce WED support for mt7996
--- 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(-)
drivers/net/wireless/mediatek/mt76/mac80211.c +16 -0
@@ -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 */
drivers/net/wireless/mediatek/mt76/mt76.h +6 -0
@@ -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 ;
drivers/net/wireless/mediatek/mt76/mt7915/main.c +1 -15
@@ -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 };
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 4/13 wifi: mt76: introduce mt76_queue_is_wed_tx_free utility routine
In reply to Lorenzo BianconiThis is a preliminary patch to introduce WED support for mt7996
--- 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(-)
drivers/net/wireless/mediatek/mt76/dma.c +3 -3
@@ -724,7 +724,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,if (ret)return ret; -if (q->flags !=MT_WED_Q_TXFREE ) +if (!mt76_queue_is_wed_tx_free (q))mt76_dma_queue_reset (dev, q);return 0 ;
@@ -775,7 +775,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)/* reset WED rx queues */ mt76_dma_wed_setup (dev, q, true); -if (q->flags !=MT_WED_Q_TXFREE ) { +if (!mt76_queue_is_wed_tx_free (q)) {mt76_dma_sync_idx (dev, q);mt76_dma_rx_fill (dev, q, false); }
@@ -818,7 +818,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)bool more;if (IS_ENABLED (CONFIG_NET_MEDIATEK_SOC_WED ) && - q->flags ==MT_WED_Q_TXFREE ) { +mt76_queue_is_wed_tx_free (q)) { dma_idx =Q_READ (dev, q, dma_idx); check_ddone = true; }
drivers/net/wireless/mediatek/mt76/mt76.h +6 -0
@@ -1560,6 +1560,12 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,struct mt76_power_limits *dest, s8 target_power); +static inline bool mt76_queue_is_wed_tx_free (struct mt76_queue *q) +{ +return (q->flags &MT_QFLAG_WED ) && +FIELD_GET (MT_QFLAG_WED_TYPE , q->flags) ==MT76_WED_Q_TXFREE ; +} +static inline bool mt76_queue_is_wed_rx (struct mt76_queue *q) { return (q->flags & MT_QFLAG_WED) &&
drivers/net/wireless/mediatek/mt76/mt7915/dma.c +1 -1
@@ -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]);
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 5/13 wifi: mt76: introduce wed pointer in mt76_queue
In reply to Lorenzo BianconiIntroduce 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.
--- 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(-)
drivers/net/wireless/mediatek/mt76/dma.c +25 -24
@@ -9,11 +9,11 @@#if IS_ENABLED (CONFIG_NET_MEDIATEK_SOC_WED ) -#define Q_READ (_dev, _q, _field) ({ \ +#define Q_READ (_q, _field) ({ \ u32 _offset = offsetof(struct mt76_queue_regs, _field); \ u32 _val; \ if ((_q)->flags & MT_QFLAG_WED) \ - _val = mtk_wed_device_reg_read(&(_dev)->mmio.wed, \ + _val = mtk_wed_device_reg_read((_q)->wed, \ ((_q)->wed_regs + \ _offset)); \ else \
@@ -21,10 +21,10 @@ _val; \ }) -#define Q_WRITE (_dev, _q, _field, _val) do { \ +#define Q_WRITE (_q, _field, _val) do { \ u32 _offset = offsetof(struct mt76_queue_regs, _field); \ if ((_q)->flags & MT_QFLAG_WED) \ - mtk_wed_device_reg_write(&(_dev)->mmio.wed, \ + mtk_wed_device_reg_write((_q)->wed, \ ((_q)->wed_regs + _offset), \ _val); \ else \
@@ -33,8 +33,8 @@#else -#define Q_READ (_dev, _q, _field) readl(&(_q)->regs->_field) -#define Q_WRITE (_dev, _q, _field, _val) writel(_val, &(_q)->regs->_field) +#define Q_READ (_q, _field) readl(&(_q)->regs->_field) +#define Q_WRITE (_q, _field, _val) writel(_val, &(_q)->regs->_field)#endif
@@ -188,9 +188,9 @@ EXPORT_SYMBOL_GPL(mt76_free_pending_rxwi);static void mt76_dma_sync_idx (struct mt76_dev *dev,struct mt76_queue *q) { -Q_WRITE (dev, q, desc_base, q->desc_dma); -Q_WRITE (dev, q, ring_size, q->ndesc); - q->head =Q_READ (dev, q, dma_idx); +Q_WRITE (q, desc_base, q->desc_dma); +Q_WRITE (q, ring_size, q->ndesc); + q->head =Q_READ (q, dma_idx); q->tail = q->head; }
@@ -206,8 +206,8 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)for (i =0 ; i < q->ndesc; i++) q->desc[i].ctrl =cpu_to_le32 (MT_DMA_CTL_DMA_DONE ); -Q_WRITE (dev, q, cpu_idx,0 ); -Q_WRITE (dev, q, dma_idx,0 ); +Q_WRITE (q, cpu_idx,0 ); +Q_WRITE (q, dma_idx,0 );mt76_dma_sync_idx (dev, q); }
@@ -343,7 +343,7 @@ static void mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) {wmb (); -Q_WRITE (dev, q, cpu_idx, q->head); +Q_WRITE (q, cpu_idx, q->head); } static void
@@ -359,7 +359,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)if (flush) last =-1 ;else - last =Q_READ (dev, q, dma_idx); + last =Q_READ (q, dma_idx);while (q->queued >0 && q->tail != last) {mt76_dma_tx_cleanup_idx (dev, q, q->tail, &entry);
@@ -371,7 +371,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush) }if (!flush && q->tail == last) - last =Q_READ (dev, q, dma_idx); + last =Q_READ (q, dma_idx); }spin_unlock_bh (&q->cleanup_lock);
@@ -641,7 +641,6 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,int mt76_dma_wed_setup (struct mt76_dev *dev,struct mt76_queue *q,bool reset) {#ifdef CONFIG_NET_MEDIATEK_SOC_WED -struct mtk_wed_device *wed = &dev->mmio.wed;int ret, type, ring;u8 flags;
@@ -649,7 +648,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)return -EINVAL ; flags = q->flags; -if (!mtk_wed_device_active (wed)) +if (!q->wed || !mtk_wed_device_active (q->wed)) q->flags &= ~MT_QFLAG_WED ;if (!(q->flags &MT_QFLAG_WED ))
@@ -660,9 +659,10 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)switch (type) {case MT76_WED_Q_TX : - ret =mtk_wed_device_tx_ring_setup (wed, ring, q->regs, reset); + ret =mtk_wed_device_tx_ring_setup (q->wed, ring, q->regs, + reset);if (!ret) - q->wed_regs = wed->tx_ring[ring].reg_base; + q->wed_regs = q->wed->tx_ring[ring].reg_base;break ;case MT76_WED_Q_TXFREE :/* WED txfree queue needs ring to be initialized before setup */
@@ -671,14 +671,15 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)mt76_dma_rx_fill (dev, q, false); q->flags = flags; - ret =mtk_wed_device_txfree_ring_setup (wed, q->regs); + ret =mtk_wed_device_txfree_ring_setup (q->wed, q->regs);if (!ret) - q->wed_regs = wed->txfree_ring.reg_base; + q->wed_regs = q->wed->txfree_ring.reg_base;break ;case MT76_WED_Q_RX : - ret =mtk_wed_device_rx_ring_setup (wed, ring, q->regs, reset); + ret =mtk_wed_device_rx_ring_setup (q->wed, ring, q->regs, + reset);if (!ret) - q->wed_regs = wed->rx_ring[ring].reg_base; + q->wed_regs = q->wed->rx_ring[ring].reg_base;break ;default : ret = -EINVAL ;
@@ -819,7 +820,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)if (IS_ENABLED (CONFIG_NET_MEDIATEK_SOC_WED ) &&mt76_queue_is_wed_tx_free (q)) { - dma_idx =Q_READ (dev, q, dma_idx); + dma_idx =Q_READ (q, dma_idx); check_ddone = true; }
@@ -829,7 +830,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)if (check_ddone) {if (q->tail == dma_idx) - dma_idx =Q_READ (dev, q, dma_idx); + dma_idx =Q_READ (q, dma_idx);if (q->tail == dma_idx)break ;
drivers/net/wireless/mediatek/mt76/mac80211.c +2 -1
@@ -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 )
drivers/net/wireless/mediatek/mt76/mt76.h +6 -4
@@ -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);
drivers/net/wireless/mediatek/mt76/mt7603/dma.c +5 -4
@@ -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;
drivers/net/wireless/mediatek/mt76/mt7615/dma.c +3 -3
@@ -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;
drivers/net/wireless/mediatek/mt76/mt76_connac.h +2 -1
@@ -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);
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +3 -2
@@ -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;
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +3 -2
@@ -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;
drivers/net/wireless/mediatek/mt76/mt7915/dma.c +11 -5
@@ -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 */
drivers/net/wireless/mediatek/mt76/mt7921/pci.c +1 -1
@@ -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;
drivers/net/wireless/mediatek/mt76/mt7925/pci.c +1 -1
@@ -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;
drivers/net/wireless/mediatek/mt76/mt7996/dma.c +1 -1
@@ -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;
drivers/net/wireless/mediatek/mt76/mt7996/init.c +2 -1
@@ -405,7 +405,8 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, ret =mt76_connac_init_tx_queues (phy->mt76,MT_TXQ_ID (band),MT7996_TX_RING_SIZE , -MT_TXQ_RING_BASE (band) + hif1_ofs,0 ); +MT_TXQ_RING_BASE (band) + hif1_ofs, +NULL ,0 );if (ret) goto error;
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 6/13 wifi: mt76: increase MT_QFLAG_WED_TYPE size
In reply to Lorenzo BianconiThis is a preliminary patch to introduce WED support for mt7996
--- drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +2 -2
@@ -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) | \
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 7/13 wifi: mt76: mt7996: add wed tx support
In reply to Lorenzo BianconiFrom: Sujuan Chen <[email protected]>
Similar to MT7915, enable Wireless Ethernet Ditpatcher for MT7996 to offload traffic received from the LAN nic and transmitted on the WLAN one
--- drivers/net/wireless/mediatek/mt76/dma.c | 9 +- drivers/net/wireless/mediatek/mt76/mt76.h | 11 ++ .../net/wireless/mediatek/mt76/mt7996/dma.c | 76 ++++++-- .../net/wireless/mediatek/mt76/mt7996/init.c | 30 ++- .../net/wireless/mediatek/mt76/mt7996/mac.c | 31 +++- .../net/wireless/mediatek/mt76/mt7996/main.c | 42 +++++ .../net/wireless/mediatek/mt76/mt7996/mmio.c | 172 ++++++++++++++++-- .../wireless/mediatek/mt76/mt7996/mt7996.h | 12 +- .../net/wireless/mediatek/mt76/mt7996/pci.c | 61 +++++-- .../net/wireless/mediatek/mt76/mt7996/regs.h | 5 + 10 files changed, 383 insertions(+), 66 deletions(-)
drivers/net/wireless/mediatek/mt76/dma.c +6 -3
@@ -988,10 +988,13 @@ void mt76_dma_cleanup(struct mt76_dev *dev)page_pool_destroy (q->page_pool); } -mt76_free_pending_txwi (dev); -mt76_free_pending_rxwi (dev); -if (mtk_wed_device_active (&dev->mmio.wed))mtk_wed_device_detach (&dev->mmio.wed); + +if (mtk_wed_device_active (&dev->mmio.wed_hif2)) +mtk_wed_device_detach (&dev->mmio.wed_hif2); + +mt76_free_pending_txwi (dev); +mt76_free_pending_rxwi (dev); }EXPORT_SYMBOL_GPL (mt76_dma_cleanup);
drivers/net/wireless/mediatek/mt76/mt76.h +11 -0
@@ -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; };
drivers/net/wireless/mediatek/mt76/mt7996/dma.c +61 -15
146 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/init.c +21 -9
@@ -156,7 +156,7 @@ mt7996_regd_notifier(struct wiphy *wiphy, }static void -mt7996_init_wiphy (struct ieee80211_hw *hw) +mt7996_init_wiphy (struct ieee80211_hw *hw,struct mtk_wed_device *wed) {struct mt7996_phy *phy =mt7996_hw_phy (hw);struct mt76_dev *mdev = &phy->dev->mt76;
@@ -168,6 +168,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) hw->max_rx_aggregation_subframes = max_subframes; hw->max_tx_aggregation_subframes = max_subframes; hw->netdev_features =NETIF_F_RXCSUM ; +if (mtk_wed_device_active (wed)) + hw->netdev_features |=NETIF_F_HW_TC ; hw->radiotap_timestamp.units_pos =IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US ;
@@ -356,6 +358,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,struct mt76_phy *mphy;u32 mac_ofs, hif1_ofs =0 ;int ret; +struct mtk_wed_device *wed = &dev->mt76.mmio.wed;if (band !=MT_BAND1 && band !=MT_BAND2 )return 0 ;
@@ -367,8 +370,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,if (phy)return 0 ; -if (band ==MT_BAND2 && dev->hif2) +if (band ==MT_BAND2 && dev->hif2) { hif1_ofs =MT_WFDMA0_PCIE1 (0 ) -MT_WFDMA0 (0 ); + wed = &dev->mt76.mmio.wed_hif2; + } mphy =mt76_alloc_phy (&dev->mt76,sizeof (*phy), &mt7996_ops, band);if (!mphy)
@@ -401,12 +406,12 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,mt76_eeprom_override (mphy);/* init wiphy according to mphy and phy */ -mt7996_init_wiphy (mphy->hw); - ret =mt76_connac_init_tx_queues (phy->mt76, -MT_TXQ_ID (band), -MT7996_TX_RING_SIZE , -MT_TXQ_RING_BASE (band) + hif1_ofs, -NULL ,0 ); +mt7996_init_wiphy (mphy->hw, wed); + ret =mt7996_init_tx_queues (mphy->priv, +MT_TXQ_ID (band), +MT7996_TX_RING_SIZE , +MT_TXQ_RING_BASE (band) + hif1_ofs, + wed);if (ret) goto error;
@@ -419,6 +424,13 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,if (ret) goto error; +if (wed == &dev->mt76.mmio.wed_hif2 &&mtk_wed_device_active (wed)) { +u32 irq_mask = dev->mt76.mmio.irqmask |MT_INT_TX_DONE_BAND2 ; + +mt76_wr (dev,MT_INT1_MASK_CSR , irq_mask); +mtk_wed_device_start (&dev->mt76.mmio.wed_hif2, irq_mask); + } +return 0 ; error:
@@ -890,7 +902,7 @@ int mt7996_register_device(struct mt7996_dev *dev)if (ret)return ret; -mt7996_init_wiphy (hw); +mt7996_init_wiphy (hw, &dev->mt76.mmio.wed); ret =mt76_register_device (&dev->mt76, true, mt76_rates,ARRAY_SIZE (mt76_rates));
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +30 -1
@@ -996,6 +996,29 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,return 0 ; } +u32 mt7996_wed_init_buf (void *ptr,dma_addr_t phys,int token_id) +{ +struct mt76_connac_fw_txp *txp = ptr +MT_TXD_SIZE ; +__le32 *txwi = ptr; +u32 val; + +memset (ptr,0 ,MT_TXD_SIZE +sizeof (*txp)); + + val =FIELD_PREP (MT_TXD0_TX_BYTES ,MT_TXD_SIZE ) | +FIELD_PREP (MT_TXD0_PKT_FMT ,MT_TX_TYPE_CT ); + txwi[0 ] =cpu_to_le32 (val); + + val =BIT (31 ) | +FIELD_PREP (MT_TXD1_HDR_FORMAT ,MT_HDR_FORMAT_802_3 ); + txwi[1 ] =cpu_to_le32 (val); + + txp->token =cpu_to_le16 (token_id); + txp->nbuf =1 ; + txp->buf[0 ] =cpu_to_le32 (phys +MT_TXD_SIZE +sizeof (*txp)); + +return MT_TXD_SIZE +sizeof (*txp); +} +static void mt7996_tx_check_aggr (struct ieee80211_sta *sta,struct sk_buff *skb) {
@@ -1403,6 +1426,12 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,switch (type) {case PKT_TYPE_TXRX_NOTIFY : +if (mtk_wed_device_active (&dev->mt76.mmio.wed_hif2) && + q ==MT_RXQ_TXFREE_BAND2 ) { +dev_kfree_skb (skb); +break ; + } +mt7996_mac_tx_free (dev, skb->data, skb->len);napi_consume_skb (skb,1 );break ;
@@ -1877,7 +1906,7 @@ void mt7996_mac_reset_work(struct work_struct *work)mt7996_wait_reset_state (dev,MT_MCU_CMD_NORMAL_STATE );/* enable DMA Tx/Tx and interrupt */ -mt7996_dma_start (dev, false); +mt7996_dma_start (dev, false, false);clear_bit (MT76_MCU_RESET , &dev->mphy.state);clear_bit (MT76_RESET , &dev->mphy.state);
drivers/net/wireless/mediatek/mt76/mt7996/main.c +42 -0
52 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +154 -18
206 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +11 -1
@@ -37,6 +37,7 @@#define MT7996_EEPROM_SIZE 7680#define MT7996_EEPROM_BLOCK_SIZE 16#define MT7996_TOKEN_SIZE 16384 +#define MT7996_HW_TOKEN_SIZE 8192#define MT7996_CFEND_RATE_DEFAULT 0x49/* OFDM 24M */ #define MT7996_CFEND_RATE_11B 0x03/* 11B LP, 11M */
@@ -334,7 +335,9 @@ int mt7996_dma_init(struct mt7996_dev *dev);void mt7996_dma_reset (struct mt7996_dev *dev,bool force);void mt7996_dma_prefetch (struct mt7996_dev *dev);void mt7996_dma_cleanup (struct mt7996_dev *dev); -void mt7996_dma_start (struct mt7996_dev *dev,bool reset); +void mt7996_dma_start (struct mt7996_dev *dev,bool reset,bool wed_reset); +int mt7996_init_tx_queues (struct mt7996_phy *phy,int idx, +int n_desc,int ring_base,struct mtk_wed_device *wed);void mt7996_init_txpower (struct mt7996_dev *dev,struct ieee80211_supported_band *sband);int mt7996_txbf_init (struct mt7996_dev *dev);
@@ -495,5 +498,12 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,void mt7996_sta_add_debugfs (struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_sta *sta,struct dentry *dir);#endif +int mt7996_mmio_wed_init (struct mt7996_dev *dev,void *pdev_ptr, +bool hif2,int *irq); +u32 mt7996_wed_init_buf (void *ptr,dma_addr_t phys,int token_id); + +#ifdef CONFIG_MTK_DEBUG +int mt7996_mtk_init_debugfs (struct mt7996_phy *phy,struct dentry *dir); +#endif #endif
drivers/net/wireless/mediatek/mt76/mt7996/pci.c +42 -19
99 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/regs.h +5 -0
@@ -330,6 +330,7 @@ enum base_rev {#define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)#define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3) +#define MT_WFDMA0_RX_INT_SEL_RING6 BIT(6)#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
@@ -374,6 +375,9 @@ enum base_rev {#define MT_WFDMA0_PCIE1_BASE 0xd8000#define MT_WFDMA0_PCIE1 (ofs) (MT_WFDMA0_PCIE1_BASE + (ofs)) +#define MT_INT_PCIE1_SOURCE_CSR_EXT MT_WFDMA0_PCIE1(0x118) +#define MT_INT_PCIE1_MASK_CSR MT_WFDMA0_PCIE1(0x11c) +#define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c)#define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0)#define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1)
@@ -419,6 +423,7 @@ enum base_rev {#define MT_INT_RX_TXFREE_MAIN BIT(17)#define MT_INT_RX_TXFREE_TRI BIT(15)#define MT_INT_MCU_CMD BIT(29) +#define MT_INT_RX_TXFREE_EXT BIT(26)#define MT_INT_RX (q) (dev->q_int_mask[__RXQ(q)])#define MT_INT_TX_MCU (q) (dev->q_int_mask[(q)])
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 8/13 wifi: mt76: dma: introduce __mt76_dma_queue_reset utility routine
In reply to Lorenzo BianconiThis is a preliminary patch to introduce WED support for mt7996
--- drivers/net/wireless/mediatek/mt76/dma.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/dma.c +12 -3
@@ -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)
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 9/13 wifi: mt76: mt7996: use u16 for val field in mt7996_mcu_set_rro signature
In reply to Lorenzo BianconiThis is a preliminary patch to introduce WED rx support for mt7996 driver.
--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +1 -1
@@ -4019,7 +4019,7 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev) &req, sizeof(req), false); } -int mt7996_mcu_set_rro (struct mt7996_dev *dev,u16 tag,u8 val) +int mt7996_mcu_set_rro (struct mt7996_dev *dev,u16 tag,u16 val) {struct {u8 __rsv1[4 ];
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +1 -1
@@ -397,7 +397,7 @@ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef);int mt7996_mcu_rf_regval (struct mt7996_dev *dev,u32 regidx,u32 *val,bool set);int mt7996_mcu_set_hdr_trans (struct mt7996_dev *dev,bool hdr_trans); -int mt7996_mcu_set_rro (struct mt7996_dev *dev,u16 tag,u8 val); +int mt7996_mcu_set_rro (struct mt7996_dev *dev,u16 tag,u16 val);int mt7996_mcu_wa_cmd (struct mt7996_dev *dev,int cmd,u32 a1,u32 a2,u32 a3);int mt7996_mcu_fw_log_2_host (struct mt7996_dev *dev,u8 type,u8 ctrl);int mt7996_mcu_fw_dbg_ctrl (struct mt7996_dev *dev,u32 module,u8 level);
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 10/13 wifi: mt76: mt7996: add wed rx support
In reply to Lorenzo BianconiFrom: Bo Jiao <[email protected]>
Similar to MT7915, enable Wireless Ethernet Ditpatcher for MT7996 to offload traffic received from the WLAN nic and transmitted on the LAN one
--- drivers/net/wireless/mediatek/mt76/dma.c | 149 +++++++++---- drivers/net/wireless/mediatek/mt76/dma.h | 43 ++++ drivers/net/wireless/mediatek/mt76/mt76.h | 50 ++++- .../net/wireless/mediatek/mt76/mt7996/dma.c | 198 ++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7996/init.c | 175 +++++++++++++++- .../net/wireless/mediatek/mt76/mt7996/mac.c | 41 +++- .../net/wireless/mediatek/mt76/mt7996/mcu.c | 24 ++- .../net/wireless/mediatek/mt76/mt7996/mcu.h | 2 + .../net/wireless/mediatek/mt76/mt7996/mmio.c | 60 ++++-- .../wireless/mediatek/mt76/mt7996/mt7996.h | 55 +++++ .../net/wireless/mediatek/mt76/mt7996/regs.h | 62 +++++- 11 files changed, 772 insertions(+), 87 deletions(-)
drivers/net/wireless/mediatek/mt76/dma.c +111 -38
@@ -189,7 +189,10 @@ static void mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) { Q_WRITE(q, desc_base, q->desc_dma); -Q_WRITE (q, ring_size, q->ndesc); +if (q->flags &MT_QFLAG_WED_RRO_EN ) +Q_WRITE (q, ring_size,MT_DMA_RRO_EN | q->ndesc); +else +Q_WRITE (q, ring_size, q->ndesc); q->head =Q_READ (q, dma_idx); q->tail = q->head; }
@@ -198,14 +201,16 @@ static void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, bool reset_idx) { - int i; - if (!q || !q->ndesc) return; -/* clear descriptors */ -for (i =0 ; i < q->ndesc; i++) - q->desc[i].ctrl =cpu_to_le32 (MT_DMA_CTL_DMA_DONE ); +if (!mt76_queue_is_wed_rro_ind (q)) { +int i; + +/* clear descriptors */ +for (i =0 ; i < q->ndesc; i++) + q->desc[i].ctrl =cpu_to_le32 (MT_DMA_CTL_DMA_DONE ); + }if (reset_idx) {Q_WRITE (q, cpu_idx,0 );
@@ -224,13 +229,22 @@ static int mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf *buf, void *data) { - struct mt76_desc *desc = &q->desc[q->head]; struct mt76_queue_entry *entry = &q->entry[q->head];struct mt76_txwi_cache *txwi =NULL ; +struct mt76_desc *desc;u32 buf1 =0 , ctrl;int idx = q->head;int rx_token; +if (mt76_queue_is_wed_rro_ind (q)) { +struct mt76_wed_rro_desc *rro_desc; + + rro_desc = (struct mt76_wed_rro_desc *)q->desc; + data = &rro_desc[q->head]; + goto done; + } + + desc = &q->desc[q->head]; ctrl =FIELD_PREP (MT_DMA_CTL_SD_LEN0 , buf[0 ].len);if (mt76_queue_is_wed_rx (q)) {
@@ -253,6 +267,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,WRITE_ONCE (desc->ctrl,cpu_to_le32 (ctrl));WRITE_ONCE (desc->info,0 ); +done: entry->dma_addr[0 ] = buf->addr; entry->dma_len[0 ] = buf->len; entry->txwi = txwi;
@@ -401,19 +416,26 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, {struct mt76_queue_entry *e = &q->entry[idx];struct mt76_desc *desc = &q->desc[idx]; -void *buf; +u32 ctrl, desc_info, buf1; +void *buf = e->buf; + +if (mt76_queue_is_wed_rro_ind (q)) + goto done; + ctrl =le32_to_cpu (READ_ONCE (desc->ctrl));if (len) { -u32 ctrl =le32_to_cpu (READ_ONCE (desc->ctrl)); *len =FIELD_GET (MT_DMA_CTL_SD_LEN0 , ctrl); *more = !(ctrl &MT_DMA_CTL_LAST_SEC0 ); } + desc_info =le32_to_cpu (desc->info);if (info) - *info =le32_to_cpu (desc->info); + *info = desc_info; + + buf1 =le32_to_cpu (desc->buf1); +mt76_dma_should_drop_buf (drop, ctrl, buf1, desc_info);if (mt76_queue_is_wed_rx (q)) { -u32 buf1 =le32_to_cpu (desc->buf1);u32 token =FIELD_GET (MT_DMA_CTL_TOKEN , buf1);struct mt76_txwi_cache *t =mt76_rx_token_release (dev, token);
@@ -429,23 +451,16 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, t->ptr =NULL ;mt76_put_rxwi (dev, t); - -if (drop) { -u32 ctrl =le32_to_cpu (READ_ONCE (desc->ctrl)); - - *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | -MT_DMA_CTL_DROP )); - +if (drop) *drop |= !!(buf1 &MT_DMA_CTL_WO_DROP ); - } }else { - buf = e->buf; - e->buf =NULL ;dma_sync_single_for_cpu (dev->dma_dev, e->dma_addr[0 ],SKB_WITH_OVERHEAD (q->buf_size),page_pool_get_dma_dir (q->page_pool)); } +done: + e->buf =NULL ;return buf; }
@@ -459,11 +474,16 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,if (!q->queued)return NULL ; -if (flush) - q->desc[idx].ctrl |=cpu_to_le32 (MT_DMA_CTL_DMA_DONE ); -else if (!(q->desc[idx].ctrl &cpu_to_le32 (MT_DMA_CTL_DMA_DONE ))) +if (mt76_queue_is_wed_rro_data (q))return NULL ; +if (!mt76_queue_is_wed_rro_ind (q)) { +if (flush) + q->desc[idx].ctrl |=cpu_to_le32 (MT_DMA_CTL_DMA_DONE ); +else if (!(q->desc[idx].ctrl &cpu_to_le32 (MT_DMA_CTL_DMA_DONE ))) +return NULL ; + } + q->tail = (q->tail +1 ) % q->ndesc; q->queued--;
@@ -615,11 +635,14 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,spin_lock_bh (&q->lock);while (q->queued < q->ndesc -1 ) { +struct mt76_queue_buf qbuf = {};enum dma_data_direction dir; -struct mt76_queue_buf qbuf;dma_addr_t addr;int offset; -void *buf; +void *buf =NULL ; + +if (mt76_queue_is_wed_rro_ind (q)) + goto done; buf =mt76_get_page_pool_buf (q, &offset, q->buf_size);if (!buf)
@@ -630,6 +653,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,dma_sync_single_for_device (dev->dma_dev, addr, len, dir); qbuf.addr = addr + q->buf_offset; +done: qbuf.len = len - q->buf_offset; qbuf.skip_unmap = false;if (mt76_dma_add_rx_buf (dev, q, &qbuf, buf) <0 ) {
@@ -639,7 +663,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, frames++; } -if (frames) +if (frames ||mt76_queue_is_wed_rx (q))mt76_dma_kick_queue (dev, q);spin_unlock_bh (&q->lock);
@@ -650,8 +674,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,int mt76_dma_wed_setup (struct mt76_dev *dev,struct mt76_queue *q,bool reset) {#ifdef CONFIG_NET_MEDIATEK_SOC_WED -int ret, type, ring; -u8 flags; +int ret =0 , type, ring; +u16 flags;if (!q || !q->ndesc)return -EINVAL ;
@@ -678,7 +702,6 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) q->flags =0 ;mt76_dma_queue_reset (dev, q);mt76_dma_rx_fill (dev, q, false); - q->flags = flags; ret =mtk_wed_device_txfree_ring_setup (q->wed, q->regs);if (!ret)
@@ -690,9 +713,31 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)if (!ret) q->wed_regs = q->wed->rx_ring[ring].reg_base;break ; +case MT76_WED_RRO_Q_DATA : + q->flags &= ~MT_QFLAG_WED ; +__mt76_dma_queue_reset (dev, q, false); +mtk_wed_device_rro_rx_ring_setup (q->wed, ring, q->regs); + q->head = q->ndesc -1 ; + q->queued = q->head; +break ; +case MT76_WED_RRO_Q_MSDU_PG : + q->flags &= ~MT_QFLAG_WED ; +__mt76_dma_queue_reset (dev, q, false); +mtk_wed_device_msdu_pg_rx_ring_setup (q->wed, ring, q->regs); + q->head = q->ndesc -1 ; + q->queued = q->head; +break ; +case MT76_WED_RRO_Q_IND : + q->flags &= ~MT_QFLAG_WED ; +mt76_dma_queue_reset (dev, q); +mt76_dma_rx_fill (dev, q, false); +mtk_wed_device_ind_rx_ring_setup (q->wed, q->regs); +break ;default : ret = -EINVAL ; + break; } + q->flags = flags;return ret;#else
@@ -716,11 +761,26 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, q->buf_size = bufsize; q->hw_idx = idx; - size = q->ndesc *sizeof (struct mt76_desc ); - q->desc =dmam_alloc_coherent (dev->dma_dev, size, &q->desc_dma,GFP_KERNEL ); + size =mt76_queue_is_wed_rro_ind (q) ?sizeof (struct mt76_wed_rro_desc ) + :sizeof (struct mt76_desc ); + q->desc =dmam_alloc_coherent (dev->dma_dev, q->ndesc * size, + &q->desc_dma,GFP_KERNEL );if (!q->desc)return -ENOMEM ; +if (mt76_queue_is_wed_rro_ind (q)) { +struct mt76_wed_rro_desc *rro_desc; +int i; + + rro_desc = (struct mt76_wed_rro_desc *)q->desc; +for (i =0 ; i < q->ndesc; i++) { +struct mt76_wed_rro_ind *cmd; + + cmd = (struct mt76_wed_rro_ind *)&rro_desc[i]; + cmd->magic_cnt =MT_DMA_WED_IND_CMD_CNT -1 ; + } + } + size = q->ndesc *sizeof (*q->entry); q->entry =devm_kzalloc (dev->dev, size,GFP_KERNEL );if (!q->entry)
@@ -734,8 +794,13 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,if (ret)return ret; -if (!mt76_queue_is_wed_tx_free (q)) -mt76_dma_queue_reset (dev, q); +if (mtk_wed_device_active (&dev->mmio.wed)) { +if ((mtk_wed_get_rx_capa (&dev->mmio.wed) &&mt76_queue_is_wed_rro (q)) || +mt76_queue_is_wed_tx_free (q)) +return 0 ; + } + +mt76_dma_queue_reset (dev, q);return 0 ; }
@@ -757,7 +822,8 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)if (!buf)break ; -mt76_put_page_pool_buf (buf, false); +if (!mt76_queue_is_wed_rro (q)) +mt76_put_page_pool_buf (buf, false); }while (1 );spin_lock_bh (&q->lock);
@@ -773,13 +839,16 @@ static void mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) {struct mt76_queue *q = &dev->q_rx[qid]; -int i;if (!q->ndesc)return ; -for (i =0 ; i < q->ndesc; i++) - q->desc[i].ctrl =cpu_to_le32 (MT_DMA_CTL_DMA_DONE ); +if (!mt76_queue_is_wed_rro_ind (q)) { +int i; + +for (i =0 ; i < q->ndesc; i++) + q->desc[i].ctrl =cpu_to_le32 (MT_DMA_CTL_DMA_DONE ); + }mt76_dma_rx_cleanup (dev, q);
@@ -991,6 +1060,10 @@ void mt76_dma_cleanup(struct mt76_dev *dev)mt76_for_each_q_rx (dev, i) {struct mt76_queue *q = &dev->q_rx[i]; +if (mtk_wed_device_active (&dev->mmio.wed) && +mt76_queue_is_wed_rro (q)) +continue ; +netif_napi_del (&dev->napi[i]);mt76_dma_rx_cleanup (dev, q);
drivers/net/wireless/mediatek/mt76/dma.h +43 -0
66 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt76.h +47 -3
95 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/dma.c +184 -14
267 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/init.c +173 -2
199 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +36 -5
78 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +15 -9
@@ -963,7 +963,7 @@ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif) }static int -mt7996_mcu_sta_ba (struct mt76_dev *dev,struct mt76_vif *mvif, +mt7996_mcu_sta_ba (struct mt7996_dev *dev,struct mt76_vif *mvif,struct ieee80211_ampdu_params *params,bool enable,bool tx) {
@@ -972,7 +972,7 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,struct sk_buff *skb;struct tlv *tlv; - skb =__mt76_connac_mcu_alloc_sta_req (dev, mvif, wcid, + skb =__mt76_connac_mcu_alloc_sta_req (&dev->mt76, mvif, wcid,MT7996_STA_UPDATE_MAX_SIZE );if (IS_ERR (skb))return PTR_ERR (skb);
@@ -986,8 +986,9 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, ba->ba_en = enable << params->tid; ba->amsdu = params->amsdu; ba->tid = params->tid; + ba->ba_rdd_rro = !tx && enable && dev->has_rro; -return mt76_mcu_skb_send_msg (dev, skb, +return mt76_mcu_skb_send_msg (&dev->mt76, skb,MCU_WMWA_UNI_CMD (STA_REC_UPDATE ), true); }
@@ -1002,8 +1003,7 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,if (enable && !params->amsdu) msta->wcid.amsdu = false; -return mt7996_mcu_sta_ba (&dev->mt76, &mvif->mt76, params, - enable, true); +return mt7996_mcu_sta_ba (dev, &mvif->mt76, params, enable, true); } int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
@@ -1013,8 +1013,7 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv;struct mt7996_vif *mvif = msta->vif; -return mt7996_mcu_sta_ba (&dev->mt76, &mvif->mt76, params, - enable, false); +return mt7996_mcu_sta_ba (dev, &mvif->mt76, params, enable, false); } static void
@@ -4023,10 +4022,8 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val) { struct { u8 __rsv1[4]; - __le16 tag; __le16 len; - union { struct { u8 type;
@@ -4041,6 +4038,11 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)u8 path;u8 __rsv2[3 ]; }__packed txfree_path; +struct { +__le16 flush_one; +__le16 flush_all; +u8 __rsv2[4 ]; + } __packed timeout; }; }__packed req = { .tag =cpu_to_le16 (tag),
@@ -4057,6 +4059,10 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)case UNI_RRO_SET_TXFREE_PATH : req.txfree_path.path = val;break ; +case UNI_RRO_SET_FLUSH_TIMEOUT : + req.timeout.flush_one =cpu_to_le16 (val); + req.timeout.flush_all =cpu_to_le16 (2 * val); +break ;default :return -EINVAL ; }
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +2 -0
@@ -669,6 +669,8 @@ enum {UNI_RRO_GET_BA_SESSION_TABLE ,UNI_RRO_SET_BYPASS_MODE ,UNI_RRO_SET_TXFREE_PATH , +UNI_RRO_DEL_BA_SESSION , +UNI_RRO_SET_FLUSH_TIMEOUT }; enum{
drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +48 -12
103 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +55 -0
83 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/regs.h +58 -4
102 lines not on this page · raw message
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 11/13 mt76: move wed reset common code in mt76 module
In reply to Lorenzo BianconiMove WED reset code shared between mt7915 and mt7996 in common module. This is a preliminary patch to introduce WED reset support for mt7996.
--- drivers/net/wireless/mediatek/mt76/dma.c | 14 ++++++++++ drivers/net/wireless/mediatek/mt76/dma.h | 9 ++++++ drivers/net/wireless/mediatek/mt76/mmio.c | 8 ++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7915/dma.c | 28 ++----------------- .../net/wireless/mediatek/mt76/mt7915/mmio.c | 9 +----- 6 files changed, 36 insertions(+), 33 deletions(-)
drivers/net/wireless/mediatek/mt76/dma.c +14 -0
@@ -1036,6 +1036,20 @@ void mt76_dma_attach(struct mt76_dev *dev) }EXPORT_SYMBOL_GPL (mt76_dma_attach); +void mt76_dma_wed_reset (struct mt76_dev *dev) +{ +struct mt76_mmio *mmio = &dev->mmio; + +if (!test_bit (MT76_STATE_WED_RESET , &dev->phy.state)) +return ; + +complete (&mmio->wed_reset); + +if (!wait_for_completion_timeout (&mmio->wed_reset_complete,3 *HZ )) +dev_err (dev->dev,"wed reset complete timeout\n" ); +} +EXPORT_SYMBOL_GPL (mt76_dma_wed_reset); +void mt76_dma_cleanup (struct mt76_dev *dev) {int i;
drivers/net/wireless/mediatek/mt76/dma.h +9 -0
@@ -78,6 +78,15 @@ int mt76_dma_rx_poll(struct napi_struct *napi, int budget);void mt76_dma_attach (struct mt76_dev *dev);void mt76_dma_cleanup (struct mt76_dev *dev);int mt76_dma_wed_setup (struct mt76_dev *dev,struct mt76_queue *q,bool reset); +void mt76_dma_wed_reset (struct mt76_dev *dev); + +static inline void +mt76_dma_reset_tx_queue (struct mt76_dev *dev,struct mt76_queue *q) +{ + dev->queue_ops->reset_q (dev, q); +if (mtk_wed_device_active (&dev->mmio.wed)) +mt76_dma_wed_setup (dev, q, true); +}static inline void mt76_dma_should_drop_buf (bool *drop,u32 ctrl,u32 buf1,u32 info)
drivers/net/wireless/mediatek/mt76/mmio.c +8 -0
@@ -179,6 +179,14 @@ void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed)spin_unlock_bh (&dev->token_lock); }EXPORT_SYMBOL_GPL (mt76_mmio_wed_offload_disable); + +void mt76_mmio_wed_reset_complete (struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + +complete (&dev->mmio.wed_reset_complete); +} +EXPORT_SYMBOL_GPL (mt76_mmio_wed_reset_complete);#endif /*CONFIG_NET_MEDIATEK_SOC_WED */ void mt76_mmio_init (struct mt76_dev *dev,void __iomem *regs)
drivers/net/wireless/mediatek/mt76/mt76.h +1 -0
@@ -1102,6 +1102,7 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size);void mt76_mmio_wed_release_rx_buf (struct mtk_wed_device *wed);int mt76_mmio_wed_offload_enable (struct mtk_wed_device *wed);void mt76_mmio_wed_offload_disable (struct mtk_wed_device *wed); +void mt76_mmio_wed_reset_complete (struct mtk_wed_device *wed);#endif /*CONFIG_NET_MEDIATEK_SOC_WED */ #define mt76xx_chip (dev) mt76_chip(&((dev)->mt76))
drivers/net/wireless/mediatek/mt76/mt7915/dma.c +3 -25
@@ -587,28 +587,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)return 0 ; } -static void mt7915_dma_wed_reset (struct mt7915_dev *dev) -{ -struct mt76_dev *mdev = &dev->mt76; - -if (!test_bit (MT76_STATE_WED_RESET , &dev->mphy.state)) -return ; - -complete (&mdev->mmio.wed_reset); - -if (!wait_for_completion_timeout (&dev->mt76.mmio.wed_reset_complete, -3 *HZ )) -dev_err (dev->mt76.dev,"wed reset complete timeout\n" ); -} - -static void -mt7915_dma_reset_tx_queue (struct mt7915_dev *dev,struct mt76_queue *q) -{ -mt76_queue_reset (dev, q); -if (mtk_wed_device_active (&dev->mt76.mmio.wed)) -mt76_dma_wed_setup (&dev->mt76, q, true); -} -int mt7915_dma_reset (struct mt7915_dev *dev,bool force) {struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1 ];
@@ -636,13 +614,13 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force)mtk_wed_device_dma_reset (wed);mt7915_dma_disable (dev, force); -mt7915_dma_wed_reset (dev); +mt76_dma_wed_reset (&dev->mt76);/* reset hw queues */ for (i =0 ; i < __MT_TXQ_MAX; i++) { -mt7915_dma_reset_tx_queue (dev, dev->mphy.q_tx[i]); +mt76_dma_reset_tx_queue (&dev->mt76, dev->mphy.q_tx[i]);if (mphy_ext) -mt7915_dma_reset_tx_queue (dev, mphy_ext->q_tx[i]); +mt76_dma_reset_tx_queue (&dev->mt76, mphy_ext->q_tx[i]); }for (i =0 ; i < __MT_MCUQ_MAX; i++)
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +1 -8
@@ -595,13 +595,6 @@ static int mt7915_mmio_wed_reset(struct mtk_wed_device *wed)return ret; } - -static void mt7915_mmio_wed_reset_complete (struct mtk_wed_device *wed) -{ - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); - -complete (&dev->mmio.wed_reset_complete); -}#endif int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
@@ -685,7 +678,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf; wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats; wed->wlan.reset = mt7915_mmio_wed_reset; - wed->wlan.reset_complete = mt7915_mmio_wed_reset_complete; + wed->wlan.reset_complete = mt76_mmio_wed_reset_complete; dev->mt76.rx_token_size = wed->wlan.rx_npkt;
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 12/13 mt76: mt7996: add wed reset support
In reply to Lorenzo BianconiIntroduce the capability to reset mt7996 chipset if requested by wed driver.
--- drivers/net/wireless/mediatek/mt76/dma.c | 14 ++++-- .../net/wireless/mediatek/mt76/mt7996/dma.c | 18 +++++-- .../net/wireless/mediatek/mt76/mt7996/mac.c | 47 ++++++++++++++++++- .../net/wireless/mediatek/mt76/mt7996/mmio.c | 37 +++++++++++++++ .../net/wireless/mediatek/mt76/mt7996/regs.h | 7 ++- 5 files changed, 114 insertions(+), 9 deletions(-)
drivers/net/wireless/mediatek/mt76/dma.c +10 -4
@@ -854,10 +854,16 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)/* reset WED rx queues */ mt76_dma_wed_setup (dev, q, true); -if (!mt76_queue_is_wed_tx_free (q)) { -mt76_dma_sync_idx (dev, q); -mt76_dma_rx_fill (dev, q, false); - } + +if (mt76_queue_is_wed_tx_free (q)) +return ; + +if (mtk_wed_device_active (&dev->mmio.wed) && +mt76_queue_is_wed_rro (q)) +return ; + +mt76_dma_sync_idx (dev, q); +mt76_dma_rx_fill (dev, q, false); } static void
drivers/net/wireless/mediatek/mt76/mt7996/dma.c +15 -3
@@ -621,21 +621,33 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)if (force)mt7996_wfsys_reset (dev); +if (dev->hif2 &&mtk_wed_device_active (&dev->mt76.mmio.wed_hif2)) +mtk_wed_device_dma_reset (&dev->mt76.mmio.wed_hif2); + +if (mtk_wed_device_active (&dev->mt76.mmio.wed)) +mtk_wed_device_dma_reset (&dev->mt76.mmio.wed); +mt7996_dma_disable (dev, force); +mt76_dma_wed_reset (&dev->mt76);/* reset hw queues */ for (i =0 ; i < __MT_TXQ_MAX; i++) { -mt76_queue_reset (dev, dev->mphy.q_tx[i]); +mt76_dma_reset_tx_queue (&dev->mt76, dev->mphy.q_tx[i]);if (phy2) -mt76_queue_reset (dev, phy2->q_tx[i]); +mt76_dma_reset_tx_queue (&dev->mt76, phy2->q_tx[i]);if (phy3) -mt76_queue_reset (dev, phy3->q_tx[i]); +mt76_dma_reset_tx_queue (&dev->mt76, phy3->q_tx[i]); }for (i =0 ; i < __MT_MCUQ_MAX; i++)mt76_queue_reset (dev, dev->mt76.q_mcu[i]);mt76_for_each_q_rx (&dev->mt76, i) { +if (mtk_wed_device_active (&dev->mt76.mmio.wed)) +if (mt76_queue_is_wed_rro (&dev->mt76.q_rx[i]) || +mt76_queue_is_wed_tx_free (&dev->mt76.q_rx[i])) +continue ; +mt76_queue_reset (dev, &dev->mt76.q_rx[i]); }
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +46 -1
84 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +37 -0
@@ -6,9 +6,11 @@#include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/rtnetlink.h> #include "mt7996.h" #include "mac.h" +#include "mcu.h" #include "../trace.h" #include "../dma.h"
@@ -195,6 +197,37 @@ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)return dev->bus_ops->rmw (mdev,__mt7996_reg_addr (dev, offset), mask, val); } +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +static int mt7996_mmio_wed_reset (struct mtk_wed_device *wed) +{ + struct mt76_dev *mdev = container_of(wed, struct mt76_dev, mmio.wed); + struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); +struct mt76_phy *mphy = &dev->mphy; +int ret; + +ASSERT_RTNL (); + +if (test_and_set_bit (MT76_STATE_WED_RESET , &mphy->state)) +return -EBUSY ; + + ret =mt7996_mcu_set_ser (dev,UNI_CMD_SER_TRIGGER ,UNI_CMD_SER_SET_RECOVER_L1 , + mphy->band_idx); +if (ret) + goto out; + +rtnl_unlock (); +if (!wait_for_completion_timeout (&mdev->mmio.wed_reset,20 *HZ )) { +dev_err (mdev->dev,"wed reset timeout\n" ); + ret = -ETIMEDOUT ; + } +rtnl_lock (); +out: +clear_bit (MT76_STATE_WED_RESET , &mphy->state); + +return ret; +} +#endif +int mt7996_mmio_wed_init (struct mt7996_dev *dev,void *pdev_ptr,bool hif2,int *irq) {
@@ -311,6 +344,10 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf; wed->wlan.offload_enable = mt76_mmio_wed_offload_enable; wed->wlan.offload_disable = mt76_mmio_wed_offload_disable; +if (!hif2) { + wed->wlan.reset = mt7996_mmio_wed_reset; + wed->wlan.reset_complete = mt76_mmio_wed_reset_complete; + }if (mtk_wed_device_attach (wed))return 0 ;
drivers/net/wireless/mediatek/mt76/mt7996/regs.h +6 -1
@@ -455,8 +455,9 @@ enum base_rev {#define MT_INT_RX_DONE_WA_TRI BIT(3)#define MT_INT_RX_TXFREE_MAIN BIT(17)#define MT_INT_RX_TXFREE_TRI BIT(15) -#define MT_INT_MCU_CMD BIT(29) +#define MT_INT_RX_DONE_BAND2_EXT BIT(23)#define MT_INT_RX_TXFREE_EXT BIT(26) +#define MT_INT_MCU_CMD BIT(29)#define MT_INT_RX_DONE_RRO_BAND0 BIT(16)#define MT_INT_RX_DONE_RRO_BAND1 BIT(16)
@@ -506,6 +507,10 @@ enum base_rev {#define MT_INT_TX_DONE_BAND1 BIT(31)#define MT_INT_TX_DONE_BAND2 BIT(15) +#define MT_INT_TX_RX_DONE_EXT (MT_INT_TX_DONE_BAND2 | \ + MT_INT_RX_DONE_BAND2_EXT | \ + MT_INT_RX_TXFREE_EXT) +#define MT_INT_TX_DONE_MCU (MT_INT_TX_MCU(MT_MCUQ_WA) | \ MT_INT_TX_MCU(MT_MCUQ_WM) | \ MT_INT_TX_MCU(MT_MCUQ_FWDL))
Signature · 1 line
2.41.0
Lorenzo Bianconi
maintainerPATCH v3 13/13 wifi: mt76: mt7996: add wed rro delete session garbage collector
In reply to Lorenzo BianconiIntroduce the capability to clear WED rro session configured in the hw according to the event reported by the MCU firmware
--- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../wireless/mediatek/mt76/mt76_connac_mcu.h | 1 + .../net/wireless/mediatek/mt76/mt7996/init.c | 52 +++++++++++ .../net/wireless/mediatek/mt76/mt7996/mac.c | 3 + .../net/wireless/mediatek/mt76/mt7996/mcu.c | 89 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7996/mcu.h | 35 ++++++++ .../wireless/mediatek/mt76/mt7996/mt7996.h | 10 +++ .../net/wireless/mediatek/mt76/mt7996/regs.h | 6 ++ 8 files changed, 197 insertions(+)
drivers/net/wireless/mediatek/mt76/mt76.h +1 -0
@@ -404,6 +404,7 @@ struct mt76_rx_tid {spinlock_t lock;struct delayed_work reorder_work; +u16 id;u16 head;u16 size;u16 nframes;
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +1 -0
@@ -1022,6 +1022,7 @@ enum {MCU_UNI_EVENT_ROC =0x27 ,MCU_UNI_EVENT_TX_DONE =0x2d ,MCU_UNI_EVENT_NIC_CAPAB =0x43 , +MCU_UNI_EVENT_WED_RRO =0x57 ,MCU_UNI_EVENT_PER_STA_INFO =0x6d , MCU_UNI_EVENT_ALL_STA_INFO = 0x6e, };
drivers/net/wireless/mediatek/mt76/mt7996/init.c +52 -0
70 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +3 -0
@@ -1822,6 +1822,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)if (phy3)ieee80211_stop_queues (phy3->mt76->hw); +cancel_work_sync (&dev->wed_rro.work);cancel_delayed_work_sync (&dev->mphy.mac_work);if (phy2)cancel_delayed_work_sync (&phy2->mt76->mac_work);
@@ -1920,6 +1921,8 @@ void mt7996_mac_reset_work(struct work_struct *work)set_bit (MT76_RESET , &dev->mphy.state);set_bit (MT76_MCU_RESET , &dev->mphy.state);wake_up (&dev->mt76.mcu.wait); + +cancel_work_sync (&dev->wed_rro.work);cancel_delayed_work_sync (&dev->mphy.mac_work);if (phy2) {set_bit (MT76_RESET , &phy2->mt76->state);
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +89 -0
104 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +35 -0
@@ -179,6 +179,41 @@ struct mt7996_mcu_all_sta_info_event { }; } __packed; +struct mt7996_mcu_wed_rro_event { +struct mt7996_mcu_rxd rxd; + +u8 __rsv1[4 ]; + +__le16 tag; +__le16 len; +} __packed; + +struct mt7996_mcu_wed_rro_ba_event { +__le16 tag; +__le16 len; + +__le16 wlan_id; +u8 tid; +u8 __rsv1; +__le32 status; +__le16 id; +u8 __rsv2[2 ]; +} __packed; + +struct mt7996_mcu_wed_rro_ba_delete_event { +__le16 tag; +__le16 len; + +__le16 session_id; +u8 __rsv2[2 ]; +} __packed; + +enum { +UNI_WED_RRO_BA_SESSION_STATUS , +UNI_WED_RRO_BA_SESSION_TBL , +UNI_WED_RRO_BA_SESSION_DELETE , +}; +enum mt7996_chan_mib_offs {UNI_MIB_OBSS_AIRTIME =26 ,UNI_MIB_NON_WIFI_TIME =27 ,
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +10 -0
@@ -182,6 +182,11 @@ struct mt7996_wed_rro_addr { u32 signature : 8; }; +struct mt7996_wed_rro_session_id { +struct list_head list; +u16 id; +}; +struct mt7996_phy {struct mt76_phy *mt76;struct mt7996_dev *dev;
@@ -276,6 +281,10 @@ struct mt7996_dev {void *ptr;dma_addr_t phy_addr; } session; + +struct work_struct work; +struct list_head poll_list; +spinlock_t lock; } wed_rro;bool ibf;
@@ -456,6 +465,7 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);void mt7996_mcu_rx_event (struct mt7996_dev *dev,struct sk_buff *skb);void mt7996_mcu_exit (struct mt7996_dev *dev);int mt7996_mcu_get_all_sta_info (struct mt7996_phy *phy,u16 tag); +int mt7996_mcu_wed_rro_reset_sessions (struct mt7996_dev *dev,u16 id);static inline u8 mt7996_max_interface_num (struct mt7996_dev *dev) {
drivers/net/wireless/mediatek/mt76/mt7996/regs.h +6 -0
@@ -71,6 +71,12 @@ enum base_rev {#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0) +#define MT_RRO_DBG_RD_CTRL MT_RRO_TOP(0xe0) +#define MT_RRO_DBG_RD_ADDR GENMASK(15, 0) +#define MT_RRO_DBG_RD_EXEC BIT(31) + +#define MT_RRO_DBG_RDAT_DW (_n) MT_RRO_TOP(0xf0 + (_n) * 0x4) +#define MT_MCU_INT_EVENT 0x2108#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)#define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
Signature · 1 line
2.41.0