mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
wifi: mt76: Introduce the NPU generic layer
Add the NPU generic layer in mt76 module. NPU will be used to enable traffic forward offloading between the MT76 NIC and the Airoha ethernet one available on the Airoha EN7581 SoC using Netfilter Flowtable APIs. Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20251017-mt76-npu-devel-v2-4-ddaa90901723@kernel.org Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
committed by
Felix Fietkau
parent
f7632a7fdd
commit
7fb554b1b6
@@ -37,6 +37,10 @@ config MT792x_USB
|
||||
tristate
|
||||
select MT76_USB
|
||||
|
||||
config MT76_NPU
|
||||
bool
|
||||
depends on MT76_CORE
|
||||
|
||||
source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig"
|
||||
source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
|
||||
source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig"
|
||||
|
||||
@@ -12,6 +12,7 @@ mt76-y := \
|
||||
mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
|
||||
tx.o agg-rx.o mcu.o wed.o scan.o channel.o
|
||||
|
||||
mt76-$(CONFIG_MT76_NPU) += npu.o
|
||||
mt76-$(CONFIG_PCI) += pci.o
|
||||
mt76-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
|
||||
|
||||
@@ -189,10 +189,15 @@ static void
|
||||
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
Q_WRITE(q, desc_base, q->desc_dma);
|
||||
if (q->flags & MT_QFLAG_WED_RRO_EN)
|
||||
if ((q->flags & MT_QFLAG_WED_RRO_EN) && !mt76_npu_device_active(dev))
|
||||
Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc);
|
||||
else
|
||||
Q_WRITE(q, ring_size, q->ndesc);
|
||||
|
||||
if (mt76_queue_is_npu_tx(q)) {
|
||||
writel(q->desc_dma, &q->regs->desc_base);
|
||||
writel(q->ndesc, &q->regs->ring_size);
|
||||
}
|
||||
q->head = Q_READ(q, dma_idx);
|
||||
q->tail = q->head;
|
||||
}
|
||||
@@ -204,7 +209,7 @@ void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
return;
|
||||
|
||||
if (!mt76_queue_is_wed_rro_ind(q) &&
|
||||
!mt76_queue_is_wed_rro_rxdmad_c(q)) {
|
||||
!mt76_queue_is_wed_rro_rxdmad_c(q) && !mt76_queue_is_npu(q)) {
|
||||
int i;
|
||||
|
||||
/* clear descriptors */
|
||||
@@ -415,6 +420,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
|
||||
|
||||
while (q->queued > 0 && q->tail != last) {
|
||||
mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry);
|
||||
mt76_npu_txdesc_cleanup(q, q->tail);
|
||||
mt76_queue_tx_complete(dev, q, &entry);
|
||||
|
||||
if (entry.txwi) {
|
||||
@@ -649,6 +655,10 @@ mt76_dma_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q,
|
||||
if (test_bit(MT76_RESET, &phy->state))
|
||||
goto free_skb;
|
||||
|
||||
/* TODO: Take into account unlinear skbs */
|
||||
if (mt76_npu_device_active(dev) && skb_linearize(skb))
|
||||
goto free_skb;
|
||||
|
||||
t = mt76_get_txwi(dev);
|
||||
if (!t)
|
||||
goto free_skb;
|
||||
@@ -696,6 +706,9 @@ mt76_dma_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q,
|
||||
if (ret < 0)
|
||||
goto unmap;
|
||||
|
||||
if (mt76_npu_device_active(dev))
|
||||
return mt76_npu_dma_add_buf(phy, q, skb, &tx_info.buf[1], txwi);
|
||||
|
||||
return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
|
||||
tx_info.info, tx_info.skb, t);
|
||||
|
||||
@@ -796,8 +809,15 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
q->hw_idx = idx;
|
||||
q->dev = dev;
|
||||
|
||||
size = mt76_queue_is_wed_rro_ind(q) ? sizeof(struct mt76_wed_rro_desc)
|
||||
: sizeof(struct mt76_desc);
|
||||
if (mt76_queue_is_wed_rro_ind(q))
|
||||
size = sizeof(struct mt76_wed_rro_desc);
|
||||
else if (mt76_queue_is_npu_tx(q))
|
||||
size = sizeof(struct airoha_npu_tx_dma_desc);
|
||||
else if (mt76_queue_is_npu_rx(q))
|
||||
size = sizeof(struct airoha_npu_rx_dma_desc);
|
||||
else
|
||||
size = sizeof(struct mt76_desc);
|
||||
|
||||
q->desc = dmam_alloc_coherent(dev->dma_dev, q->ndesc * size,
|
||||
&q->desc_dma, GFP_KERNEL);
|
||||
if (!q->desc)
|
||||
@@ -813,6 +833,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76_npu_queue_setup(dev, q);
|
||||
ret = mt76_wed_dma_setup(dev, q, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -840,6 +861,11 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
if (!q->ndesc)
|
||||
return;
|
||||
|
||||
if (mt76_queue_is_npu(q)) {
|
||||
mt76_npu_queue_cleanup(dev, q);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
spin_lock_bh(&q->lock);
|
||||
buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more, NULL);
|
||||
@@ -870,7 +896,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
|
||||
return;
|
||||
|
||||
if (!mt76_queue_is_wed_rro_ind(q) &&
|
||||
!mt76_queue_is_wed_rro_rxdmad_c(q)) {
|
||||
!mt76_queue_is_wed_rro_rxdmad_c(q) && !mt76_queue_is_npu(q)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < q->ndesc; i++)
|
||||
@@ -890,7 +916,10 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
|
||||
return;
|
||||
|
||||
mt76_dma_sync_idx(dev, q);
|
||||
mt76_dma_rx_fill_buf(dev, q, false);
|
||||
if (mt76_queue_is_npu(q))
|
||||
mt76_npu_fill_rx_queue(dev, q);
|
||||
else
|
||||
mt76_dma_rx_fill(dev, q, false);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -70,6 +70,42 @@
|
||||
writel(_val, &(_q)->regs->_field); \
|
||||
} while (0)
|
||||
|
||||
#elif IS_ENABLED(CONFIG_MT76_NPU)
|
||||
|
||||
#define Q_READ(_q, _field) ({ \
|
||||
u32 _offset = offsetof(struct mt76_queue_regs, _field); \
|
||||
u32 _val = 0; \
|
||||
if ((_q)->flags & MT_QFLAG_NPU) { \
|
||||
struct airoha_npu *npu; \
|
||||
\
|
||||
rcu_read_lock(); \
|
||||
npu = rcu_dereference(q->dev->mmio.npu); \
|
||||
if (npu) \
|
||||
regmap_read(npu->regmap, \
|
||||
((_q)->wed_regs + _offset), &_val); \
|
||||
rcu_read_unlock(); \
|
||||
} else { \
|
||||
_val = readl(&(_q)->regs->_field); \
|
||||
} \
|
||||
_val; \
|
||||
})
|
||||
|
||||
#define Q_WRITE(_q, _field, _val) do { \
|
||||
u32 _offset = offsetof(struct mt76_queue_regs, _field); \
|
||||
if ((_q)->flags & MT_QFLAG_NPU) { \
|
||||
struct airoha_npu *npu; \
|
||||
\
|
||||
rcu_read_lock(); \
|
||||
npu = rcu_dereference(q->dev->mmio.npu); \
|
||||
if (npu) \
|
||||
regmap_write(npu->regmap, \
|
||||
((_q)->wed_regs + _offset), _val); \
|
||||
rcu_read_unlock(); \
|
||||
} else { \
|
||||
writel(_val, &(_q)->regs->_field); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define Q_READ(_q, _field) readl(&(_q)->regs->_field)
|
||||
|
||||
@@ -630,6 +630,8 @@ int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
case MT_RXQ_MAIN:
|
||||
case MT_RXQ_BAND1:
|
||||
case MT_RXQ_BAND2:
|
||||
case MT_RXQ_NPU0:
|
||||
case MT_RXQ_NPU1:
|
||||
pp_params.pool_size = 256;
|
||||
break;
|
||||
default:
|
||||
@@ -814,6 +816,7 @@ void mt76_free_device(struct mt76_dev *dev)
|
||||
destroy_workqueue(dev->wq);
|
||||
dev->wq = NULL;
|
||||
}
|
||||
mt76_npu_deinit(dev);
|
||||
ieee80211_free_hw(dev->hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_free_device);
|
||||
@@ -1553,7 +1556,8 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
|
||||
|
||||
while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) {
|
||||
mt76_check_sta(dev, skb);
|
||||
if (mtk_wed_device_active(&dev->mmio.wed))
|
||||
if (mtk_wed_device_active(&dev->mmio.wed) ||
|
||||
mt76_npu_device_active(dev))
|
||||
__skb_queue_tail(&frames, skb);
|
||||
else
|
||||
mt76_rx_aggr_reorder(skb, &frames);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/leds.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/average.h>
|
||||
#include <linux/soc/airoha/airoha_offload.h>
|
||||
#include <linux/soc/mediatek/mtk_wed.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
@@ -34,6 +35,7 @@
|
||||
#define MT_QFLAG_WED_RRO BIT(6)
|
||||
#define MT_QFLAG_WED_RRO_EN BIT(7)
|
||||
#define MT_QFLAG_EMI_EN BIT(8)
|
||||
#define MT_QFLAG_NPU BIT(9)
|
||||
|
||||
#define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \
|
||||
FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
|
||||
@@ -48,6 +50,12 @@
|
||||
#define MT_WED_RRO_Q_IND __MT_WED_RRO_Q(MT76_WED_RRO_Q_IND, 0)
|
||||
#define MT_WED_RRO_Q_RXDMAD_C __MT_WED_RRO_Q(MT76_WED_RRO_Q_RXDMAD_C, 0)
|
||||
|
||||
#define __MT_NPU_Q(_type, _n) (MT_QFLAG_NPU | \
|
||||
FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
|
||||
FIELD_PREP(MT_QFLAG_WED_RING, _n))
|
||||
#define MT_NPU_Q_TX(_n) __MT_NPU_Q(MT76_WED_Q_TX, _n)
|
||||
#define MT_NPU_Q_RX(_n) __MT_NPU_Q(MT76_WED_Q_RX, _n)
|
||||
|
||||
struct mt76_dev;
|
||||
struct mt76_phy;
|
||||
struct mt76_wcid;
|
||||
@@ -139,6 +147,8 @@ enum mt76_rxq_id {
|
||||
MT_RXQ_TXFREE_BAND2,
|
||||
MT_RXQ_RRO_IND,
|
||||
MT_RXQ_RRO_RXDMAD_C,
|
||||
MT_RXQ_NPU0,
|
||||
MT_RXQ_NPU1,
|
||||
__MT_RXQ_MAX
|
||||
};
|
||||
|
||||
@@ -707,6 +717,11 @@ struct mt76_mmio {
|
||||
struct mtk_wed_device wed_hif2;
|
||||
struct completion wed_reset;
|
||||
struct completion wed_reset_complete;
|
||||
|
||||
struct airoha_ppe_dev __rcu *ppe_dev;
|
||||
struct airoha_npu __rcu *npu;
|
||||
phys_addr_t phy_addr;
|
||||
int npu_type;
|
||||
};
|
||||
|
||||
struct mt76_rx_status {
|
||||
@@ -1617,6 +1632,109 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state);
|
||||
int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len);
|
||||
|
||||
#ifdef CONFIG_MT76_NPU
|
||||
void mt76_npu_check_ppe(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
u32 info);
|
||||
int mt76_npu_dma_add_buf(struct mt76_phy *phy, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_queue_buf *buf,
|
||||
void *txwi_ptr);
|
||||
int mt76_npu_rx_queue_init(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
int mt76_npu_fill_rx_queue(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
void mt76_npu_queue_cleanup(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
void mt76_npu_disable_irqs(struct mt76_dev *dev);
|
||||
int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr, int type);
|
||||
void mt76_npu_deinit(struct mt76_dev *dev);
|
||||
void mt76_npu_queue_setup(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
void mt76_npu_txdesc_cleanup(struct mt76_queue *q, int index);
|
||||
int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct net_device *dev, enum tc_setup_type type,
|
||||
void *type_data);
|
||||
#else
|
||||
static inline void mt76_npu_check_ppe(struct mt76_dev *dev,
|
||||
struct sk_buff *skb, u32 info)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mt76_npu_dma_add_buf(struct mt76_phy *phy,
|
||||
struct mt76_queue *q,
|
||||
struct sk_buff *skb,
|
||||
struct mt76_queue_buf *buf,
|
||||
void *txwi_ptr)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int mt76_npu_fill_rx_queue(struct mt76_dev *dev,
|
||||
struct mt76_queue *q)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mt76_npu_queue_cleanup(struct mt76_dev *dev,
|
||||
struct mt76_queue *q)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mt76_npu_disable_irqs(struct mt76_dev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr,
|
||||
int type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mt76_npu_deinit(struct mt76_dev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mt76_npu_queue_setup(struct mt76_dev *dev,
|
||||
struct mt76_queue *q)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mt76_npu_txdesc_cleanup(struct mt76_queue *q,
|
||||
int index)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mt76_npu_net_setup_tc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct net_device *dev,
|
||||
enum tc_setup_type type,
|
||||
void *type_data)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* CONFIG_MT76_NPU */
|
||||
|
||||
static inline bool mt76_npu_device_active(struct mt76_dev *dev)
|
||||
{
|
||||
return !!rcu_access_pointer(dev->mmio.npu);
|
||||
}
|
||||
|
||||
static inline bool mt76_ppe_device_active(struct mt76_dev *dev)
|
||||
{
|
||||
return !!rcu_access_pointer(dev->mmio.ppe_dev);
|
||||
}
|
||||
|
||||
static inline int mt76_npu_send_msg(struct airoha_npu *npu, int ifindex,
|
||||
enum airoha_npu_wlan_set_cmd cmd,
|
||||
u32 val, gfp_t gfp)
|
||||
{
|
||||
return airoha_npu_wlan_send_msg(npu, ifindex, cmd, &val, sizeof(val),
|
||||
gfp);
|
||||
}
|
||||
|
||||
static inline int mt76_npu_get_msg(struct airoha_npu *npu, int ifindex,
|
||||
enum airoha_npu_wlan_get_cmd cmd,
|
||||
u32 *val, gfp_t gfp)
|
||||
{
|
||||
return airoha_npu_wlan_get_msg(npu, ifindex, cmd, val, sizeof(*val),
|
||||
gfp);
|
||||
}
|
||||
|
||||
static inline void mt76_testmode_reset(struct mt76_phy *phy, bool disable)
|
||||
{
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
@@ -1858,6 +1976,23 @@ static inline bool mt76_queue_is_emi(struct mt76_queue *q)
|
||||
return q->flags & MT_QFLAG_EMI_EN;
|
||||
}
|
||||
|
||||
static inline bool mt76_queue_is_npu(struct mt76_queue *q)
|
||||
{
|
||||
return q->flags & MT_QFLAG_NPU;
|
||||
}
|
||||
|
||||
static inline bool mt76_queue_is_npu_tx(struct mt76_queue *q)
|
||||
{
|
||||
return mt76_queue_is_npu(q) &&
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TX;
|
||||
}
|
||||
|
||||
static inline bool mt76_queue_is_npu_rx(struct mt76_queue *q)
|
||||
{
|
||||
return mt76_queue_is_npu(q) &&
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
|
||||
}
|
||||
|
||||
struct mt76_txwi_cache *
|
||||
mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
|
||||
int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@
|
||||
#ifndef AIROHA_OFFLOAD_H
|
||||
#define AIROHA_OFFLOAD_H
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user