1 /* SPDX-License-Identifier: ISC */
8 mt7603_init_tx_queue(struct mt7603_dev
*dev
, struct mt76_queue
*q
,
14 q
->regs
= dev
->mt76
.mmio
.regs
+ MT_TX_RING_BASE
+ idx
* MT_RING_SIZE
;
17 ret
= mt76_queue_alloc(dev
, q
);
21 mt7603_irq_enable(dev
, MT_INT_TX_DONE(idx
));
27 mt7603_rx_loopback_skb(struct mt7603_dev
*dev
, struct sk_buff
*skb
)
29 __le32
*txd
= (__le32
*)skb
->data
;
30 struct mt7603_sta
*msta
;
31 struct mt76_wcid
*wcid
;
35 if (skb
->len
< sizeof(MT_TXD_SIZE
) + sizeof(struct ieee80211_hdr
))
38 val
= le32_to_cpu(txd
[1]);
39 idx
= FIELD_GET(MT_TXD1_WLAN_IDX
, val
);
40 skb
->priority
= FIELD_GET(MT_TXD1_TID
, val
);
42 if (idx
>= MT7603_WTBL_STA
- 1)
45 wcid
= rcu_dereference(dev
->mt76
.wcid
[idx
]);
49 msta
= container_of(wcid
, struct mt7603_sta
, wcid
);
50 val
= le32_to_cpu(txd
[0]);
51 skb_set_queue_mapping(skb
, FIELD_GET(MT_TXD0_Q_IDX
, val
));
53 spin_lock_bh(&dev
->ps_lock
);
54 __skb_queue_tail(&msta
->psq
, skb
);
55 if (skb_queue_len(&msta
->psq
) >= 64) {
56 skb
= __skb_dequeue(&msta
->psq
);
59 spin_unlock_bh(&dev
->ps_lock
);
66 void mt7603_queue_rx_skb(struct mt76_dev
*mdev
, enum mt76_rxq_id q
,
69 struct mt7603_dev
*dev
= container_of(mdev
, struct mt7603_dev
, mt76
);
70 __le32
*rxd
= (__le32
*)skb
->data
;
71 __le32
*end
= (__le32
*)&skb
->data
[skb
->len
];
72 enum rx_pkt_type type
;
74 type
= FIELD_GET(MT_RXD0_PKT_TYPE
, le32_to_cpu(rxd
[0]));
76 if (q
== MT_RXQ_MCU
) {
77 if (type
== PKT_TYPE_RX_EVENT
)
78 mt76_mcu_rx_event(&dev
->mt76
, skb
);
80 mt7603_rx_loopback_skb(dev
, skb
);
86 for (rxd
++; rxd
+ 5 <= end
; rxd
+= 5)
87 mt7603_mac_add_txs(dev
, rxd
);
90 case PKT_TYPE_RX_EVENT
:
91 mt76_mcu_rx_event(&dev
->mt76
, skb
);
94 if (mt7603_mac_fill_rx(dev
, skb
) == 0) {
95 mt76_rx(&dev
->mt76
, q
, skb
);
106 mt7603_init_rx_queue(struct mt7603_dev
*dev
, struct mt76_queue
*q
,
107 int idx
, int n_desc
, int bufsize
)
111 q
->regs
= dev
->mt76
.mmio
.regs
+ MT_RX_RING_BASE
+ idx
* MT_RING_SIZE
;
113 q
->buf_size
= bufsize
;
115 ret
= mt76_queue_alloc(dev
, q
);
119 mt7603_irq_enable(dev
, MT_INT_RX_DONE(idx
));
125 mt7603_tx_tasklet(unsigned long data
)
127 struct mt7603_dev
*dev
= (struct mt7603_dev
*)data
;
130 dev
->tx_dma_check
= 0;
131 for (i
= MT_TXQ_MCU
; i
>= 0; i
--)
132 mt76_queue_tx_cleanup(dev
, i
, false);
134 mt7603_irq_enable(dev
, MT_INT_TX_DONE_ALL
);
137 int mt7603_dma_init(struct mt7603_dev
*dev
)
139 static const u8 wmm_queue_map
[] = {
140 [IEEE80211_AC_BK
] = 0,
141 [IEEE80211_AC_BE
] = 1,
142 [IEEE80211_AC_VI
] = 2,
143 [IEEE80211_AC_VO
] = 3,
148 mt76_dma_attach(&dev
->mt76
);
150 init_waitqueue_head(&dev
->mt76
.mmio
.mcu
.wait
);
151 skb_queue_head_init(&dev
->mt76
.mmio
.mcu
.res_q
);
153 tasklet_init(&dev
->tx_tasklet
, mt7603_tx_tasklet
, (unsigned long)dev
);
155 mt76_clear(dev
, MT_WPDMA_GLO_CFG
,
156 MT_WPDMA_GLO_CFG_TX_DMA_EN
|
157 MT_WPDMA_GLO_CFG_RX_DMA_EN
|
158 MT_WPDMA_GLO_CFG_DMA_BURST_SIZE
|
159 MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE
);
161 mt76_wr(dev
, MT_WPDMA_RST_IDX
, ~0);
162 mt7603_pse_client_reset(dev
);
164 for (i
= 0; i
< ARRAY_SIZE(wmm_queue_map
); i
++) {
165 ret
= mt7603_init_tx_queue(dev
, &dev
->mt76
.q_tx
[i
],
172 ret
= mt7603_init_tx_queue(dev
, &dev
->mt76
.q_tx
[MT_TXQ_PSD
],
173 MT_TX_HW_QUEUE_MGMT
, MT_TX_RING_SIZE
);
177 ret
= mt7603_init_tx_queue(dev
, &dev
->mt76
.q_tx
[MT_TXQ_MCU
],
178 MT_TX_HW_QUEUE_MCU
, MT_MCU_RING_SIZE
);
182 ret
= mt7603_init_tx_queue(dev
, &dev
->mt76
.q_tx
[MT_TXQ_BEACON
],
183 MT_TX_HW_QUEUE_BCN
, MT_MCU_RING_SIZE
);
187 ret
= mt7603_init_tx_queue(dev
, &dev
->mt76
.q_tx
[MT_TXQ_CAB
],
188 MT_TX_HW_QUEUE_BMC
, MT_MCU_RING_SIZE
);
192 ret
= mt7603_init_rx_queue(dev
, &dev
->mt76
.q_rx
[MT_RXQ_MCU
], 1,
193 MT_MCU_RING_SIZE
, MT_RX_BUF_SIZE
);
197 ret
= mt7603_init_rx_queue(dev
, &dev
->mt76
.q_rx
[MT_RXQ_MAIN
], 0,
198 MT7603_RX_RING_SIZE
, MT_RX_BUF_SIZE
);
202 mt76_wr(dev
, MT_DELAY_INT_CFG
, 0);
203 return mt76_init_queues(dev
);
206 void mt7603_dma_cleanup(struct mt7603_dev
*dev
)
208 mt76_clear(dev
, MT_WPDMA_GLO_CFG
,
209 MT_WPDMA_GLO_CFG_TX_DMA_EN
|
210 MT_WPDMA_GLO_CFG_RX_DMA_EN
|
211 MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE
);
213 tasklet_kill(&dev
->tx_tasklet
);
214 mt76_dma_cleanup(&dev
->mt76
);