1 | // SPDX-License-Identifier: ISC |
2 | /* Copyright (C) 2020 MediaTek Inc. */ |
3 | |
4 | #include "mt76_connac.h" |
5 | #include "mt76_connac2_mac.h" |
6 | #include "dma.h" |
7 | |
8 | #define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) |
9 | #define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ |
10 | IEEE80211_RADIOTAP_HE_##f) |
11 | |
12 | void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss) |
13 | { |
14 | static const u8 ppet16_ppet8_ru3_ru0[] = { 0x1c, 0xc7, 0x71 }; |
15 | u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ |
16 | |
17 | he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | |
18 | FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, |
19 | ru_bit_mask); |
20 | |
21 | ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE * |
22 | nss * hweight8(ru_bit_mask) * 2; |
23 | ppet_size = DIV_ROUND_UP(ppet_bits, 8); |
24 | |
25 | for (i = 0; i < ppet_size - 1; i++) |
26 | he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3]; |
27 | |
28 | he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] & |
29 | (0xff >> (8 - (ppet_bits - 1) % 8)); |
30 | } |
31 | EXPORT_SYMBOL_GPL(mt76_connac_gen_ppe_thresh); |
32 | |
33 | int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm) |
34 | { |
35 | struct mt76_dev *dev = phy->dev; |
36 | |
37 | if (mt76_is_usb(dev)) |
38 | return 0; |
39 | |
40 | cancel_delayed_work_sync(dwork: &pm->ps_work); |
41 | if (!test_bit(MT76_STATE_PM, &phy->state)) |
42 | return 0; |
43 | |
44 | if (pm->suspended) |
45 | return 0; |
46 | |
47 | queue_work(wq: dev->wq, work: &pm->wake_work); |
48 | if (!wait_event_timeout(pm->wait, |
49 | !test_bit(MT76_STATE_PM, &phy->state), |
50 | 3 * HZ)) { |
51 | ieee80211_wake_queues(hw: phy->hw); |
52 | return -ETIMEDOUT; |
53 | } |
54 | |
55 | return 0; |
56 | } |
57 | EXPORT_SYMBOL_GPL(mt76_connac_pm_wake); |
58 | |
59 | void mt76_connac_power_save_sched(struct mt76_phy *phy, |
60 | struct mt76_connac_pm *pm) |
61 | { |
62 | struct mt76_dev *dev = phy->dev; |
63 | |
64 | if (mt76_is_usb(dev)) |
65 | return; |
66 | |
67 | if (!pm->enable) |
68 | return; |
69 | |
70 | if (pm->suspended) |
71 | return; |
72 | |
73 | pm->last_activity = jiffies; |
74 | |
75 | if (!test_bit(MT76_STATE_PM, &phy->state)) { |
76 | cancel_delayed_work(dwork: &phy->mac_work); |
77 | queue_delayed_work(wq: dev->wq, dwork: &pm->ps_work, delay: pm->idle_timeout); |
78 | } |
79 | } |
80 | EXPORT_SYMBOL_GPL(mt76_connac_power_save_sched); |
81 | |
82 | void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm, |
83 | struct mt76_wcid *wcid) |
84 | { |
85 | int i; |
86 | |
87 | spin_lock_bh(lock: &pm->txq_lock); |
88 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
89 | if (wcid && pm->tx_q[i].wcid != wcid) |
90 | continue; |
91 | |
92 | dev_kfree_skb(pm->tx_q[i].skb); |
93 | pm->tx_q[i].skb = NULL; |
94 | } |
95 | spin_unlock_bh(lock: &pm->txq_lock); |
96 | } |
97 | EXPORT_SYMBOL_GPL(mt76_connac_free_pending_tx_skbs); |
98 | |
99 | void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw, |
100 | struct mt76_connac_pm *pm, |
101 | struct mt76_wcid *wcid, |
102 | struct sk_buff *skb) |
103 | { |
104 | int qid = skb_get_queue_mapping(skb); |
105 | struct mt76_phy *phy = hw->priv; |
106 | |
107 | spin_lock_bh(lock: &pm->txq_lock); |
108 | if (!pm->tx_q[qid].skb) { |
109 | ieee80211_stop_queues(hw); |
110 | pm->tx_q[qid].wcid = wcid; |
111 | pm->tx_q[qid].skb = skb; |
112 | queue_work(wq: phy->dev->wq, work: &pm->wake_work); |
113 | } else { |
114 | dev_kfree_skb(skb); |
115 | } |
116 | spin_unlock_bh(lock: &pm->txq_lock); |
117 | } |
118 | EXPORT_SYMBOL_GPL(mt76_connac_pm_queue_skb); |
119 | |
120 | void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy, |
121 | struct mt76_connac_pm *pm) |
122 | { |
123 | int i; |
124 | |
125 | spin_lock_bh(lock: &pm->txq_lock); |
126 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
127 | struct mt76_wcid *wcid = pm->tx_q[i].wcid; |
128 | struct ieee80211_sta *sta = NULL; |
129 | |
130 | if (!pm->tx_q[i].skb) |
131 | continue; |
132 | |
133 | if (wcid && wcid->sta) |
134 | sta = container_of((void *)wcid, struct ieee80211_sta, |
135 | drv_priv); |
136 | |
137 | mt76_tx(dev: phy, sta, wcid, skb: pm->tx_q[i].skb); |
138 | pm->tx_q[i].skb = NULL; |
139 | } |
140 | spin_unlock_bh(lock: &pm->txq_lock); |
141 | |
142 | mt76_worker_schedule(w: &phy->dev->tx_worker); |
143 | } |
144 | EXPORT_SYMBOL_GPL(mt76_connac_pm_dequeue_skbs); |
145 | |
146 | void mt76_connac_tx_complete_skb(struct mt76_dev *mdev, |
147 | struct mt76_queue_entry *e) |
148 | { |
149 | if (!e->txwi) { |
150 | dev_kfree_skb_any(skb: e->skb); |
151 | return; |
152 | } |
153 | |
154 | if (e->skb) |
155 | mt76_tx_complete_skb(dev: mdev, wcid: e->wcid, skb: e->skb); |
156 | } |
157 | EXPORT_SYMBOL_GPL(mt76_connac_tx_complete_skb); |
158 | |
159 | void mt76_connac_write_hw_txp(struct mt76_dev *dev, |
160 | struct mt76_tx_info *tx_info, |
161 | void *txp_ptr, u32 id) |
162 | { |
163 | struct mt76_connac_hw_txp *txp = txp_ptr; |
164 | struct mt76_connac_txp_ptr *ptr = &txp->ptr[0]; |
165 | int i, nbuf = tx_info->nbuf - 1; |
166 | u32 last_mask; |
167 | |
168 | tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp); |
169 | tx_info->nbuf = 1; |
170 | |
171 | txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID); |
172 | |
173 | if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev)) |
174 | last_mask = MT_TXD_LEN_LAST; |
175 | else |
176 | last_mask = MT_TXD_LEN_AMSDU_LAST | |
177 | MT_TXD_LEN_MSDU_LAST; |
178 | |
179 | for (i = 0; i < nbuf; i++) { |
180 | u16 len = tx_info->buf[i + 1].len & MT_TXD_LEN_MASK; |
181 | u32 addr = tx_info->buf[i + 1].addr; |
182 | |
183 | if (i == nbuf - 1) |
184 | len |= last_mask; |
185 | |
186 | if (i & 1) { |
187 | ptr->buf1 = cpu_to_le32(addr); |
188 | ptr->len1 = cpu_to_le16(len); |
189 | ptr++; |
190 | } else { |
191 | ptr->buf0 = cpu_to_le32(addr); |
192 | ptr->len0 = cpu_to_le16(len); |
193 | } |
194 | } |
195 | } |
196 | EXPORT_SYMBOL_GPL(mt76_connac_write_hw_txp); |
197 | |
198 | static void |
199 | mt76_connac_txp_skb_unmap_fw(struct mt76_dev *mdev, |
200 | struct mt76_connac_fw_txp *txp) |
201 | { |
202 | struct device *dev = is_connac_v1(dev: mdev) ? mdev->dev : mdev->dma_dev; |
203 | int i; |
204 | |
205 | for (i = 0; i < txp->nbuf; i++) |
206 | dma_unmap_single(dev, le32_to_cpu(txp->buf[i]), |
207 | le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); |
208 | } |
209 | |
210 | static void |
211 | mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev, |
212 | struct mt76_connac_hw_txp *txp) |
213 | { |
214 | u32 last_mask; |
215 | int i; |
216 | |
217 | if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev)) |
218 | last_mask = MT_TXD_LEN_LAST; |
219 | else |
220 | last_mask = MT_TXD_LEN_MSDU_LAST; |
221 | |
222 | for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) { |
223 | struct mt76_connac_txp_ptr *ptr = &txp->ptr[i]; |
224 | bool last; |
225 | u16 len; |
226 | |
227 | len = le16_to_cpu(ptr->len0); |
228 | last = len & last_mask; |
229 | len &= MT_TXD_LEN_MASK; |
230 | dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len, |
231 | DMA_TO_DEVICE); |
232 | if (last) |
233 | break; |
234 | |
235 | len = le16_to_cpu(ptr->len1); |
236 | last = len & last_mask; |
237 | len &= MT_TXD_LEN_MASK; |
238 | dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len, |
239 | DMA_TO_DEVICE); |
240 | if (last) |
241 | break; |
242 | } |
243 | } |
244 | |
245 | void mt76_connac_txp_skb_unmap(struct mt76_dev *dev, |
246 | struct mt76_txwi_cache *t) |
247 | { |
248 | struct mt76_connac_txp_common *txp; |
249 | |
250 | txp = mt76_connac_txwi_to_txp(dev, t); |
251 | if (is_mt76_fw_txp(dev)) |
252 | mt76_connac_txp_skb_unmap_fw(mdev: dev, txp: &txp->fw); |
253 | else |
254 | mt76_connac_txp_skb_unmap_hw(dev, txp: &txp->hw); |
255 | } |
256 | EXPORT_SYMBOL_GPL(mt76_connac_txp_skb_unmap); |
257 | |
258 | int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc, |
259 | int ring_base, void *wed, u32 flags) |
260 | { |
261 | int i, err; |
262 | |
263 | err = mt76_init_tx_queue(phy, qid: 0, idx, n_desc, ring_base, |
264 | wed, flags); |
265 | if (err < 0) |
266 | return err; |
267 | |
268 | for (i = 1; i <= MT_TXQ_PSD; i++) |
269 | phy->q_tx[i] = phy->q_tx[0]; |
270 | |
271 | return 0; |
272 | } |
273 | EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues); |
274 | |
275 | #define __bitrate_mask_check(_mcs, _mode) \ |
276 | ({ \ |
277 | u8 i = 0; \ |
278 | for (nss = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \ |
279 | if (!mask->control[band]._mcs[i]) \ |
280 | continue; \ |
281 | if (hweight16(mask->control[band]._mcs[i]) == 1) { \ |
282 | mode = MT_PHY_TYPE_##_mode; \ |
283 | rateidx = ffs(mask->control[band]._mcs[i]) - 1; \ |
284 | if (mode == MT_PHY_TYPE_HT) \ |
285 | rateidx += 8 * i; \ |
286 | else \ |
287 | nss = i + 1; \ |
288 | goto out; \ |
289 | } \ |
290 | } \ |
291 | }) |
292 | |
293 | u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, |
294 | struct ieee80211_vif *vif, |
295 | bool beacon, bool mcast) |
296 | { |
297 | struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; |
298 | struct cfg80211_chan_def *chandef = mvif->ctx ? |
299 | &mvif->ctx->def : &mphy->chandef; |
300 | u8 nss = 0, mode = 0, band = chandef->chan->band; |
301 | int rateidx = 0, mcast_rate; |
302 | |
303 | if (!vif) |
304 | goto legacy; |
305 | |
306 | if (is_mt7921(dev: mphy->dev)) { |
307 | rateidx = ffs(vif->bss_conf.basic_rates) - 1; |
308 | goto legacy; |
309 | } |
310 | |
311 | if (beacon) { |
312 | struct cfg80211_bitrate_mask *mask; |
313 | |
314 | mask = &vif->bss_conf.beacon_tx_rate; |
315 | |
316 | __bitrate_mask_check(he_mcs, HE_SU); |
317 | __bitrate_mask_check(vht_mcs, VHT); |
318 | __bitrate_mask_check(ht_mcs, HT); |
319 | |
320 | if (hweight32(mask->control[band].legacy) == 1) { |
321 | rateidx = ffs(mask->control[band].legacy) - 1; |
322 | goto legacy; |
323 | } |
324 | } |
325 | |
326 | mcast_rate = vif->bss_conf.mcast_rate[band]; |
327 | if (mcast && mcast_rate > 0) |
328 | rateidx = mcast_rate - 1; |
329 | else |
330 | rateidx = ffs(vif->bss_conf.basic_rates) - 1; |
331 | |
332 | legacy: |
333 | rateidx = mt76_calculate_default_rate(phy: mphy, vif, rateidx); |
334 | mode = rateidx >> 8; |
335 | rateidx &= GENMASK(7, 0); |
336 | out: |
337 | return FIELD_PREP(MT_TX_RATE_NSS, nss) | |
338 | FIELD_PREP(MT_TX_RATE_IDX, rateidx) | |
339 | FIELD_PREP(MT_TX_RATE_MODE, mode); |
340 | } |
341 | EXPORT_SYMBOL_GPL(mt76_connac2_mac_tx_rate_val); |
342 | |
343 | static void |
344 | mt76_connac2_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb, |
345 | struct mt76_wcid *wcid) |
346 | { |
347 | u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; |
348 | u8 fc_type, fc_stype; |
349 | u16 ethertype; |
350 | bool wmm = false; |
351 | u32 val; |
352 | |
353 | if (wcid->sta) { |
354 | struct ieee80211_sta *sta; |
355 | |
356 | sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); |
357 | wmm = sta->wme; |
358 | } |
359 | |
360 | val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | |
361 | FIELD_PREP(MT_TXD1_TID, tid); |
362 | |
363 | ethertype = get_unaligned_be16(p: &skb->data[12]); |
364 | if (ethertype >= ETH_P_802_3_MIN) |
365 | val |= MT_TXD1_ETH_802_3; |
366 | |
367 | txwi[1] |= cpu_to_le32(val); |
368 | |
369 | fc_type = IEEE80211_FTYPE_DATA >> 2; |
370 | fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; |
371 | |
372 | val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | |
373 | FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); |
374 | |
375 | txwi[2] |= cpu_to_le32(val); |
376 | |
377 | val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | |
378 | FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); |
379 | |
380 | txwi[7] |= cpu_to_le32(val); |
381 | } |
382 | |
383 | static void |
384 | mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, |
385 | struct sk_buff *skb, |
386 | struct ieee80211_key_conf *key) |
387 | { |
388 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
389 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; |
390 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
391 | bool multicast = is_multicast_ether_addr(addr: hdr->addr1); |
392 | u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; |
393 | __le16 fc = hdr->frame_control; |
394 | u8 fc_type, fc_stype; |
395 | u32 val; |
396 | |
397 | if (ieee80211_is_action(fc) && |
398 | mgmt->u.action.category == WLAN_CATEGORY_BACK && |
399 | mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { |
400 | u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); |
401 | |
402 | txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA); |
403 | tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK; |
404 | } else if (ieee80211_is_back_req(fc: hdr->frame_control)) { |
405 | struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr; |
406 | u16 control = le16_to_cpu(bar->control); |
407 | |
408 | tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control); |
409 | } |
410 | |
411 | val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | |
412 | FIELD_PREP(MT_TXD1_HDR_INFO, |
413 | ieee80211_get_hdrlen_from_skb(skb) / 2) | |
414 | FIELD_PREP(MT_TXD1_TID, tid); |
415 | |
416 | txwi[1] |= cpu_to_le32(val); |
417 | |
418 | fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; |
419 | fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; |
420 | |
421 | val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | |
422 | FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | |
423 | FIELD_PREP(MT_TXD2_MULTICAST, multicast); |
424 | |
425 | if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && |
426 | key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { |
427 | val |= MT_TXD2_BIP; |
428 | txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); |
429 | } |
430 | |
431 | if (!ieee80211_is_data(fc) || multicast || |
432 | info->flags & IEEE80211_TX_CTL_USE_MINRATE) |
433 | val |= MT_TXD2_FIX_RATE; |
434 | |
435 | txwi[2] |= cpu_to_le32(val); |
436 | |
437 | if (ieee80211_is_beacon(fc)) { |
438 | txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); |
439 | txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); |
440 | } |
441 | |
442 | if (info->flags & IEEE80211_TX_CTL_INJECTED) { |
443 | u16 seqno = le16_to_cpu(hdr->seq_ctrl); |
444 | |
445 | if (ieee80211_is_back_req(fc: hdr->frame_control)) { |
446 | struct ieee80211_bar *bar; |
447 | |
448 | bar = (struct ieee80211_bar *)skb->data; |
449 | seqno = le16_to_cpu(bar->start_seq_num); |
450 | } |
451 | |
452 | val = MT_TXD3_SN_VALID | |
453 | FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); |
454 | txwi[3] |= cpu_to_le32(val); |
455 | txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU); |
456 | } |
457 | |
458 | if (mt76_is_mmio(dev)) { |
459 | val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | |
460 | FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); |
461 | txwi[7] |= cpu_to_le32(val); |
462 | } else { |
463 | val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) | |
464 | FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype); |
465 | txwi[8] |= cpu_to_le32(val); |
466 | } |
467 | } |
468 | |
469 | void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, |
470 | struct sk_buff *skb, struct mt76_wcid *wcid, |
471 | struct ieee80211_key_conf *key, int pid, |
472 | enum mt76_txq_id qid, u32 changed) |
473 | { |
474 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
475 | u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; |
476 | struct ieee80211_vif *vif = info->control.vif; |
477 | struct mt76_phy *mphy = &dev->phy; |
478 | u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0, band_idx = 0; |
479 | u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE; |
480 | bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; |
481 | bool beacon = !!(changed & (BSS_CHANGED_BEACON | |
482 | BSS_CHANGED_BEACON_ENABLED)); |
483 | bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | |
484 | BSS_CHANGED_FILS_DISCOVERY)); |
485 | bool amsdu_en = wcid->amsdu; |
486 | |
487 | if (vif) { |
488 | struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; |
489 | |
490 | omac_idx = mvif->omac_idx; |
491 | wmm_idx = mvif->wmm_idx; |
492 | band_idx = mvif->band_idx; |
493 | } |
494 | |
495 | if (phy_idx && dev->phys[MT_BAND1]) |
496 | mphy = dev->phys[MT_BAND1]; |
497 | |
498 | if (inband_disc) { |
499 | p_fmt = MT_TX_TYPE_FW; |
500 | q_idx = MT_LMAC_ALTX0; |
501 | } else if (beacon) { |
502 | p_fmt = MT_TX_TYPE_FW; |
503 | q_idx = MT_LMAC_BCN0; |
504 | } else if (qid >= MT_TXQ_PSD) { |
505 | p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; |
506 | q_idx = MT_LMAC_ALTX0; |
507 | } else { |
508 | p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; |
509 | q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS + |
510 | mt76_connac_lmac_mapping(ac: skb_get_queue_mapping(skb)); |
511 | |
512 | /* mt7915 WA only counts WED path */ |
513 | if (is_mt7915(dev) && mtk_wed_device_active(&dev->mmio.wed)) |
514 | wcid->stats.tx_packets++; |
515 | } |
516 | |
517 | val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) | |
518 | FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | |
519 | FIELD_PREP(MT_TXD0_Q_IDX, q_idx); |
520 | txwi[0] = cpu_to_le32(val); |
521 | |
522 | val = MT_TXD1_LONG_FORMAT | |
523 | FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | |
524 | FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); |
525 | if (!is_mt7921(dev)) |
526 | val |= MT_TXD1_VTA; |
527 | if (phy_idx || band_idx) |
528 | val |= MT_TXD1_TGID; |
529 | |
530 | txwi[1] = cpu_to_le32(val); |
531 | txwi[2] = 0; |
532 | |
533 | val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15); |
534 | if (!is_mt7921(dev)) |
535 | val |= MT_TXD3_SW_POWER_MGMT; |
536 | if (key) |
537 | val |= MT_TXD3_PROTECT_FRAME; |
538 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) |
539 | val |= MT_TXD3_NO_ACK; |
540 | |
541 | txwi[3] = cpu_to_le32(val); |
542 | txwi[4] = 0; |
543 | |
544 | val = FIELD_PREP(MT_TXD5_PID, pid); |
545 | if (pid >= MT_PACKET_ID_FIRST) { |
546 | val |= MT_TXD5_TX_STATUS_HOST; |
547 | amsdu_en = 0; |
548 | } |
549 | |
550 | txwi[5] = cpu_to_le32(val); |
551 | txwi[6] = 0; |
552 | txwi[7] = amsdu_en ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; |
553 | |
554 | if (is_8023) |
555 | mt76_connac2_mac_write_txwi_8023(txwi, skb, wcid); |
556 | else |
557 | mt76_connac2_mac_write_txwi_80211(dev, txwi, skb, key); |
558 | |
559 | if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) { |
560 | /* Fixed rata is available just for 802.11 txd */ |
561 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
562 | bool multicast = ieee80211_is_data(fc: hdr->frame_control) && |
563 | is_multicast_ether_addr(addr: hdr->addr1); |
564 | u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, |
565 | multicast); |
566 | u32 val = MT_TXD6_FIXED_BW; |
567 | |
568 | /* hardware won't add HTC for mgmt/ctrl frame */ |
569 | txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD); |
570 | |
571 | val |= FIELD_PREP(MT_TXD6_TX_RATE, rate); |
572 | txwi[6] |= cpu_to_le32(val); |
573 | txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); |
574 | |
575 | if (!is_mt7921(dev)) { |
576 | u8 spe_idx = mt76_connac_spe_idx(antenna_mask: mphy->antenna_mask); |
577 | |
578 | if (!spe_idx) |
579 | spe_idx = 24 + phy_idx; |
580 | txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, spe_idx)); |
581 | } |
582 | |
583 | txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU); |
584 | } |
585 | } |
586 | EXPORT_SYMBOL_GPL(mt76_connac2_mac_write_txwi); |
587 | |
588 | bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, |
589 | __le32 *txs_data) |
590 | { |
591 | struct mt76_sta_stats *stats = &wcid->stats; |
592 | struct ieee80211_supported_band *sband; |
593 | struct mt76_phy *mphy; |
594 | struct rate_info rate = {}; |
595 | bool cck = false; |
596 | u32 txrate, txs, mode, stbc; |
597 | |
598 | txs = le32_to_cpu(txs_data[0]); |
599 | |
600 | /* PPDU based reporting */ |
601 | if (mtk_wed_device_active(&dev->mmio.wed) && |
602 | FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) { |
603 | stats->tx_bytes += |
604 | le32_get_bits(v: txs_data[5], MT_TXS5_MPDU_TX_BYTE) - |
605 | le32_get_bits(v: txs_data[7], MT_TXS7_MPDU_RETRY_BYTE); |
606 | stats->tx_failed += |
607 | le32_get_bits(v: txs_data[6], MT_TXS6_MPDU_FAIL_CNT); |
608 | stats->tx_retries += |
609 | le32_get_bits(v: txs_data[7], MT_TXS7_MPDU_RETRY_CNT); |
610 | |
611 | if (wcid->sta) { |
612 | struct ieee80211_sta *sta; |
613 | u8 tid; |
614 | |
615 | sta = container_of((void *)wcid, struct ieee80211_sta, |
616 | drv_priv); |
617 | tid = FIELD_GET(MT_TXS0_TID, txs); |
618 | |
619 | ieee80211_refresh_tx_agg_session_timer(sta, tid); |
620 | } |
621 | } |
622 | |
623 | txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); |
624 | |
625 | rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); |
626 | rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; |
627 | stbc = FIELD_GET(MT_TX_RATE_STBC, txrate); |
628 | |
629 | if (stbc && rate.nss > 1) |
630 | rate.nss >>= 1; |
631 | |
632 | if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) |
633 | stats->tx_nss[rate.nss - 1]++; |
634 | if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) |
635 | stats->tx_mcs[rate.mcs]++; |
636 | |
637 | mode = FIELD_GET(MT_TX_RATE_MODE, txrate); |
638 | switch (mode) { |
639 | case MT_PHY_TYPE_CCK: |
640 | cck = true; |
641 | fallthrough; |
642 | case MT_PHY_TYPE_OFDM: |
643 | mphy = &dev->phy; |
644 | if (wcid->phy_idx == MT_BAND1 && dev->phys[MT_BAND1]) |
645 | mphy = dev->phys[MT_BAND1]; |
646 | |
647 | if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) |
648 | sband = &mphy->sband_5g.sband; |
649 | else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) |
650 | sband = &mphy->sband_6g.sband; |
651 | else |
652 | sband = &mphy->sband_2g.sband; |
653 | |
654 | rate.mcs = mt76_get_rate(dev: mphy->dev, sband, idx: rate.mcs, cck); |
655 | rate.legacy = sband->bitrates[rate.mcs].bitrate; |
656 | break; |
657 | case MT_PHY_TYPE_HT: |
658 | case MT_PHY_TYPE_HT_GF: |
659 | if (rate.mcs > 31) |
660 | return false; |
661 | |
662 | rate.flags = RATE_INFO_FLAGS_MCS; |
663 | if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) |
664 | rate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
665 | break; |
666 | case MT_PHY_TYPE_VHT: |
667 | if (rate.mcs > 9) |
668 | return false; |
669 | |
670 | rate.flags = RATE_INFO_FLAGS_VHT_MCS; |
671 | break; |
672 | case MT_PHY_TYPE_HE_SU: |
673 | case MT_PHY_TYPE_HE_EXT_SU: |
674 | case MT_PHY_TYPE_HE_TB: |
675 | case MT_PHY_TYPE_HE_MU: |
676 | if (rate.mcs > 11) |
677 | return false; |
678 | |
679 | rate.he_gi = wcid->rate.he_gi; |
680 | rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); |
681 | rate.flags = RATE_INFO_FLAGS_HE_MCS; |
682 | break; |
683 | default: |
684 | return false; |
685 | } |
686 | |
687 | stats->tx_mode[mode]++; |
688 | |
689 | switch (FIELD_GET(MT_TXS0_BW, txs)) { |
690 | case IEEE80211_STA_RX_BW_160: |
691 | rate.bw = RATE_INFO_BW_160; |
692 | stats->tx_bw[3]++; |
693 | break; |
694 | case IEEE80211_STA_RX_BW_80: |
695 | rate.bw = RATE_INFO_BW_80; |
696 | stats->tx_bw[2]++; |
697 | break; |
698 | case IEEE80211_STA_RX_BW_40: |
699 | rate.bw = RATE_INFO_BW_40; |
700 | stats->tx_bw[1]++; |
701 | break; |
702 | default: |
703 | rate.bw = RATE_INFO_BW_20; |
704 | stats->tx_bw[0]++; |
705 | break; |
706 | } |
707 | wcid->rate = rate; |
708 | |
709 | return true; |
710 | } |
711 | EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_txs); |
712 | |
713 | bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid, |
714 | int pid, __le32 *txs_data) |
715 | { |
716 | struct sk_buff_head list; |
717 | struct sk_buff *skb; |
718 | |
719 | if (le32_get_bits(v: txs_data[0], MT_TXS0_TXS_FORMAT) == MT_TXS_PPDU_FMT) |
720 | return false; |
721 | |
722 | mt76_tx_status_lock(dev, list: &list); |
723 | skb = mt76_tx_status_skb_get(dev, wcid, pktid: pid, list: &list); |
724 | if (skb) { |
725 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
726 | |
727 | if (!(le32_to_cpu(txs_data[0]) & MT_TXS0_ACK_ERROR_MASK)) |
728 | info->flags |= IEEE80211_TX_STAT_ACK; |
729 | |
730 | info->status.ampdu_len = 1; |
731 | info->status.ampdu_ack_len = |
732 | !!(info->flags & IEEE80211_TX_STAT_ACK); |
733 | info->status.rates[0].idx = -1; |
734 | |
735 | mt76_connac2_mac_fill_txs(dev, wcid, txs_data); |
736 | mt76_tx_status_skb_done(dev, skb, list: &list); |
737 | } |
738 | mt76_tx_status_unlock(dev, list: &list); |
739 | |
740 | return !!skb; |
741 | } |
742 | EXPORT_SYMBOL_GPL(mt76_connac2_mac_add_txs_skb); |
743 | |
744 | static void |
745 | mt76_connac2_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, |
746 | struct ieee80211_radiotap_he *he, |
747 | __le32 *rxv) |
748 | { |
749 | u32 ru_h, ru_l; |
750 | u8 ru, offs = 0; |
751 | |
752 | ru_l = le32_get_bits(v: rxv[0], MT_PRXV_HE_RU_ALLOC_L); |
753 | ru_h = le32_get_bits(v: rxv[1], MT_PRXV_HE_RU_ALLOC_H); |
754 | ru = (u8)(ru_l | ru_h << 4); |
755 | |
756 | status->bw = RATE_INFO_BW_HE_RU; |
757 | |
758 | switch (ru) { |
759 | case 0 ... 36: |
760 | status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; |
761 | offs = ru; |
762 | break; |
763 | case 37 ... 52: |
764 | status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; |
765 | offs = ru - 37; |
766 | break; |
767 | case 53 ... 60: |
768 | status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; |
769 | offs = ru - 53; |
770 | break; |
771 | case 61 ... 64: |
772 | status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; |
773 | offs = ru - 61; |
774 | break; |
775 | case 65 ... 66: |
776 | status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; |
777 | offs = ru - 65; |
778 | break; |
779 | case 67: |
780 | status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; |
781 | break; |
782 | case 68: |
783 | status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; |
784 | break; |
785 | } |
786 | |
787 | he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); |
788 | he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | |
789 | le16_encode_bits(v: offs, |
790 | field: IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); |
791 | } |
792 | |
793 | static void |
794 | mt76_connac2_mac_decode_he_mu_radiotap(struct mt76_dev *dev, struct sk_buff *skb, |
795 | __le32 *rxv) |
796 | { |
797 | struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; |
798 | static struct ieee80211_radiotap_he_mu mu_known = { |
799 | .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | |
800 | HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | |
801 | HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | |
802 | HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), |
803 | .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), |
804 | }; |
805 | struct ieee80211_radiotap_he_mu *he_mu; |
806 | |
807 | if (is_mt7921(dev)) { |
808 | mu_known.flags1 |= HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN); |
809 | mu_known.flags2 |= HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN); |
810 | } |
811 | |
812 | status->flag |= RX_FLAG_RADIOTAP_HE_MU; |
813 | |
814 | he_mu = skb_push(skb, len: sizeof(mu_known)); |
815 | memcpy(he_mu, &mu_known, sizeof(mu_known)); |
816 | |
817 | #define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) |
818 | |
819 | he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); |
820 | if (status->he_dcm) |
821 | he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); |
822 | |
823 | he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | |
824 | MU_PREP(FLAGS2_SIG_B_SYMS_USERS, |
825 | le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER)); |
826 | |
827 | he_mu->ru_ch1[0] = le32_get_bits(v: rxv[3], MT_CRXV_HE_RU0); |
828 | |
829 | if (status->bw >= RATE_INFO_BW_40) { |
830 | he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); |
831 | he_mu->ru_ch2[0] = |
832 | le32_get_bits(v: rxv[3], MT_CRXV_HE_RU1); |
833 | } |
834 | |
835 | if (status->bw >= RATE_INFO_BW_80) { |
836 | he_mu->ru_ch1[1] = |
837 | le32_get_bits(v: rxv[3], MT_CRXV_HE_RU2); |
838 | he_mu->ru_ch2[1] = |
839 | le32_get_bits(v: rxv[3], MT_CRXV_HE_RU3); |
840 | } |
841 | } |
842 | |
843 | void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev, |
844 | struct sk_buff *skb, |
845 | __le32 *rxv, u32 mode) |
846 | { |
847 | struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; |
848 | static const struct ieee80211_radiotap_he known = { |
849 | .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | |
850 | HE_BITS(DATA1_DATA_DCM_KNOWN) | |
851 | HE_BITS(DATA1_STBC_KNOWN) | |
852 | HE_BITS(DATA1_CODING_KNOWN) | |
853 | HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | |
854 | HE_BITS(DATA1_DOPPLER_KNOWN) | |
855 | HE_BITS(DATA1_SPTL_REUSE_KNOWN) | |
856 | HE_BITS(DATA1_BSS_COLOR_KNOWN), |
857 | .data2 = HE_BITS(DATA2_GI_KNOWN) | |
858 | HE_BITS(DATA2_TXBF_KNOWN) | |
859 | HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | |
860 | HE_BITS(DATA2_TXOP_KNOWN), |
861 | }; |
862 | u32 ltf_size = le32_get_bits(v: rxv[2], MT_CRXV_HE_LTF_SIZE) + 1; |
863 | struct ieee80211_radiotap_he *he; |
864 | |
865 | status->flag |= RX_FLAG_RADIOTAP_HE; |
866 | |
867 | he = skb_push(skb, len: sizeof(known)); |
868 | memcpy(he, &known, sizeof(known)); |
869 | |
870 | he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) | |
871 | HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]); |
872 | he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); |
873 | he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) | |
874 | le16_encode_bits(v: ltf_size, |
875 | field: IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); |
876 | if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) |
877 | he->data5 |= HE_BITS(DATA5_TXBF); |
878 | he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) | |
879 | HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]); |
880 | |
881 | switch (mode) { |
882 | case MT_PHY_TYPE_HE_SU: |
883 | he->data1 |= HE_BITS(DATA1_FORMAT_SU) | |
884 | HE_BITS(DATA1_UL_DL_KNOWN) | |
885 | HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | |
886 | HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); |
887 | |
888 | he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) | |
889 | HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); |
890 | break; |
891 | case MT_PHY_TYPE_HE_EXT_SU: |
892 | he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | |
893 | HE_BITS(DATA1_UL_DL_KNOWN) | |
894 | HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); |
895 | |
896 | he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); |
897 | break; |
898 | case MT_PHY_TYPE_HE_MU: |
899 | he->data1 |= HE_BITS(DATA1_FORMAT_MU) | |
900 | HE_BITS(DATA1_UL_DL_KNOWN); |
901 | |
902 | he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); |
903 | he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]); |
904 | |
905 | mt76_connac2_mac_decode_he_radiotap_ru(status, he, rxv); |
906 | mt76_connac2_mac_decode_he_mu_radiotap(dev, skb, rxv); |
907 | break; |
908 | case MT_PHY_TYPE_HE_TB: |
909 | he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | |
910 | HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | |
911 | HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | |
912 | HE_BITS(DATA1_SPTL_REUSE4_KNOWN); |
913 | |
914 | he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) | |
915 | HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) | |
916 | HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) | |
917 | HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]); |
918 | |
919 | mt76_connac2_mac_decode_he_radiotap_ru(status, he, rxv); |
920 | break; |
921 | default: |
922 | break; |
923 | } |
924 | } |
925 | EXPORT_SYMBOL_GPL(mt76_connac2_mac_decode_he_radiotap); |
926 | |
927 | /* The HW does not translate the mac header to 802.3 for mesh point */ |
928 | int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif, |
929 | struct sk_buff *skb, u16 hdr_offset) |
930 | { |
931 | struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; |
932 | struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_offset); |
933 | __le32 *rxd = (__le32 *)skb->data; |
934 | struct ieee80211_sta *sta; |
935 | struct ieee80211_hdr hdr; |
936 | u16 frame_control; |
937 | |
938 | if (le32_get_bits(v: rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) != |
939 | MT_RXD3_NORMAL_U2M) |
940 | return -EINVAL; |
941 | |
942 | if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4)) |
943 | return -EINVAL; |
944 | |
945 | sta = container_of((void *)status->wcid, struct ieee80211_sta, drv_priv); |
946 | |
947 | /* store the info from RXD and ethhdr to avoid being overridden */ |
948 | frame_control = le32_get_bits(v: rxd[6], MT_RXD6_FRAME_CONTROL); |
949 | hdr.frame_control = cpu_to_le16(frame_control); |
950 | hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_SEQ_CTRL)); |
951 | hdr.duration_id = 0; |
952 | |
953 | ether_addr_copy(dst: hdr.addr1, src: vif->addr); |
954 | ether_addr_copy(dst: hdr.addr2, src: sta->addr); |
955 | switch (frame_control & (IEEE80211_FCTL_TODS | |
956 | IEEE80211_FCTL_FROMDS)) { |
957 | case 0: |
958 | ether_addr_copy(dst: hdr.addr3, src: vif->bss_conf.bssid); |
959 | break; |
960 | case IEEE80211_FCTL_FROMDS: |
961 | ether_addr_copy(dst: hdr.addr3, src: eth_hdr->h_source); |
962 | break; |
963 | case IEEE80211_FCTL_TODS: |
964 | ether_addr_copy(dst: hdr.addr3, src: eth_hdr->h_dest); |
965 | break; |
966 | case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS: |
967 | ether_addr_copy(dst: hdr.addr3, src: eth_hdr->h_dest); |
968 | ether_addr_copy(dst: hdr.addr4, src: eth_hdr->h_source); |
969 | break; |
970 | default: |
971 | return -EINVAL; |
972 | } |
973 | |
974 | skb_pull(skb, len: hdr_offset + sizeof(struct ethhdr) - 2); |
975 | if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) || |
976 | eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX)) |
977 | ether_addr_copy(dst: skb_push(skb, ETH_ALEN), src: bridge_tunnel_header); |
978 | else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN) |
979 | ether_addr_copy(dst: skb_push(skb, ETH_ALEN), src: rfc1042_header); |
980 | else |
981 | skb_pull(skb, len: 2); |
982 | |
983 | if (ieee80211_has_order(fc: hdr.frame_control)) |
984 | memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[9], |
985 | IEEE80211_HT_CTL_LEN); |
986 | if (ieee80211_is_data_qos(fc: hdr.frame_control)) { |
987 | __le16 qos_ctrl; |
988 | |
989 | qos_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_QOS_CTL)); |
990 | memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl, |
991 | IEEE80211_QOS_CTL_LEN); |
992 | } |
993 | |
994 | if (ieee80211_has_a4(fc: hdr.frame_control)) |
995 | memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr)); |
996 | else |
997 | memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6); |
998 | |
999 | return 0; |
1000 | } |
1001 | EXPORT_SYMBOL_GPL(mt76_connac2_reverse_frag0_hdr_trans); |
1002 | |
1003 | int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev, |
1004 | struct mt76_rx_status *status, |
1005 | struct ieee80211_supported_band *sband, |
1006 | __le32 *rxv, u8 *mode) |
1007 | { |
1008 | u32 v0, v2; |
1009 | u8 stbc, gi, bw, dcm, nss; |
1010 | int i, idx; |
1011 | bool cck = false; |
1012 | |
1013 | v0 = le32_to_cpu(rxv[0]); |
1014 | v2 = le32_to_cpu(rxv[2]); |
1015 | |
1016 | idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0); |
1017 | nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1; |
1018 | |
1019 | if (!is_mt7915(dev)) { |
1020 | stbc = FIELD_GET(MT_PRXV_HT_STBC, v0); |
1021 | gi = FIELD_GET(MT_PRXV_HT_SGI, v0); |
1022 | *mode = FIELD_GET(MT_PRXV_TX_MODE, v0); |
1023 | if (is_mt7921(dev)) |
1024 | dcm = !!(idx & MT_PRXV_TX_DCM); |
1025 | else |
1026 | dcm = FIELD_GET(MT_PRXV_DCM, v0); |
1027 | bw = FIELD_GET(MT_PRXV_FRAME_MODE, v0); |
1028 | } else { |
1029 | stbc = FIELD_GET(MT_CRXV_HT_STBC, v2); |
1030 | gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2); |
1031 | *mode = FIELD_GET(MT_CRXV_TX_MODE, v2); |
1032 | dcm = !!(idx & GENMASK(3, 0) & MT_PRXV_TX_DCM); |
1033 | bw = FIELD_GET(MT_CRXV_FRAME_MODE, v2); |
1034 | } |
1035 | |
1036 | switch (*mode) { |
1037 | case MT_PHY_TYPE_CCK: |
1038 | cck = true; |
1039 | fallthrough; |
1040 | case MT_PHY_TYPE_OFDM: |
1041 | i = mt76_get_rate(dev, sband, idx: i, cck); |
1042 | break; |
1043 | case MT_PHY_TYPE_HT_GF: |
1044 | case MT_PHY_TYPE_HT: |
1045 | status->encoding = RX_ENC_HT; |
1046 | if (gi) |
1047 | status->enc_flags |= RX_ENC_FLAG_SHORT_GI; |
1048 | if (i > 31) |
1049 | return -EINVAL; |
1050 | break; |
1051 | case MT_PHY_TYPE_VHT: |
1052 | status->nss = nss; |
1053 | status->encoding = RX_ENC_VHT; |
1054 | if (gi) |
1055 | status->enc_flags |= RX_ENC_FLAG_SHORT_GI; |
1056 | if (i > 11) |
1057 | return -EINVAL; |
1058 | break; |
1059 | case MT_PHY_TYPE_HE_MU: |
1060 | case MT_PHY_TYPE_HE_SU: |
1061 | case MT_PHY_TYPE_HE_EXT_SU: |
1062 | case MT_PHY_TYPE_HE_TB: |
1063 | status->nss = nss; |
1064 | status->encoding = RX_ENC_HE; |
1065 | i &= GENMASK(3, 0); |
1066 | |
1067 | if (gi <= NL80211_RATE_INFO_HE_GI_3_2) |
1068 | status->he_gi = gi; |
1069 | |
1070 | status->he_dcm = dcm; |
1071 | break; |
1072 | default: |
1073 | return -EINVAL; |
1074 | } |
1075 | status->rate_idx = i; |
1076 | |
1077 | switch (bw) { |
1078 | case IEEE80211_STA_RX_BW_20: |
1079 | break; |
1080 | case IEEE80211_STA_RX_BW_40: |
1081 | if (*mode & MT_PHY_TYPE_HE_EXT_SU && |
1082 | (idx & MT_PRXV_TX_ER_SU_106T)) { |
1083 | status->bw = RATE_INFO_BW_HE_RU; |
1084 | status->he_ru = |
1085 | NL80211_RATE_INFO_HE_RU_ALLOC_106; |
1086 | } else { |
1087 | status->bw = RATE_INFO_BW_40; |
1088 | } |
1089 | break; |
1090 | case IEEE80211_STA_RX_BW_80: |
1091 | status->bw = RATE_INFO_BW_80; |
1092 | break; |
1093 | case IEEE80211_STA_RX_BW_160: |
1094 | status->bw = RATE_INFO_BW_160; |
1095 | break; |
1096 | default: |
1097 | return -EINVAL; |
1098 | } |
1099 | |
1100 | status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; |
1101 | if (*mode < MT_PHY_TYPE_HE_SU && gi) |
1102 | status->enc_flags |= RX_ENC_FLAG_SHORT_GI; |
1103 | |
1104 | return 0; |
1105 | } |
1106 | EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate); |
1107 | |
1108 | void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) |
1109 | { |
1110 | struct mt76_wcid *wcid; |
1111 | u16 fc, tid; |
1112 | u32 val; |
1113 | |
1114 | if (!sta || |
1115 | !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) |
1116 | return; |
1117 | |
1118 | tid = le32_get_bits(v: txwi[1], MT_TXD1_TID); |
1119 | if (tid >= 6) /* skip VO queue */ |
1120 | return; |
1121 | |
1122 | val = le32_to_cpu(txwi[2]); |
1123 | fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | |
1124 | FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; |
1125 | if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) |
1126 | return; |
1127 | |
1128 | wcid = (struct mt76_wcid *)sta->drv_priv; |
1129 | if (!test_and_set_bit(nr: tid, addr: &wcid->ampdu_state)) |
1130 | ieee80211_start_tx_ba_session(sta, tid, timeout: 0); |
1131 | } |
1132 | EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr); |
1133 | |
1134 | void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t, |
1135 | struct ieee80211_sta *sta, |
1136 | struct list_head *free_list) |
1137 | { |
1138 | struct mt76_wcid *wcid; |
1139 | __le32 *txwi; |
1140 | u16 wcid_idx; |
1141 | |
1142 | mt76_connac_txp_skb_unmap(dev, t); |
1143 | if (!t->skb) |
1144 | goto out; |
1145 | |
1146 | txwi = (__le32 *)mt76_get_txwi_ptr(dev, t); |
1147 | if (sta) { |
1148 | wcid = (struct mt76_wcid *)sta->drv_priv; |
1149 | wcid_idx = wcid->idx; |
1150 | } else { |
1151 | wcid_idx = le32_get_bits(v: txwi[1], MT_TXD1_WLAN_IDX); |
1152 | wcid = rcu_dereference(dev->wcid[wcid_idx]); |
1153 | |
1154 | if (wcid && wcid->sta) { |
1155 | sta = container_of((void *)wcid, struct ieee80211_sta, |
1156 | drv_priv); |
1157 | spin_lock_bh(lock: &dev->sta_poll_lock); |
1158 | if (list_empty(head: &wcid->poll_list)) |
1159 | list_add_tail(new: &wcid->poll_list, |
1160 | head: &dev->sta_poll_list); |
1161 | spin_unlock_bh(lock: &dev->sta_poll_lock); |
1162 | } |
1163 | } |
1164 | |
1165 | if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) |
1166 | mt76_connac2_tx_check_aggr(sta, txwi); |
1167 | |
1168 | __mt76_tx_complete_skb(dev, wcid: wcid_idx, skb: t->skb, free_list); |
1169 | out: |
1170 | t->skb = NULL; |
1171 | mt76_put_txwi(dev, t); |
1172 | } |
1173 | EXPORT_SYMBOL_GPL(mt76_connac2_txwi_free); |
1174 | |
1175 | void mt76_connac2_tx_token_put(struct mt76_dev *dev) |
1176 | { |
1177 | struct mt76_txwi_cache *txwi; |
1178 | int id; |
1179 | |
1180 | spin_lock_bh(lock: &dev->token_lock); |
1181 | idr_for_each_entry(&dev->token, txwi, id) { |
1182 | mt76_connac2_txwi_free(dev, txwi, NULL, NULL); |
1183 | dev->token_count--; |
1184 | } |
1185 | spin_unlock_bh(lock: &dev->token_lock); |
1186 | idr_destroy(&dev->token); |
1187 | } |
1188 | EXPORT_SYMBOL_GPL(mt76_connac2_tx_token_put); |
1189 | |