diff --git a/mt7603.h b/mt7603.h index 9dc090f4..2e644748 100644 --- a/mt7603.h +++ b/mt7603.h @@ -114,6 +114,7 @@ static inline void mt7603_irq_disable(struct mt7603_dev *dev, u32 mask) void mt7603_mac_start(struct mt7603_dev *dev); void mt7603_mac_stop(struct mt7603_dev *dev); +int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb); int mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def); int mt7603_mcu_set_channel(struct mt7603_dev *dev); diff --git a/mt7603_dma.c b/mt7603_dma.c index 30b85696..c1da0ec3 100644 --- a/mt7603_dma.c +++ b/mt7603_dma.c @@ -146,6 +146,12 @@ mt7603_process_rx_skb(struct mt7603_dev *dev, struct mt76_queue *q, skb_queue_tail(&dev->mcu.res_q, skb); wake_up(&dev->mcu.wait); return; + case PKT_TYPE_NORMAL: + if (mt7603_mac_fill_rx(dev, skb) == 0) { + ieee80211_rx(mt76_hw(dev), skb); + return; + } + /* fall through */ default: dev_kfree_skb(skb); } diff --git a/mt7603_dma.h b/mt7603_dma.h index 60254ba8..eea58dd9 100644 --- a/mt7603_dma.h +++ b/mt7603_dma.h @@ -16,8 +16,17 @@ #include "dma.h" +#define MT_RXD0_LENGTH GENMASK(15, 0) #define MT_RXD0_PKT_TYPE GENMASK(31, 29) +#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) +#define MT_RXD0_NORMAL_IP_SUM BIT(23) +#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) +#define MT_RXD0_NORMAL_GROUP_1 BIT(25) +#define MT_RXD0_NORMAL_GROUP_2 BIT(26) +#define MT_RXD0_NORMAL_GROUP_3 BIT(27) +#define MT_RXD0_NORMAL_GROUP_4 BIT(28) + enum rx_pkt_type { PKT_TYPE_TXS = 0, PKT_TYPE_TXRXV = 1, diff --git a/mt7603_mac.c b/mt7603_mac.c index 3e8481ed..70f935b7 100644 --- a/mt7603_mac.c +++ b/mt7603_mac.c @@ -12,6 +12,7 @@ */ #include "mt7603.h" +#include "mt7603_dma.h" #define MT_PSE_PAGE_SIZE 128 @@ -107,6 +108,41 @@ void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx) mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); } +int +mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) +{ + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + __le32 *rxd = (__le32 *) skb->data; + u32 rxd0 = le32_to_cpu(rxd[0]); + + rxd += 4; + if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { + rxd += 4; + if ((u8 *) rxd - skb->data >= skb->len) + return -EINVAL; + } + if (rxd0 & MT_RXD0_NORMAL_GROUP_1) { + rxd += 4; + if ((u8 *) rxd - skb->data >= skb->len) + return -EINVAL; + } + if (rxd0 & MT_RXD0_NORMAL_GROUP_2) { + rxd += 2; + if ((u8 *) rxd - skb->data >= skb->len) + return -EINVAL; + } + if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { + rxd += 6; + if ((u8 *) rxd - skb->data >= skb->len) + return -EINVAL; + } + + memset(status, 0, sizeof(*status)); + skb_pull(skb, (u8 *) rxd - skb->data); + + return 0; +} + void mt7603_mac_start(struct mt7603_dev *dev) { mt76_clear(dev, MT_WF_ARB_SCR, MT_WF_ARB_TX_DISABLE | MT_WF_ARB_RX_DISABLE);