diff --git a/package/kernel/mt76/patches/0149-npu-wlan-offload-l2.patch b/package/kernel/mt76/patches/0149-npu-wlan-offload-l2.patch new file mode 100644 index 00000000000000..549f8808fb5e79 --- /dev/null +++ b/package/kernel/mt76/patches/0149-npu-wlan-offload-l2.patch @@ -0,0 +1,118 @@ +--- a/mt76.h ++++ b/mt76.h +@@ -1778,6 +1778,8 @@ int mt76_testmode_set_state(struct mt76_ + int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len); + + int mt76_npu_rx_poll(struct napi_struct *napi, int budget); ++void mt76_npu_check_ppe(struct mt76_dev *dev, struct sk_buff *skb, ++ u32 info); + int mt76_npu_rx_queue_init(struct mt76_dev *dev, struct mt76_queue *q); + int mt76_npu_dma_add_buf(struct mt76_phy *phy, struct mt76_queue *q, + struct sk_buff *skb, struct mt76_queue_buf *buf, +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -624,6 +624,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *de + status->flag |= RX_FLAG_8023; + mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], mlink ? mlink->sta : NULL, skb, + *info); ++ mt76_npu_check_ppe(&dev->mt76, skb, *info); + } + + if (rxv && !(status->flag & RX_FLAG_8023) && +--- a/npu.c ++++ b/npu.c +@@ -70,13 +70,12 @@ static void mt76_npu_queue_cleanup(struc + } + + static struct sk_buff *mt76_npu_dequeue(struct mt76_dev *dev, +- struct airoha_ppe_dev *ppe_dev, +- struct mt76_queue *q) ++ struct mt76_queue *q, ++ u32 *info) + { + struct airoha_npu_rx_dma_desc *desc = q->desc; + int i, nframes, index = q->tail; + struct sk_buff *skb = NULL; +- u16 hash, reason; + + nframes = FIELD_GET(NPU_RX_DMA_PKT_COUNT_MASK, desc[index].info); + nframes = max_t(int, nframes, 1); +@@ -113,27 +112,46 @@ static struct sk_buff *mt76_npu_dequeue( + len, q->buf_size); + } + +- hash = FIELD_GET(NPU_RX_DMA_FOE_ID_MASK, desc[index].info); +- reason = FIELD_GET(NPU_RX_DMA_CRSN_MASK, desc[index].info); +- ++ *info = desc[index].info; + index = (index + 1) % q->ndesc; + } + q->tail = index; + q->queued -= i; + Q_WRITE(q, dma_idx, q->tail); + +- if (skb) { +- skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); +- if (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) +- ppe_dev->ops.check_skb(ppe_dev, skb, hash, true); +- } +- + return skb; + } + +-int mt76_npu_rx_poll(struct napi_struct *napi, int budget) ++void mt76_npu_check_ppe(struct mt76_dev *dev, struct sk_buff *skb, ++ u32 info) + { + struct airoha_ppe_dev *ppe_dev; ++ u16 reason, hash; ++ ++ if (!mt76_npu_device_active(dev)) ++ return; ++ ++ rcu_read_lock(); ++ ++ ppe_dev = rcu_dereference(dev->mmio.ppe_dev); ++ if (!ppe_dev) ++ goto out; ++ ++ hash = FIELD_GET(NPU_RX_DMA_FOE_ID_MASK, info); ++ skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); ++ ++ reason = FIELD_GET(NPU_RX_DMA_CRSN_MASK, info); ++ if (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) { ++ skb_set_mac_header(skb, 0); ++ ppe_dev->ops.check_skb(ppe_dev, skb, hash, true); ++ } ++out: ++ rcu_read_unlock(); ++} ++EXPORT_SYMBOL_GPL(mt76_npu_check_ppe); ++ ++int mt76_npu_rx_poll(struct napi_struct *napi, int budget) ++{ + struct airoha_npu *npu; + enum mt76_rxq_id qid; + struct mt76_dev *dev; +@@ -148,18 +166,15 @@ int mt76_npu_rx_poll(struct napi_struct + if (!npu) + goto out; + +- ppe_dev = rcu_dereference(dev->mmio.ppe_dev); +- if (!ppe_dev) +- goto out; +- + while (done < budget) { + struct sk_buff *skb; ++ u32 info = 0; + +- skb = mt76_npu_dequeue(dev, ppe_dev, &dev->q_rx[qid]); ++ skb = mt76_npu_dequeue(dev, &dev->q_rx[qid], &info); + if (!skb) + break; + +- dev->drv->rx_skb(dev, qid, skb, 0); ++ dev->drv->rx_skb(dev, qid, skb, &info); + mt76_rx_poll_complete(dev, qid, napi); + done++; + }