xref: /linux/drivers/net/wireless/mediatek/mt76/mt7603/mac.c (revision b5903c470328b15f828ebb9c42da63da6d0cf8a1)
1c8846e10SFelix Fietkau /* SPDX-License-Identifier: ISC */
2c8846e10SFelix Fietkau 
3c8846e10SFelix Fietkau #include <linux/etherdevice.h>
4c8846e10SFelix Fietkau #include <linux/timekeeping.h>
5c8846e10SFelix Fietkau #include "mt7603.h"
6c8846e10SFelix Fietkau #include "mac.h"
7c8846e10SFelix Fietkau 
8c8846e10SFelix Fietkau #define MT_PSE_PAGE_SIZE	128
9c8846e10SFelix Fietkau 
10c8846e10SFelix Fietkau static u32
11c8846e10SFelix Fietkau mt7603_ac_queue_mask0(u32 mask)
12c8846e10SFelix Fietkau {
13c8846e10SFelix Fietkau 	u32 ret = 0;
14c8846e10SFelix Fietkau 
15c8846e10SFelix Fietkau 	ret |= GENMASK(3, 0) * !!(mask & BIT(0));
16c8846e10SFelix Fietkau 	ret |= GENMASK(8, 5) * !!(mask & BIT(1));
17c8846e10SFelix Fietkau 	ret |= GENMASK(13, 10) * !!(mask & BIT(2));
18c8846e10SFelix Fietkau 	ret |= GENMASK(19, 16) * !!(mask & BIT(3));
19c8846e10SFelix Fietkau 	return ret;
20c8846e10SFelix Fietkau }
21c8846e10SFelix Fietkau 
22c8846e10SFelix Fietkau static void
23c8846e10SFelix Fietkau mt76_stop_tx_ac(struct mt7603_dev *dev, u32 mask)
24c8846e10SFelix Fietkau {
25c8846e10SFelix Fietkau 	mt76_set(dev, MT_WF_ARB_TX_STOP_0, mt7603_ac_queue_mask0(mask));
26c8846e10SFelix Fietkau }
27c8846e10SFelix Fietkau 
28c8846e10SFelix Fietkau static void
29c8846e10SFelix Fietkau mt76_start_tx_ac(struct mt7603_dev *dev, u32 mask)
30c8846e10SFelix Fietkau {
31c8846e10SFelix Fietkau 	mt76_set(dev, MT_WF_ARB_TX_START_0, mt7603_ac_queue_mask0(mask));
32c8846e10SFelix Fietkau }
33c8846e10SFelix Fietkau 
34c8846e10SFelix Fietkau void mt7603_mac_set_timing(struct mt7603_dev *dev)
35c8846e10SFelix Fietkau {
36c8846e10SFelix Fietkau 	u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
37c8846e10SFelix Fietkau 		  FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
38c8846e10SFelix Fietkau 	u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
39c8846e10SFelix Fietkau 		   FIELD_PREP(MT_TIMEOUT_VAL_CCA, 24);
40c8846e10SFelix Fietkau 	int offset = 3 * dev->coverage_class;
41c8846e10SFelix Fietkau 	u32 reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
42c8846e10SFelix Fietkau 			 FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
43c8846e10SFelix Fietkau 	int sifs;
44c8846e10SFelix Fietkau 	u32 val;
45c8846e10SFelix Fietkau 
46c8846e10SFelix Fietkau 	if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ)
47c8846e10SFelix Fietkau 		sifs = 16;
48c8846e10SFelix Fietkau 	else
49c8846e10SFelix Fietkau 		sifs = 10;
50c8846e10SFelix Fietkau 
51c8846e10SFelix Fietkau 	mt76_set(dev, MT_ARB_SCR,
52c8846e10SFelix Fietkau 		 MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
53c8846e10SFelix Fietkau 	udelay(1);
54c8846e10SFelix Fietkau 
55c8846e10SFelix Fietkau 	mt76_wr(dev, MT_TIMEOUT_CCK, cck + reg_offset);
56c8846e10SFelix Fietkau 	mt76_wr(dev, MT_TIMEOUT_OFDM, ofdm + reg_offset);
57c8846e10SFelix Fietkau 	mt76_wr(dev, MT_IFS,
58c8846e10SFelix Fietkau 		FIELD_PREP(MT_IFS_EIFS, 360) |
59c8846e10SFelix Fietkau 		FIELD_PREP(MT_IFS_RIFS, 2) |
60c8846e10SFelix Fietkau 		FIELD_PREP(MT_IFS_SIFS, sifs) |
61c8846e10SFelix Fietkau 		FIELD_PREP(MT_IFS_SLOT, dev->slottime));
62c8846e10SFelix Fietkau 
63c8846e10SFelix Fietkau 	if (dev->slottime < 20)
64c8846e10SFelix Fietkau 		val = MT7603_CFEND_RATE_DEFAULT;
65c8846e10SFelix Fietkau 	else
66c8846e10SFelix Fietkau 		val = MT7603_CFEND_RATE_11B;
67c8846e10SFelix Fietkau 
68c8846e10SFelix Fietkau 	mt76_rmw_field(dev, MT_AGG_CONTROL, MT_AGG_CONTROL_CFEND_RATE, val);
69c8846e10SFelix Fietkau 
70c8846e10SFelix Fietkau 	mt76_clear(dev, MT_ARB_SCR,
71c8846e10SFelix Fietkau 		   MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
72c8846e10SFelix Fietkau }
73c8846e10SFelix Fietkau 
74c8846e10SFelix Fietkau static void
75c8846e10SFelix Fietkau mt7603_wtbl_update(struct mt7603_dev *dev, int idx, u32 mask)
76c8846e10SFelix Fietkau {
77c8846e10SFelix Fietkau 	mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
78c8846e10SFelix Fietkau 		 FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask);
79c8846e10SFelix Fietkau 
80c8846e10SFelix Fietkau 	mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
81c8846e10SFelix Fietkau }
82c8846e10SFelix Fietkau 
83c8846e10SFelix Fietkau static u32
84c8846e10SFelix Fietkau mt7603_wtbl1_addr(int idx)
85c8846e10SFelix Fietkau {
86c8846e10SFelix Fietkau 	return MT_WTBL1_BASE + idx * MT_WTBL1_SIZE;
87c8846e10SFelix Fietkau }
88c8846e10SFelix Fietkau 
89c8846e10SFelix Fietkau static u32
90c8846e10SFelix Fietkau mt7603_wtbl2_addr(int idx)
91c8846e10SFelix Fietkau {
92c8846e10SFelix Fietkau 	/* Mapped to WTBL2 */
93c8846e10SFelix Fietkau 	return MT_PCIE_REMAP_BASE_1 + idx * MT_WTBL2_SIZE;
94c8846e10SFelix Fietkau }
95c8846e10SFelix Fietkau 
96c8846e10SFelix Fietkau static u32
97c8846e10SFelix Fietkau mt7603_wtbl3_addr(int idx)
98c8846e10SFelix Fietkau {
99c8846e10SFelix Fietkau 	u32 base = mt7603_wtbl2_addr(MT7603_WTBL_SIZE);
100c8846e10SFelix Fietkau 
101c8846e10SFelix Fietkau 	return base + idx * MT_WTBL3_SIZE;
102c8846e10SFelix Fietkau }
103c8846e10SFelix Fietkau 
104c8846e10SFelix Fietkau static u32
105c8846e10SFelix Fietkau mt7603_wtbl4_addr(int idx)
106c8846e10SFelix Fietkau {
107c8846e10SFelix Fietkau 	u32 base = mt7603_wtbl3_addr(MT7603_WTBL_SIZE);
108c8846e10SFelix Fietkau 
109c8846e10SFelix Fietkau 	return base + idx * MT_WTBL4_SIZE;
110c8846e10SFelix Fietkau }
111c8846e10SFelix Fietkau 
112c8846e10SFelix Fietkau void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, int vif,
113c8846e10SFelix Fietkau 		      const u8 *mac_addr)
114c8846e10SFelix Fietkau {
115c8846e10SFelix Fietkau 	const void *_mac = mac_addr;
116c8846e10SFelix Fietkau 	u32 addr = mt7603_wtbl1_addr(idx);
117c8846e10SFelix Fietkau 	u32 w0 = 0, w1 = 0;
118c8846e10SFelix Fietkau 	int i;
119c8846e10SFelix Fietkau 
120c8846e10SFelix Fietkau 	if (_mac) {
121c8846e10SFelix Fietkau 		w0 = FIELD_PREP(MT_WTBL1_W0_ADDR_HI,
122c8846e10SFelix Fietkau 				get_unaligned_le16(_mac + 4));
123c8846e10SFelix Fietkau 		w1 = FIELD_PREP(MT_WTBL1_W1_ADDR_LO,
124c8846e10SFelix Fietkau 				get_unaligned_le32(_mac));
125c8846e10SFelix Fietkau 	}
126c8846e10SFelix Fietkau 
127c8846e10SFelix Fietkau 	if (vif < 0)
128c8846e10SFelix Fietkau 		vif = 0;
129c8846e10SFelix Fietkau 	else
130c8846e10SFelix Fietkau 		w0 |= MT_WTBL1_W0_RX_CHECK_A1;
131c8846e10SFelix Fietkau 	w0 |= FIELD_PREP(MT_WTBL1_W0_MUAR_IDX, vif);
132c8846e10SFelix Fietkau 
133c8846e10SFelix Fietkau 	mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
134c8846e10SFelix Fietkau 
135c8846e10SFelix Fietkau 	mt76_set(dev, addr + 0 * 4, w0);
136c8846e10SFelix Fietkau 	mt76_set(dev, addr + 1 * 4, w1);
137c8846e10SFelix Fietkau 	mt76_set(dev, addr + 2 * 4, MT_WTBL1_W2_ADMISSION_CONTROL);
138c8846e10SFelix Fietkau 
139c8846e10SFelix Fietkau 	mt76_stop_tx_ac(dev, GENMASK(3, 0));
140c8846e10SFelix Fietkau 	addr = mt7603_wtbl2_addr(idx);
141c8846e10SFelix Fietkau 	for (i = 0; i < MT_WTBL2_SIZE; i += 4)
142c8846e10SFelix Fietkau 		mt76_wr(dev, addr + i, 0);
143c8846e10SFelix Fietkau 	mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2);
144c8846e10SFelix Fietkau 	mt76_start_tx_ac(dev, GENMASK(3, 0));
145c8846e10SFelix Fietkau 
146c8846e10SFelix Fietkau 	addr = mt7603_wtbl3_addr(idx);
147c8846e10SFelix Fietkau 	for (i = 0; i < MT_WTBL3_SIZE; i += 4)
148c8846e10SFelix Fietkau 		mt76_wr(dev, addr + i, 0);
149c8846e10SFelix Fietkau 
150c8846e10SFelix Fietkau 	addr = mt7603_wtbl4_addr(idx);
151c8846e10SFelix Fietkau 	for (i = 0; i < MT_WTBL4_SIZE; i += 4)
152c8846e10SFelix Fietkau 		mt76_wr(dev, addr + i, 0);
153c8846e10SFelix Fietkau }
154c8846e10SFelix Fietkau 
155c8846e10SFelix Fietkau static void
156c8846e10SFelix Fietkau mt7603_wtbl_set_skip_tx(struct mt7603_dev *dev, int idx, bool enabled)
157c8846e10SFelix Fietkau {
158c8846e10SFelix Fietkau 	u32 addr = mt7603_wtbl1_addr(idx);
159c8846e10SFelix Fietkau 	u32 val = mt76_rr(dev, addr + 3 * 4);
160c8846e10SFelix Fietkau 
161c8846e10SFelix Fietkau 	val &= ~MT_WTBL1_W3_SKIP_TX;
162c8846e10SFelix Fietkau 	val |= enabled * MT_WTBL1_W3_SKIP_TX;
163c8846e10SFelix Fietkau 
164c8846e10SFelix Fietkau 	mt76_wr(dev, addr + 3 * 4, val);
165c8846e10SFelix Fietkau }
166c8846e10SFelix Fietkau 
167c8846e10SFelix Fietkau void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort)
168c8846e10SFelix Fietkau {
169c8846e10SFelix Fietkau 	int i, port, queue;
170c8846e10SFelix Fietkau 
171c8846e10SFelix Fietkau 	if (abort) {
172c8846e10SFelix Fietkau 		port = 3; /* PSE */
173c8846e10SFelix Fietkau 		queue = 8; /* free queue */
174c8846e10SFelix Fietkau 	} else {
175c8846e10SFelix Fietkau 		port = 0; /* HIF */
176c8846e10SFelix Fietkau 		queue = 1; /* MCU queue */
177c8846e10SFelix Fietkau 	}
178c8846e10SFelix Fietkau 
179c8846e10SFelix Fietkau 	mt7603_wtbl_set_skip_tx(dev, idx, true);
180c8846e10SFelix Fietkau 
181c8846e10SFelix Fietkau 	mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN |
182c8846e10SFelix Fietkau 			FIELD_PREP(MT_TX_ABORT_WCID, idx));
183c8846e10SFelix Fietkau 
184c8846e10SFelix Fietkau 	for (i = 0; i < 4; i++) {
185c8846e10SFelix Fietkau 		mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
186c8846e10SFelix Fietkau 			FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) |
187c8846e10SFelix Fietkau 			FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, i) |
188c8846e10SFelix Fietkau 			FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) |
189c8846e10SFelix Fietkau 			FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue));
190c8846e10SFelix Fietkau 
191c8846e10SFelix Fietkau 		WARN_ON_ONCE(!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY,
192c8846e10SFelix Fietkau 					0, 5000));
193c8846e10SFelix Fietkau 	}
194c8846e10SFelix Fietkau 
195c8846e10SFelix Fietkau 	mt76_wr(dev, MT_TX_ABORT, 0);
196c8846e10SFelix Fietkau 
197c8846e10SFelix Fietkau 	mt7603_wtbl_set_skip_tx(dev, idx, false);
198c8846e10SFelix Fietkau }
199c8846e10SFelix Fietkau 
200c8846e10SFelix Fietkau void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta,
201c8846e10SFelix Fietkau 			  bool enabled)
202c8846e10SFelix Fietkau {
203c8846e10SFelix Fietkau 	u32 addr = mt7603_wtbl1_addr(sta->wcid.idx);
204c8846e10SFelix Fietkau 
205c8846e10SFelix Fietkau 	if (sta->smps == enabled)
206c8846e10SFelix Fietkau 		return;
207c8846e10SFelix Fietkau 
208c8846e10SFelix Fietkau 	mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_SMPS, enabled);
209c8846e10SFelix Fietkau 	sta->smps = enabled;
210c8846e10SFelix Fietkau }
211c8846e10SFelix Fietkau 
212c8846e10SFelix Fietkau void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta,
213c8846e10SFelix Fietkau 			bool enabled)
214c8846e10SFelix Fietkau {
215c8846e10SFelix Fietkau 	int idx = sta->wcid.idx;
216c8846e10SFelix Fietkau 	u32 addr;
217c8846e10SFelix Fietkau 
218c8846e10SFelix Fietkau 	spin_lock_bh(&dev->ps_lock);
219c8846e10SFelix Fietkau 
220c8846e10SFelix Fietkau 	if (sta->ps == enabled)
221c8846e10SFelix Fietkau 		goto out;
222c8846e10SFelix Fietkau 
223c8846e10SFelix Fietkau 	mt76_wr(dev, MT_PSE_RTA,
224c8846e10SFelix Fietkau 		FIELD_PREP(MT_PSE_RTA_TAG_ID, idx) |
225c8846e10SFelix Fietkau 		FIELD_PREP(MT_PSE_RTA_PORT_ID, 0) |
226c8846e10SFelix Fietkau 		FIELD_PREP(MT_PSE_RTA_QUEUE_ID, 1) |
227c8846e10SFelix Fietkau 		FIELD_PREP(MT_PSE_RTA_REDIRECT_EN, enabled) |
228c8846e10SFelix Fietkau 		MT_PSE_RTA_WRITE | MT_PSE_RTA_BUSY);
229c8846e10SFelix Fietkau 
230c8846e10SFelix Fietkau 	mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000);
231c8846e10SFelix Fietkau 
232c8846e10SFelix Fietkau 	if (enabled)
233c8846e10SFelix Fietkau 		mt7603_filter_tx(dev, idx, false);
234c8846e10SFelix Fietkau 
235c8846e10SFelix Fietkau 	addr = mt7603_wtbl1_addr(idx);
236c8846e10SFelix Fietkau 	mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
237c8846e10SFelix Fietkau 	mt76_rmw(dev, addr + 3 * 4, MT_WTBL1_W3_POWER_SAVE,
238c8846e10SFelix Fietkau 		 enabled * MT_WTBL1_W3_POWER_SAVE);
239c8846e10SFelix Fietkau 	mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
240c8846e10SFelix Fietkau 	sta->ps = enabled;
241c8846e10SFelix Fietkau 
242c8846e10SFelix Fietkau out:
243c8846e10SFelix Fietkau 	spin_unlock_bh(&dev->ps_lock);
244c8846e10SFelix Fietkau }
245c8846e10SFelix Fietkau 
246c8846e10SFelix Fietkau void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx)
247c8846e10SFelix Fietkau {
248c8846e10SFelix Fietkau 	int wtbl2_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL2_SIZE;
249c8846e10SFelix Fietkau 	int wtbl2_frame = idx / wtbl2_frame_size;
250c8846e10SFelix Fietkau 	int wtbl2_entry = idx % wtbl2_frame_size;
251c8846e10SFelix Fietkau 
252c8846e10SFelix Fietkau 	int wtbl3_base_frame = MT_WTBL3_OFFSET / MT_PSE_PAGE_SIZE;
253c8846e10SFelix Fietkau 	int wtbl3_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL3_SIZE;
254c8846e10SFelix Fietkau 	int wtbl3_frame = wtbl3_base_frame + idx / wtbl3_frame_size;
255c8846e10SFelix Fietkau 	int wtbl3_entry = (idx % wtbl3_frame_size) * 2;
256c8846e10SFelix Fietkau 
257c8846e10SFelix Fietkau 	int wtbl4_base_frame = MT_WTBL4_OFFSET / MT_PSE_PAGE_SIZE;
258c8846e10SFelix Fietkau 	int wtbl4_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL4_SIZE;
259c8846e10SFelix Fietkau 	int wtbl4_frame = wtbl4_base_frame + idx / wtbl4_frame_size;
260c8846e10SFelix Fietkau 	int wtbl4_entry = idx % wtbl4_frame_size;
261c8846e10SFelix Fietkau 
262c8846e10SFelix Fietkau 	u32 addr = MT_WTBL1_BASE + idx * MT_WTBL1_SIZE;
263c8846e10SFelix Fietkau 	int i;
264c8846e10SFelix Fietkau 
265c8846e10SFelix Fietkau 	mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
266c8846e10SFelix Fietkau 
267c8846e10SFelix Fietkau 	mt76_wr(dev, addr + 0 * 4,
268c8846e10SFelix Fietkau 		MT_WTBL1_W0_RX_CHECK_A1 |
269c8846e10SFelix Fietkau 		MT_WTBL1_W0_RX_CHECK_A2 |
270c8846e10SFelix Fietkau 		MT_WTBL1_W0_RX_VALID);
271c8846e10SFelix Fietkau 	mt76_wr(dev, addr + 1 * 4, 0);
272c8846e10SFelix Fietkau 	mt76_wr(dev, addr + 2 * 4, 0);
273c8846e10SFelix Fietkau 
274c8846e10SFelix Fietkau 	mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
275c8846e10SFelix Fietkau 
276c8846e10SFelix Fietkau 	mt76_wr(dev, addr + 3 * 4,
277c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL1_W3_WTBL2_FRAME_ID, wtbl2_frame) |
278c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL1_W3_WTBL2_ENTRY_ID, wtbl2_entry) |
279c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL1_W3_WTBL4_FRAME_ID, wtbl4_frame) |
280c8846e10SFelix Fietkau 		MT_WTBL1_W3_I_PSM | MT_WTBL1_W3_KEEP_I_PSM);
281c8846e10SFelix Fietkau 	mt76_wr(dev, addr + 4 * 4,
282c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL1_W4_WTBL3_FRAME_ID, wtbl3_frame) |
283c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL1_W4_WTBL3_ENTRY_ID, wtbl3_entry) |
284c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL1_W4_WTBL4_ENTRY_ID, wtbl4_entry));
285c8846e10SFelix Fietkau 
286c8846e10SFelix Fietkau 	mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
287c8846e10SFelix Fietkau 
288c8846e10SFelix Fietkau 	addr = mt7603_wtbl2_addr(idx);
289c8846e10SFelix Fietkau 
290c8846e10SFelix Fietkau 	/* Clear BA information */
291c8846e10SFelix Fietkau 	mt76_wr(dev, addr + (15 * 4), 0);
292c8846e10SFelix Fietkau 
293c8846e10SFelix Fietkau 	mt76_stop_tx_ac(dev, GENMASK(3, 0));
294c8846e10SFelix Fietkau 	for (i = 2; i <= 4; i++)
295c8846e10SFelix Fietkau 		mt76_wr(dev, addr + (i * 4), 0);
296c8846e10SFelix Fietkau 	mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2);
297c8846e10SFelix Fietkau 	mt76_start_tx_ac(dev, GENMASK(3, 0));
298c8846e10SFelix Fietkau 
299c8846e10SFelix Fietkau 	mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_RX_COUNT_CLEAR);
300c8846e10SFelix Fietkau 	mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_TX_COUNT_CLEAR);
301c8846e10SFelix Fietkau 	mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
302c8846e10SFelix Fietkau }
303c8846e10SFelix Fietkau 
304c8846e10SFelix Fietkau void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta)
305c8846e10SFelix Fietkau {
306c8846e10SFelix Fietkau 	struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
307c8846e10SFelix Fietkau 	int idx = msta->wcid.idx;
308c8846e10SFelix Fietkau 	u32 addr;
309c8846e10SFelix Fietkau 	u32 val;
310c8846e10SFelix Fietkau 
311c8846e10SFelix Fietkau 	addr = mt7603_wtbl1_addr(idx);
312c8846e10SFelix Fietkau 
313c8846e10SFelix Fietkau 	val = mt76_rr(dev, addr + 2 * 4);
314c8846e10SFelix Fietkau 	val &= MT_WTBL1_W2_KEY_TYPE | MT_WTBL1_W2_ADMISSION_CONTROL;
315c8846e10SFelix Fietkau 	val |= FIELD_PREP(MT_WTBL1_W2_AMPDU_FACTOR, sta->ht_cap.ampdu_factor) |
316c8846e10SFelix Fietkau 	       FIELD_PREP(MT_WTBL1_W2_MPDU_DENSITY, sta->ht_cap.ampdu_density) |
317c8846e10SFelix Fietkau 	       MT_WTBL1_W2_TXS_BAF_REPORT;
318c8846e10SFelix Fietkau 
319c8846e10SFelix Fietkau 	if (sta->ht_cap.cap)
320c8846e10SFelix Fietkau 		val |= MT_WTBL1_W2_HT;
321c8846e10SFelix Fietkau 	if (sta->vht_cap.cap)
322c8846e10SFelix Fietkau 		val |= MT_WTBL1_W2_VHT;
323c8846e10SFelix Fietkau 
324c8846e10SFelix Fietkau 	mt76_wr(dev, addr + 2 * 4, val);
325c8846e10SFelix Fietkau 
326c8846e10SFelix Fietkau 	addr = mt7603_wtbl2_addr(idx);
327c8846e10SFelix Fietkau 	val = mt76_rr(dev, addr + 9 * 4);
328c8846e10SFelix Fietkau 	val &= ~(MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 |
329c8846e10SFelix Fietkau 		 MT_WTBL2_W9_SHORT_GI_80);
330c8846e10SFelix Fietkau 	if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
331c8846e10SFelix Fietkau 		val |= MT_WTBL2_W9_SHORT_GI_20;
332c8846e10SFelix Fietkau 	if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
333c8846e10SFelix Fietkau 		val |= MT_WTBL2_W9_SHORT_GI_40;
334c8846e10SFelix Fietkau 	mt76_wr(dev, addr + 9 * 4, val);
335c8846e10SFelix Fietkau }
336c8846e10SFelix Fietkau 
337c8846e10SFelix Fietkau void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid)
338c8846e10SFelix Fietkau {
339c8846e10SFelix Fietkau 	mt76_wr(dev, MT_BA_CONTROL_0, get_unaligned_le32(addr));
340c8846e10SFelix Fietkau 	mt76_wr(dev, MT_BA_CONTROL_1,
341c8846e10SFelix Fietkau 		(get_unaligned_le16(addr + 4) |
342c8846e10SFelix Fietkau 		 FIELD_PREP(MT_BA_CONTROL_1_TID, tid) |
343c8846e10SFelix Fietkau 		 MT_BA_CONTROL_1_RESET));
344c8846e10SFelix Fietkau }
345c8846e10SFelix Fietkau 
346aa3cb24bSFelix Fietkau void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid,
347c8846e10SFelix Fietkau 			    int ba_size)
348c8846e10SFelix Fietkau {
349c8846e10SFelix Fietkau 	u32 addr = mt7603_wtbl2_addr(wcid);
350c8846e10SFelix Fietkau 	u32 tid_mask = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) |
351c8846e10SFelix Fietkau 		       (MT_WTBL2_W15_BA_WIN_SIZE <<
352c8846e10SFelix Fietkau 			(tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT));
353c8846e10SFelix Fietkau 	u32 tid_val;
354c8846e10SFelix Fietkau 	int i;
355c8846e10SFelix Fietkau 
356c8846e10SFelix Fietkau 	if (ba_size < 0) {
357c8846e10SFelix Fietkau 		/* disable */
358c8846e10SFelix Fietkau 		mt76_clear(dev, addr + (15 * 4), tid_mask);
359c8846e10SFelix Fietkau 		return;
360c8846e10SFelix Fietkau 	}
361c8846e10SFelix Fietkau 
362c8846e10SFelix Fietkau 	for (i = 7; i > 0; i--) {
363c8846e10SFelix Fietkau 		if (ba_size >= MT_AGG_SIZE_LIMIT(i))
364c8846e10SFelix Fietkau 			break;
365c8846e10SFelix Fietkau 	}
366c8846e10SFelix Fietkau 
367c8846e10SFelix Fietkau 	tid_val = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) |
368c8846e10SFelix Fietkau 		  i << (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT);
369c8846e10SFelix Fietkau 
370c8846e10SFelix Fietkau 	mt76_rmw(dev, addr + (15 * 4), tid_mask, tid_val);
371c8846e10SFelix Fietkau }
372c8846e10SFelix Fietkau 
373c8846e10SFelix Fietkau static int
374c8846e10SFelix Fietkau mt7603_get_rate(struct mt7603_dev *dev, struct ieee80211_supported_band *sband,
375c8846e10SFelix Fietkau 		int idx, bool cck)
376c8846e10SFelix Fietkau {
377c8846e10SFelix Fietkau 	int offset = 0;
378c8846e10SFelix Fietkau 	int len = sband->n_bitrates;
379c8846e10SFelix Fietkau 	int i;
380c8846e10SFelix Fietkau 
381c8846e10SFelix Fietkau 	if (cck) {
382c8846e10SFelix Fietkau 		if (sband == &dev->mt76.sband_5g.sband)
383c8846e10SFelix Fietkau 			return 0;
384c8846e10SFelix Fietkau 
385c8846e10SFelix Fietkau 		idx &= ~BIT(2); /* short preamble */
386c8846e10SFelix Fietkau 	} else if (sband == &dev->mt76.sband_2g.sband) {
387c8846e10SFelix Fietkau 		offset = 4;
388c8846e10SFelix Fietkau 	}
389c8846e10SFelix Fietkau 
390c8846e10SFelix Fietkau 	for (i = offset; i < len; i++) {
391c8846e10SFelix Fietkau 		if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx)
392c8846e10SFelix Fietkau 			return i;
393c8846e10SFelix Fietkau 	}
394c8846e10SFelix Fietkau 
395c8846e10SFelix Fietkau 	return 0;
396c8846e10SFelix Fietkau }
397c8846e10SFelix Fietkau 
398c8846e10SFelix Fietkau static struct mt76_wcid *
399c8846e10SFelix Fietkau mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast)
400c8846e10SFelix Fietkau {
401c8846e10SFelix Fietkau 	struct mt7603_sta *sta;
402c8846e10SFelix Fietkau 	struct mt76_wcid *wcid;
403c8846e10SFelix Fietkau 
404c8846e10SFelix Fietkau 	if (idx >= ARRAY_SIZE(dev->mt76.wcid))
405c8846e10SFelix Fietkau 		return NULL;
406c8846e10SFelix Fietkau 
407c8846e10SFelix Fietkau 	wcid = rcu_dereference(dev->mt76.wcid[idx]);
408c8846e10SFelix Fietkau 	if (unicast || !wcid)
409c8846e10SFelix Fietkau 		return wcid;
410c8846e10SFelix Fietkau 
411c8846e10SFelix Fietkau 	if (!wcid->sta)
412c8846e10SFelix Fietkau 		return NULL;
413c8846e10SFelix Fietkau 
414c8846e10SFelix Fietkau 	sta = container_of(wcid, struct mt7603_sta, wcid);
415c8846e10SFelix Fietkau 	if (!sta->vif)
416c8846e10SFelix Fietkau 		return NULL;
417c8846e10SFelix Fietkau 
418c8846e10SFelix Fietkau 	return &sta->vif->sta.wcid;
419c8846e10SFelix Fietkau }
420c8846e10SFelix Fietkau 
421c8846e10SFelix Fietkau static void
422c8846e10SFelix Fietkau mt7603_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id)
423c8846e10SFelix Fietkau {
424c8846e10SFelix Fietkau 	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
425c8846e10SFelix Fietkau 	int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
426c8846e10SFelix Fietkau 	u8 *pn = status->iv;
427c8846e10SFelix Fietkau 	u8 *hdr;
428c8846e10SFelix Fietkau 
429c8846e10SFelix Fietkau 	__skb_push(skb, 8);
430c8846e10SFelix Fietkau 	memmove(skb->data, skb->data + 8, hdr_len);
431c8846e10SFelix Fietkau 	hdr = skb->data + hdr_len;
432c8846e10SFelix Fietkau 
433c8846e10SFelix Fietkau 	hdr[0] = pn[5];
434c8846e10SFelix Fietkau 	hdr[1] = pn[4];
435c8846e10SFelix Fietkau 	hdr[2] = 0;
436c8846e10SFelix Fietkau 	hdr[3] = 0x20 | (key_id << 6);
437c8846e10SFelix Fietkau 	hdr[4] = pn[3];
438c8846e10SFelix Fietkau 	hdr[5] = pn[2];
439c8846e10SFelix Fietkau 	hdr[6] = pn[1];
440c8846e10SFelix Fietkau 	hdr[7] = pn[0];
441c8846e10SFelix Fietkau 
442c8846e10SFelix Fietkau 	status->flag &= ~RX_FLAG_IV_STRIPPED;
443c8846e10SFelix Fietkau }
444c8846e10SFelix Fietkau 
445c8846e10SFelix Fietkau int
446c8846e10SFelix Fietkau mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
447c8846e10SFelix Fietkau {
448c8846e10SFelix Fietkau 	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
449c8846e10SFelix Fietkau 	struct ieee80211_supported_band *sband;
450c8846e10SFelix Fietkau 	struct ieee80211_hdr *hdr;
451c8846e10SFelix Fietkau 	__le32 *rxd = (__le32 *)skb->data;
452c8846e10SFelix Fietkau 	u32 rxd0 = le32_to_cpu(rxd[0]);
453c8846e10SFelix Fietkau 	u32 rxd1 = le32_to_cpu(rxd[1]);
454c8846e10SFelix Fietkau 	u32 rxd2 = le32_to_cpu(rxd[2]);
455c8846e10SFelix Fietkau 	bool unicast = rxd1 & MT_RXD1_NORMAL_U2M;
456c8846e10SFelix Fietkau 	bool insert_ccmp_hdr = false;
457c8846e10SFelix Fietkau 	bool remove_pad;
458c8846e10SFelix Fietkau 	int idx;
459c8846e10SFelix Fietkau 	int i;
460c8846e10SFelix Fietkau 
461c8846e10SFelix Fietkau 	memset(status, 0, sizeof(*status));
462c8846e10SFelix Fietkau 
463c8846e10SFelix Fietkau 	i = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1);
464c8846e10SFelix Fietkau 	sband = (i & 1) ? &dev->mt76.sband_5g.sband : &dev->mt76.sband_2g.sband;
465c8846e10SFelix Fietkau 	i >>= 1;
466c8846e10SFelix Fietkau 
467c8846e10SFelix Fietkau 	idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2);
468c8846e10SFelix Fietkau 	status->wcid = mt7603_rx_get_wcid(dev, idx, unicast);
469c8846e10SFelix Fietkau 
470c8846e10SFelix Fietkau 	status->band = sband->band;
471c8846e10SFelix Fietkau 	if (i < sband->n_channels)
472c8846e10SFelix Fietkau 		status->freq = sband->channels[i].center_freq;
473c8846e10SFelix Fietkau 
474c8846e10SFelix Fietkau 	if (rxd2 & MT_RXD2_NORMAL_FCS_ERR)
475c8846e10SFelix Fietkau 		status->flag |= RX_FLAG_FAILED_FCS_CRC;
476c8846e10SFelix Fietkau 
477c8846e10SFelix Fietkau 	if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR)
478c8846e10SFelix Fietkau 		status->flag |= RX_FLAG_MMIC_ERROR;
479c8846e10SFelix Fietkau 
480c8846e10SFelix Fietkau 	if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 &&
481c8846e10SFelix Fietkau 	    !(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) {
482c8846e10SFelix Fietkau 		status->flag |= RX_FLAG_DECRYPTED;
483c8846e10SFelix Fietkau 		status->flag |= RX_FLAG_IV_STRIPPED;
484c8846e10SFelix Fietkau 		status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
485c8846e10SFelix Fietkau 	}
486c8846e10SFelix Fietkau 
487c8846e10SFelix Fietkau 	remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET;
488c8846e10SFelix Fietkau 
489c8846e10SFelix Fietkau 	if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
490c8846e10SFelix Fietkau 		return -EINVAL;
491c8846e10SFelix Fietkau 
492c8846e10SFelix Fietkau 	if (!sband->channels)
493c8846e10SFelix Fietkau 		return -EINVAL;
494c8846e10SFelix Fietkau 
495c8846e10SFelix Fietkau 	rxd += 4;
496c8846e10SFelix Fietkau 	if (rxd0 & MT_RXD0_NORMAL_GROUP_4) {
497c8846e10SFelix Fietkau 		rxd += 4;
498c8846e10SFelix Fietkau 		if ((u8 *)rxd - skb->data >= skb->len)
499c8846e10SFelix Fietkau 			return -EINVAL;
500c8846e10SFelix Fietkau 	}
501c8846e10SFelix Fietkau 	if (rxd0 & MT_RXD0_NORMAL_GROUP_1) {
502c8846e10SFelix Fietkau 		u8 *data = (u8 *)rxd;
503c8846e10SFelix Fietkau 
504c8846e10SFelix Fietkau 		if (status->flag & RX_FLAG_DECRYPTED) {
505c8846e10SFelix Fietkau 			status->iv[0] = data[5];
506c8846e10SFelix Fietkau 			status->iv[1] = data[4];
507c8846e10SFelix Fietkau 			status->iv[2] = data[3];
508c8846e10SFelix Fietkau 			status->iv[3] = data[2];
509c8846e10SFelix Fietkau 			status->iv[4] = data[1];
510c8846e10SFelix Fietkau 			status->iv[5] = data[0];
511c8846e10SFelix Fietkau 
512c8846e10SFelix Fietkau 			insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
513c8846e10SFelix Fietkau 		}
514c8846e10SFelix Fietkau 
515c8846e10SFelix Fietkau 		rxd += 4;
516c8846e10SFelix Fietkau 		if ((u8 *)rxd - skb->data >= skb->len)
517c8846e10SFelix Fietkau 			return -EINVAL;
518c8846e10SFelix Fietkau 	}
519c8846e10SFelix Fietkau 	if (rxd0 & MT_RXD0_NORMAL_GROUP_2) {
520c8846e10SFelix Fietkau 		rxd += 2;
521c8846e10SFelix Fietkau 		if ((u8 *)rxd - skb->data >= skb->len)
522c8846e10SFelix Fietkau 			return -EINVAL;
523c8846e10SFelix Fietkau 	}
524c8846e10SFelix Fietkau 	if (rxd0 & MT_RXD0_NORMAL_GROUP_3) {
525c8846e10SFelix Fietkau 		u32 rxdg0 = le32_to_cpu(rxd[0]);
526c8846e10SFelix Fietkau 		u32 rxdg3 = le32_to_cpu(rxd[3]);
527c8846e10SFelix Fietkau 		bool cck = false;
528c8846e10SFelix Fietkau 
529c8846e10SFelix Fietkau 		i = FIELD_GET(MT_RXV1_TX_RATE, rxdg0);
530c8846e10SFelix Fietkau 		switch (FIELD_GET(MT_RXV1_TX_MODE, rxdg0)) {
531c8846e10SFelix Fietkau 		case MT_PHY_TYPE_CCK:
532c8846e10SFelix Fietkau 			cck = true;
533c8846e10SFelix Fietkau 			/* fall through */
534c8846e10SFelix Fietkau 		case MT_PHY_TYPE_OFDM:
535c8846e10SFelix Fietkau 			i = mt7603_get_rate(dev, sband, i, cck);
536c8846e10SFelix Fietkau 			break;
537c8846e10SFelix Fietkau 		case MT_PHY_TYPE_HT_GF:
538c8846e10SFelix Fietkau 		case MT_PHY_TYPE_HT:
539c8846e10SFelix Fietkau 			status->encoding = RX_ENC_HT;
540c8846e10SFelix Fietkau 			if (i > 15)
541c8846e10SFelix Fietkau 				return -EINVAL;
542c8846e10SFelix Fietkau 			break;
543c8846e10SFelix Fietkau 		default:
544c8846e10SFelix Fietkau 			return -EINVAL;
545c8846e10SFelix Fietkau 		}
546c8846e10SFelix Fietkau 
547c8846e10SFelix Fietkau 		if (rxdg0 & MT_RXV1_HT_SHORT_GI)
548c8846e10SFelix Fietkau 			status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
549c8846e10SFelix Fietkau 		if (rxdg0 & MT_RXV1_HT_AD_CODE)
550c8846e10SFelix Fietkau 			status->enc_flags |= RX_ENC_FLAG_LDPC;
551c8846e10SFelix Fietkau 
552c8846e10SFelix Fietkau 		status->enc_flags |= RX_ENC_FLAG_STBC_MASK *
553c8846e10SFelix Fietkau 				    FIELD_GET(MT_RXV1_HT_STBC, rxdg0);
554c8846e10SFelix Fietkau 
555c8846e10SFelix Fietkau 		status->rate_idx = i;
556c8846e10SFelix Fietkau 
557c8846e10SFelix Fietkau 		status->chains = dev->mt76.antenna_mask;
558c8846e10SFelix Fietkau 		status->chain_signal[0] = FIELD_GET(MT_RXV4_IB_RSSI0, rxdg3) +
559c8846e10SFelix Fietkau 					  dev->rssi_offset[0];
560c8846e10SFelix Fietkau 		status->chain_signal[1] = FIELD_GET(MT_RXV4_IB_RSSI1, rxdg3) +
561c8846e10SFelix Fietkau 					  dev->rssi_offset[1];
562c8846e10SFelix Fietkau 
563c8846e10SFelix Fietkau 		status->signal = status->chain_signal[0];
564c8846e10SFelix Fietkau 		if (status->chains & BIT(1))
565c8846e10SFelix Fietkau 			status->signal = max(status->signal,
566c8846e10SFelix Fietkau 					     status->chain_signal[1]);
567c8846e10SFelix Fietkau 
568c8846e10SFelix Fietkau 		if (FIELD_GET(MT_RXV1_FRAME_MODE, rxdg0) == 1)
569c8846e10SFelix Fietkau 			status->bw = RATE_INFO_BW_40;
570c8846e10SFelix Fietkau 
571c8846e10SFelix Fietkau 		rxd += 6;
572c8846e10SFelix Fietkau 		if ((u8 *)rxd - skb->data >= skb->len)
573c8846e10SFelix Fietkau 			return -EINVAL;
574c8846e10SFelix Fietkau 	} else {
575c8846e10SFelix Fietkau 		return -EINVAL;
576c8846e10SFelix Fietkau 	}
577c8846e10SFelix Fietkau 
578c8846e10SFelix Fietkau 	skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad);
579c8846e10SFelix Fietkau 
580c8846e10SFelix Fietkau 	if (insert_ccmp_hdr) {
581c8846e10SFelix Fietkau 		u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
582c8846e10SFelix Fietkau 
583c8846e10SFelix Fietkau 		mt7603_insert_ccmp_hdr(skb, key_id);
584c8846e10SFelix Fietkau 	}
585c8846e10SFelix Fietkau 
586c8846e10SFelix Fietkau 	hdr = (struct ieee80211_hdr *)skb->data;
587c8846e10SFelix Fietkau 	if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
588c8846e10SFelix Fietkau 		return 0;
589c8846e10SFelix Fietkau 
590c8846e10SFelix Fietkau 	status->aggr = unicast &&
591c8846e10SFelix Fietkau 		       !ieee80211_is_qos_nullfunc(hdr->frame_control);
592c8846e10SFelix Fietkau 	status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
593c8846e10SFelix Fietkau 	status->seqno = hdr->seq_ctrl >> 4;
594c8846e10SFelix Fietkau 
595c8846e10SFelix Fietkau 	return 0;
596c8846e10SFelix Fietkau }
597c8846e10SFelix Fietkau 
598c8846e10SFelix Fietkau static u16
599c8846e10SFelix Fietkau mt7603_mac_tx_rate_val(struct mt7603_dev *dev,
600c8846e10SFelix Fietkau 		       const struct ieee80211_tx_rate *rate, bool stbc, u8 *bw)
601c8846e10SFelix Fietkau {
602c8846e10SFelix Fietkau 	u8 phy, nss, rate_idx;
603c8846e10SFelix Fietkau 	u16 rateval;
604c8846e10SFelix Fietkau 
605c8846e10SFelix Fietkau 	*bw = 0;
606c8846e10SFelix Fietkau 	if (rate->flags & IEEE80211_TX_RC_MCS) {
607c8846e10SFelix Fietkau 		rate_idx = rate->idx;
608c8846e10SFelix Fietkau 		nss = 1 + (rate->idx >> 3);
609c8846e10SFelix Fietkau 		phy = MT_PHY_TYPE_HT;
610c8846e10SFelix Fietkau 		if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD)
611c8846e10SFelix Fietkau 			phy = MT_PHY_TYPE_HT_GF;
612c8846e10SFelix Fietkau 		if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
613c8846e10SFelix Fietkau 			*bw = 1;
614c8846e10SFelix Fietkau 	} else {
615c8846e10SFelix Fietkau 		const struct ieee80211_rate *r;
616c8846e10SFelix Fietkau 		int band = dev->mt76.chandef.chan->band;
617c8846e10SFelix Fietkau 		u16 val;
618c8846e10SFelix Fietkau 
619c8846e10SFelix Fietkau 		nss = 1;
620c8846e10SFelix Fietkau 		r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx];
621c8846e10SFelix Fietkau 		if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
622c8846e10SFelix Fietkau 			val = r->hw_value_short;
623c8846e10SFelix Fietkau 		else
624c8846e10SFelix Fietkau 			val = r->hw_value;
625c8846e10SFelix Fietkau 
626c8846e10SFelix Fietkau 		phy = val >> 8;
627c8846e10SFelix Fietkau 		rate_idx = val & 0xff;
628c8846e10SFelix Fietkau 	}
629c8846e10SFelix Fietkau 
630c8846e10SFelix Fietkau 	rateval = (FIELD_PREP(MT_TX_RATE_IDX, rate_idx) |
631c8846e10SFelix Fietkau 		   FIELD_PREP(MT_TX_RATE_MODE, phy));
632c8846e10SFelix Fietkau 
633c8846e10SFelix Fietkau 	if (stbc && nss == 1)
634c8846e10SFelix Fietkau 		rateval |= MT_TX_RATE_STBC;
635c8846e10SFelix Fietkau 
636c8846e10SFelix Fietkau 	return rateval;
637c8846e10SFelix Fietkau }
638c8846e10SFelix Fietkau 
639c8846e10SFelix Fietkau void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta,
640c8846e10SFelix Fietkau 			   struct ieee80211_tx_rate *probe_rate,
641c8846e10SFelix Fietkau 			   struct ieee80211_tx_rate *rates)
642c8846e10SFelix Fietkau {
643c8846e10SFelix Fietkau 	int wcid = sta->wcid.idx;
644c8846e10SFelix Fietkau 	u32 addr = mt7603_wtbl2_addr(wcid);
645c8846e10SFelix Fietkau 	bool stbc = false;
646c8846e10SFelix Fietkau 	int n_rates = sta->n_rates;
647c8846e10SFelix Fietkau 	u8 bw, bw_prev, bw_idx = 0;
648c8846e10SFelix Fietkau 	u16 val[4];
649c8846e10SFelix Fietkau 	u16 probe_val;
650c8846e10SFelix Fietkau 	u32 w9 = mt76_rr(dev, addr + 9 * 4);
651c8846e10SFelix Fietkau 	int i;
652c8846e10SFelix Fietkau 
653c8846e10SFelix Fietkau 	if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000))
654c8846e10SFelix Fietkau 		return;
655c8846e10SFelix Fietkau 
656c8846e10SFelix Fietkau 	for (i = n_rates; i < 4; i++)
657c8846e10SFelix Fietkau 		rates[i] = rates[n_rates - 1];
658c8846e10SFelix Fietkau 
659c8846e10SFelix Fietkau 	w9 &= MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 |
660c8846e10SFelix Fietkau 	      MT_WTBL2_W9_SHORT_GI_80;
661c8846e10SFelix Fietkau 
662c8846e10SFelix Fietkau 	val[0] = mt7603_mac_tx_rate_val(dev, &rates[0], stbc, &bw);
663c8846e10SFelix Fietkau 	bw_prev = bw;
664c8846e10SFelix Fietkau 
665c8846e10SFelix Fietkau 	if (probe_rate) {
666c8846e10SFelix Fietkau 		probe_val = mt7603_mac_tx_rate_val(dev, probe_rate, stbc, &bw);
667c8846e10SFelix Fietkau 		if (bw)
668c8846e10SFelix Fietkau 			bw_idx = 1;
669c8846e10SFelix Fietkau 		else
670c8846e10SFelix Fietkau 			bw_prev = 0;
671c8846e10SFelix Fietkau 	} else {
672c8846e10SFelix Fietkau 		probe_val = val[0];
673c8846e10SFelix Fietkau 	}
674c8846e10SFelix Fietkau 
675c8846e10SFelix Fietkau 	w9 |= FIELD_PREP(MT_WTBL2_W9_CC_BW_SEL, bw);
676c8846e10SFelix Fietkau 	w9 |= FIELD_PREP(MT_WTBL2_W9_BW_CAP, bw);
677c8846e10SFelix Fietkau 
678c8846e10SFelix Fietkau 	val[1] = mt7603_mac_tx_rate_val(dev, &rates[1], stbc, &bw);
679c8846e10SFelix Fietkau 	if (bw_prev) {
680c8846e10SFelix Fietkau 		bw_idx = 3;
681c8846e10SFelix Fietkau 		bw_prev = bw;
682c8846e10SFelix Fietkau 	}
683c8846e10SFelix Fietkau 
684c8846e10SFelix Fietkau 	val[2] = mt7603_mac_tx_rate_val(dev, &rates[2], stbc, &bw);
685c8846e10SFelix Fietkau 	if (bw_prev) {
686c8846e10SFelix Fietkau 		bw_idx = 5;
687c8846e10SFelix Fietkau 		bw_prev = bw;
688c8846e10SFelix Fietkau 	}
689c8846e10SFelix Fietkau 
690c8846e10SFelix Fietkau 	val[3] = mt7603_mac_tx_rate_val(dev, &rates[3], stbc, &bw);
691c8846e10SFelix Fietkau 	if (bw_prev)
692c8846e10SFelix Fietkau 		bw_idx = 7;
693c8846e10SFelix Fietkau 
694c8846e10SFelix Fietkau 	w9 |= FIELD_PREP(MT_WTBL2_W9_CHANGE_BW_RATE,
695c8846e10SFelix Fietkau 		       bw_idx ? bw_idx - 1 : 7);
696c8846e10SFelix Fietkau 
697c8846e10SFelix Fietkau 	mt76_wr(dev, MT_WTBL_RIUCR0, w9);
698c8846e10SFelix Fietkau 
699c8846e10SFelix Fietkau 	mt76_wr(dev, MT_WTBL_RIUCR1,
700c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR1_RATE0, probe_val) |
701c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR1_RATE1, val[0]) |
702c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[0]));
703c8846e10SFelix Fietkau 
704c8846e10SFelix Fietkau 	mt76_wr(dev, MT_WTBL_RIUCR2,
705c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[0] >> 8) |
706c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR2_RATE3, val[1]) |
707c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[1]) |
708c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, val[2]));
709c8846e10SFelix Fietkau 
710c8846e10SFelix Fietkau 	mt76_wr(dev, MT_WTBL_RIUCR3,
711c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, val[2] >> 4) |
712c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[2]) |
713c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_RIUCR3_RATE7, val[3]));
714c8846e10SFelix Fietkau 
715c8846e10SFelix Fietkau 	mt76_wr(dev, MT_WTBL_UPDATE,
716c8846e10SFelix Fietkau 		FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) |
717c8846e10SFelix Fietkau 		MT_WTBL_UPDATE_RATE_UPDATE |
718c8846e10SFelix Fietkau 		MT_WTBL_UPDATE_TX_COUNT_CLEAR);
719c8846e10SFelix Fietkau 
720c8846e10SFelix Fietkau 	if (!sta->wcid.tx_rate_set)
721c8846e10SFelix Fietkau 		mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
722c8846e10SFelix Fietkau 
723c8846e10SFelix Fietkau 	sta->rate_count = 2 * MT7603_RATE_RETRY * n_rates;
724c8846e10SFelix Fietkau 	sta->wcid.tx_rate_set = true;
725c8846e10SFelix Fietkau }
726c8846e10SFelix Fietkau 
727c8846e10SFelix Fietkau static enum mt7603_cipher_type
728c8846e10SFelix Fietkau mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
729c8846e10SFelix Fietkau {
730c8846e10SFelix Fietkau 	memset(key_data, 0, 32);
731c8846e10SFelix Fietkau 	if (!key)
732c8846e10SFelix Fietkau 		return MT_CIPHER_NONE;
733c8846e10SFelix Fietkau 
734c8846e10SFelix Fietkau 	if (key->keylen > 32)
735c8846e10SFelix Fietkau 		return MT_CIPHER_NONE;
736c8846e10SFelix Fietkau 
737c8846e10SFelix Fietkau 	memcpy(key_data, key->key, key->keylen);
738c8846e10SFelix Fietkau 
739c8846e10SFelix Fietkau 	switch (key->cipher) {
740c8846e10SFelix Fietkau 	case WLAN_CIPHER_SUITE_WEP40:
741c8846e10SFelix Fietkau 		return MT_CIPHER_WEP40;
742c8846e10SFelix Fietkau 	case WLAN_CIPHER_SUITE_WEP104:
743c8846e10SFelix Fietkau 		return MT_CIPHER_WEP104;
744c8846e10SFelix Fietkau 	case WLAN_CIPHER_SUITE_TKIP:
745c8846e10SFelix Fietkau 		/* Rx/Tx MIC keys are swapped */
746c8846e10SFelix Fietkau 		memcpy(key_data + 16, key->key + 24, 8);
747c8846e10SFelix Fietkau 		memcpy(key_data + 24, key->key + 16, 8);
748c8846e10SFelix Fietkau 		return MT_CIPHER_TKIP;
749c8846e10SFelix Fietkau 	case WLAN_CIPHER_SUITE_CCMP:
750c8846e10SFelix Fietkau 		return MT_CIPHER_AES_CCMP;
751c8846e10SFelix Fietkau 	default:
752c8846e10SFelix Fietkau 		return MT_CIPHER_NONE;
753c8846e10SFelix Fietkau 	}
754c8846e10SFelix Fietkau }
755c8846e10SFelix Fietkau 
756c8846e10SFelix Fietkau int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
757c8846e10SFelix Fietkau 			struct ieee80211_key_conf *key)
758c8846e10SFelix Fietkau {
759c8846e10SFelix Fietkau 	enum mt7603_cipher_type cipher;
760c8846e10SFelix Fietkau 	u32 addr = mt7603_wtbl3_addr(wcid);
761c8846e10SFelix Fietkau 	u8 key_data[32];
762c8846e10SFelix Fietkau 	int key_len = sizeof(key_data);
763c8846e10SFelix Fietkau 
764c8846e10SFelix Fietkau 	cipher = mt7603_mac_get_key_info(key, key_data);
765c8846e10SFelix Fietkau 	if (cipher == MT_CIPHER_NONE && key)
766c8846e10SFelix Fietkau 		return -EOPNOTSUPP;
767c8846e10SFelix Fietkau 
768c8846e10SFelix Fietkau 	if (key && (cipher == MT_CIPHER_WEP40 || cipher == MT_CIPHER_WEP104)) {
769c8846e10SFelix Fietkau 		addr += key->keyidx * 16;
770c8846e10SFelix Fietkau 		key_len = 16;
771c8846e10SFelix Fietkau 	}
772c8846e10SFelix Fietkau 
773c8846e10SFelix Fietkau 	mt76_wr_copy(dev, addr, key_data, key_len);
774c8846e10SFelix Fietkau 
775c8846e10SFelix Fietkau 	addr = mt7603_wtbl1_addr(wcid);
776c8846e10SFelix Fietkau 	mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_KEY_TYPE, cipher);
777c8846e10SFelix Fietkau 	if (key)
778c8846e10SFelix Fietkau 		mt76_rmw_field(dev, addr, MT_WTBL1_W0_KEY_IDX, key->keyidx);
779c8846e10SFelix Fietkau 	mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, !!key);
780c8846e10SFelix Fietkau 
781c8846e10SFelix Fietkau 	return 0;
782c8846e10SFelix Fietkau }
783c8846e10SFelix Fietkau 
784c8846e10SFelix Fietkau static int
785c8846e10SFelix Fietkau mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
786300832adSLorenzo Bianconi 		      struct sk_buff *skb, enum mt76_txq_id qid,
787c8846e10SFelix Fietkau 		      struct mt76_wcid *wcid, struct ieee80211_sta *sta,
788c8846e10SFelix Fietkau 		      int pid, struct ieee80211_key_conf *key)
789c8846e10SFelix Fietkau {
790c8846e10SFelix Fietkau 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
791c8846e10SFelix Fietkau 	struct ieee80211_tx_rate *rate = &info->control.rates[0];
792c8846e10SFelix Fietkau 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
793aa3cb24bSFelix Fietkau 	struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data;
794c8846e10SFelix Fietkau 	struct ieee80211_vif *vif = info->control.vif;
795af005f26SLorenzo Bianconi 	struct mt76_queue *q = dev->mt76.q_tx[qid].q;
796c8846e10SFelix Fietkau 	struct mt7603_vif *mvif;
797c8846e10SFelix Fietkau 	int wlan_idx;
798c8846e10SFelix Fietkau 	int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
799c8846e10SFelix Fietkau 	int tx_count = 8;
800c8846e10SFelix Fietkau 	u8 frame_type, frame_subtype;
801c8846e10SFelix Fietkau 	u16 fc = le16_to_cpu(hdr->frame_control);
802aa3cb24bSFelix Fietkau 	u16 seqno = 0;
803c8846e10SFelix Fietkau 	u8 vif_idx = 0;
804c8846e10SFelix Fietkau 	u32 val;
805c8846e10SFelix Fietkau 	u8 bw;
806c8846e10SFelix Fietkau 
807c8846e10SFelix Fietkau 	if (vif) {
808c8846e10SFelix Fietkau 		mvif = (struct mt7603_vif *)vif->drv_priv;
809c8846e10SFelix Fietkau 		vif_idx = mvif->idx;
810300832adSLorenzo Bianconi 		if (vif_idx && qid >= MT_TXQ_BEACON)
811c8846e10SFelix Fietkau 			vif_idx += 0x10;
812c8846e10SFelix Fietkau 	}
813c8846e10SFelix Fietkau 
814c8846e10SFelix Fietkau 	if (sta) {
815c8846e10SFelix Fietkau 		struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
816c8846e10SFelix Fietkau 
817c8846e10SFelix Fietkau 		tx_count = msta->rate_count;
818c8846e10SFelix Fietkau 	}
819c8846e10SFelix Fietkau 
820c8846e10SFelix Fietkau 	if (wcid)
821c8846e10SFelix Fietkau 		wlan_idx = wcid->idx;
822c8846e10SFelix Fietkau 	else
823c8846e10SFelix Fietkau 		wlan_idx = MT7603_WTBL_RESERVED;
824c8846e10SFelix Fietkau 
825c8846e10SFelix Fietkau 	frame_type = (fc & IEEE80211_FCTL_FTYPE) >> 2;
826c8846e10SFelix Fietkau 	frame_subtype = (fc & IEEE80211_FCTL_STYPE) >> 4;
827c8846e10SFelix Fietkau 
828c8846e10SFelix Fietkau 	val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) |
829c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD0_Q_IDX, q->hw_idx);
830c8846e10SFelix Fietkau 	txwi[0] = cpu_to_le32(val);
831c8846e10SFelix Fietkau 
832c8846e10SFelix Fietkau 	val = MT_TXD1_LONG_FORMAT |
833c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD1_OWN_MAC, vif_idx) |
834c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD1_TID,
835c8846e10SFelix Fietkau 			 skb->priority & IEEE80211_QOS_CTL_TID_MASK) |
836c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
837c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD1_HDR_INFO, hdr_len / 2) |
838c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD1_WLAN_IDX, wlan_idx) |
839c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD1_PROTECTED, !!key);
840c8846e10SFelix Fietkau 	txwi[1] = cpu_to_le32(val);
841c8846e10SFelix Fietkau 
842c8846e10SFelix Fietkau 	if (info->flags & IEEE80211_TX_CTL_NO_ACK)
843c8846e10SFelix Fietkau 		txwi[1] |= cpu_to_le32(MT_TXD1_NO_ACK);
844c8846e10SFelix Fietkau 
845c8846e10SFelix Fietkau 	val = FIELD_PREP(MT_TXD2_FRAME_TYPE, frame_type) |
846c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD2_SUB_TYPE, frame_subtype) |
847c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD2_MULTICAST,
848c8846e10SFelix Fietkau 			 is_multicast_ether_addr(hdr->addr1));
849c8846e10SFelix Fietkau 	txwi[2] = cpu_to_le32(val);
850c8846e10SFelix Fietkau 
851c8846e10SFelix Fietkau 	if (!(info->flags & IEEE80211_TX_CTL_AMPDU))
852c8846e10SFelix Fietkau 		txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE);
853c8846e10SFelix Fietkau 
854c8846e10SFelix Fietkau 	txwi[4] = 0;
855c8846e10SFelix Fietkau 
856c8846e10SFelix Fietkau 	val = MT_TXD5_TX_STATUS_HOST | MT_TXD5_SW_POWER_MGMT |
857c8846e10SFelix Fietkau 	      FIELD_PREP(MT_TXD5_PID, pid);
858c8846e10SFelix Fietkau 	txwi[5] = cpu_to_le32(val);
859c8846e10SFelix Fietkau 
860c8846e10SFelix Fietkau 	txwi[6] = 0;
861c8846e10SFelix Fietkau 
862c8846e10SFelix Fietkau 	if (rate->idx >= 0 && rate->count &&
863c8846e10SFelix Fietkau 	    !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) {
864c8846e10SFelix Fietkau 		bool stbc = info->flags & IEEE80211_TX_CTL_STBC;
865c8846e10SFelix Fietkau 		u16 rateval = mt7603_mac_tx_rate_val(dev, rate, stbc, &bw);
866c8846e10SFelix Fietkau 
867c8846e10SFelix Fietkau 		txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE);
868c8846e10SFelix Fietkau 
869c8846e10SFelix Fietkau 		val = MT_TXD6_FIXED_BW |
870c8846e10SFelix Fietkau 		      FIELD_PREP(MT_TXD6_BW, bw) |
871c8846e10SFelix Fietkau 		      FIELD_PREP(MT_TXD6_TX_RATE, rateval);
872c8846e10SFelix Fietkau 		txwi[6] |= cpu_to_le32(val);
873c8846e10SFelix Fietkau 
874c8846e10SFelix Fietkau 		if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
875c8846e10SFelix Fietkau 			txwi[6] |= cpu_to_le32(MT_TXD6_SGI);
876c8846e10SFelix Fietkau 
877c8846e10SFelix Fietkau 		if (!(rate->flags & IEEE80211_TX_RC_MCS))
878c8846e10SFelix Fietkau 			txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE);
879c8846e10SFelix Fietkau 
880c8846e10SFelix Fietkau 		tx_count = rate->count;
881c8846e10SFelix Fietkau 	}
882c8846e10SFelix Fietkau 
883c8846e10SFelix Fietkau 	/* use maximum tx count for beacons and buffered multicast */
884300832adSLorenzo Bianconi 	if (qid >= MT_TXQ_BEACON)
885c8846e10SFelix Fietkau 		tx_count = 0x1f;
886c8846e10SFelix Fietkau 
887c8846e10SFelix Fietkau 	val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count) |
888aa3cb24bSFelix Fietkau 		  MT_TXD3_SN_VALID;
889aa3cb24bSFelix Fietkau 
890aa3cb24bSFelix Fietkau 	if (ieee80211_is_data_qos(hdr->frame_control))
891aa3cb24bSFelix Fietkau 		seqno = le16_to_cpu(hdr->seq_ctrl);
892aa3cb24bSFelix Fietkau 	else if (ieee80211_is_back_req(hdr->frame_control))
893aa3cb24bSFelix Fietkau 		seqno = le16_to_cpu(bar->start_seq_num);
894aa3cb24bSFelix Fietkau 	else
895aa3cb24bSFelix Fietkau 		val &= ~MT_TXD3_SN_VALID;
896aa3cb24bSFelix Fietkau 
897aa3cb24bSFelix Fietkau 	val |= FIELD_PREP(MT_TXD3_SEQ, seqno >> 4);
898aa3cb24bSFelix Fietkau 
899c8846e10SFelix Fietkau 	txwi[3] = cpu_to_le32(val);
900c8846e10SFelix Fietkau 
901c8846e10SFelix Fietkau 	if (key) {
902c8846e10SFelix Fietkau 		u64 pn = atomic64_inc_return(&key->tx_pn);
903c8846e10SFelix Fietkau 
904c8846e10SFelix Fietkau 		txwi[3] |= cpu_to_le32(MT_TXD3_PN_VALID);
905c8846e10SFelix Fietkau 		txwi[4] = cpu_to_le32(pn & GENMASK(31, 0));
906c8846e10SFelix Fietkau 		txwi[5] |= cpu_to_le32(FIELD_PREP(MT_TXD5_PN_HIGH, pn >> 32));
907c8846e10SFelix Fietkau 	}
908c8846e10SFelix Fietkau 
909c8846e10SFelix Fietkau 	txwi[7] = 0;
910c8846e10SFelix Fietkau 
911c8846e10SFelix Fietkau 	return 0;
912c8846e10SFelix Fietkau }
913c8846e10SFelix Fietkau 
914c8846e10SFelix Fietkau int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
915300832adSLorenzo Bianconi 			  struct sk_buff *skb, enum mt76_txq_id qid,
916c8846e10SFelix Fietkau 			  struct mt76_wcid *wcid, struct ieee80211_sta *sta,
917*b5903c47SLorenzo Bianconi 			  struct mt76_tx_info *tx_info)
918c8846e10SFelix Fietkau {
919c8846e10SFelix Fietkau 	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
920c8846e10SFelix Fietkau 	struct mt7603_sta *msta = container_of(wcid, struct mt7603_sta, wcid);
921c8846e10SFelix Fietkau 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
922c8846e10SFelix Fietkau 	struct ieee80211_key_conf *key = info->control.hw_key;
923c8846e10SFelix Fietkau 	int pid;
924c8846e10SFelix Fietkau 
925c8846e10SFelix Fietkau 	if (!wcid)
926c8846e10SFelix Fietkau 		wcid = &dev->global_sta.wcid;
927c8846e10SFelix Fietkau 
928c8846e10SFelix Fietkau 	if (sta) {
929c8846e10SFelix Fietkau 		msta = (struct mt7603_sta *)sta->drv_priv;
930c8846e10SFelix Fietkau 
931c8846e10SFelix Fietkau 		if ((info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER |
932c8846e10SFelix Fietkau 				    IEEE80211_TX_CTL_CLEAR_PS_FILT)) ||
933c8846e10SFelix Fietkau 		    (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
934c8846e10SFelix Fietkau 			mt7603_wtbl_set_ps(dev, msta, false);
935c8846e10SFelix Fietkau 	}
936c8846e10SFelix Fietkau 
937c8846e10SFelix Fietkau 	pid = mt76_tx_status_skb_add(mdev, wcid, skb);
938c8846e10SFelix Fietkau 
939c8846e10SFelix Fietkau 	if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
940c8846e10SFelix Fietkau 		spin_lock_bh(&dev->mt76.lock);
941c8846e10SFelix Fietkau 		msta->rate_probe = true;
942c8846e10SFelix Fietkau 		mt7603_wtbl_set_rates(dev, msta, &info->control.rates[0],
943c8846e10SFelix Fietkau 				      msta->rates);
944c8846e10SFelix Fietkau 		spin_unlock_bh(&dev->mt76.lock);
945c8846e10SFelix Fietkau 	}
946c8846e10SFelix Fietkau 
947300832adSLorenzo Bianconi 	mt7603_mac_write_txwi(dev, txwi_ptr, skb, qid, wcid, sta, pid, key);
948c8846e10SFelix Fietkau 
949c8846e10SFelix Fietkau 	return 0;
950c8846e10SFelix Fietkau }
951c8846e10SFelix Fietkau 
952c8846e10SFelix Fietkau static bool
953c8846e10SFelix Fietkau mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta,
954c8846e10SFelix Fietkau 		struct ieee80211_tx_info *info, __le32 *txs_data)
955c8846e10SFelix Fietkau {
956c8846e10SFelix Fietkau 	struct ieee80211_supported_band *sband;
957c8846e10SFelix Fietkau 	int final_idx = 0;
958c8846e10SFelix Fietkau 	u32 final_rate;
959c8846e10SFelix Fietkau 	u32 final_rate_flags;
960c8846e10SFelix Fietkau 	bool final_mpdu;
961c8846e10SFelix Fietkau 	bool ack_timeout;
962c8846e10SFelix Fietkau 	bool fixed_rate;
963c8846e10SFelix Fietkau 	bool probe;
964c8846e10SFelix Fietkau 	bool ampdu;
965c8846e10SFelix Fietkau 	bool cck = false;
966c8846e10SFelix Fietkau 	int count;
967c8846e10SFelix Fietkau 	u32 txs;
968c8846e10SFelix Fietkau 	u8 pid;
969c8846e10SFelix Fietkau 	int idx;
970c8846e10SFelix Fietkau 	int i;
971c8846e10SFelix Fietkau 
972c8846e10SFelix Fietkau 	fixed_rate = info->status.rates[0].count;
973c8846e10SFelix Fietkau 	probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
974c8846e10SFelix Fietkau 
975c8846e10SFelix Fietkau 	txs = le32_to_cpu(txs_data[4]);
976c8846e10SFelix Fietkau 	final_mpdu = txs & MT_TXS4_ACKED_MPDU;
977c8846e10SFelix Fietkau 	ampdu = !fixed_rate && (txs & MT_TXS4_AMPDU);
978c8846e10SFelix Fietkau 	pid = FIELD_GET(MT_TXS4_PID, txs);
979c8846e10SFelix Fietkau 	count = FIELD_GET(MT_TXS4_TX_COUNT, txs);
980c8846e10SFelix Fietkau 
981c8846e10SFelix Fietkau 	txs = le32_to_cpu(txs_data[0]);
982c8846e10SFelix Fietkau 	final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs);
983c8846e10SFelix Fietkau 	ack_timeout = txs & MT_TXS0_ACK_TIMEOUT;
984c8846e10SFelix Fietkau 
985c8846e10SFelix Fietkau 	if (!ampdu && (txs & MT_TXS0_RTS_TIMEOUT))
986c8846e10SFelix Fietkau 		return false;
987c8846e10SFelix Fietkau 
988c8846e10SFelix Fietkau 	if (txs & MT_TXS0_QUEUE_TIMEOUT)
989c8846e10SFelix Fietkau 		return false;
990c8846e10SFelix Fietkau 
991c8846e10SFelix Fietkau 	if (!ack_timeout)
992c8846e10SFelix Fietkau 		info->flags |= IEEE80211_TX_STAT_ACK;
993c8846e10SFelix Fietkau 
994c8846e10SFelix Fietkau 	info->status.ampdu_len = 1;
995c8846e10SFelix Fietkau 	info->status.ampdu_ack_len = !!(info->flags &
996c8846e10SFelix Fietkau 					IEEE80211_TX_STAT_ACK);
997c8846e10SFelix Fietkau 
998c8846e10SFelix Fietkau 	if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU))
999c8846e10SFelix Fietkau 		info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU;
1000c8846e10SFelix Fietkau 
1001c8846e10SFelix Fietkau 	if (fixed_rate && !probe) {
1002c8846e10SFelix Fietkau 		info->status.rates[0].count = count;
1003c8846e10SFelix Fietkau 		goto out;
1004c8846e10SFelix Fietkau 	}
1005c8846e10SFelix Fietkau 
1006c8846e10SFelix Fietkau 	for (i = 0, idx = 0; i < ARRAY_SIZE(info->status.rates); i++) {
1007c8846e10SFelix Fietkau 		int cur_count = min_t(int, count, 2 * MT7603_RATE_RETRY);
1008c8846e10SFelix Fietkau 
1009c8846e10SFelix Fietkau 		if (!i && probe) {
1010c8846e10SFelix Fietkau 			cur_count = 1;
1011c8846e10SFelix Fietkau 		} else {
1012c8846e10SFelix Fietkau 			info->status.rates[i] = sta->rates[idx];
1013c8846e10SFelix Fietkau 			idx++;
1014c8846e10SFelix Fietkau 		}
1015c8846e10SFelix Fietkau 
1016c8846e10SFelix Fietkau 		if (i && info->status.rates[i].idx < 0) {
1017c8846e10SFelix Fietkau 			info->status.rates[i - 1].count += count;
1018c8846e10SFelix Fietkau 			break;
1019c8846e10SFelix Fietkau 		}
1020c8846e10SFelix Fietkau 
1021c8846e10SFelix Fietkau 		if (!count) {
1022c8846e10SFelix Fietkau 			info->status.rates[i].idx = -1;
1023c8846e10SFelix Fietkau 			break;
1024c8846e10SFelix Fietkau 		}
1025c8846e10SFelix Fietkau 
1026c8846e10SFelix Fietkau 		info->status.rates[i].count = cur_count;
1027c8846e10SFelix Fietkau 		final_idx = i;
1028c8846e10SFelix Fietkau 		count -= cur_count;
1029c8846e10SFelix Fietkau 	}
1030c8846e10SFelix Fietkau 
1031c8846e10SFelix Fietkau out:
1032c8846e10SFelix Fietkau 	final_rate_flags = info->status.rates[final_idx].flags;
1033c8846e10SFelix Fietkau 
1034c8846e10SFelix Fietkau 	switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) {
1035c8846e10SFelix Fietkau 	case MT_PHY_TYPE_CCK:
1036c8846e10SFelix Fietkau 		cck = true;
1037c8846e10SFelix Fietkau 		/* fall through */
1038c8846e10SFelix Fietkau 	case MT_PHY_TYPE_OFDM:
1039c8846e10SFelix Fietkau 		if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ)
1040c8846e10SFelix Fietkau 			sband = &dev->mt76.sband_5g.sband;
1041c8846e10SFelix Fietkau 		else
1042c8846e10SFelix Fietkau 			sband = &dev->mt76.sband_2g.sband;
1043c8846e10SFelix Fietkau 		final_rate &= GENMASK(5, 0);
1044c8846e10SFelix Fietkau 		final_rate = mt7603_get_rate(dev, sband, final_rate, cck);
1045c8846e10SFelix Fietkau 		final_rate_flags = 0;
1046c8846e10SFelix Fietkau 		break;
1047c8846e10SFelix Fietkau 	case MT_PHY_TYPE_HT_GF:
1048c8846e10SFelix Fietkau 	case MT_PHY_TYPE_HT:
1049c8846e10SFelix Fietkau 		final_rate_flags |= IEEE80211_TX_RC_MCS;
1050c8846e10SFelix Fietkau 		final_rate &= GENMASK(5, 0);
105176352769SFelix Fietkau 		if (final_rate > 15)
1052c8846e10SFelix Fietkau 			return false;
1053c8846e10SFelix Fietkau 		break;
1054c8846e10SFelix Fietkau 	default:
1055c8846e10SFelix Fietkau 		return false;
1056c8846e10SFelix Fietkau 	}
1057c8846e10SFelix Fietkau 
1058c8846e10SFelix Fietkau 	info->status.rates[final_idx].idx = final_rate;
1059c8846e10SFelix Fietkau 	info->status.rates[final_idx].flags = final_rate_flags;
1060c8846e10SFelix Fietkau 
1061c8846e10SFelix Fietkau 	return true;
1062c8846e10SFelix Fietkau }
1063c8846e10SFelix Fietkau 
1064c8846e10SFelix Fietkau static bool
1065c8846e10SFelix Fietkau mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid,
1066c8846e10SFelix Fietkau 		       __le32 *txs_data)
1067c8846e10SFelix Fietkau {
1068c8846e10SFelix Fietkau 	struct mt76_dev *mdev = &dev->mt76;
1069c8846e10SFelix Fietkau 	struct sk_buff_head list;
1070c8846e10SFelix Fietkau 	struct sk_buff *skb;
1071c8846e10SFelix Fietkau 
1072c8846e10SFelix Fietkau 	if (pid < MT_PACKET_ID_FIRST)
1073c8846e10SFelix Fietkau 		return false;
1074c8846e10SFelix Fietkau 
1075c8846e10SFelix Fietkau 	mt76_tx_status_lock(mdev, &list);
1076c8846e10SFelix Fietkau 	skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list);
1077c8846e10SFelix Fietkau 	if (skb) {
1078c8846e10SFelix Fietkau 		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1079c8846e10SFelix Fietkau 
1080c8846e10SFelix Fietkau 		if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
1081c8846e10SFelix Fietkau 			spin_lock_bh(&dev->mt76.lock);
1082c8846e10SFelix Fietkau 			if (sta->rate_probe) {
1083c8846e10SFelix Fietkau 				mt7603_wtbl_set_rates(dev, sta, NULL,
1084c8846e10SFelix Fietkau 						      sta->rates);
1085c8846e10SFelix Fietkau 				sta->rate_probe = false;
1086c8846e10SFelix Fietkau 			}
1087c8846e10SFelix Fietkau 			spin_unlock_bh(&dev->mt76.lock);
1088c8846e10SFelix Fietkau 		}
1089c8846e10SFelix Fietkau 
1090c8846e10SFelix Fietkau 		if (!mt7603_fill_txs(dev, sta, info, txs_data)) {
1091c8846e10SFelix Fietkau 			ieee80211_tx_info_clear_status(info);
1092c8846e10SFelix Fietkau 			info->status.rates[0].idx = -1;
1093c8846e10SFelix Fietkau 		}
1094c8846e10SFelix Fietkau 
1095c8846e10SFelix Fietkau 		mt76_tx_status_skb_done(mdev, skb, &list);
1096c8846e10SFelix Fietkau 	}
1097c8846e10SFelix Fietkau 	mt76_tx_status_unlock(mdev, &list);
1098c8846e10SFelix Fietkau 
1099c8846e10SFelix Fietkau 	return !!skb;
1100c8846e10SFelix Fietkau }
1101c8846e10SFelix Fietkau 
1102c8846e10SFelix Fietkau void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
1103c8846e10SFelix Fietkau {
1104c8846e10SFelix Fietkau 	struct ieee80211_tx_info info = {};
1105c8846e10SFelix Fietkau 	struct ieee80211_sta *sta = NULL;
1106c8846e10SFelix Fietkau 	struct mt7603_sta *msta = NULL;
1107c8846e10SFelix Fietkau 	struct mt76_wcid *wcid;
1108c8846e10SFelix Fietkau 	__le32 *txs_data = data;
1109c8846e10SFelix Fietkau 	u32 txs;
1110c8846e10SFelix Fietkau 	u8 wcidx;
1111c8846e10SFelix Fietkau 	u8 pid;
1112c8846e10SFelix Fietkau 
1113c8846e10SFelix Fietkau 	txs = le32_to_cpu(txs_data[4]);
1114c8846e10SFelix Fietkau 	pid = FIELD_GET(MT_TXS4_PID, txs);
1115c8846e10SFelix Fietkau 	txs = le32_to_cpu(txs_data[3]);
1116c8846e10SFelix Fietkau 	wcidx = FIELD_GET(MT_TXS3_WCID, txs);
1117c8846e10SFelix Fietkau 
1118c8846e10SFelix Fietkau 	if (pid == MT_PACKET_ID_NO_ACK)
1119c8846e10SFelix Fietkau 		return;
1120c8846e10SFelix Fietkau 
1121c8846e10SFelix Fietkau 	if (wcidx >= ARRAY_SIZE(dev->mt76.wcid))
1122c8846e10SFelix Fietkau 		return;
1123c8846e10SFelix Fietkau 
1124c8846e10SFelix Fietkau 	rcu_read_lock();
1125c8846e10SFelix Fietkau 
1126c8846e10SFelix Fietkau 	wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
1127c8846e10SFelix Fietkau 	if (!wcid)
1128c8846e10SFelix Fietkau 		goto out;
1129c8846e10SFelix Fietkau 
1130c8846e10SFelix Fietkau 	msta = container_of(wcid, struct mt7603_sta, wcid);
1131c8846e10SFelix Fietkau 	sta = wcid_to_sta(wcid);
1132c8846e10SFelix Fietkau 
1133c8846e10SFelix Fietkau 	if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data))
1134c8846e10SFelix Fietkau 		goto out;
1135c8846e10SFelix Fietkau 
1136c8846e10SFelix Fietkau 	if (wcidx >= MT7603_WTBL_STA || !sta)
1137c8846e10SFelix Fietkau 		goto out;
1138c8846e10SFelix Fietkau 
1139c8846e10SFelix Fietkau 	if (mt7603_fill_txs(dev, msta, &info, txs_data))
1140c8846e10SFelix Fietkau 		ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info);
1141c8846e10SFelix Fietkau 
1142c8846e10SFelix Fietkau out:
1143c8846e10SFelix Fietkau 	rcu_read_unlock();
1144c8846e10SFelix Fietkau }
1145c8846e10SFelix Fietkau 
1146e226ba2eSLorenzo Bianconi void mt7603_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
1147e226ba2eSLorenzo Bianconi 			    struct mt76_queue_entry *e)
1148c8846e10SFelix Fietkau {
1149c8846e10SFelix Fietkau 	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
1150c8846e10SFelix Fietkau 	struct sk_buff *skb = e->skb;
1151c8846e10SFelix Fietkau 
1152c8846e10SFelix Fietkau 	if (!e->txwi) {
1153c8846e10SFelix Fietkau 		dev_kfree_skb_any(skb);
1154c8846e10SFelix Fietkau 		return;
1155c8846e10SFelix Fietkau 	}
1156c8846e10SFelix Fietkau 
1157e226ba2eSLorenzo Bianconi 	if (qid < 4)
1158c8846e10SFelix Fietkau 		dev->tx_hang_check = 0;
1159c8846e10SFelix Fietkau 
1160c8846e10SFelix Fietkau 	mt76_tx_complete_skb(mdev, skb);
1161c8846e10SFelix Fietkau }
1162c8846e10SFelix Fietkau 
1163c8846e10SFelix Fietkau static bool
1164c8846e10SFelix Fietkau wait_for_wpdma(struct mt7603_dev *dev)
1165c8846e10SFelix Fietkau {
1166c8846e10SFelix Fietkau 	return mt76_poll(dev, MT_WPDMA_GLO_CFG,
1167c8846e10SFelix Fietkau 			 MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
1168c8846e10SFelix Fietkau 			 MT_WPDMA_GLO_CFG_RX_DMA_BUSY,
1169c8846e10SFelix Fietkau 			 0, 1000);
1170c8846e10SFelix Fietkau }
1171c8846e10SFelix Fietkau 
1172c8846e10SFelix Fietkau static void mt7603_pse_reset(struct mt7603_dev *dev)
1173c8846e10SFelix Fietkau {
1174c8846e10SFelix Fietkau 	/* Clear previous reset result */
1175c8846e10SFelix Fietkau 	if (!dev->reset_cause[RESET_CAUSE_RESET_FAILED])
1176c8846e10SFelix Fietkau 		mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE_S);
1177c8846e10SFelix Fietkau 
1178c8846e10SFelix Fietkau 	/* Reset PSE */
1179c8846e10SFelix Fietkau 	mt76_set(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE);
1180c8846e10SFelix Fietkau 
1181c8846e10SFelix Fietkau 	if (!mt76_poll_msec(dev, MT_MCU_DEBUG_RESET,
1182c8846e10SFelix Fietkau 			    MT_MCU_DEBUG_RESET_PSE_S,
1183c8846e10SFelix Fietkau 			    MT_MCU_DEBUG_RESET_PSE_S, 500)) {
1184c8846e10SFelix Fietkau 		dev->reset_cause[RESET_CAUSE_RESET_FAILED]++;
1185c8846e10SFelix Fietkau 		mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE);
1186c8846e10SFelix Fietkau 	} else {
1187c8846e10SFelix Fietkau 		dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0;
1188c8846e10SFelix Fietkau 		mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_QUEUES);
1189c8846e10SFelix Fietkau 	}
1190c8846e10SFelix Fietkau 
1191c8846e10SFelix Fietkau 	if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] >= 3)
1192c8846e10SFelix Fietkau 		dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0;
1193c8846e10SFelix Fietkau }
1194c8846e10SFelix Fietkau 
1195c8846e10SFelix Fietkau void mt7603_mac_dma_start(struct mt7603_dev *dev)
1196c8846e10SFelix Fietkau {
1197c8846e10SFelix Fietkau 	mt7603_mac_start(dev);
1198c8846e10SFelix Fietkau 
1199c8846e10SFelix Fietkau 	wait_for_wpdma(dev);
1200c8846e10SFelix Fietkau 	usleep_range(50, 100);
1201c8846e10SFelix Fietkau 
1202c8846e10SFelix Fietkau 	mt76_set(dev, MT_WPDMA_GLO_CFG,
1203c8846e10SFelix Fietkau 		 (MT_WPDMA_GLO_CFG_TX_DMA_EN |
1204c8846e10SFelix Fietkau 		  MT_WPDMA_GLO_CFG_RX_DMA_EN |
1205c8846e10SFelix Fietkau 		  FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3) |
1206c8846e10SFelix Fietkau 		  MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE));
1207c8846e10SFelix Fietkau 
1208c8846e10SFelix Fietkau 	mt7603_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL);
1209c8846e10SFelix Fietkau }
1210c8846e10SFelix Fietkau 
1211c8846e10SFelix Fietkau void mt7603_mac_start(struct mt7603_dev *dev)
1212c8846e10SFelix Fietkau {
1213c8846e10SFelix Fietkau 	mt76_clear(dev, MT_ARB_SCR,
1214c8846e10SFelix Fietkau 		   MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
1215c8846e10SFelix Fietkau 	mt76_wr(dev, MT_WF_ARB_TX_START_0, ~0);
1216c8846e10SFelix Fietkau 	mt76_set(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START);
1217c8846e10SFelix Fietkau }
1218c8846e10SFelix Fietkau 
1219c8846e10SFelix Fietkau void mt7603_mac_stop(struct mt7603_dev *dev)
1220c8846e10SFelix Fietkau {
1221c8846e10SFelix Fietkau 	mt76_set(dev, MT_ARB_SCR,
1222c8846e10SFelix Fietkau 		 MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
1223c8846e10SFelix Fietkau 	mt76_wr(dev, MT_WF_ARB_TX_START_0, 0);
1224c8846e10SFelix Fietkau 	mt76_clear(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START);
1225c8846e10SFelix Fietkau }
1226c8846e10SFelix Fietkau 
1227c8846e10SFelix Fietkau void mt7603_pse_client_reset(struct mt7603_dev *dev)
1228c8846e10SFelix Fietkau {
1229c8846e10SFelix Fietkau 	u32 addr;
1230c8846e10SFelix Fietkau 
1231c8846e10SFelix Fietkau 	addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR +
1232c8846e10SFelix Fietkau 				   MT_CLIENT_RESET_TX);
1233c8846e10SFelix Fietkau 
1234c8846e10SFelix Fietkau 	/* Clear previous reset state */
1235c8846e10SFelix Fietkau 	mt76_clear(dev, addr,
1236c8846e10SFelix Fietkau 		   MT_CLIENT_RESET_TX_R_E_1 |
1237c8846e10SFelix Fietkau 		   MT_CLIENT_RESET_TX_R_E_2 |
1238c8846e10SFelix Fietkau 		   MT_CLIENT_RESET_TX_R_E_1_S |
1239c8846e10SFelix Fietkau 		   MT_CLIENT_RESET_TX_R_E_2_S);
1240c8846e10SFelix Fietkau 
1241c8846e10SFelix Fietkau 	/* Start PSE client TX abort */
1242c8846e10SFelix Fietkau 	mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1);
1243c8846e10SFelix Fietkau 	mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S,
1244c8846e10SFelix Fietkau 		       MT_CLIENT_RESET_TX_R_E_1_S, 500);
1245c8846e10SFelix Fietkau 
1246c8846e10SFelix Fietkau 	mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_2);
1247c8846e10SFelix Fietkau 	mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET);
1248c8846e10SFelix Fietkau 
1249c8846e10SFelix Fietkau 	/* Wait for PSE client to clear TX FIFO */
1250c8846e10SFelix Fietkau 	mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_2_S,
1251c8846e10SFelix Fietkau 		       MT_CLIENT_RESET_TX_R_E_2_S, 500);
1252c8846e10SFelix Fietkau 
1253c8846e10SFelix Fietkau 	/* Clear PSE client TX abort state */
1254c8846e10SFelix Fietkau 	mt76_clear(dev, addr,
1255c8846e10SFelix Fietkau 		   MT_CLIENT_RESET_TX_R_E_1 |
1256c8846e10SFelix Fietkau 		   MT_CLIENT_RESET_TX_R_E_2);
1257c8846e10SFelix Fietkau }
1258c8846e10SFelix Fietkau 
1259c8846e10SFelix Fietkau static void mt7603_dma_sched_reset(struct mt7603_dev *dev)
1260c8846e10SFelix Fietkau {
1261c8846e10SFelix Fietkau 	if (!is_mt7628(dev))
1262c8846e10SFelix Fietkau 		return;
1263c8846e10SFelix Fietkau 
1264c8846e10SFelix Fietkau 	mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET);
1265c8846e10SFelix Fietkau 	mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET);
1266c8846e10SFelix Fietkau }
1267c8846e10SFelix Fietkau 
1268c8846e10SFelix Fietkau static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
1269c8846e10SFelix Fietkau {
1270c8846e10SFelix Fietkau 	int beacon_int = dev->beacon_int;
1271c8846e10SFelix Fietkau 	u32 mask = dev->mt76.mmio.irqmask;
1272c8846e10SFelix Fietkau 	int i;
1273c8846e10SFelix Fietkau 
1274c8846e10SFelix Fietkau 	ieee80211_stop_queues(dev->mt76.hw);
1275c8846e10SFelix Fietkau 	set_bit(MT76_RESET, &dev->mt76.state);
1276c8846e10SFelix Fietkau 
1277c8846e10SFelix Fietkau 	/* lock/unlock all queues to ensure that no tx is pending */
1278c8846e10SFelix Fietkau 	mt76_txq_schedule_all(&dev->mt76);
1279c8846e10SFelix Fietkau 
1280c8846e10SFelix Fietkau 	tasklet_disable(&dev->tx_tasklet);
1281c8846e10SFelix Fietkau 	tasklet_disable(&dev->pre_tbtt_tasklet);
1282c8846e10SFelix Fietkau 	napi_disable(&dev->mt76.napi[0]);
1283c8846e10SFelix Fietkau 	napi_disable(&dev->mt76.napi[1]);
1284c8846e10SFelix Fietkau 
1285c8846e10SFelix Fietkau 	mutex_lock(&dev->mt76.mutex);
1286c8846e10SFelix Fietkau 
1287c8846e10SFelix Fietkau 	mt7603_beacon_set_timer(dev, -1, 0);
1288c8846e10SFelix Fietkau 
1289c8846e10SFelix Fietkau 	if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] ||
1290c8846e10SFelix Fietkau 	    dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY ||
1291c8846e10SFelix Fietkau 	    dev->cur_reset_cause == RESET_CAUSE_BEACON_STUCK ||
1292c8846e10SFelix Fietkau 	    dev->cur_reset_cause == RESET_CAUSE_TX_HANG)
1293c8846e10SFelix Fietkau 		mt7603_pse_reset(dev);
1294c8846e10SFelix Fietkau 
1295c8846e10SFelix Fietkau 	if (dev->reset_cause[RESET_CAUSE_RESET_FAILED])
1296c8846e10SFelix Fietkau 		goto skip_dma_reset;
1297c8846e10SFelix Fietkau 
1298c8846e10SFelix Fietkau 	mt7603_mac_stop(dev);
1299c8846e10SFelix Fietkau 
1300c8846e10SFelix Fietkau 	mt76_clear(dev, MT_WPDMA_GLO_CFG,
1301c8846e10SFelix Fietkau 		   MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
1302c8846e10SFelix Fietkau 		   MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
1303c8846e10SFelix Fietkau 	usleep_range(1000, 2000);
1304c8846e10SFelix Fietkau 
1305c8846e10SFelix Fietkau 	mt7603_irq_disable(dev, mask);
1306c8846e10SFelix Fietkau 
1307c8846e10SFelix Fietkau 	mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF);
1308c8846e10SFelix Fietkau 
1309c8846e10SFelix Fietkau 	mt7603_pse_client_reset(dev);
1310c8846e10SFelix Fietkau 
1311c8846e10SFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++)
1312c8846e10SFelix Fietkau 		mt76_queue_tx_cleanup(dev, i, true);
1313c8846e10SFelix Fietkau 
1314c8846e10SFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++)
1315c8846e10SFelix Fietkau 		mt76_queue_rx_reset(dev, i);
1316c8846e10SFelix Fietkau 
1317c8846e10SFelix Fietkau 	mt7603_dma_sched_reset(dev);
1318c8846e10SFelix Fietkau 
1319c8846e10SFelix Fietkau 	mt7603_mac_dma_start(dev);
1320c8846e10SFelix Fietkau 
1321c8846e10SFelix Fietkau 	mt7603_irq_enable(dev, mask);
1322c8846e10SFelix Fietkau 
1323c8846e10SFelix Fietkau skip_dma_reset:
1324c8846e10SFelix Fietkau 	clear_bit(MT76_RESET, &dev->mt76.state);
1325c8846e10SFelix Fietkau 	mutex_unlock(&dev->mt76.mutex);
1326c8846e10SFelix Fietkau 
1327c8846e10SFelix Fietkau 	tasklet_enable(&dev->tx_tasklet);
1328c8846e10SFelix Fietkau 	tasklet_schedule(&dev->tx_tasklet);
1329c8846e10SFelix Fietkau 
1330c8846e10SFelix Fietkau 	tasklet_enable(&dev->pre_tbtt_tasklet);
1331c8846e10SFelix Fietkau 	mt7603_beacon_set_timer(dev, -1, beacon_int);
1332c8846e10SFelix Fietkau 
1333c8846e10SFelix Fietkau 	napi_enable(&dev->mt76.napi[0]);
1334c8846e10SFelix Fietkau 	napi_schedule(&dev->mt76.napi[0]);
1335c8846e10SFelix Fietkau 
1336c8846e10SFelix Fietkau 	napi_enable(&dev->mt76.napi[1]);
1337c8846e10SFelix Fietkau 	napi_schedule(&dev->mt76.napi[1]);
1338c8846e10SFelix Fietkau 
1339c8846e10SFelix Fietkau 	ieee80211_wake_queues(dev->mt76.hw);
1340c8846e10SFelix Fietkau 	mt76_txq_schedule_all(&dev->mt76);
1341c8846e10SFelix Fietkau }
1342c8846e10SFelix Fietkau 
1343c8846e10SFelix Fietkau static u32 mt7603_dma_debug(struct mt7603_dev *dev, u8 index)
1344c8846e10SFelix Fietkau {
1345c8846e10SFelix Fietkau 	u32 val;
1346c8846e10SFelix Fietkau 
1347c8846e10SFelix Fietkau 	mt76_wr(dev, MT_WPDMA_DEBUG,
1348c8846e10SFelix Fietkau 		FIELD_PREP(MT_WPDMA_DEBUG_IDX, index) |
1349c8846e10SFelix Fietkau 		MT_WPDMA_DEBUG_SEL);
1350c8846e10SFelix Fietkau 
1351c8846e10SFelix Fietkau 	val = mt76_rr(dev, MT_WPDMA_DEBUG);
1352c8846e10SFelix Fietkau 	return FIELD_GET(MT_WPDMA_DEBUG_VALUE, val);
1353c8846e10SFelix Fietkau }
1354c8846e10SFelix Fietkau 
1355c8846e10SFelix Fietkau static bool mt7603_rx_fifo_busy(struct mt7603_dev *dev)
1356c8846e10SFelix Fietkau {
1357c8846e10SFelix Fietkau 	if (is_mt7628(dev))
1358c8846e10SFelix Fietkau 		return mt7603_dma_debug(dev, 9) & BIT(9);
1359c8846e10SFelix Fietkau 
1360c8846e10SFelix Fietkau 	return mt7603_dma_debug(dev, 2) & BIT(8);
1361c8846e10SFelix Fietkau }
1362c8846e10SFelix Fietkau 
1363c8846e10SFelix Fietkau static bool mt7603_rx_dma_busy(struct mt7603_dev *dev)
1364c8846e10SFelix Fietkau {
1365c8846e10SFelix Fietkau 	if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_RX_DMA_BUSY))
1366c8846e10SFelix Fietkau 		return false;
1367c8846e10SFelix Fietkau 
1368c8846e10SFelix Fietkau 	return mt7603_rx_fifo_busy(dev);
1369c8846e10SFelix Fietkau }
1370c8846e10SFelix Fietkau 
1371c8846e10SFelix Fietkau static bool mt7603_tx_dma_busy(struct mt7603_dev *dev)
1372c8846e10SFelix Fietkau {
1373c8846e10SFelix Fietkau 	u32 val;
1374c8846e10SFelix Fietkau 
1375c8846e10SFelix Fietkau 	if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_TX_DMA_BUSY))
1376c8846e10SFelix Fietkau 		return false;
1377c8846e10SFelix Fietkau 
1378c8846e10SFelix Fietkau 	val = mt7603_dma_debug(dev, 9);
1379c8846e10SFelix Fietkau 	return (val & BIT(8)) && (val & 0xf) != 0xf;
1380c8846e10SFelix Fietkau }
1381c8846e10SFelix Fietkau 
1382c8846e10SFelix Fietkau static bool mt7603_tx_hang(struct mt7603_dev *dev)
1383c8846e10SFelix Fietkau {
1384c8846e10SFelix Fietkau 	struct mt76_queue *q;
1385c8846e10SFelix Fietkau 	u32 dma_idx, prev_dma_idx;
1386c8846e10SFelix Fietkau 	int i;
1387c8846e10SFelix Fietkau 
1388c8846e10SFelix Fietkau 	for (i = 0; i < 4; i++) {
1389af005f26SLorenzo Bianconi 		q = dev->mt76.q_tx[i].q;
1390c8846e10SFelix Fietkau 
1391c8846e10SFelix Fietkau 		if (!q->queued)
1392c8846e10SFelix Fietkau 			continue;
1393c8846e10SFelix Fietkau 
1394c8846e10SFelix Fietkau 		prev_dma_idx = dev->tx_dma_idx[i];
1395c8846e10SFelix Fietkau 		dma_idx = ioread32(&q->regs->dma_idx);
1396c8846e10SFelix Fietkau 		dev->tx_dma_idx[i] = dma_idx;
1397c8846e10SFelix Fietkau 
1398c8846e10SFelix Fietkau 		if (dma_idx == prev_dma_idx &&
1399c8846e10SFelix Fietkau 		    dma_idx != ioread32(&q->regs->cpu_idx))
1400c8846e10SFelix Fietkau 			break;
1401c8846e10SFelix Fietkau 	}
1402c8846e10SFelix Fietkau 
1403c8846e10SFelix Fietkau 	return i < 4;
1404c8846e10SFelix Fietkau }
1405c8846e10SFelix Fietkau 
1406c8846e10SFelix Fietkau static bool mt7603_rx_pse_busy(struct mt7603_dev *dev)
1407c8846e10SFelix Fietkau {
1408c8846e10SFelix Fietkau 	u32 addr, val;
1409c8846e10SFelix Fietkau 
1410c8846e10SFelix Fietkau 	if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES)
1411c8846e10SFelix Fietkau 		return true;
1412c8846e10SFelix Fietkau 
1413c8846e10SFelix Fietkau 	if (mt7603_rx_fifo_busy(dev))
1414c8846e10SFelix Fietkau 		return false;
1415c8846e10SFelix Fietkau 
1416c8846e10SFelix Fietkau 	addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS);
1417c8846e10SFelix Fietkau 	mt76_wr(dev, addr, 3);
1418c8846e10SFelix Fietkau 	val = mt76_rr(dev, addr) >> 16;
1419c8846e10SFelix Fietkau 
1420c8846e10SFelix Fietkau 	if (is_mt7628(dev) && (val & 0x4001) == 0x4001)
1421c8846e10SFelix Fietkau 		return true;
1422c8846e10SFelix Fietkau 
1423c8846e10SFelix Fietkau 	return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001;
1424c8846e10SFelix Fietkau }
1425c8846e10SFelix Fietkau 
1426c8846e10SFelix Fietkau static bool
1427c8846e10SFelix Fietkau mt7603_watchdog_check(struct mt7603_dev *dev, u8 *counter,
1428c8846e10SFelix Fietkau 		      enum mt7603_reset_cause cause,
1429c8846e10SFelix Fietkau 		      bool (*check)(struct mt7603_dev *dev))
1430c8846e10SFelix Fietkau {
1431c8846e10SFelix Fietkau 	if (dev->reset_test == cause + 1) {
1432c8846e10SFelix Fietkau 		dev->reset_test = 0;
1433c8846e10SFelix Fietkau 		goto trigger;
1434c8846e10SFelix Fietkau 	}
1435c8846e10SFelix Fietkau 
1436c8846e10SFelix Fietkau 	if (check) {
1437c8846e10SFelix Fietkau 		if (!check(dev) && *counter < MT7603_WATCHDOG_TIMEOUT) {
1438c8846e10SFelix Fietkau 			*counter = 0;
1439c8846e10SFelix Fietkau 			return false;
1440c8846e10SFelix Fietkau 		}
1441c8846e10SFelix Fietkau 
1442c8846e10SFelix Fietkau 		(*counter)++;
1443c8846e10SFelix Fietkau 	}
1444c8846e10SFelix Fietkau 
1445c8846e10SFelix Fietkau 	if (*counter < MT7603_WATCHDOG_TIMEOUT)
1446c8846e10SFelix Fietkau 		return false;
1447c8846e10SFelix Fietkau trigger:
1448c8846e10SFelix Fietkau 	dev->cur_reset_cause = cause;
1449c8846e10SFelix Fietkau 	dev->reset_cause[cause]++;
1450c8846e10SFelix Fietkau 	return true;
1451c8846e10SFelix Fietkau }
1452c8846e10SFelix Fietkau 
1453c8846e10SFelix Fietkau void mt7603_update_channel(struct mt76_dev *mdev)
1454c8846e10SFelix Fietkau {
1455c8846e10SFelix Fietkau 	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
1456c8846e10SFelix Fietkau 	struct mt76_channel_state *state;
1457c8846e10SFelix Fietkau 	ktime_t cur_time;
1458c8846e10SFelix Fietkau 	u32 busy;
1459c8846e10SFelix Fietkau 
1460c8846e10SFelix Fietkau 	if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
1461c8846e10SFelix Fietkau 		return;
1462c8846e10SFelix Fietkau 
1463c8846e10SFelix Fietkau 	state = mt76_channel_state(&dev->mt76, dev->mt76.chandef.chan);
1464c8846e10SFelix Fietkau 	busy = mt76_rr(dev, MT_MIB_STAT_PSCCA);
1465c8846e10SFelix Fietkau 
1466c8846e10SFelix Fietkau 	spin_lock_bh(&dev->mt76.cc_lock);
1467c8846e10SFelix Fietkau 	cur_time = ktime_get_boottime();
1468c8846e10SFelix Fietkau 	state->cc_busy += busy;
1469c8846e10SFelix Fietkau 	state->cc_active += ktime_to_us(ktime_sub(cur_time, dev->survey_time));
1470c8846e10SFelix Fietkau 	dev->survey_time = cur_time;
1471c8846e10SFelix Fietkau 	spin_unlock_bh(&dev->mt76.cc_lock);
1472c8846e10SFelix Fietkau }
1473c8846e10SFelix Fietkau 
1474c8846e10SFelix Fietkau void
1475c8846e10SFelix Fietkau mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val)
1476c8846e10SFelix Fietkau {
1477c8846e10SFelix Fietkau 	u32 rxtd_6 = 0xd7c80000;
1478c8846e10SFelix Fietkau 
1479c8846e10SFelix Fietkau 	if (val == dev->ed_strict_mode)
1480c8846e10SFelix Fietkau 		return;
1481c8846e10SFelix Fietkau 
1482c8846e10SFelix Fietkau 	dev->ed_strict_mode = val;
1483c8846e10SFelix Fietkau 
1484c8846e10SFelix Fietkau 	/* Ensure that ED/CCA does not trigger if disabled */
1485c8846e10SFelix Fietkau 	if (!dev->ed_monitor)
1486c8846e10SFelix Fietkau 		rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x34);
1487c8846e10SFelix Fietkau 	else
1488c8846e10SFelix Fietkau 		rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x7d);
1489c8846e10SFelix Fietkau 
1490c8846e10SFelix Fietkau 	if (dev->ed_monitor && !dev->ed_strict_mode)
1491c8846e10SFelix Fietkau 		rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x0f);
1492c8846e10SFelix Fietkau 	else
1493c8846e10SFelix Fietkau 		rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x10);
1494c8846e10SFelix Fietkau 
1495c8846e10SFelix Fietkau 	mt76_wr(dev, MT_RXTD(6), rxtd_6);
1496c8846e10SFelix Fietkau 
1497c8846e10SFelix Fietkau 	mt76_rmw_field(dev, MT_RXTD(13), MT_RXTD_13_ACI_TH_EN,
1498c8846e10SFelix Fietkau 		       dev->ed_monitor && !dev->ed_strict_mode);
1499c8846e10SFelix Fietkau }
1500c8846e10SFelix Fietkau 
1501c8846e10SFelix Fietkau static void
1502c8846e10SFelix Fietkau mt7603_edcca_check(struct mt7603_dev *dev)
1503c8846e10SFelix Fietkau {
1504c8846e10SFelix Fietkau 	u32 val = mt76_rr(dev, MT_AGC(41));
1505c8846e10SFelix Fietkau 	ktime_t cur_time;
1506c8846e10SFelix Fietkau 	int rssi0, rssi1;
1507c8846e10SFelix Fietkau 	u32 active;
1508c8846e10SFelix Fietkau 	u32 ed_busy;
1509c8846e10SFelix Fietkau 
1510c8846e10SFelix Fietkau 	if (!dev->ed_monitor)
1511c8846e10SFelix Fietkau 		return;
1512c8846e10SFelix Fietkau 
1513c8846e10SFelix Fietkau 	rssi0 = FIELD_GET(MT_AGC_41_RSSI_0, val);
1514c8846e10SFelix Fietkau 	if (rssi0 > 128)
1515c8846e10SFelix Fietkau 		rssi0 -= 256;
1516c8846e10SFelix Fietkau 
1517c8846e10SFelix Fietkau 	rssi1 = FIELD_GET(MT_AGC_41_RSSI_1, val);
1518c8846e10SFelix Fietkau 	if (rssi1 > 128)
1519c8846e10SFelix Fietkau 		rssi1 -= 256;
1520c8846e10SFelix Fietkau 
1521c8846e10SFelix Fietkau 	if (max(rssi0, rssi1) >= -40 &&
1522c8846e10SFelix Fietkau 	    dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH)
1523c8846e10SFelix Fietkau 		dev->ed_strong_signal++;
1524c8846e10SFelix Fietkau 	else if (dev->ed_strong_signal > 0)
1525c8846e10SFelix Fietkau 		dev->ed_strong_signal--;
1526c8846e10SFelix Fietkau 
1527c8846e10SFelix Fietkau 	cur_time = ktime_get_boottime();
1528c8846e10SFelix Fietkau 	ed_busy = mt76_rr(dev, MT_MIB_STAT_ED) & MT_MIB_STAT_ED_MASK;
1529c8846e10SFelix Fietkau 
1530c8846e10SFelix Fietkau 	active = ktime_to_us(ktime_sub(cur_time, dev->ed_time));
1531c8846e10SFelix Fietkau 	dev->ed_time = cur_time;
1532c8846e10SFelix Fietkau 
1533c8846e10SFelix Fietkau 	if (!active)
1534c8846e10SFelix Fietkau 		return;
1535c8846e10SFelix Fietkau 
1536c8846e10SFelix Fietkau 	if (100 * ed_busy / active > 90) {
1537c8846e10SFelix Fietkau 		if (dev->ed_trigger < 0)
1538c8846e10SFelix Fietkau 			dev->ed_trigger = 0;
1539c8846e10SFelix Fietkau 		dev->ed_trigger++;
1540c8846e10SFelix Fietkau 	} else {
1541c8846e10SFelix Fietkau 		if (dev->ed_trigger > 0)
1542c8846e10SFelix Fietkau 			dev->ed_trigger = 0;
1543c8846e10SFelix Fietkau 		dev->ed_trigger--;
1544c8846e10SFelix Fietkau 	}
1545c8846e10SFelix Fietkau 
1546c8846e10SFelix Fietkau 	if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH ||
1547c8846e10SFelix Fietkau 	    dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH / 2) {
1548c8846e10SFelix Fietkau 		mt7603_edcca_set_strict(dev, true);
1549c8846e10SFelix Fietkau 	} else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH) {
1550c8846e10SFelix Fietkau 		mt7603_edcca_set_strict(dev, false);
1551c8846e10SFelix Fietkau 	}
1552c8846e10SFelix Fietkau 
1553c8846e10SFelix Fietkau 	if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH)
1554c8846e10SFelix Fietkau 		dev->ed_trigger = MT7603_EDCCA_BLOCK_TH;
1555c8846e10SFelix Fietkau 	else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH)
1556c8846e10SFelix Fietkau 		dev->ed_trigger = -MT7603_EDCCA_BLOCK_TH;
1557c8846e10SFelix Fietkau }
1558c8846e10SFelix Fietkau 
1559c8846e10SFelix Fietkau void mt7603_cca_stats_reset(struct mt7603_dev *dev)
1560c8846e10SFelix Fietkau {
1561c8846e10SFelix Fietkau 	mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET);
1562c8846e10SFelix Fietkau 	mt76_clear(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET);
1563c8846e10SFelix Fietkau 	mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_EN);
1564c8846e10SFelix Fietkau }
1565c8846e10SFelix Fietkau 
1566c8846e10SFelix Fietkau static void
1567c8846e10SFelix Fietkau mt7603_adjust_sensitivity(struct mt7603_dev *dev)
1568c8846e10SFelix Fietkau {
1569c8846e10SFelix Fietkau 	u32 agc0 = dev->agc0, agc3 = dev->agc3;
1570c8846e10SFelix Fietkau 	u32 adj;
1571c8846e10SFelix Fietkau 
1572c8846e10SFelix Fietkau 	if (!dev->sensitivity || dev->sensitivity < -100) {
1573c8846e10SFelix Fietkau 		dev->sensitivity = 0;
1574c8846e10SFelix Fietkau 	} else if (dev->sensitivity <= -84) {
1575c8846e10SFelix Fietkau 		adj = 7 + (dev->sensitivity + 92) / 2;
1576c8846e10SFelix Fietkau 
1577c8846e10SFelix Fietkau 		agc0 = 0x56f0076f;
1578c8846e10SFelix Fietkau 		agc0 |= adj << 12;
1579c8846e10SFelix Fietkau 		agc0 |= adj << 16;
1580c8846e10SFelix Fietkau 		agc3 = 0x81d0d5e3;
1581c8846e10SFelix Fietkau 	} else if (dev->sensitivity <= -72) {
1582c8846e10SFelix Fietkau 		adj = 7 + (dev->sensitivity + 80) / 2;
1583c8846e10SFelix Fietkau 
1584c8846e10SFelix Fietkau 		agc0 = 0x6af0006f;
1585c8846e10SFelix Fietkau 		agc0 |= adj << 8;
1586c8846e10SFelix Fietkau 		agc0 |= adj << 12;
1587c8846e10SFelix Fietkau 		agc0 |= adj << 16;
1588c8846e10SFelix Fietkau 
1589c8846e10SFelix Fietkau 		agc3 = 0x8181d5e3;
1590c8846e10SFelix Fietkau 	} else {
1591c8846e10SFelix Fietkau 		if (dev->sensitivity > -54)
1592c8846e10SFelix Fietkau 			dev->sensitivity = -54;
1593c8846e10SFelix Fietkau 
1594c8846e10SFelix Fietkau 		adj = 7 + (dev->sensitivity + 80) / 2;
1595c8846e10SFelix Fietkau 
1596c8846e10SFelix Fietkau 		agc0 = 0x7ff0000f;
1597c8846e10SFelix Fietkau 		agc0 |= adj << 4;
1598c8846e10SFelix Fietkau 		agc0 |= adj << 8;
1599c8846e10SFelix Fietkau 		agc0 |= adj << 12;
1600c8846e10SFelix Fietkau 		agc0 |= adj << 16;
1601c8846e10SFelix Fietkau 
1602c8846e10SFelix Fietkau 		agc3 = 0x818181e3;
1603c8846e10SFelix Fietkau 	}
1604c8846e10SFelix Fietkau 
1605c8846e10SFelix Fietkau 	mt76_wr(dev, MT_AGC(0), agc0);
1606c8846e10SFelix Fietkau 	mt76_wr(dev, MT_AGC1(0), agc0);
1607c8846e10SFelix Fietkau 
1608c8846e10SFelix Fietkau 	mt76_wr(dev, MT_AGC(3), agc3);
1609c8846e10SFelix Fietkau 	mt76_wr(dev, MT_AGC1(3), agc3);
1610c8846e10SFelix Fietkau }
1611c8846e10SFelix Fietkau 
1612c8846e10SFelix Fietkau static void
1613c8846e10SFelix Fietkau mt7603_false_cca_check(struct mt7603_dev *dev)
1614c8846e10SFelix Fietkau {
1615c8846e10SFelix Fietkau 	int pd_cck, pd_ofdm, mdrdy_cck, mdrdy_ofdm;
1616c8846e10SFelix Fietkau 	int false_cca;
1617c8846e10SFelix Fietkau 	int min_signal;
1618c8846e10SFelix Fietkau 	u32 val;
1619c8846e10SFelix Fietkau 
1620c8846e10SFelix Fietkau 	val = mt76_rr(dev, MT_PHYCTRL_STAT_PD);
1621c8846e10SFelix Fietkau 	pd_cck = FIELD_GET(MT_PHYCTRL_STAT_PD_CCK, val);
1622c8846e10SFelix Fietkau 	pd_ofdm = FIELD_GET(MT_PHYCTRL_STAT_PD_OFDM, val);
1623c8846e10SFelix Fietkau 
1624c8846e10SFelix Fietkau 	val = mt76_rr(dev, MT_PHYCTRL_STAT_MDRDY);
1625c8846e10SFelix Fietkau 	mdrdy_cck = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_CCK, val);
1626c8846e10SFelix Fietkau 	mdrdy_ofdm = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_OFDM, val);
1627c8846e10SFelix Fietkau 
1628c8846e10SFelix Fietkau 	dev->false_cca_ofdm = pd_ofdm - mdrdy_ofdm;
1629c8846e10SFelix Fietkau 	dev->false_cca_cck = pd_cck - mdrdy_cck;
1630c8846e10SFelix Fietkau 
1631c8846e10SFelix Fietkau 	mt7603_cca_stats_reset(dev);
1632c8846e10SFelix Fietkau 
1633c8846e10SFelix Fietkau 	min_signal = mt76_get_min_avg_rssi(&dev->mt76);
1634c8846e10SFelix Fietkau 	if (!min_signal) {
1635c8846e10SFelix Fietkau 		dev->sensitivity = 0;
1636c8846e10SFelix Fietkau 		dev->last_cca_adj = jiffies;
1637c8846e10SFelix Fietkau 		goto out;
1638c8846e10SFelix Fietkau 	}
1639c8846e10SFelix Fietkau 
1640c8846e10SFelix Fietkau 	min_signal -= 15;
1641c8846e10SFelix Fietkau 
1642c8846e10SFelix Fietkau 	false_cca = dev->false_cca_ofdm + dev->false_cca_cck;
1643c8846e10SFelix Fietkau 	if (false_cca > 600) {
1644c8846e10SFelix Fietkau 		if (!dev->sensitivity)
1645c8846e10SFelix Fietkau 			dev->sensitivity = -92;
1646c8846e10SFelix Fietkau 		else
1647c8846e10SFelix Fietkau 			dev->sensitivity += 2;
1648c8846e10SFelix Fietkau 		dev->last_cca_adj = jiffies;
1649c8846e10SFelix Fietkau 	} else if (false_cca < 100 ||
1650c8846e10SFelix Fietkau 		   time_after(jiffies, dev->last_cca_adj + 10 * HZ)) {
1651c8846e10SFelix Fietkau 		dev->last_cca_adj = jiffies;
1652c8846e10SFelix Fietkau 		if (!dev->sensitivity)
1653c8846e10SFelix Fietkau 			goto out;
1654c8846e10SFelix Fietkau 
1655c8846e10SFelix Fietkau 		dev->sensitivity -= 2;
1656c8846e10SFelix Fietkau 	}
1657c8846e10SFelix Fietkau 
1658c8846e10SFelix Fietkau 	if (dev->sensitivity && dev->sensitivity > min_signal) {
1659c8846e10SFelix Fietkau 		dev->sensitivity = min_signal;
1660c8846e10SFelix Fietkau 		dev->last_cca_adj = jiffies;
1661c8846e10SFelix Fietkau 	}
1662c8846e10SFelix Fietkau 
1663c8846e10SFelix Fietkau out:
1664c8846e10SFelix Fietkau 	mt7603_adjust_sensitivity(dev);
1665c8846e10SFelix Fietkau }
1666c8846e10SFelix Fietkau 
1667c8846e10SFelix Fietkau void mt7603_mac_work(struct work_struct *work)
1668c8846e10SFelix Fietkau {
1669c8846e10SFelix Fietkau 	struct mt7603_dev *dev = container_of(work, struct mt7603_dev,
1670c8846e10SFelix Fietkau 					      mac_work.work);
1671c8846e10SFelix Fietkau 	bool reset = false;
1672c8846e10SFelix Fietkau 
1673c8846e10SFelix Fietkau 	mt76_tx_status_check(&dev->mt76, NULL, false);
1674c8846e10SFelix Fietkau 
1675c8846e10SFelix Fietkau 	mutex_lock(&dev->mt76.mutex);
1676c8846e10SFelix Fietkau 
1677c8846e10SFelix Fietkau 	dev->mac_work_count++;
1678c8846e10SFelix Fietkau 	mt7603_update_channel(&dev->mt76);
1679c8846e10SFelix Fietkau 	mt7603_edcca_check(dev);
1680c8846e10SFelix Fietkau 
1681c8846e10SFelix Fietkau 	if (dev->mac_work_count == 10)
1682c8846e10SFelix Fietkau 		mt7603_false_cca_check(dev);
1683c8846e10SFelix Fietkau 
1684c8846e10SFelix Fietkau 	if (mt7603_watchdog_check(dev, &dev->rx_pse_check,
1685c8846e10SFelix Fietkau 				  RESET_CAUSE_RX_PSE_BUSY,
1686c8846e10SFelix Fietkau 				  mt7603_rx_pse_busy) ||
1687c8846e10SFelix Fietkau 	    mt7603_watchdog_check(dev, &dev->beacon_check,
1688c8846e10SFelix Fietkau 				  RESET_CAUSE_BEACON_STUCK,
1689c8846e10SFelix Fietkau 				  NULL) ||
1690c8846e10SFelix Fietkau 	    mt7603_watchdog_check(dev, &dev->tx_hang_check,
1691c8846e10SFelix Fietkau 				  RESET_CAUSE_TX_HANG,
1692c8846e10SFelix Fietkau 				  mt7603_tx_hang) ||
1693c8846e10SFelix Fietkau 	    mt7603_watchdog_check(dev, &dev->tx_dma_check,
1694c8846e10SFelix Fietkau 				  RESET_CAUSE_TX_BUSY,
1695c8846e10SFelix Fietkau 				  mt7603_tx_dma_busy) ||
1696c8846e10SFelix Fietkau 	    mt7603_watchdog_check(dev, &dev->rx_dma_check,
1697c8846e10SFelix Fietkau 				  RESET_CAUSE_RX_BUSY,
1698c8846e10SFelix Fietkau 				  mt7603_rx_dma_busy) ||
1699c8846e10SFelix Fietkau 	    mt7603_watchdog_check(dev, &dev->mcu_hang,
1700c8846e10SFelix Fietkau 				  RESET_CAUSE_MCU_HANG,
1701c8846e10SFelix Fietkau 				  NULL) ||
1702c8846e10SFelix Fietkau 	    dev->reset_cause[RESET_CAUSE_RESET_FAILED]) {
1703c8846e10SFelix Fietkau 		dev->beacon_check = 0;
1704c8846e10SFelix Fietkau 		dev->tx_dma_check = 0;
1705c8846e10SFelix Fietkau 		dev->tx_hang_check = 0;
1706c8846e10SFelix Fietkau 		dev->rx_dma_check = 0;
1707c8846e10SFelix Fietkau 		dev->rx_pse_check = 0;
1708c8846e10SFelix Fietkau 		dev->mcu_hang = 0;
1709c8846e10SFelix Fietkau 		dev->rx_dma_idx = ~0;
1710c8846e10SFelix Fietkau 		memset(dev->tx_dma_idx, 0xff, sizeof(dev->tx_dma_idx));
1711c8846e10SFelix Fietkau 		reset = true;
1712c8846e10SFelix Fietkau 		dev->mac_work_count = 0;
1713c8846e10SFelix Fietkau 	}
1714c8846e10SFelix Fietkau 
1715c8846e10SFelix Fietkau 	if (dev->mac_work_count >= 10)
1716c8846e10SFelix Fietkau 		dev->mac_work_count = 0;
1717c8846e10SFelix Fietkau 
1718c8846e10SFelix Fietkau 	mutex_unlock(&dev->mt76.mutex);
1719c8846e10SFelix Fietkau 
1720c8846e10SFelix Fietkau 	if (reset)
1721c8846e10SFelix Fietkau 		mt7603_mac_watchdog_reset(dev);
1722c8846e10SFelix Fietkau 
1723c8846e10SFelix Fietkau 	ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
1724c8846e10SFelix Fietkau 				     msecs_to_jiffies(MT7603_WATCHDOG_TIME));
1725c8846e10SFelix Fietkau }
1726