1cbb3ec25SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2cbb3ec25SBjoern A. Zeeb /*
3cbb3ec25SBjoern A. Zeeb * Copyright (C) 2022 MediaTek Inc.
4cbb3ec25SBjoern A. Zeeb */
5cbb3ec25SBjoern A. Zeeb
6cbb3ec25SBjoern A. Zeeb #include <linux/etherdevice.h>
7cbb3ec25SBjoern A. Zeeb #include <linux/timekeeping.h>
8cbb3ec25SBjoern A. Zeeb #include "coredump.h"
9cbb3ec25SBjoern A. Zeeb #include "mt7996.h"
10cbb3ec25SBjoern A. Zeeb #include "../dma.h"
11cbb3ec25SBjoern A. Zeeb #include "mac.h"
12cbb3ec25SBjoern A. Zeeb #include "mcu.h"
13cbb3ec25SBjoern A. Zeeb #if defined(__FreeBSD__)
14cbb3ec25SBjoern A. Zeeb #include <linux/delay.h>
15cbb3ec25SBjoern A. Zeeb #endif
16cbb3ec25SBjoern A. Zeeb
17cbb3ec25SBjoern A. Zeeb #define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
18cbb3ec25SBjoern A. Zeeb
19cbb3ec25SBjoern A. Zeeb static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
20cbb3ec25SBjoern A. Zeeb .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
21cbb3ec25SBjoern A. Zeeb .radar_pattern = {
22cbb3ec25SBjoern A. Zeeb [5] = { 1, 0, 6, 32, 28, 0, 990, 5010, 17, 1, 1 },
23cbb3ec25SBjoern A. Zeeb [6] = { 1, 0, 9, 32, 28, 0, 615, 5010, 27, 1, 1 },
24cbb3ec25SBjoern A. Zeeb [7] = { 1, 0, 15, 32, 28, 0, 240, 445, 27, 1, 1 },
25cbb3ec25SBjoern A. Zeeb [8] = { 1, 0, 12, 32, 28, 0, 240, 510, 42, 1, 1 },
26cbb3ec25SBjoern A. Zeeb [9] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 12, 32, 28, { }, 126 },
27cbb3ec25SBjoern A. Zeeb [10] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 15, 32, 24, { }, 126 },
28cbb3ec25SBjoern A. Zeeb [11] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 18, 32, 28, { }, 54 },
29cbb3ec25SBjoern A. Zeeb [12] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 27, 32, 24, { }, 54 },
30cbb3ec25SBjoern A. Zeeb },
31cbb3ec25SBjoern A. Zeeb };
32cbb3ec25SBjoern A. Zeeb
33cbb3ec25SBjoern A. Zeeb static const struct mt7996_dfs_radar_spec fcc_radar_specs = {
34cbb3ec25SBjoern A. Zeeb .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
35cbb3ec25SBjoern A. Zeeb .radar_pattern = {
36cbb3ec25SBjoern A. Zeeb [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 },
37cbb3ec25SBjoern A. Zeeb [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 },
38cbb3ec25SBjoern A. Zeeb [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 },
39cbb3ec25SBjoern A. Zeeb [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 },
40cbb3ec25SBjoern A. Zeeb [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 },
41cbb3ec25SBjoern A. Zeeb },
42cbb3ec25SBjoern A. Zeeb };
43cbb3ec25SBjoern A. Zeeb
44cbb3ec25SBjoern A. Zeeb static const struct mt7996_dfs_radar_spec jp_radar_specs = {
45cbb3ec25SBjoern A. Zeeb .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
46cbb3ec25SBjoern A. Zeeb .radar_pattern = {
47cbb3ec25SBjoern A. Zeeb [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 },
48cbb3ec25SBjoern A. Zeeb [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 },
49cbb3ec25SBjoern A. Zeeb [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 },
50cbb3ec25SBjoern A. Zeeb [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 },
51cbb3ec25SBjoern A. Zeeb [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 },
52cbb3ec25SBjoern A. Zeeb [13] = { 1, 0, 7, 32, 28, 0, 3836, 3856, 14, 1, 1 },
53cbb3ec25SBjoern A. Zeeb [14] = { 1, 0, 6, 32, 28, 0, 615, 5010, 110, 1, 1 },
54cbb3ec25SBjoern A. Zeeb [15] = { 1, 1, 0, 0, 0, 0, 15, 5010, 110, 0, 0, 12, 32, 28 },
55cbb3ec25SBjoern A. Zeeb },
56cbb3ec25SBjoern A. Zeeb };
57cbb3ec25SBjoern A. Zeeb
mt7996_rx_get_wcid(struct mt7996_dev * dev,u16 idx,bool unicast)58cbb3ec25SBjoern A. Zeeb static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
59cbb3ec25SBjoern A. Zeeb u16 idx, bool unicast)
60cbb3ec25SBjoern A. Zeeb {
61cbb3ec25SBjoern A. Zeeb struct mt7996_sta *sta;
62cbb3ec25SBjoern A. Zeeb struct mt76_wcid *wcid;
63cbb3ec25SBjoern A. Zeeb
64cbb3ec25SBjoern A. Zeeb if (idx >= ARRAY_SIZE(dev->mt76.wcid))
65cbb3ec25SBjoern A. Zeeb return NULL;
66cbb3ec25SBjoern A. Zeeb
67cbb3ec25SBjoern A. Zeeb wcid = rcu_dereference(dev->mt76.wcid[idx]);
68cbb3ec25SBjoern A. Zeeb if (unicast || !wcid)
69cbb3ec25SBjoern A. Zeeb return wcid;
70cbb3ec25SBjoern A. Zeeb
71cbb3ec25SBjoern A. Zeeb if (!wcid->sta)
72cbb3ec25SBjoern A. Zeeb return NULL;
73cbb3ec25SBjoern A. Zeeb
74cbb3ec25SBjoern A. Zeeb sta = container_of(wcid, struct mt7996_sta, wcid);
75cbb3ec25SBjoern A. Zeeb if (!sta->vif)
76cbb3ec25SBjoern A. Zeeb return NULL;
77cbb3ec25SBjoern A. Zeeb
78*8ba4d145SBjoern A. Zeeb return &sta->vif->deflink.sta.wcid;
79cbb3ec25SBjoern A. Zeeb }
80cbb3ec25SBjoern A. Zeeb
mt7996_mac_wtbl_update(struct mt7996_dev * dev,int idx,u32 mask)81cbb3ec25SBjoern A. Zeeb bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
82cbb3ec25SBjoern A. Zeeb {
83cbb3ec25SBjoern A. Zeeb mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
84cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask);
85cbb3ec25SBjoern A. Zeeb
86cbb3ec25SBjoern A. Zeeb return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY,
87cbb3ec25SBjoern A. Zeeb 0, 5000);
88cbb3ec25SBjoern A. Zeeb }
89cbb3ec25SBjoern A. Zeeb
mt7996_mac_wtbl_lmac_addr(struct mt7996_dev * dev,u16 wcid,u8 dw)90cbb3ec25SBjoern A. Zeeb u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw)
91cbb3ec25SBjoern A. Zeeb {
92cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
93cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
94cbb3ec25SBjoern A. Zeeb
95cbb3ec25SBjoern A. Zeeb return MT_WTBL_LMAC_OFFS(wcid, dw);
96cbb3ec25SBjoern A. Zeeb }
97cbb3ec25SBjoern A. Zeeb
mt7996_mac_sta_poll(struct mt7996_dev * dev)98cbb3ec25SBjoern A. Zeeb static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
99cbb3ec25SBjoern A. Zeeb {
100cbb3ec25SBjoern A. Zeeb static const u8 ac_to_tid[] = {
101cbb3ec25SBjoern A. Zeeb [IEEE80211_AC_BE] = 0,
102cbb3ec25SBjoern A. Zeeb [IEEE80211_AC_BK] = 1,
103cbb3ec25SBjoern A. Zeeb [IEEE80211_AC_VI] = 4,
104cbb3ec25SBjoern A. Zeeb [IEEE80211_AC_VO] = 6
105cbb3ec25SBjoern A. Zeeb };
106cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta;
107cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta;
108cbb3ec25SBjoern A. Zeeb u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
109cbb3ec25SBjoern A. Zeeb LIST_HEAD(sta_poll_list);
110cbb3ec25SBjoern A. Zeeb int i;
111cbb3ec25SBjoern A. Zeeb
112cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock);
113cbb3ec25SBjoern A. Zeeb list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
114cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock);
115cbb3ec25SBjoern A. Zeeb
116cbb3ec25SBjoern A. Zeeb rcu_read_lock();
117cbb3ec25SBjoern A. Zeeb
118cbb3ec25SBjoern A. Zeeb while (true) {
119cbb3ec25SBjoern A. Zeeb bool clear = false;
120cbb3ec25SBjoern A. Zeeb u32 addr, val;
121cbb3ec25SBjoern A. Zeeb u16 idx;
122cbb3ec25SBjoern A. Zeeb s8 rssi[4];
123cbb3ec25SBjoern A. Zeeb
124cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock);
125cbb3ec25SBjoern A. Zeeb if (list_empty(&sta_poll_list)) {
126cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock);
127cbb3ec25SBjoern A. Zeeb break;
128cbb3ec25SBjoern A. Zeeb }
129cbb3ec25SBjoern A. Zeeb msta = list_first_entry(&sta_poll_list,
130cbb3ec25SBjoern A. Zeeb struct mt7996_sta, wcid.poll_list);
131cbb3ec25SBjoern A. Zeeb list_del_init(&msta->wcid.poll_list);
132cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock);
133cbb3ec25SBjoern A. Zeeb
134cbb3ec25SBjoern A. Zeeb idx = msta->wcid.idx;
135cbb3ec25SBjoern A. Zeeb
136cbb3ec25SBjoern A. Zeeb /* refresh peer's airtime reporting */
137cbb3ec25SBjoern A. Zeeb addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
138cbb3ec25SBjoern A. Zeeb
139cbb3ec25SBjoern A. Zeeb for (i = 0; i < IEEE80211_NUM_ACS; i++) {
140cbb3ec25SBjoern A. Zeeb u32 tx_last = msta->airtime_ac[i];
141cbb3ec25SBjoern A. Zeeb u32 rx_last = msta->airtime_ac[i + 4];
142cbb3ec25SBjoern A. Zeeb
143cbb3ec25SBjoern A. Zeeb msta->airtime_ac[i] = mt76_rr(dev, addr);
144cbb3ec25SBjoern A. Zeeb msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
145cbb3ec25SBjoern A. Zeeb
146cbb3ec25SBjoern A. Zeeb tx_time[i] = msta->airtime_ac[i] - tx_last;
147cbb3ec25SBjoern A. Zeeb rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
148cbb3ec25SBjoern A. Zeeb
149cbb3ec25SBjoern A. Zeeb if ((tx_last | rx_last) & BIT(30))
150cbb3ec25SBjoern A. Zeeb clear = true;
151cbb3ec25SBjoern A. Zeeb
152cbb3ec25SBjoern A. Zeeb addr += 8;
153cbb3ec25SBjoern A. Zeeb }
154cbb3ec25SBjoern A. Zeeb
155cbb3ec25SBjoern A. Zeeb if (clear) {
156cbb3ec25SBjoern A. Zeeb mt7996_mac_wtbl_update(dev, idx,
157cbb3ec25SBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
158cbb3ec25SBjoern A. Zeeb memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac));
159cbb3ec25SBjoern A. Zeeb }
160cbb3ec25SBjoern A. Zeeb
161cbb3ec25SBjoern A. Zeeb if (!msta->wcid.sta)
162cbb3ec25SBjoern A. Zeeb continue;
163cbb3ec25SBjoern A. Zeeb
164cbb3ec25SBjoern A. Zeeb sta = container_of((void *)msta, struct ieee80211_sta,
165cbb3ec25SBjoern A. Zeeb drv_priv);
166cbb3ec25SBjoern A. Zeeb for (i = 0; i < IEEE80211_NUM_ACS; i++) {
167cbb3ec25SBjoern A. Zeeb u8 q = mt76_connac_lmac_mapping(i);
168cbb3ec25SBjoern A. Zeeb u32 tx_cur = tx_time[q];
169cbb3ec25SBjoern A. Zeeb u32 rx_cur = rx_time[q];
170cbb3ec25SBjoern A. Zeeb u8 tid = ac_to_tid[i];
171cbb3ec25SBjoern A. Zeeb
172cbb3ec25SBjoern A. Zeeb if (!tx_cur && !rx_cur)
173cbb3ec25SBjoern A. Zeeb continue;
174cbb3ec25SBjoern A. Zeeb
175cbb3ec25SBjoern A. Zeeb ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur);
176cbb3ec25SBjoern A. Zeeb }
177cbb3ec25SBjoern A. Zeeb
178cbb3ec25SBjoern A. Zeeb /* get signal strength of resp frames (CTS/BA/ACK) */
179cbb3ec25SBjoern A. Zeeb addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34);
180cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, addr);
181cbb3ec25SBjoern A. Zeeb
182cbb3ec25SBjoern A. Zeeb rssi[0] = to_rssi(GENMASK(7, 0), val);
183cbb3ec25SBjoern A. Zeeb rssi[1] = to_rssi(GENMASK(15, 8), val);
184cbb3ec25SBjoern A. Zeeb rssi[2] = to_rssi(GENMASK(23, 16), val);
185cbb3ec25SBjoern A. Zeeb rssi[3] = to_rssi(GENMASK(31, 14), val);
186cbb3ec25SBjoern A. Zeeb
187cbb3ec25SBjoern A. Zeeb msta->ack_signal =
188*8ba4d145SBjoern A. Zeeb mt76_rx_signal(msta->vif->deflink.phy->mt76->antenna_mask, rssi);
189cbb3ec25SBjoern A. Zeeb
190cbb3ec25SBjoern A. Zeeb ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
191cbb3ec25SBjoern A. Zeeb }
192cbb3ec25SBjoern A. Zeeb
193cbb3ec25SBjoern A. Zeeb rcu_read_unlock();
194cbb3ec25SBjoern A. Zeeb }
195cbb3ec25SBjoern A. Zeeb
mt7996_mac_enable_rtscts(struct mt7996_dev * dev,struct ieee80211_vif * vif,bool enable)196cbb3ec25SBjoern A. Zeeb void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
197cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, bool enable)
198cbb3ec25SBjoern A. Zeeb {
199cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
200cbb3ec25SBjoern A. Zeeb u32 addr;
201cbb3ec25SBjoern A. Zeeb
202*8ba4d145SBjoern A. Zeeb addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->deflink.sta.wcid.idx, 5);
203cbb3ec25SBjoern A. Zeeb if (enable)
204cbb3ec25SBjoern A. Zeeb mt76_set(dev, addr, BIT(5));
205cbb3ec25SBjoern A. Zeeb else
206cbb3ec25SBjoern A. Zeeb mt76_clear(dev, addr, BIT(5));
207cbb3ec25SBjoern A. Zeeb }
208cbb3ec25SBjoern A. Zeeb
209cbb3ec25SBjoern A. Zeeb /* The HW does not translate the mac header to 802.3 for mesh point */
mt7996_reverse_frag0_hdr_trans(struct sk_buff * skb,u16 hdr_gap)210cbb3ec25SBjoern A. Zeeb static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
211cbb3ec25SBjoern A. Zeeb {
212cbb3ec25SBjoern A. Zeeb struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
213cbb3ec25SBjoern A. Zeeb struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap);
214cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)status->wcid;
215cbb3ec25SBjoern A. Zeeb __le32 *rxd = (__le32 *)skb->data;
216cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta;
217cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif;
218cbb3ec25SBjoern A. Zeeb struct ieee80211_hdr hdr;
219cbb3ec25SBjoern A. Zeeb u16 frame_control;
220cbb3ec25SBjoern A. Zeeb
221cbb3ec25SBjoern A. Zeeb if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
222cbb3ec25SBjoern A. Zeeb MT_RXD3_NORMAL_U2M)
223cbb3ec25SBjoern A. Zeeb return -EINVAL;
224cbb3ec25SBjoern A. Zeeb
225cbb3ec25SBjoern A. Zeeb if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4))
226cbb3ec25SBjoern A. Zeeb return -EINVAL;
227cbb3ec25SBjoern A. Zeeb
228cbb3ec25SBjoern A. Zeeb if (!msta || !msta->vif)
229cbb3ec25SBjoern A. Zeeb return -EINVAL;
230cbb3ec25SBjoern A. Zeeb
231cbb3ec25SBjoern A. Zeeb sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
232cbb3ec25SBjoern A. Zeeb vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
233cbb3ec25SBjoern A. Zeeb
234cbb3ec25SBjoern A. Zeeb /* store the info from RXD and ethhdr to avoid being overridden */
235cbb3ec25SBjoern A. Zeeb frame_control = le32_get_bits(rxd[8], MT_RXD8_FRAME_CONTROL);
236cbb3ec25SBjoern A. Zeeb hdr.frame_control = cpu_to_le16(frame_control);
237cbb3ec25SBjoern A. Zeeb hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_SEQ_CTRL));
238cbb3ec25SBjoern A. Zeeb hdr.duration_id = 0;
239cbb3ec25SBjoern A. Zeeb
240cbb3ec25SBjoern A. Zeeb ether_addr_copy(hdr.addr1, vif->addr);
241cbb3ec25SBjoern A. Zeeb ether_addr_copy(hdr.addr2, sta->addr);
242cbb3ec25SBjoern A. Zeeb switch (frame_control & (IEEE80211_FCTL_TODS |
243cbb3ec25SBjoern A. Zeeb IEEE80211_FCTL_FROMDS)) {
244cbb3ec25SBjoern A. Zeeb case 0:
245cbb3ec25SBjoern A. Zeeb ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);
246cbb3ec25SBjoern A. Zeeb break;
247cbb3ec25SBjoern A. Zeeb case IEEE80211_FCTL_FROMDS:
248cbb3ec25SBjoern A. Zeeb ether_addr_copy(hdr.addr3, eth_hdr->h_source);
249cbb3ec25SBjoern A. Zeeb break;
250cbb3ec25SBjoern A. Zeeb case IEEE80211_FCTL_TODS:
251cbb3ec25SBjoern A. Zeeb ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
252cbb3ec25SBjoern A. Zeeb break;
253cbb3ec25SBjoern A. Zeeb case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS:
254cbb3ec25SBjoern A. Zeeb ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
255cbb3ec25SBjoern A. Zeeb ether_addr_copy(hdr.addr4, eth_hdr->h_source);
256cbb3ec25SBjoern A. Zeeb break;
257cbb3ec25SBjoern A. Zeeb default:
258cbb3ec25SBjoern A. Zeeb return -EINVAL;
259cbb3ec25SBjoern A. Zeeb }
260cbb3ec25SBjoern A. Zeeb
261cbb3ec25SBjoern A. Zeeb skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2);
262cbb3ec25SBjoern A. Zeeb if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||
263cbb3ec25SBjoern A. Zeeb eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))
264cbb3ec25SBjoern A. Zeeb ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);
265cbb3ec25SBjoern A. Zeeb else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)
266cbb3ec25SBjoern A. Zeeb ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);
267cbb3ec25SBjoern A. Zeeb else
268cbb3ec25SBjoern A. Zeeb skb_pull(skb, 2);
269cbb3ec25SBjoern A. Zeeb
270cbb3ec25SBjoern A. Zeeb if (ieee80211_has_order(hdr.frame_control))
271cbb3ec25SBjoern A. Zeeb memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[11],
272cbb3ec25SBjoern A. Zeeb IEEE80211_HT_CTL_LEN);
273cbb3ec25SBjoern A. Zeeb if (ieee80211_is_data_qos(hdr.frame_control)) {
274cbb3ec25SBjoern A. Zeeb __le16 qos_ctrl;
275cbb3ec25SBjoern A. Zeeb
276cbb3ec25SBjoern A. Zeeb qos_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_QOS_CTL));
277cbb3ec25SBjoern A. Zeeb memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,
278cbb3ec25SBjoern A. Zeeb IEEE80211_QOS_CTL_LEN);
279cbb3ec25SBjoern A. Zeeb }
280cbb3ec25SBjoern A. Zeeb
281cbb3ec25SBjoern A. Zeeb if (ieee80211_has_a4(hdr.frame_control))
282cbb3ec25SBjoern A. Zeeb memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
283cbb3ec25SBjoern A. Zeeb else
284cbb3ec25SBjoern A. Zeeb memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6);
285cbb3ec25SBjoern A. Zeeb
286cbb3ec25SBjoern A. Zeeb return 0;
287cbb3ec25SBjoern A. Zeeb }
288cbb3ec25SBjoern A. Zeeb
289cbb3ec25SBjoern A. Zeeb static int
mt7996_mac_fill_rx_rate(struct mt7996_dev * dev,struct mt76_rx_status * status,struct ieee80211_supported_band * sband,__le32 * rxv,u8 * mode)290cbb3ec25SBjoern A. Zeeb mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
291cbb3ec25SBjoern A. Zeeb struct mt76_rx_status *status,
292cbb3ec25SBjoern A. Zeeb struct ieee80211_supported_band *sband,
293cbb3ec25SBjoern A. Zeeb __le32 *rxv, u8 *mode)
294cbb3ec25SBjoern A. Zeeb {
295cbb3ec25SBjoern A. Zeeb u32 v0, v2;
296cbb3ec25SBjoern A. Zeeb u8 stbc, gi, bw, dcm, nss;
297cbb3ec25SBjoern A. Zeeb int i, idx;
298cbb3ec25SBjoern A. Zeeb bool cck = false;
299cbb3ec25SBjoern A. Zeeb
300cbb3ec25SBjoern A. Zeeb v0 = le32_to_cpu(rxv[0]);
301cbb3ec25SBjoern A. Zeeb v2 = le32_to_cpu(rxv[2]);
302cbb3ec25SBjoern A. Zeeb
303cbb3ec25SBjoern A. Zeeb idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
304cbb3ec25SBjoern A. Zeeb i = idx;
305cbb3ec25SBjoern A. Zeeb nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
306cbb3ec25SBjoern A. Zeeb
307cbb3ec25SBjoern A. Zeeb stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
308cbb3ec25SBjoern A. Zeeb gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
309cbb3ec25SBjoern A. Zeeb *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
310cbb3ec25SBjoern A. Zeeb dcm = FIELD_GET(MT_PRXV_DCM, v2);
311cbb3ec25SBjoern A. Zeeb bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
312cbb3ec25SBjoern A. Zeeb
313cbb3ec25SBjoern A. Zeeb switch (*mode) {
314cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_CCK:
315cbb3ec25SBjoern A. Zeeb cck = true;
316cbb3ec25SBjoern A. Zeeb fallthrough;
317cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_OFDM:
318cbb3ec25SBjoern A. Zeeb i = mt76_get_rate(&dev->mt76, sband, i, cck);
319cbb3ec25SBjoern A. Zeeb break;
320cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HT_GF:
321cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HT:
322cbb3ec25SBjoern A. Zeeb status->encoding = RX_ENC_HT;
323cbb3ec25SBjoern A. Zeeb if (gi)
324cbb3ec25SBjoern A. Zeeb status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
325cbb3ec25SBjoern A. Zeeb if (i > 31)
326cbb3ec25SBjoern A. Zeeb return -EINVAL;
327cbb3ec25SBjoern A. Zeeb break;
328cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_VHT:
329cbb3ec25SBjoern A. Zeeb status->nss = nss;
330cbb3ec25SBjoern A. Zeeb status->encoding = RX_ENC_VHT;
331cbb3ec25SBjoern A. Zeeb if (gi)
332cbb3ec25SBjoern A. Zeeb status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
333cbb3ec25SBjoern A. Zeeb if (i > 11)
334cbb3ec25SBjoern A. Zeeb return -EINVAL;
335cbb3ec25SBjoern A. Zeeb break;
336cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HE_MU:
337cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HE_SU:
338cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HE_EXT_SU:
339cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HE_TB:
340cbb3ec25SBjoern A. Zeeb status->nss = nss;
341cbb3ec25SBjoern A. Zeeb status->encoding = RX_ENC_HE;
342cbb3ec25SBjoern A. Zeeb i &= GENMASK(3, 0);
343cbb3ec25SBjoern A. Zeeb
344cbb3ec25SBjoern A. Zeeb if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
345cbb3ec25SBjoern A. Zeeb status->he_gi = gi;
346cbb3ec25SBjoern A. Zeeb
347cbb3ec25SBjoern A. Zeeb status->he_dcm = dcm;
348cbb3ec25SBjoern A. Zeeb break;
349cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_EHT_SU:
350cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_EHT_TRIG:
351cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_EHT_MU:
352cbb3ec25SBjoern A. Zeeb status->nss = nss;
353cbb3ec25SBjoern A. Zeeb status->encoding = RX_ENC_EHT;
354cbb3ec25SBjoern A. Zeeb i &= GENMASK(3, 0);
355cbb3ec25SBjoern A. Zeeb
356cbb3ec25SBjoern A. Zeeb if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
357cbb3ec25SBjoern A. Zeeb status->eht.gi = gi;
358cbb3ec25SBjoern A. Zeeb break;
359cbb3ec25SBjoern A. Zeeb default:
360cbb3ec25SBjoern A. Zeeb return -EINVAL;
361cbb3ec25SBjoern A. Zeeb }
362cbb3ec25SBjoern A. Zeeb status->rate_idx = i;
363cbb3ec25SBjoern A. Zeeb
364cbb3ec25SBjoern A. Zeeb switch (bw) {
365cbb3ec25SBjoern A. Zeeb case IEEE80211_STA_RX_BW_20:
366cbb3ec25SBjoern A. Zeeb break;
367cbb3ec25SBjoern A. Zeeb case IEEE80211_STA_RX_BW_40:
368cbb3ec25SBjoern A. Zeeb if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
369cbb3ec25SBjoern A. Zeeb (idx & MT_PRXV_TX_ER_SU_106T)) {
370cbb3ec25SBjoern A. Zeeb status->bw = RATE_INFO_BW_HE_RU;
371cbb3ec25SBjoern A. Zeeb status->he_ru =
372cbb3ec25SBjoern A. Zeeb NL80211_RATE_INFO_HE_RU_ALLOC_106;
373cbb3ec25SBjoern A. Zeeb } else {
374cbb3ec25SBjoern A. Zeeb status->bw = RATE_INFO_BW_40;
375cbb3ec25SBjoern A. Zeeb }
376cbb3ec25SBjoern A. Zeeb break;
377cbb3ec25SBjoern A. Zeeb case IEEE80211_STA_RX_BW_80:
378cbb3ec25SBjoern A. Zeeb status->bw = RATE_INFO_BW_80;
379cbb3ec25SBjoern A. Zeeb break;
380cbb3ec25SBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
381cbb3ec25SBjoern A. Zeeb status->bw = RATE_INFO_BW_160;
382cbb3ec25SBjoern A. Zeeb break;
383*8ba4d145SBjoern A. Zeeb /* rxv reports bw 320-1 and 320-2 separately */
384cbb3ec25SBjoern A. Zeeb case IEEE80211_STA_RX_BW_320:
385*8ba4d145SBjoern A. Zeeb case IEEE80211_STA_RX_BW_320 + 1:
386cbb3ec25SBjoern A. Zeeb status->bw = RATE_INFO_BW_320;
387cbb3ec25SBjoern A. Zeeb break;
388cbb3ec25SBjoern A. Zeeb default:
389cbb3ec25SBjoern A. Zeeb return -EINVAL;
390cbb3ec25SBjoern A. Zeeb }
391cbb3ec25SBjoern A. Zeeb
392cbb3ec25SBjoern A. Zeeb status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
393cbb3ec25SBjoern A. Zeeb if (*mode < MT_PHY_TYPE_HE_SU && gi)
394cbb3ec25SBjoern A. Zeeb status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
395cbb3ec25SBjoern A. Zeeb
396cbb3ec25SBjoern A. Zeeb return 0;
397cbb3ec25SBjoern A. Zeeb }
398cbb3ec25SBjoern A. Zeeb
399*8ba4d145SBjoern A. Zeeb static void
mt7996_wed_check_ppe(struct mt7996_dev * dev,struct mt76_queue * q,struct mt7996_sta * msta,struct sk_buff * skb,u32 info)400*8ba4d145SBjoern A. Zeeb mt7996_wed_check_ppe(struct mt7996_dev *dev, struct mt76_queue *q,
401*8ba4d145SBjoern A. Zeeb struct mt7996_sta *msta, struct sk_buff *skb,
402*8ba4d145SBjoern A. Zeeb u32 info)
403*8ba4d145SBjoern A. Zeeb {
404*8ba4d145SBjoern A. Zeeb struct ieee80211_vif *vif;
405*8ba4d145SBjoern A. Zeeb struct wireless_dev *wdev;
406*8ba4d145SBjoern A. Zeeb
407*8ba4d145SBjoern A. Zeeb if (!msta || !msta->vif)
408*8ba4d145SBjoern A. Zeeb return;
409*8ba4d145SBjoern A. Zeeb
410*8ba4d145SBjoern A. Zeeb if (!mt76_queue_is_wed_rx(q))
411*8ba4d145SBjoern A. Zeeb return;
412*8ba4d145SBjoern A. Zeeb
413*8ba4d145SBjoern A. Zeeb if (!(info & MT_DMA_INFO_PPE_VLD))
414*8ba4d145SBjoern A. Zeeb return;
415*8ba4d145SBjoern A. Zeeb
416*8ba4d145SBjoern A. Zeeb vif = container_of((void *)msta->vif, struct ieee80211_vif,
417*8ba4d145SBjoern A. Zeeb drv_priv);
418*8ba4d145SBjoern A. Zeeb wdev = ieee80211_vif_to_wdev(vif);
419*8ba4d145SBjoern A. Zeeb skb->dev = wdev->netdev;
420*8ba4d145SBjoern A. Zeeb
421*8ba4d145SBjoern A. Zeeb mtk_wed_device_ppe_check(&dev->mt76.mmio.wed, skb,
422*8ba4d145SBjoern A. Zeeb FIELD_GET(MT_DMA_PPE_CPU_REASON, info),
423*8ba4d145SBjoern A. Zeeb FIELD_GET(MT_DMA_PPE_ENTRY, info));
424*8ba4d145SBjoern A. Zeeb }
425*8ba4d145SBjoern A. Zeeb
426cbb3ec25SBjoern A. Zeeb static int
mt7996_mac_fill_rx(struct mt7996_dev * dev,enum mt76_rxq_id q,struct sk_buff * skb,u32 * info)427*8ba4d145SBjoern A. Zeeb mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
428*8ba4d145SBjoern A. Zeeb struct sk_buff *skb, u32 *info)
429cbb3ec25SBjoern A. Zeeb {
430cbb3ec25SBjoern A. Zeeb struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
431cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
432cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = &dev->phy;
433cbb3ec25SBjoern A. Zeeb struct ieee80211_supported_band *sband;
434cbb3ec25SBjoern A. Zeeb __le32 *rxd = (__le32 *)skb->data;
435cbb3ec25SBjoern A. Zeeb __le32 *rxv = NULL;
436cbb3ec25SBjoern A. Zeeb u32 rxd0 = le32_to_cpu(rxd[0]);
437cbb3ec25SBjoern A. Zeeb u32 rxd1 = le32_to_cpu(rxd[1]);
438cbb3ec25SBjoern A. Zeeb u32 rxd2 = le32_to_cpu(rxd[2]);
439cbb3ec25SBjoern A. Zeeb u32 rxd3 = le32_to_cpu(rxd[3]);
440cbb3ec25SBjoern A. Zeeb u32 rxd4 = le32_to_cpu(rxd[4]);
441*8ba4d145SBjoern A. Zeeb u32 csum_mask = MT_RXD3_NORMAL_IP_SUM | MT_RXD3_NORMAL_UDP_TCP_SUM;
442cbb3ec25SBjoern A. Zeeb u32 csum_status = *(u32 *)skb->cb;
443cbb3ec25SBjoern A. Zeeb u32 mesh_mask = MT_RXD0_MESH | MT_RXD0_MHCP;
444cbb3ec25SBjoern A. Zeeb bool is_mesh = (rxd0 & mesh_mask) == mesh_mask;
445cbb3ec25SBjoern A. Zeeb bool unicast, insert_ccmp_hdr = false;
446cbb3ec25SBjoern A. Zeeb u8 remove_pad, amsdu_info, band_idx;
447cbb3ec25SBjoern A. Zeeb u8 mode = 0, qos_ctl = 0;
448cbb3ec25SBjoern A. Zeeb bool hdr_trans;
449cbb3ec25SBjoern A. Zeeb u16 hdr_gap;
450cbb3ec25SBjoern A. Zeeb u16 seq_ctrl = 0;
451cbb3ec25SBjoern A. Zeeb __le16 fc = 0;
452cbb3ec25SBjoern A. Zeeb int idx;
453*8ba4d145SBjoern A. Zeeb u8 hw_aggr = false;
454*8ba4d145SBjoern A. Zeeb struct mt7996_sta *msta = NULL;
455cbb3ec25SBjoern A. Zeeb
456*8ba4d145SBjoern A. Zeeb hw_aggr = status->aggr;
457cbb3ec25SBjoern A. Zeeb memset(status, 0, sizeof(*status));
458cbb3ec25SBjoern A. Zeeb
459cbb3ec25SBjoern A. Zeeb band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1);
460cbb3ec25SBjoern A. Zeeb mphy = dev->mt76.phys[band_idx];
461cbb3ec25SBjoern A. Zeeb phy = mphy->priv;
462cbb3ec25SBjoern A. Zeeb status->phy_idx = mphy->band_idx;
463cbb3ec25SBjoern A. Zeeb
464cbb3ec25SBjoern A. Zeeb if (!test_bit(MT76_STATE_RUNNING, &mphy->state))
465cbb3ec25SBjoern A. Zeeb return -EINVAL;
466cbb3ec25SBjoern A. Zeeb
467cbb3ec25SBjoern A. Zeeb if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
468cbb3ec25SBjoern A. Zeeb return -EINVAL;
469cbb3ec25SBjoern A. Zeeb
470cbb3ec25SBjoern A. Zeeb hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
471cbb3ec25SBjoern A. Zeeb if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM))
472cbb3ec25SBjoern A. Zeeb return -EINVAL;
473cbb3ec25SBjoern A. Zeeb
474cbb3ec25SBjoern A. Zeeb /* ICV error or CCMP/BIP/WPI MIC error */
475cbb3ec25SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_ICV_ERR)
476cbb3ec25SBjoern A. Zeeb status->flag |= RX_FLAG_ONLY_MONITOR;
477cbb3ec25SBjoern A. Zeeb
478cbb3ec25SBjoern A. Zeeb unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
479cbb3ec25SBjoern A. Zeeb idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
480cbb3ec25SBjoern A. Zeeb status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
481cbb3ec25SBjoern A. Zeeb
482cbb3ec25SBjoern A. Zeeb if (status->wcid) {
483cbb3ec25SBjoern A. Zeeb msta = container_of(status->wcid, struct mt7996_sta, wcid);
484*8ba4d145SBjoern A. Zeeb mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
485cbb3ec25SBjoern A. Zeeb }
486cbb3ec25SBjoern A. Zeeb
487cbb3ec25SBjoern A. Zeeb status->freq = mphy->chandef.chan->center_freq;
488cbb3ec25SBjoern A. Zeeb status->band = mphy->chandef.chan->band;
489cbb3ec25SBjoern A. Zeeb if (status->band == NL80211_BAND_5GHZ)
490cbb3ec25SBjoern A. Zeeb sband = &mphy->sband_5g.sband;
491cbb3ec25SBjoern A. Zeeb else if (status->band == NL80211_BAND_6GHZ)
492cbb3ec25SBjoern A. Zeeb sband = &mphy->sband_6g.sband;
493cbb3ec25SBjoern A. Zeeb else
494cbb3ec25SBjoern A. Zeeb sband = &mphy->sband_2g.sband;
495cbb3ec25SBjoern A. Zeeb
496cbb3ec25SBjoern A. Zeeb if (!sband->channels)
497cbb3ec25SBjoern A. Zeeb return -EINVAL;
498cbb3ec25SBjoern A. Zeeb
499*8ba4d145SBjoern A. Zeeb if ((rxd3 & csum_mask) == csum_mask &&
500cbb3ec25SBjoern A. Zeeb !(csum_status & (BIT(0) | BIT(2) | BIT(3))))
501cbb3ec25SBjoern A. Zeeb skb->ip_summed = CHECKSUM_UNNECESSARY;
502cbb3ec25SBjoern A. Zeeb
503cbb3ec25SBjoern A. Zeeb if (rxd1 & MT_RXD3_NORMAL_FCS_ERR)
504cbb3ec25SBjoern A. Zeeb status->flag |= RX_FLAG_FAILED_FCS_CRC;
505cbb3ec25SBjoern A. Zeeb
506cbb3ec25SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR)
507cbb3ec25SBjoern A. Zeeb status->flag |= RX_FLAG_MMIC_ERROR;
508cbb3ec25SBjoern A. Zeeb
509cbb3ec25SBjoern A. Zeeb if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 &&
510cbb3ec25SBjoern A. Zeeb !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) {
511cbb3ec25SBjoern A. Zeeb status->flag |= RX_FLAG_DECRYPTED;
512cbb3ec25SBjoern A. Zeeb status->flag |= RX_FLAG_IV_STRIPPED;
513cbb3ec25SBjoern A. Zeeb status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
514cbb3ec25SBjoern A. Zeeb }
515cbb3ec25SBjoern A. Zeeb
516cbb3ec25SBjoern A. Zeeb remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2);
517cbb3ec25SBjoern A. Zeeb
518cbb3ec25SBjoern A. Zeeb if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
519cbb3ec25SBjoern A. Zeeb return -EINVAL;
520cbb3ec25SBjoern A. Zeeb
521cbb3ec25SBjoern A. Zeeb rxd += 8;
522cbb3ec25SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_4) {
523cbb3ec25SBjoern A. Zeeb u32 v0 = le32_to_cpu(rxd[0]);
524cbb3ec25SBjoern A. Zeeb u32 v2 = le32_to_cpu(rxd[2]);
525cbb3ec25SBjoern A. Zeeb
526cbb3ec25SBjoern A. Zeeb fc = cpu_to_le16(FIELD_GET(MT_RXD8_FRAME_CONTROL, v0));
527cbb3ec25SBjoern A. Zeeb qos_ctl = FIELD_GET(MT_RXD10_QOS_CTL, v2);
528cbb3ec25SBjoern A. Zeeb seq_ctrl = FIELD_GET(MT_RXD10_SEQ_CTRL, v2);
529cbb3ec25SBjoern A. Zeeb
530cbb3ec25SBjoern A. Zeeb rxd += 4;
531cbb3ec25SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
532cbb3ec25SBjoern A. Zeeb return -EINVAL;
533cbb3ec25SBjoern A. Zeeb }
534cbb3ec25SBjoern A. Zeeb
535cbb3ec25SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_1) {
536cbb3ec25SBjoern A. Zeeb u8 *data = (u8 *)rxd;
537cbb3ec25SBjoern A. Zeeb
538cbb3ec25SBjoern A. Zeeb if (status->flag & RX_FLAG_DECRYPTED) {
539cbb3ec25SBjoern A. Zeeb switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) {
540cbb3ec25SBjoern A. Zeeb case MT_CIPHER_AES_CCMP:
541cbb3ec25SBjoern A. Zeeb case MT_CIPHER_CCMP_CCX:
542cbb3ec25SBjoern A. Zeeb case MT_CIPHER_CCMP_256:
543cbb3ec25SBjoern A. Zeeb insert_ccmp_hdr =
544cbb3ec25SBjoern A. Zeeb FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
545cbb3ec25SBjoern A. Zeeb fallthrough;
546cbb3ec25SBjoern A. Zeeb case MT_CIPHER_TKIP:
547cbb3ec25SBjoern A. Zeeb case MT_CIPHER_TKIP_NO_MIC:
548cbb3ec25SBjoern A. Zeeb case MT_CIPHER_GCMP:
549cbb3ec25SBjoern A. Zeeb case MT_CIPHER_GCMP_256:
550cbb3ec25SBjoern A. Zeeb status->iv[0] = data[5];
551cbb3ec25SBjoern A. Zeeb status->iv[1] = data[4];
552cbb3ec25SBjoern A. Zeeb status->iv[2] = data[3];
553cbb3ec25SBjoern A. Zeeb status->iv[3] = data[2];
554cbb3ec25SBjoern A. Zeeb status->iv[4] = data[1];
555cbb3ec25SBjoern A. Zeeb status->iv[5] = data[0];
556cbb3ec25SBjoern A. Zeeb break;
557cbb3ec25SBjoern A. Zeeb default:
558cbb3ec25SBjoern A. Zeeb break;
559cbb3ec25SBjoern A. Zeeb }
560cbb3ec25SBjoern A. Zeeb }
561cbb3ec25SBjoern A. Zeeb rxd += 4;
562cbb3ec25SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
563cbb3ec25SBjoern A. Zeeb return -EINVAL;
564cbb3ec25SBjoern A. Zeeb }
565cbb3ec25SBjoern A. Zeeb
566cbb3ec25SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_2) {
567cbb3ec25SBjoern A. Zeeb status->timestamp = le32_to_cpu(rxd[0]);
568cbb3ec25SBjoern A. Zeeb status->flag |= RX_FLAG_MACTIME_START;
569cbb3ec25SBjoern A. Zeeb
570cbb3ec25SBjoern A. Zeeb if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) {
571cbb3ec25SBjoern A. Zeeb status->flag |= RX_FLAG_AMPDU_DETAILS;
572cbb3ec25SBjoern A. Zeeb
573cbb3ec25SBjoern A. Zeeb /* all subframes of an A-MPDU have the same timestamp */
574cbb3ec25SBjoern A. Zeeb if (phy->rx_ampdu_ts != status->timestamp) {
575cbb3ec25SBjoern A. Zeeb if (!++phy->ampdu_ref)
576cbb3ec25SBjoern A. Zeeb phy->ampdu_ref++;
577cbb3ec25SBjoern A. Zeeb }
578cbb3ec25SBjoern A. Zeeb phy->rx_ampdu_ts = status->timestamp;
579cbb3ec25SBjoern A. Zeeb
580cbb3ec25SBjoern A. Zeeb status->ampdu_ref = phy->ampdu_ref;
581cbb3ec25SBjoern A. Zeeb }
582cbb3ec25SBjoern A. Zeeb
583cbb3ec25SBjoern A. Zeeb rxd += 4;
584cbb3ec25SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
585cbb3ec25SBjoern A. Zeeb return -EINVAL;
586cbb3ec25SBjoern A. Zeeb }
587cbb3ec25SBjoern A. Zeeb
588cbb3ec25SBjoern A. Zeeb /* RXD Group 3 - P-RXV */
589cbb3ec25SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
590cbb3ec25SBjoern A. Zeeb u32 v3;
591cbb3ec25SBjoern A. Zeeb int ret;
592cbb3ec25SBjoern A. Zeeb
593cbb3ec25SBjoern A. Zeeb rxv = rxd;
594cbb3ec25SBjoern A. Zeeb rxd += 4;
595cbb3ec25SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
596cbb3ec25SBjoern A. Zeeb return -EINVAL;
597cbb3ec25SBjoern A. Zeeb
598cbb3ec25SBjoern A. Zeeb v3 = le32_to_cpu(rxv[3]);
599cbb3ec25SBjoern A. Zeeb
600cbb3ec25SBjoern A. Zeeb status->chains = mphy->antenna_mask;
601cbb3ec25SBjoern A. Zeeb status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v3);
602cbb3ec25SBjoern A. Zeeb status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v3);
603cbb3ec25SBjoern A. Zeeb status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v3);
604cbb3ec25SBjoern A. Zeeb status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v3);
605cbb3ec25SBjoern A. Zeeb
606cbb3ec25SBjoern A. Zeeb /* RXD Group 5 - C-RXV */
607cbb3ec25SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
608cbb3ec25SBjoern A. Zeeb rxd += 24;
609cbb3ec25SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
610cbb3ec25SBjoern A. Zeeb return -EINVAL;
611cbb3ec25SBjoern A. Zeeb }
612cbb3ec25SBjoern A. Zeeb
613cbb3ec25SBjoern A. Zeeb ret = mt7996_mac_fill_rx_rate(dev, status, sband, rxv, &mode);
614cbb3ec25SBjoern A. Zeeb if (ret < 0)
615cbb3ec25SBjoern A. Zeeb return ret;
616cbb3ec25SBjoern A. Zeeb }
617cbb3ec25SBjoern A. Zeeb
618cbb3ec25SBjoern A. Zeeb amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4);
619cbb3ec25SBjoern A. Zeeb status->amsdu = !!amsdu_info;
620cbb3ec25SBjoern A. Zeeb if (status->amsdu) {
621cbb3ec25SBjoern A. Zeeb status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME;
622cbb3ec25SBjoern A. Zeeb status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME;
623cbb3ec25SBjoern A. Zeeb }
624cbb3ec25SBjoern A. Zeeb
625cbb3ec25SBjoern A. Zeeb hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad;
626cbb3ec25SBjoern A. Zeeb if (hdr_trans && ieee80211_has_morefrags(fc)) {
627cbb3ec25SBjoern A. Zeeb if (mt7996_reverse_frag0_hdr_trans(skb, hdr_gap))
628cbb3ec25SBjoern A. Zeeb return -EINVAL;
629cbb3ec25SBjoern A. Zeeb hdr_trans = false;
630cbb3ec25SBjoern A. Zeeb } else {
631cbb3ec25SBjoern A. Zeeb int pad_start = 0;
632cbb3ec25SBjoern A. Zeeb
633cbb3ec25SBjoern A. Zeeb skb_pull(skb, hdr_gap);
634cbb3ec25SBjoern A. Zeeb if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) {
635cbb3ec25SBjoern A. Zeeb pad_start = ieee80211_get_hdrlen_from_skb(skb);
636cbb3ec25SBjoern A. Zeeb } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) {
637cbb3ec25SBjoern A. Zeeb /* When header translation failure is indicated,
638cbb3ec25SBjoern A. Zeeb * the hardware will insert an extra 2-byte field
639cbb3ec25SBjoern A. Zeeb * containing the data length after the protocol
640cbb3ec25SBjoern A. Zeeb * type field. This happens either when the LLC-SNAP
641cbb3ec25SBjoern A. Zeeb * pattern did not match, or if a VLAN header was
642cbb3ec25SBjoern A. Zeeb * detected.
643cbb3ec25SBjoern A. Zeeb */
644cbb3ec25SBjoern A. Zeeb pad_start = 12;
645cbb3ec25SBjoern A. Zeeb if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q)
646cbb3ec25SBjoern A. Zeeb pad_start += 4;
647cbb3ec25SBjoern A. Zeeb else
648cbb3ec25SBjoern A. Zeeb pad_start = 0;
649cbb3ec25SBjoern A. Zeeb }
650cbb3ec25SBjoern A. Zeeb
651cbb3ec25SBjoern A. Zeeb if (pad_start) {
652cbb3ec25SBjoern A. Zeeb memmove(skb->data + 2, skb->data, pad_start);
653cbb3ec25SBjoern A. Zeeb skb_pull(skb, 2);
654cbb3ec25SBjoern A. Zeeb }
655cbb3ec25SBjoern A. Zeeb }
656cbb3ec25SBjoern A. Zeeb
657cbb3ec25SBjoern A. Zeeb if (!hdr_trans) {
658cbb3ec25SBjoern A. Zeeb struct ieee80211_hdr *hdr;
659cbb3ec25SBjoern A. Zeeb
660cbb3ec25SBjoern A. Zeeb if (insert_ccmp_hdr) {
661cbb3ec25SBjoern A. Zeeb u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
662cbb3ec25SBjoern A. Zeeb
663cbb3ec25SBjoern A. Zeeb mt76_insert_ccmp_hdr(skb, key_id);
664cbb3ec25SBjoern A. Zeeb }
665cbb3ec25SBjoern A. Zeeb
666cbb3ec25SBjoern A. Zeeb hdr = mt76_skb_get_hdr(skb);
667cbb3ec25SBjoern A. Zeeb fc = hdr->frame_control;
668cbb3ec25SBjoern A. Zeeb if (ieee80211_is_data_qos(fc)) {
669cbb3ec25SBjoern A. Zeeb u8 *qos = ieee80211_get_qos_ctl(hdr);
670cbb3ec25SBjoern A. Zeeb
671cbb3ec25SBjoern A. Zeeb seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
672cbb3ec25SBjoern A. Zeeb qos_ctl = *qos;
673cbb3ec25SBjoern A. Zeeb
674cbb3ec25SBjoern A. Zeeb /* Mesh DA/SA/Length will be stripped after hardware
675cbb3ec25SBjoern A. Zeeb * de-amsdu, so here needs to clear amsdu present bit
676cbb3ec25SBjoern A. Zeeb * to mark it as a normal mesh frame.
677cbb3ec25SBjoern A. Zeeb */
678cbb3ec25SBjoern A. Zeeb if (ieee80211_has_a4(fc) && is_mesh && status->amsdu)
679cbb3ec25SBjoern A. Zeeb *qos &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
680cbb3ec25SBjoern A. Zeeb }
681*8ba4d145SBjoern A. Zeeb skb_set_mac_header(skb, (unsigned char *)hdr - skb->data);
682cbb3ec25SBjoern A. Zeeb } else {
683cbb3ec25SBjoern A. Zeeb status->flag |= RX_FLAG_8023;
684*8ba4d145SBjoern A. Zeeb mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb,
685*8ba4d145SBjoern A. Zeeb *info);
686cbb3ec25SBjoern A. Zeeb }
687cbb3ec25SBjoern A. Zeeb
688*8ba4d145SBjoern A. Zeeb if (rxv && !(status->flag & RX_FLAG_8023)) {
689*8ba4d145SBjoern A. Zeeb switch (status->encoding) {
690*8ba4d145SBjoern A. Zeeb case RX_ENC_EHT:
691*8ba4d145SBjoern A. Zeeb mt76_connac3_mac_decode_eht_radiotap(skb, rxv, mode);
692*8ba4d145SBjoern A. Zeeb break;
693*8ba4d145SBjoern A. Zeeb case RX_ENC_HE:
694cbb3ec25SBjoern A. Zeeb mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
695*8ba4d145SBjoern A. Zeeb break;
696*8ba4d145SBjoern A. Zeeb default:
697*8ba4d145SBjoern A. Zeeb break;
698*8ba4d145SBjoern A. Zeeb }
699*8ba4d145SBjoern A. Zeeb }
700cbb3ec25SBjoern A. Zeeb
701*8ba4d145SBjoern A. Zeeb if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr)
702cbb3ec25SBjoern A. Zeeb return 0;
703cbb3ec25SBjoern A. Zeeb
704cbb3ec25SBjoern A. Zeeb status->aggr = unicast &&
705cbb3ec25SBjoern A. Zeeb !ieee80211_is_qos_nullfunc(fc);
706cbb3ec25SBjoern A. Zeeb status->qos_ctl = qos_ctl;
707cbb3ec25SBjoern A. Zeeb status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);
708cbb3ec25SBjoern A. Zeeb
709cbb3ec25SBjoern A. Zeeb return 0;
710cbb3ec25SBjoern A. Zeeb }
711cbb3ec25SBjoern A. Zeeb
712cbb3ec25SBjoern A. Zeeb static void
mt7996_mac_write_txwi_8023(struct mt7996_dev * dev,__le32 * txwi,struct sk_buff * skb,struct mt76_wcid * wcid)713cbb3ec25SBjoern A. Zeeb mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
714cbb3ec25SBjoern A. Zeeb struct sk_buff *skb, struct mt76_wcid *wcid)
715cbb3ec25SBjoern A. Zeeb {
716cbb3ec25SBjoern A. Zeeb u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
717cbb3ec25SBjoern A. Zeeb u8 fc_type, fc_stype;
718cbb3ec25SBjoern A. Zeeb u16 ethertype;
719cbb3ec25SBjoern A. Zeeb bool wmm = false;
720cbb3ec25SBjoern A. Zeeb u32 val;
721cbb3ec25SBjoern A. Zeeb
722cbb3ec25SBjoern A. Zeeb if (wcid->sta) {
723cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta;
724cbb3ec25SBjoern A. Zeeb
725cbb3ec25SBjoern A. Zeeb sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
726cbb3ec25SBjoern A. Zeeb wmm = sta->wme;
727cbb3ec25SBjoern A. Zeeb }
728cbb3ec25SBjoern A. Zeeb
729cbb3ec25SBjoern A. Zeeb val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
730cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD1_TID, tid);
731cbb3ec25SBjoern A. Zeeb
732cbb3ec25SBjoern A. Zeeb ethertype = get_unaligned_be16(&skb->data[12]);
733cbb3ec25SBjoern A. Zeeb if (ethertype >= ETH_P_802_3_MIN)
734cbb3ec25SBjoern A. Zeeb val |= MT_TXD1_ETH_802_3;
735cbb3ec25SBjoern A. Zeeb
736cbb3ec25SBjoern A. Zeeb txwi[1] |= cpu_to_le32(val);
737cbb3ec25SBjoern A. Zeeb
738cbb3ec25SBjoern A. Zeeb fc_type = IEEE80211_FTYPE_DATA >> 2;
739cbb3ec25SBjoern A. Zeeb fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
740cbb3ec25SBjoern A. Zeeb
741cbb3ec25SBjoern A. Zeeb val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
742cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
743cbb3ec25SBjoern A. Zeeb
744cbb3ec25SBjoern A. Zeeb txwi[2] |= cpu_to_le32(val);
745*8ba4d145SBjoern A. Zeeb
746*8ba4d145SBjoern A. Zeeb if (wcid->amsdu)
747*8ba4d145SBjoern A. Zeeb txwi[3] |= cpu_to_le32(MT_TXD3_HW_AMSDU);
748cbb3ec25SBjoern A. Zeeb }
749cbb3ec25SBjoern A. Zeeb
750cbb3ec25SBjoern A. Zeeb static void
mt7996_mac_write_txwi_80211(struct mt7996_dev * dev,__le32 * txwi,struct sk_buff * skb,struct ieee80211_key_conf * key)751cbb3ec25SBjoern A. Zeeb mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
752cbb3ec25SBjoern A. Zeeb struct sk_buff *skb, struct ieee80211_key_conf *key)
753cbb3ec25SBjoern A. Zeeb {
754cbb3ec25SBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
755cbb3ec25SBjoern A. Zeeb struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
756cbb3ec25SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
757cbb3ec25SBjoern A. Zeeb bool multicast = is_multicast_ether_addr(hdr->addr1);
758cbb3ec25SBjoern A. Zeeb u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
759*8ba4d145SBjoern A. Zeeb __le16 fc = hdr->frame_control, sc = hdr->seq_ctrl;
760cbb3ec25SBjoern A. Zeeb u8 fc_type, fc_stype;
761cbb3ec25SBjoern A. Zeeb u32 val;
762cbb3ec25SBjoern A. Zeeb
763cbb3ec25SBjoern A. Zeeb if (ieee80211_is_action(fc) &&
764cbb3ec25SBjoern A. Zeeb mgmt->u.action.category == WLAN_CATEGORY_BACK &&
765cbb3ec25SBjoern A. Zeeb mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)
766cbb3ec25SBjoern A. Zeeb tid = MT_TX_ADDBA;
767cbb3ec25SBjoern A. Zeeb else if (ieee80211_is_mgmt(hdr->frame_control))
768cbb3ec25SBjoern A. Zeeb tid = MT_TX_NORMAL;
769cbb3ec25SBjoern A. Zeeb
770cbb3ec25SBjoern A. Zeeb val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
771cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD1_HDR_INFO,
772cbb3ec25SBjoern A. Zeeb ieee80211_get_hdrlen_from_skb(skb) / 2) |
773cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD1_TID, tid);
774cbb3ec25SBjoern A. Zeeb
775cbb3ec25SBjoern A. Zeeb if (!ieee80211_is_data(fc) || multicast ||
776cbb3ec25SBjoern A. Zeeb info->flags & IEEE80211_TX_CTL_USE_MINRATE)
777cbb3ec25SBjoern A. Zeeb val |= MT_TXD1_FIXED_RATE;
778cbb3ec25SBjoern A. Zeeb
779cbb3ec25SBjoern A. Zeeb if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
780cbb3ec25SBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
781cbb3ec25SBjoern A. Zeeb val |= MT_TXD1_BIP;
782cbb3ec25SBjoern A. Zeeb txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
783cbb3ec25SBjoern A. Zeeb }
784cbb3ec25SBjoern A. Zeeb
785cbb3ec25SBjoern A. Zeeb txwi[1] |= cpu_to_le32(val);
786cbb3ec25SBjoern A. Zeeb
787cbb3ec25SBjoern A. Zeeb fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
788cbb3ec25SBjoern A. Zeeb fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
789cbb3ec25SBjoern A. Zeeb
790cbb3ec25SBjoern A. Zeeb val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
791cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
792cbb3ec25SBjoern A. Zeeb
793*8ba4d145SBjoern A. Zeeb if (ieee80211_has_morefrags(fc) && ieee80211_is_first_frag(sc))
794*8ba4d145SBjoern A. Zeeb val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_FIRST);
795*8ba4d145SBjoern A. Zeeb else if (ieee80211_has_morefrags(fc) && !ieee80211_is_first_frag(sc))
796*8ba4d145SBjoern A. Zeeb val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_MID);
797*8ba4d145SBjoern A. Zeeb else if (!ieee80211_has_morefrags(fc) && !ieee80211_is_first_frag(sc))
798*8ba4d145SBjoern A. Zeeb val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_LAST);
799*8ba4d145SBjoern A. Zeeb else
800*8ba4d145SBjoern A. Zeeb val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_NONE);
801*8ba4d145SBjoern A. Zeeb
802cbb3ec25SBjoern A. Zeeb txwi[2] |= cpu_to_le32(val);
803cbb3ec25SBjoern A. Zeeb
804cbb3ec25SBjoern A. Zeeb txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast));
805cbb3ec25SBjoern A. Zeeb if (ieee80211_is_beacon(fc)) {
806cbb3ec25SBjoern A. Zeeb txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
807cbb3ec25SBjoern A. Zeeb txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
808cbb3ec25SBjoern A. Zeeb }
809cbb3ec25SBjoern A. Zeeb
810cbb3ec25SBjoern A. Zeeb if (info->flags & IEEE80211_TX_CTL_INJECTED) {
811*8ba4d145SBjoern A. Zeeb u16 seqno = le16_to_cpu(sc);
812cbb3ec25SBjoern A. Zeeb
813cbb3ec25SBjoern A. Zeeb if (ieee80211_is_back_req(hdr->frame_control)) {
814cbb3ec25SBjoern A. Zeeb struct ieee80211_bar *bar;
815cbb3ec25SBjoern A. Zeeb
816cbb3ec25SBjoern A. Zeeb bar = (struct ieee80211_bar *)skb->data;
817cbb3ec25SBjoern A. Zeeb seqno = le16_to_cpu(bar->start_seq_num);
818cbb3ec25SBjoern A. Zeeb }
819cbb3ec25SBjoern A. Zeeb
820cbb3ec25SBjoern A. Zeeb val = MT_TXD3_SN_VALID |
821cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
822cbb3ec25SBjoern A. Zeeb txwi[3] |= cpu_to_le32(val);
823cbb3ec25SBjoern A. Zeeb txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
824cbb3ec25SBjoern A. Zeeb }
825cbb3ec25SBjoern A. Zeeb }
826cbb3ec25SBjoern A. Zeeb
mt7996_mac_write_txwi(struct mt7996_dev * dev,__le32 * txwi,struct sk_buff * skb,struct mt76_wcid * wcid,struct ieee80211_key_conf * key,int pid,enum mt76_txq_id qid,u32 changed)827cbb3ec25SBjoern A. Zeeb void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
828cbb3ec25SBjoern A. Zeeb struct sk_buff *skb, struct mt76_wcid *wcid,
829cbb3ec25SBjoern A. Zeeb struct ieee80211_key_conf *key, int pid,
830cbb3ec25SBjoern A. Zeeb enum mt76_txq_id qid, u32 changed)
831cbb3ec25SBjoern A. Zeeb {
832*8ba4d145SBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
833cbb3ec25SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
834cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif = info->control.vif;
835cbb3ec25SBjoern A. Zeeb u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
836cbb3ec25SBjoern A. Zeeb u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
837cbb3ec25SBjoern A. Zeeb bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
838*8ba4d145SBjoern A. Zeeb struct mt76_vif_link *mvif;
839cbb3ec25SBjoern A. Zeeb u16 tx_count = 15;
840cbb3ec25SBjoern A. Zeeb u32 val;
841cbb3ec25SBjoern A. Zeeb bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
842cbb3ec25SBjoern A. Zeeb BSS_CHANGED_FILS_DISCOVERY));
843*8ba4d145SBjoern A. Zeeb bool beacon = !!(changed & (BSS_CHANGED_BEACON |
844*8ba4d145SBjoern A. Zeeb BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
845cbb3ec25SBjoern A. Zeeb
846*8ba4d145SBjoern A. Zeeb mvif = vif ? (struct mt76_vif_link *)vif->drv_priv : NULL;
847cbb3ec25SBjoern A. Zeeb if (mvif) {
848cbb3ec25SBjoern A. Zeeb omac_idx = mvif->omac_idx;
849cbb3ec25SBjoern A. Zeeb wmm_idx = mvif->wmm_idx;
850cbb3ec25SBjoern A. Zeeb band_idx = mvif->band_idx;
851cbb3ec25SBjoern A. Zeeb }
852cbb3ec25SBjoern A. Zeeb
853cbb3ec25SBjoern A. Zeeb if (inband_disc) {
854cbb3ec25SBjoern A. Zeeb p_fmt = MT_TX_TYPE_FW;
855cbb3ec25SBjoern A. Zeeb q_idx = MT_LMAC_ALTX0;
856cbb3ec25SBjoern A. Zeeb } else if (beacon) {
857cbb3ec25SBjoern A. Zeeb p_fmt = MT_TX_TYPE_FW;
858cbb3ec25SBjoern A. Zeeb q_idx = MT_LMAC_BCN0;
859cbb3ec25SBjoern A. Zeeb } else if (qid >= MT_TXQ_PSD) {
860cbb3ec25SBjoern A. Zeeb p_fmt = MT_TX_TYPE_CT;
861cbb3ec25SBjoern A. Zeeb q_idx = MT_LMAC_ALTX0;
862cbb3ec25SBjoern A. Zeeb } else {
863cbb3ec25SBjoern A. Zeeb p_fmt = MT_TX_TYPE_CT;
864cbb3ec25SBjoern A. Zeeb q_idx = wmm_idx * MT7996_MAX_WMM_SETS +
865cbb3ec25SBjoern A. Zeeb mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
866cbb3ec25SBjoern A. Zeeb }
867cbb3ec25SBjoern A. Zeeb
868cbb3ec25SBjoern A. Zeeb val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) |
869cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
870cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
871cbb3ec25SBjoern A. Zeeb txwi[0] = cpu_to_le32(val);
872cbb3ec25SBjoern A. Zeeb
873cbb3ec25SBjoern A. Zeeb val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
874cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
875cbb3ec25SBjoern A. Zeeb
876cbb3ec25SBjoern A. Zeeb if (band_idx)
877cbb3ec25SBjoern A. Zeeb val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
878cbb3ec25SBjoern A. Zeeb
879cbb3ec25SBjoern A. Zeeb txwi[1] = cpu_to_le32(val);
880cbb3ec25SBjoern A. Zeeb txwi[2] = 0;
881cbb3ec25SBjoern A. Zeeb
882cbb3ec25SBjoern A. Zeeb val = MT_TXD3_SW_POWER_MGMT |
883cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
884cbb3ec25SBjoern A. Zeeb if (key)
885cbb3ec25SBjoern A. Zeeb val |= MT_TXD3_PROTECT_FRAME;
886cbb3ec25SBjoern A. Zeeb if (info->flags & IEEE80211_TX_CTL_NO_ACK)
887cbb3ec25SBjoern A. Zeeb val |= MT_TXD3_NO_ACK;
888cbb3ec25SBjoern A. Zeeb
889cbb3ec25SBjoern A. Zeeb txwi[3] = cpu_to_le32(val);
890cbb3ec25SBjoern A. Zeeb txwi[4] = 0;
891cbb3ec25SBjoern A. Zeeb
892cbb3ec25SBjoern A. Zeeb val = FIELD_PREP(MT_TXD5_PID, pid);
893cbb3ec25SBjoern A. Zeeb if (pid >= MT_PACKET_ID_FIRST)
894cbb3ec25SBjoern A. Zeeb val |= MT_TXD5_TX_STATUS_HOST;
895cbb3ec25SBjoern A. Zeeb txwi[5] = cpu_to_le32(val);
896cbb3ec25SBjoern A. Zeeb
897*8ba4d145SBjoern A. Zeeb val = MT_TXD6_DIS_MAT | MT_TXD6_DAS;
898*8ba4d145SBjoern A. Zeeb if (is_mt7996(&dev->mt76))
899*8ba4d145SBjoern A. Zeeb val |= FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
900*8ba4d145SBjoern A. Zeeb else if (is_8023 || !ieee80211_is_mgmt(hdr->frame_control))
901*8ba4d145SBjoern A. Zeeb val |= FIELD_PREP(MT_TXD6_MSDU_CNT_V2, 1);
902*8ba4d145SBjoern A. Zeeb
903cbb3ec25SBjoern A. Zeeb txwi[6] = cpu_to_le32(val);
904cbb3ec25SBjoern A. Zeeb txwi[7] = 0;
905cbb3ec25SBjoern A. Zeeb
906cbb3ec25SBjoern A. Zeeb if (is_8023)
907cbb3ec25SBjoern A. Zeeb mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid);
908cbb3ec25SBjoern A. Zeeb else
909cbb3ec25SBjoern A. Zeeb mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
910cbb3ec25SBjoern A. Zeeb
911cbb3ec25SBjoern A. Zeeb if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
912cbb3ec25SBjoern A. Zeeb bool mcast = ieee80211_is_data(hdr->frame_control) &&
913cbb3ec25SBjoern A. Zeeb is_multicast_ether_addr(hdr->addr1);
914cbb3ec25SBjoern A. Zeeb u8 idx = MT7996_BASIC_RATES_TBL;
915cbb3ec25SBjoern A. Zeeb
916cbb3ec25SBjoern A. Zeeb if (mvif) {
917cbb3ec25SBjoern A. Zeeb if (mcast && mvif->mcast_rates_idx)
918cbb3ec25SBjoern A. Zeeb idx = mvif->mcast_rates_idx;
919cbb3ec25SBjoern A. Zeeb else if (beacon && mvif->beacon_rates_idx)
920cbb3ec25SBjoern A. Zeeb idx = mvif->beacon_rates_idx;
921cbb3ec25SBjoern A. Zeeb else
922cbb3ec25SBjoern A. Zeeb idx = mvif->basic_rates_idx;
923cbb3ec25SBjoern A. Zeeb }
924cbb3ec25SBjoern A. Zeeb
925*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW;
926*8ba4d145SBjoern A. Zeeb txwi[6] |= cpu_to_le32(val);
927cbb3ec25SBjoern A. Zeeb txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
928cbb3ec25SBjoern A. Zeeb }
929cbb3ec25SBjoern A. Zeeb }
930cbb3ec25SBjoern A. Zeeb
mt7996_tx_prepare_skb(struct mt76_dev * mdev,void * txwi_ptr,enum mt76_txq_id qid,struct mt76_wcid * wcid,struct ieee80211_sta * sta,struct mt76_tx_info * tx_info)931cbb3ec25SBjoern A. Zeeb int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
932cbb3ec25SBjoern A. Zeeb enum mt76_txq_id qid, struct mt76_wcid *wcid,
933cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta,
934cbb3ec25SBjoern A. Zeeb struct mt76_tx_info *tx_info)
935cbb3ec25SBjoern A. Zeeb {
936cbb3ec25SBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
937cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
938cbb3ec25SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
939cbb3ec25SBjoern A. Zeeb struct ieee80211_key_conf *key = info->control.hw_key;
940cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif = info->control.vif;
941cbb3ec25SBjoern A. Zeeb struct mt76_connac_txp_common *txp;
942cbb3ec25SBjoern A. Zeeb struct mt76_txwi_cache *t;
943cbb3ec25SBjoern A. Zeeb int id, i, pid, nbuf = tx_info->nbuf - 1;
944cbb3ec25SBjoern A. Zeeb bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
945cbb3ec25SBjoern A. Zeeb u8 *txwi = (u8 *)txwi_ptr;
946cbb3ec25SBjoern A. Zeeb
947cbb3ec25SBjoern A. Zeeb if (unlikely(tx_info->skb->len <= ETH_HLEN))
948cbb3ec25SBjoern A. Zeeb return -EINVAL;
949cbb3ec25SBjoern A. Zeeb
950cbb3ec25SBjoern A. Zeeb if (!wcid)
951cbb3ec25SBjoern A. Zeeb wcid = &dev->mt76.global_wcid;
952cbb3ec25SBjoern A. Zeeb
953cbb3ec25SBjoern A. Zeeb t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
954cbb3ec25SBjoern A. Zeeb t->skb = tx_info->skb;
955cbb3ec25SBjoern A. Zeeb
956cbb3ec25SBjoern A. Zeeb id = mt76_token_consume(mdev, &t);
957cbb3ec25SBjoern A. Zeeb if (id < 0)
958cbb3ec25SBjoern A. Zeeb return id;
959cbb3ec25SBjoern A. Zeeb
960cbb3ec25SBjoern A. Zeeb pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
961cbb3ec25SBjoern A. Zeeb mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
962cbb3ec25SBjoern A. Zeeb pid, qid, 0);
963cbb3ec25SBjoern A. Zeeb
964cbb3ec25SBjoern A. Zeeb txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
965cbb3ec25SBjoern A. Zeeb for (i = 0; i < nbuf; i++) {
966*8ba4d145SBjoern A. Zeeb u16 len;
967*8ba4d145SBjoern A. Zeeb
968*8ba4d145SBjoern A. Zeeb len = FIELD_PREP(MT_TXP_BUF_LEN, tx_info->buf[i + 1].len);
969*8ba4d145SBjoern A. Zeeb #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
970*8ba4d145SBjoern A. Zeeb len |= FIELD_PREP(MT_TXP_DMA_ADDR_H,
971*8ba4d145SBjoern A. Zeeb tx_info->buf[i + 1].addr >> 32);
972*8ba4d145SBjoern A. Zeeb #endif
973*8ba4d145SBjoern A. Zeeb
974cbb3ec25SBjoern A. Zeeb txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
975*8ba4d145SBjoern A. Zeeb txp->fw.len[i] = cpu_to_le16(len);
976cbb3ec25SBjoern A. Zeeb }
977cbb3ec25SBjoern A. Zeeb txp->fw.nbuf = nbuf;
978cbb3ec25SBjoern A. Zeeb
979cbb3ec25SBjoern A. Zeeb txp->fw.flags =
980cbb3ec25SBjoern A. Zeeb cpu_to_le16(MT_CT_INFO_FROM_HOST | MT_CT_INFO_APPLY_TXD);
981cbb3ec25SBjoern A. Zeeb
982cbb3ec25SBjoern A. Zeeb if (!key)
983cbb3ec25SBjoern A. Zeeb txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
984cbb3ec25SBjoern A. Zeeb
985cbb3ec25SBjoern A. Zeeb if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control))
986cbb3ec25SBjoern A. Zeeb txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
987cbb3ec25SBjoern A. Zeeb
988cbb3ec25SBjoern A. Zeeb if (vif) {
989cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
990cbb3ec25SBjoern A. Zeeb
991*8ba4d145SBjoern A. Zeeb txp->fw.bss_idx = mvif->deflink.mt76.idx;
992cbb3ec25SBjoern A. Zeeb }
993cbb3ec25SBjoern A. Zeeb
994cbb3ec25SBjoern A. Zeeb txp->fw.token = cpu_to_le16(id);
995*8ba4d145SBjoern A. Zeeb txp->fw.rept_wds_wcid = cpu_to_le16(sta ? wcid->idx : 0xfff);
996*8ba4d145SBjoern A. Zeeb
997*8ba4d145SBjoern A. Zeeb tx_info->skb = NULL;
998cbb3ec25SBjoern A. Zeeb
999cbb3ec25SBjoern A. Zeeb /* pass partial skb header to fw */
1000cbb3ec25SBjoern A. Zeeb tx_info->buf[1].len = MT_CT_PARSE_LEN;
1001cbb3ec25SBjoern A. Zeeb tx_info->buf[1].skip_unmap = true;
1002cbb3ec25SBjoern A. Zeeb tx_info->nbuf = MT_CT_DMA_BUF_NUM;
1003cbb3ec25SBjoern A. Zeeb
1004cbb3ec25SBjoern A. Zeeb return 0;
1005cbb3ec25SBjoern A. Zeeb }
1006cbb3ec25SBjoern A. Zeeb
mt7996_wed_init_buf(void * ptr,dma_addr_t phys,int token_id)1007*8ba4d145SBjoern A. Zeeb u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
1008*8ba4d145SBjoern A. Zeeb {
1009*8ba4d145SBjoern A. Zeeb #if defined(__linux__)
1010*8ba4d145SBjoern A. Zeeb struct mt76_connac_fw_txp *txp = ptr + MT_TXD_SIZE;
1011*8ba4d145SBjoern A. Zeeb #elif defined(__FreeBSD__)
1012*8ba4d145SBjoern A. Zeeb struct mt76_connac_fw_txp *txp = (void *)((u8 *)ptr + MT_TXD_SIZE);
1013*8ba4d145SBjoern A. Zeeb #endif
1014*8ba4d145SBjoern A. Zeeb __le32 *txwi = ptr;
1015*8ba4d145SBjoern A. Zeeb u32 val;
1016*8ba4d145SBjoern A. Zeeb
1017*8ba4d145SBjoern A. Zeeb memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp));
1018*8ba4d145SBjoern A. Zeeb
1019*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) |
1020*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT);
1021*8ba4d145SBjoern A. Zeeb txwi[0] = cpu_to_le32(val);
1022*8ba4d145SBjoern A. Zeeb
1023*8ba4d145SBjoern A. Zeeb val = BIT(31) |
1024*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3);
1025*8ba4d145SBjoern A. Zeeb txwi[1] = cpu_to_le32(val);
1026*8ba4d145SBjoern A. Zeeb
1027*8ba4d145SBjoern A. Zeeb txp->token = cpu_to_le16(token_id);
1028*8ba4d145SBjoern A. Zeeb txp->nbuf = 1;
1029*8ba4d145SBjoern A. Zeeb txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp));
1030*8ba4d145SBjoern A. Zeeb
1031*8ba4d145SBjoern A. Zeeb return MT_TXD_SIZE + sizeof(*txp);
1032*8ba4d145SBjoern A. Zeeb }
1033*8ba4d145SBjoern A. Zeeb
1034cbb3ec25SBjoern A. Zeeb static void
mt7996_tx_check_aggr(struct ieee80211_sta * sta,struct sk_buff * skb)1035*8ba4d145SBjoern A. Zeeb mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
1036cbb3ec25SBjoern A. Zeeb {
1037cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta;
1038*8ba4d145SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1039*8ba4d145SBjoern A. Zeeb bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
1040cbb3ec25SBjoern A. Zeeb u16 fc, tid;
1041cbb3ec25SBjoern A. Zeeb
1042cbb3ec25SBjoern A. Zeeb if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
1043cbb3ec25SBjoern A. Zeeb return;
1044cbb3ec25SBjoern A. Zeeb
1045*8ba4d145SBjoern A. Zeeb tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
1046cbb3ec25SBjoern A. Zeeb if (tid >= 6) /* skip VO queue */
1047cbb3ec25SBjoern A. Zeeb return;
1048cbb3ec25SBjoern A. Zeeb
1049*8ba4d145SBjoern A. Zeeb if (is_8023) {
1050*8ba4d145SBjoern A. Zeeb fc = IEEE80211_FTYPE_DATA |
1051*8ba4d145SBjoern A. Zeeb (sta->wme ? IEEE80211_STYPE_QOS_DATA : IEEE80211_STYPE_DATA);
1052*8ba4d145SBjoern A. Zeeb } else {
1053*8ba4d145SBjoern A. Zeeb /* No need to get precise TID for Action/Management Frame,
1054*8ba4d145SBjoern A. Zeeb * since it will not meet the following Frame Control
1055*8ba4d145SBjoern A. Zeeb * condition anyway.
1056*8ba4d145SBjoern A. Zeeb */
1057*8ba4d145SBjoern A. Zeeb
1058*8ba4d145SBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1059*8ba4d145SBjoern A. Zeeb
1060*8ba4d145SBjoern A. Zeeb fc = le16_to_cpu(hdr->frame_control) &
1061*8ba4d145SBjoern A. Zeeb (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
1062*8ba4d145SBjoern A. Zeeb }
1063*8ba4d145SBjoern A. Zeeb
1064cbb3ec25SBjoern A. Zeeb if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
1065cbb3ec25SBjoern A. Zeeb return;
1066cbb3ec25SBjoern A. Zeeb
1067cbb3ec25SBjoern A. Zeeb msta = (struct mt7996_sta *)sta->drv_priv;
1068cbb3ec25SBjoern A. Zeeb if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
1069cbb3ec25SBjoern A. Zeeb ieee80211_start_tx_ba_session(sta, tid, 0);
1070cbb3ec25SBjoern A. Zeeb }
1071cbb3ec25SBjoern A. Zeeb
1072cbb3ec25SBjoern A. Zeeb static void
mt7996_txwi_free(struct mt7996_dev * dev,struct mt76_txwi_cache * t,struct ieee80211_sta * sta,struct list_head * free_list)1073cbb3ec25SBjoern A. Zeeb mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
1074cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta, struct list_head *free_list)
1075cbb3ec25SBjoern A. Zeeb {
1076cbb3ec25SBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76;
1077cbb3ec25SBjoern A. Zeeb struct mt76_wcid *wcid;
1078cbb3ec25SBjoern A. Zeeb __le32 *txwi;
1079cbb3ec25SBjoern A. Zeeb u16 wcid_idx;
1080cbb3ec25SBjoern A. Zeeb
1081cbb3ec25SBjoern A. Zeeb mt76_connac_txp_skb_unmap(mdev, t);
1082cbb3ec25SBjoern A. Zeeb if (!t->skb)
1083cbb3ec25SBjoern A. Zeeb goto out;
1084cbb3ec25SBjoern A. Zeeb
1085cbb3ec25SBjoern A. Zeeb txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
1086cbb3ec25SBjoern A. Zeeb if (sta) {
1087cbb3ec25SBjoern A. Zeeb wcid = (struct mt76_wcid *)sta->drv_priv;
1088cbb3ec25SBjoern A. Zeeb wcid_idx = wcid->idx;
1089cbb3ec25SBjoern A. Zeeb
1090cbb3ec25SBjoern A. Zeeb if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
1091*8ba4d145SBjoern A. Zeeb mt7996_tx_check_aggr(sta, t->skb);
1092cbb3ec25SBjoern A. Zeeb } else {
1093*8ba4d145SBjoern A. Zeeb wcid_idx = le32_get_bits(txwi[9], MT_TXD9_WLAN_IDX);
1094cbb3ec25SBjoern A. Zeeb }
1095cbb3ec25SBjoern A. Zeeb
1096cbb3ec25SBjoern A. Zeeb __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
1097cbb3ec25SBjoern A. Zeeb
1098cbb3ec25SBjoern A. Zeeb out:
1099cbb3ec25SBjoern A. Zeeb t->skb = NULL;
1100cbb3ec25SBjoern A. Zeeb mt76_put_txwi(mdev, t);
1101cbb3ec25SBjoern A. Zeeb }
1102cbb3ec25SBjoern A. Zeeb
1103cbb3ec25SBjoern A. Zeeb static void
mt7996_mac_tx_free(struct mt7996_dev * dev,void * data,int len)1104cbb3ec25SBjoern A. Zeeb mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
1105cbb3ec25SBjoern A. Zeeb {
1106cbb3ec25SBjoern A. Zeeb __le32 *tx_free = (__le32 *)data, *cur_info;
1107cbb3ec25SBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76;
1108cbb3ec25SBjoern A. Zeeb struct mt76_phy *phy2 = mdev->phys[MT_BAND1];
1109cbb3ec25SBjoern A. Zeeb struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
1110cbb3ec25SBjoern A. Zeeb struct mt76_txwi_cache *txwi;
1111cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta = NULL;
1112*8ba4d145SBjoern A. Zeeb struct mt76_wcid *wcid = NULL;
1113cbb3ec25SBjoern A. Zeeb LIST_HEAD(free_list);
1114cbb3ec25SBjoern A. Zeeb struct sk_buff *skb, *tmp;
1115cbb3ec25SBjoern A. Zeeb #if defined(__linux__)
1116cbb3ec25SBjoern A. Zeeb void *end = data + len;
1117cbb3ec25SBjoern A. Zeeb #elif defined(__FreeBSD__)
1118cbb3ec25SBjoern A. Zeeb void *end = (u8 *)data + len;
1119cbb3ec25SBjoern A. Zeeb #endif
1120cbb3ec25SBjoern A. Zeeb bool wake = false;
1121cbb3ec25SBjoern A. Zeeb u16 total, count = 0;
1122cbb3ec25SBjoern A. Zeeb
1123cbb3ec25SBjoern A. Zeeb /* clean DMA queues and unmap buffers first */
1124cbb3ec25SBjoern A. Zeeb mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
1125cbb3ec25SBjoern A. Zeeb mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
1126cbb3ec25SBjoern A. Zeeb if (phy2) {
1127cbb3ec25SBjoern A. Zeeb mt76_queue_tx_cleanup(dev, phy2->q_tx[MT_TXQ_PSD], false);
1128cbb3ec25SBjoern A. Zeeb mt76_queue_tx_cleanup(dev, phy2->q_tx[MT_TXQ_BE], false);
1129cbb3ec25SBjoern A. Zeeb }
1130cbb3ec25SBjoern A. Zeeb if (phy3) {
1131cbb3ec25SBjoern A. Zeeb mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_PSD], false);
1132cbb3ec25SBjoern A. Zeeb mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false);
1133cbb3ec25SBjoern A. Zeeb }
1134cbb3ec25SBjoern A. Zeeb
1135*8ba4d145SBjoern A. Zeeb if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 5))
1136cbb3ec25SBjoern A. Zeeb return;
1137cbb3ec25SBjoern A. Zeeb
1138cbb3ec25SBjoern A. Zeeb total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT);
1139cbb3ec25SBjoern A. Zeeb for (cur_info = &tx_free[2]; count < total; cur_info++) {
1140cbb3ec25SBjoern A. Zeeb u32 msdu, info;
1141cbb3ec25SBjoern A. Zeeb u8 i;
1142cbb3ec25SBjoern A. Zeeb
1143cbb3ec25SBjoern A. Zeeb if (WARN_ON_ONCE((void *)cur_info >= end))
1144cbb3ec25SBjoern A. Zeeb return;
1145cbb3ec25SBjoern A. Zeeb /* 1'b1: new wcid pair.
1146cbb3ec25SBjoern A. Zeeb * 1'b0: msdu_id with the same 'wcid pair' as above.
1147cbb3ec25SBjoern A. Zeeb */
1148cbb3ec25SBjoern A. Zeeb info = le32_to_cpu(*cur_info);
1149cbb3ec25SBjoern A. Zeeb if (info & MT_TXFREE_INFO_PAIR) {
1150cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta;
1151cbb3ec25SBjoern A. Zeeb u16 idx;
1152cbb3ec25SBjoern A. Zeeb
1153cbb3ec25SBjoern A. Zeeb idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
1154cbb3ec25SBjoern A. Zeeb wcid = rcu_dereference(dev->mt76.wcid[idx]);
1155cbb3ec25SBjoern A. Zeeb sta = wcid_to_sta(wcid);
1156cbb3ec25SBjoern A. Zeeb if (!sta)
1157cbb3ec25SBjoern A. Zeeb continue;
1158cbb3ec25SBjoern A. Zeeb
1159cbb3ec25SBjoern A. Zeeb msta = container_of(wcid, struct mt7996_sta, wcid);
1160*8ba4d145SBjoern A. Zeeb mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
1161*8ba4d145SBjoern A. Zeeb continue;
1162*8ba4d145SBjoern A. Zeeb } else if (info & MT_TXFREE_INFO_HEADER) {
1163*8ba4d145SBjoern A. Zeeb u32 tx_retries = 0, tx_failed = 0;
1164*8ba4d145SBjoern A. Zeeb
1165*8ba4d145SBjoern A. Zeeb if (!wcid)
1166*8ba4d145SBjoern A. Zeeb continue;
1167*8ba4d145SBjoern A. Zeeb
1168*8ba4d145SBjoern A. Zeeb tx_retries =
1169*8ba4d145SBjoern A. Zeeb FIELD_GET(MT_TXFREE_INFO_COUNT, info) - 1;
1170*8ba4d145SBjoern A. Zeeb tx_failed = tx_retries +
1171*8ba4d145SBjoern A. Zeeb !!FIELD_GET(MT_TXFREE_INFO_STAT, info);
1172*8ba4d145SBjoern A. Zeeb
1173*8ba4d145SBjoern A. Zeeb wcid->stats.tx_retries += tx_retries;
1174*8ba4d145SBjoern A. Zeeb wcid->stats.tx_failed += tx_failed;
1175cbb3ec25SBjoern A. Zeeb continue;
1176cbb3ec25SBjoern A. Zeeb }
1177cbb3ec25SBjoern A. Zeeb
1178cbb3ec25SBjoern A. Zeeb for (i = 0; i < 2; i++) {
1179cbb3ec25SBjoern A. Zeeb msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID;
1180cbb3ec25SBjoern A. Zeeb if (msdu == MT_TXFREE_INFO_MSDU_ID)
1181cbb3ec25SBjoern A. Zeeb continue;
1182cbb3ec25SBjoern A. Zeeb
1183cbb3ec25SBjoern A. Zeeb count++;
1184cbb3ec25SBjoern A. Zeeb txwi = mt76_token_release(mdev, msdu, &wake);
1185cbb3ec25SBjoern A. Zeeb if (!txwi)
1186cbb3ec25SBjoern A. Zeeb continue;
1187cbb3ec25SBjoern A. Zeeb
1188cbb3ec25SBjoern A. Zeeb mt7996_txwi_free(dev, txwi, sta, &free_list);
1189cbb3ec25SBjoern A. Zeeb }
1190cbb3ec25SBjoern A. Zeeb }
1191cbb3ec25SBjoern A. Zeeb
1192cbb3ec25SBjoern A. Zeeb mt7996_mac_sta_poll(dev);
1193cbb3ec25SBjoern A. Zeeb
1194cbb3ec25SBjoern A. Zeeb if (wake)
1195cbb3ec25SBjoern A. Zeeb mt76_set_tx_blocked(&dev->mt76, false);
1196cbb3ec25SBjoern A. Zeeb
1197cbb3ec25SBjoern A. Zeeb mt76_worker_schedule(&dev->mt76.tx_worker);
1198cbb3ec25SBjoern A. Zeeb
1199cbb3ec25SBjoern A. Zeeb list_for_each_entry_safe(skb, tmp, &free_list, list) {
1200cbb3ec25SBjoern A. Zeeb skb_list_del_init(skb);
1201cbb3ec25SBjoern A. Zeeb napi_consume_skb(skb, 1);
1202cbb3ec25SBjoern A. Zeeb }
1203cbb3ec25SBjoern A. Zeeb }
1204cbb3ec25SBjoern A. Zeeb
1205cbb3ec25SBjoern A. Zeeb static bool
mt7996_mac_add_txs_skb(struct mt7996_dev * dev,struct mt76_wcid * wcid,int pid,__le32 * txs_data)1206cbb3ec25SBjoern A. Zeeb mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
1207cbb3ec25SBjoern A. Zeeb int pid, __le32 *txs_data)
1208cbb3ec25SBjoern A. Zeeb {
1209cbb3ec25SBjoern A. Zeeb struct mt76_sta_stats *stats = &wcid->stats;
1210cbb3ec25SBjoern A. Zeeb struct ieee80211_supported_band *sband;
1211cbb3ec25SBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76;
1212cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy;
1213cbb3ec25SBjoern A. Zeeb struct ieee80211_tx_info *info;
1214cbb3ec25SBjoern A. Zeeb struct sk_buff_head list;
1215cbb3ec25SBjoern A. Zeeb struct rate_info rate = {};
1216*8ba4d145SBjoern A. Zeeb struct sk_buff *skb = NULL;
1217cbb3ec25SBjoern A. Zeeb bool cck = false;
1218cbb3ec25SBjoern A. Zeeb u32 txrate, txs, mode, stbc;
1219cbb3ec25SBjoern A. Zeeb
1220cbb3ec25SBjoern A. Zeeb txs = le32_to_cpu(txs_data[0]);
1221cbb3ec25SBjoern A. Zeeb
1222*8ba4d145SBjoern A. Zeeb mt76_tx_status_lock(mdev, &list);
1223*8ba4d145SBjoern A. Zeeb
1224*8ba4d145SBjoern A. Zeeb /* only report MPDU TXS */
1225*8ba4d145SBjoern A. Zeeb if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) == 0) {
1226*8ba4d145SBjoern A. Zeeb skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
1227*8ba4d145SBjoern A. Zeeb if (skb) {
1228cbb3ec25SBjoern A. Zeeb info = IEEE80211_SKB_CB(skb);
1229cbb3ec25SBjoern A. Zeeb if (!(txs & MT_TXS0_ACK_ERROR_MASK))
1230cbb3ec25SBjoern A. Zeeb info->flags |= IEEE80211_TX_STAT_ACK;
1231cbb3ec25SBjoern A. Zeeb
1232cbb3ec25SBjoern A. Zeeb info->status.ampdu_len = 1;
1233*8ba4d145SBjoern A. Zeeb info->status.ampdu_ack_len =
1234*8ba4d145SBjoern A. Zeeb !!(info->flags & IEEE80211_TX_STAT_ACK);
1235cbb3ec25SBjoern A. Zeeb
1236cbb3ec25SBjoern A. Zeeb info->status.rates[0].idx = -1;
1237*8ba4d145SBjoern A. Zeeb }
1238*8ba4d145SBjoern A. Zeeb }
1239*8ba4d145SBjoern A. Zeeb
1240*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wcid->sta) {
1241*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta;
1242*8ba4d145SBjoern A. Zeeb u8 tid;
1243*8ba4d145SBjoern A. Zeeb
1244*8ba4d145SBjoern A. Zeeb sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
1245*8ba4d145SBjoern A. Zeeb tid = FIELD_GET(MT_TXS0_TID, txs);
1246*8ba4d145SBjoern A. Zeeb ieee80211_refresh_tx_agg_session_timer(sta, tid);
1247*8ba4d145SBjoern A. Zeeb }
1248cbb3ec25SBjoern A. Zeeb
1249cbb3ec25SBjoern A. Zeeb txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
1250cbb3ec25SBjoern A. Zeeb
1251cbb3ec25SBjoern A. Zeeb rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
1252cbb3ec25SBjoern A. Zeeb rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
1253cbb3ec25SBjoern A. Zeeb stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
1254cbb3ec25SBjoern A. Zeeb
1255cbb3ec25SBjoern A. Zeeb if (stbc && rate.nss > 1)
1256cbb3ec25SBjoern A. Zeeb rate.nss >>= 1;
1257cbb3ec25SBjoern A. Zeeb
1258cbb3ec25SBjoern A. Zeeb if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
1259cbb3ec25SBjoern A. Zeeb stats->tx_nss[rate.nss - 1]++;
1260cbb3ec25SBjoern A. Zeeb if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
1261cbb3ec25SBjoern A. Zeeb stats->tx_mcs[rate.mcs]++;
1262cbb3ec25SBjoern A. Zeeb
1263cbb3ec25SBjoern A. Zeeb mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
1264cbb3ec25SBjoern A. Zeeb switch (mode) {
1265cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_CCK:
1266cbb3ec25SBjoern A. Zeeb cck = true;
1267cbb3ec25SBjoern A. Zeeb fallthrough;
1268cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_OFDM:
1269cbb3ec25SBjoern A. Zeeb mphy = mt76_dev_phy(mdev, wcid->phy_idx);
1270cbb3ec25SBjoern A. Zeeb
1271cbb3ec25SBjoern A. Zeeb if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
1272cbb3ec25SBjoern A. Zeeb sband = &mphy->sband_5g.sband;
1273cbb3ec25SBjoern A. Zeeb else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
1274cbb3ec25SBjoern A. Zeeb sband = &mphy->sband_6g.sband;
1275cbb3ec25SBjoern A. Zeeb else
1276cbb3ec25SBjoern A. Zeeb sband = &mphy->sband_2g.sband;
1277cbb3ec25SBjoern A. Zeeb
1278cbb3ec25SBjoern A. Zeeb rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck);
1279cbb3ec25SBjoern A. Zeeb rate.legacy = sband->bitrates[rate.mcs].bitrate;
1280cbb3ec25SBjoern A. Zeeb break;
1281cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HT:
1282cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HT_GF:
1283cbb3ec25SBjoern A. Zeeb if (rate.mcs > 31)
1284cbb3ec25SBjoern A. Zeeb goto out;
1285cbb3ec25SBjoern A. Zeeb
1286cbb3ec25SBjoern A. Zeeb rate.flags = RATE_INFO_FLAGS_MCS;
1287cbb3ec25SBjoern A. Zeeb if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
1288cbb3ec25SBjoern A. Zeeb rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1289cbb3ec25SBjoern A. Zeeb break;
1290cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_VHT:
1291cbb3ec25SBjoern A. Zeeb if (rate.mcs > 9)
1292cbb3ec25SBjoern A. Zeeb goto out;
1293cbb3ec25SBjoern A. Zeeb
1294cbb3ec25SBjoern A. Zeeb rate.flags = RATE_INFO_FLAGS_VHT_MCS;
1295*8ba4d145SBjoern A. Zeeb if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
1296*8ba4d145SBjoern A. Zeeb rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1297cbb3ec25SBjoern A. Zeeb break;
1298cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HE_SU:
1299cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HE_EXT_SU:
1300cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HE_TB:
1301cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_HE_MU:
1302cbb3ec25SBjoern A. Zeeb if (rate.mcs > 11)
1303cbb3ec25SBjoern A. Zeeb goto out;
1304cbb3ec25SBjoern A. Zeeb
1305cbb3ec25SBjoern A. Zeeb rate.he_gi = wcid->rate.he_gi;
1306cbb3ec25SBjoern A. Zeeb rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
1307cbb3ec25SBjoern A. Zeeb rate.flags = RATE_INFO_FLAGS_HE_MCS;
1308cbb3ec25SBjoern A. Zeeb break;
1309cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_EHT_SU:
1310cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_EHT_TRIG:
1311cbb3ec25SBjoern A. Zeeb case MT_PHY_TYPE_EHT_MU:
1312cbb3ec25SBjoern A. Zeeb if (rate.mcs > 13)
1313cbb3ec25SBjoern A. Zeeb goto out;
1314cbb3ec25SBjoern A. Zeeb
1315cbb3ec25SBjoern A. Zeeb rate.eht_gi = wcid->rate.eht_gi;
1316cbb3ec25SBjoern A. Zeeb rate.flags = RATE_INFO_FLAGS_EHT_MCS;
1317cbb3ec25SBjoern A. Zeeb break;
1318cbb3ec25SBjoern A. Zeeb default:
1319cbb3ec25SBjoern A. Zeeb goto out;
1320cbb3ec25SBjoern A. Zeeb }
1321cbb3ec25SBjoern A. Zeeb
1322cbb3ec25SBjoern A. Zeeb stats->tx_mode[mode]++;
1323cbb3ec25SBjoern A. Zeeb
1324cbb3ec25SBjoern A. Zeeb switch (FIELD_GET(MT_TXS0_BW, txs)) {
1325cbb3ec25SBjoern A. Zeeb case IEEE80211_STA_RX_BW_320:
1326cbb3ec25SBjoern A. Zeeb rate.bw = RATE_INFO_BW_320;
1327cbb3ec25SBjoern A. Zeeb stats->tx_bw[4]++;
1328cbb3ec25SBjoern A. Zeeb break;
1329cbb3ec25SBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
1330cbb3ec25SBjoern A. Zeeb rate.bw = RATE_INFO_BW_160;
1331cbb3ec25SBjoern A. Zeeb stats->tx_bw[3]++;
1332cbb3ec25SBjoern A. Zeeb break;
1333cbb3ec25SBjoern A. Zeeb case IEEE80211_STA_RX_BW_80:
1334cbb3ec25SBjoern A. Zeeb rate.bw = RATE_INFO_BW_80;
1335cbb3ec25SBjoern A. Zeeb stats->tx_bw[2]++;
1336cbb3ec25SBjoern A. Zeeb break;
1337cbb3ec25SBjoern A. Zeeb case IEEE80211_STA_RX_BW_40:
1338cbb3ec25SBjoern A. Zeeb rate.bw = RATE_INFO_BW_40;
1339cbb3ec25SBjoern A. Zeeb stats->tx_bw[1]++;
1340cbb3ec25SBjoern A. Zeeb break;
1341cbb3ec25SBjoern A. Zeeb default:
1342cbb3ec25SBjoern A. Zeeb rate.bw = RATE_INFO_BW_20;
1343cbb3ec25SBjoern A. Zeeb stats->tx_bw[0]++;
1344cbb3ec25SBjoern A. Zeeb break;
1345cbb3ec25SBjoern A. Zeeb }
1346cbb3ec25SBjoern A. Zeeb wcid->rate = rate;
1347cbb3ec25SBjoern A. Zeeb
1348cbb3ec25SBjoern A. Zeeb out:
1349*8ba4d145SBjoern A. Zeeb if (skb)
1350cbb3ec25SBjoern A. Zeeb mt76_tx_status_skb_done(mdev, skb, &list);
1351cbb3ec25SBjoern A. Zeeb mt76_tx_status_unlock(mdev, &list);
1352cbb3ec25SBjoern A. Zeeb
1353cbb3ec25SBjoern A. Zeeb return !!skb;
1354cbb3ec25SBjoern A. Zeeb }
1355cbb3ec25SBjoern A. Zeeb
mt7996_mac_add_txs(struct mt7996_dev * dev,void * data)1356cbb3ec25SBjoern A. Zeeb static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
1357cbb3ec25SBjoern A. Zeeb {
1358cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = NULL;
1359cbb3ec25SBjoern A. Zeeb struct mt76_wcid *wcid;
1360cbb3ec25SBjoern A. Zeeb __le32 *txs_data = data;
1361cbb3ec25SBjoern A. Zeeb u16 wcidx;
1362cbb3ec25SBjoern A. Zeeb u8 pid;
1363cbb3ec25SBjoern A. Zeeb
1364cbb3ec25SBjoern A. Zeeb wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
1365cbb3ec25SBjoern A. Zeeb pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
1366cbb3ec25SBjoern A. Zeeb
1367*8ba4d145SBjoern A. Zeeb if (pid < MT_PACKET_ID_NO_SKB)
1368cbb3ec25SBjoern A. Zeeb return;
1369cbb3ec25SBjoern A. Zeeb
1370cbb3ec25SBjoern A. Zeeb if (wcidx >= mt7996_wtbl_size(dev))
1371cbb3ec25SBjoern A. Zeeb return;
1372cbb3ec25SBjoern A. Zeeb
1373cbb3ec25SBjoern A. Zeeb rcu_read_lock();
1374cbb3ec25SBjoern A. Zeeb
1375cbb3ec25SBjoern A. Zeeb wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
1376cbb3ec25SBjoern A. Zeeb if (!wcid)
1377cbb3ec25SBjoern A. Zeeb goto out;
1378cbb3ec25SBjoern A. Zeeb
1379cbb3ec25SBjoern A. Zeeb msta = container_of(wcid, struct mt7996_sta, wcid);
1380cbb3ec25SBjoern A. Zeeb
1381cbb3ec25SBjoern A. Zeeb mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data);
1382cbb3ec25SBjoern A. Zeeb
1383cbb3ec25SBjoern A. Zeeb if (!wcid->sta)
1384cbb3ec25SBjoern A. Zeeb goto out;
1385cbb3ec25SBjoern A. Zeeb
1386*8ba4d145SBjoern A. Zeeb mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
1387cbb3ec25SBjoern A. Zeeb
1388cbb3ec25SBjoern A. Zeeb out:
1389cbb3ec25SBjoern A. Zeeb rcu_read_unlock();
1390cbb3ec25SBjoern A. Zeeb }
1391cbb3ec25SBjoern A. Zeeb
mt7996_rx_check(struct mt76_dev * mdev,void * data,int len)1392cbb3ec25SBjoern A. Zeeb bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len)
1393cbb3ec25SBjoern A. Zeeb {
1394cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
1395cbb3ec25SBjoern A. Zeeb __le32 *rxd = (__le32 *)data;
1396cbb3ec25SBjoern A. Zeeb __le32 *end = (__le32 *)&rxd[len / 4];
1397cbb3ec25SBjoern A. Zeeb enum rx_pkt_type type;
1398cbb3ec25SBjoern A. Zeeb
1399cbb3ec25SBjoern A. Zeeb type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
1400cbb3ec25SBjoern A. Zeeb if (type != PKT_TYPE_NORMAL) {
1401cbb3ec25SBjoern A. Zeeb u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK);
1402cbb3ec25SBjoern A. Zeeb
1403cbb3ec25SBjoern A. Zeeb if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) ==
1404cbb3ec25SBjoern A. Zeeb MT_RXD0_SW_PKT_TYPE_FRAME))
1405cbb3ec25SBjoern A. Zeeb return true;
1406cbb3ec25SBjoern A. Zeeb }
1407cbb3ec25SBjoern A. Zeeb
1408cbb3ec25SBjoern A. Zeeb switch (type) {
1409cbb3ec25SBjoern A. Zeeb case PKT_TYPE_TXRX_NOTIFY:
1410cbb3ec25SBjoern A. Zeeb mt7996_mac_tx_free(dev, data, len);
1411cbb3ec25SBjoern A. Zeeb return false;
1412cbb3ec25SBjoern A. Zeeb case PKT_TYPE_TXS:
1413cbb3ec25SBjoern A. Zeeb for (rxd += 4; rxd + 8 <= end; rxd += 8)
1414cbb3ec25SBjoern A. Zeeb mt7996_mac_add_txs(dev, rxd);
1415cbb3ec25SBjoern A. Zeeb return false;
1416cbb3ec25SBjoern A. Zeeb case PKT_TYPE_RX_FW_MONITOR:
1417*8ba4d145SBjoern A. Zeeb #if defined(CONFIG_MT7996_DEBUGFS)
1418cbb3ec25SBjoern A. Zeeb mt7996_debugfs_rx_fw_monitor(dev, data, len);
1419*8ba4d145SBjoern A. Zeeb #endif
1420cbb3ec25SBjoern A. Zeeb return false;
1421cbb3ec25SBjoern A. Zeeb default:
1422cbb3ec25SBjoern A. Zeeb return true;
1423cbb3ec25SBjoern A. Zeeb }
1424cbb3ec25SBjoern A. Zeeb }
1425cbb3ec25SBjoern A. Zeeb
mt7996_queue_rx_skb(struct mt76_dev * mdev,enum mt76_rxq_id q,struct sk_buff * skb,u32 * info)1426cbb3ec25SBjoern A. Zeeb void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
1427cbb3ec25SBjoern A. Zeeb struct sk_buff *skb, u32 *info)
1428cbb3ec25SBjoern A. Zeeb {
1429cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
1430cbb3ec25SBjoern A. Zeeb __le32 *rxd = (__le32 *)skb->data;
1431cbb3ec25SBjoern A. Zeeb __le32 *end = (__le32 *)&skb->data[skb->len];
1432cbb3ec25SBjoern A. Zeeb enum rx_pkt_type type;
1433cbb3ec25SBjoern A. Zeeb
1434cbb3ec25SBjoern A. Zeeb type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
1435cbb3ec25SBjoern A. Zeeb if (type != PKT_TYPE_NORMAL) {
1436cbb3ec25SBjoern A. Zeeb u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK);
1437cbb3ec25SBjoern A. Zeeb
1438cbb3ec25SBjoern A. Zeeb if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) ==
1439cbb3ec25SBjoern A. Zeeb MT_RXD0_SW_PKT_TYPE_FRAME))
1440cbb3ec25SBjoern A. Zeeb type = PKT_TYPE_NORMAL;
1441cbb3ec25SBjoern A. Zeeb }
1442cbb3ec25SBjoern A. Zeeb
1443cbb3ec25SBjoern A. Zeeb switch (type) {
1444cbb3ec25SBjoern A. Zeeb case PKT_TYPE_TXRX_NOTIFY:
1445*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2) &&
1446*8ba4d145SBjoern A. Zeeb q == MT_RXQ_TXFREE_BAND2) {
1447*8ba4d145SBjoern A. Zeeb dev_kfree_skb(skb);
1448*8ba4d145SBjoern A. Zeeb break;
1449*8ba4d145SBjoern A. Zeeb }
1450*8ba4d145SBjoern A. Zeeb
1451cbb3ec25SBjoern A. Zeeb mt7996_mac_tx_free(dev, skb->data, skb->len);
1452cbb3ec25SBjoern A. Zeeb napi_consume_skb(skb, 1);
1453cbb3ec25SBjoern A. Zeeb break;
1454cbb3ec25SBjoern A. Zeeb case PKT_TYPE_RX_EVENT:
1455cbb3ec25SBjoern A. Zeeb mt7996_mcu_rx_event(dev, skb);
1456cbb3ec25SBjoern A. Zeeb break;
1457cbb3ec25SBjoern A. Zeeb case PKT_TYPE_TXS:
1458cbb3ec25SBjoern A. Zeeb for (rxd += 4; rxd + 8 <= end; rxd += 8)
1459cbb3ec25SBjoern A. Zeeb mt7996_mac_add_txs(dev, rxd);
1460cbb3ec25SBjoern A. Zeeb dev_kfree_skb(skb);
1461cbb3ec25SBjoern A. Zeeb break;
1462cbb3ec25SBjoern A. Zeeb case PKT_TYPE_RX_FW_MONITOR:
1463*8ba4d145SBjoern A. Zeeb #if defined(CONFIG_MT7996_DEBUGFS)
1464cbb3ec25SBjoern A. Zeeb mt7996_debugfs_rx_fw_monitor(dev, skb->data, skb->len);
1465*8ba4d145SBjoern A. Zeeb #endif
1466cbb3ec25SBjoern A. Zeeb dev_kfree_skb(skb);
1467cbb3ec25SBjoern A. Zeeb break;
1468cbb3ec25SBjoern A. Zeeb case PKT_TYPE_NORMAL:
1469*8ba4d145SBjoern A. Zeeb if (!mt7996_mac_fill_rx(dev, q, skb, info)) {
1470cbb3ec25SBjoern A. Zeeb mt76_rx(&dev->mt76, q, skb);
1471cbb3ec25SBjoern A. Zeeb return;
1472cbb3ec25SBjoern A. Zeeb }
1473cbb3ec25SBjoern A. Zeeb fallthrough;
1474cbb3ec25SBjoern A. Zeeb default:
1475cbb3ec25SBjoern A. Zeeb dev_kfree_skb(skb);
1476cbb3ec25SBjoern A. Zeeb break;
1477cbb3ec25SBjoern A. Zeeb }
1478cbb3ec25SBjoern A. Zeeb }
1479cbb3ec25SBjoern A. Zeeb
mt7996_mac_cca_stats_reset(struct mt7996_phy * phy)1480cbb3ec25SBjoern A. Zeeb void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy)
1481cbb3ec25SBjoern A. Zeeb {
1482cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev;
1483cbb3ec25SBjoern A. Zeeb u32 reg = MT_WF_PHYRX_BAND_RX_CTRL1(phy->mt76->band_idx);
1484cbb3ec25SBjoern A. Zeeb
1485cbb3ec25SBjoern A. Zeeb mt76_clear(dev, reg, MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN);
1486cbb3ec25SBjoern A. Zeeb mt76_set(dev, reg, BIT(11) | BIT(9));
1487cbb3ec25SBjoern A. Zeeb }
1488cbb3ec25SBjoern A. Zeeb
mt7996_mac_reset_counters(struct mt7996_phy * phy)1489cbb3ec25SBjoern A. Zeeb void mt7996_mac_reset_counters(struct mt7996_phy *phy)
1490cbb3ec25SBjoern A. Zeeb {
1491cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev;
1492cbb3ec25SBjoern A. Zeeb u8 band_idx = phy->mt76->band_idx;
1493cbb3ec25SBjoern A. Zeeb int i;
1494cbb3ec25SBjoern A. Zeeb
1495cbb3ec25SBjoern A. Zeeb for (i = 0; i < 16; i++)
1496cbb3ec25SBjoern A. Zeeb mt76_rr(dev, MT_TX_AGG_CNT(band_idx, i));
1497cbb3ec25SBjoern A. Zeeb
1498cbb3ec25SBjoern A. Zeeb phy->mt76->survey_time = ktime_get_boottime();
1499cbb3ec25SBjoern A. Zeeb
1500cbb3ec25SBjoern A. Zeeb memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats));
1501cbb3ec25SBjoern A. Zeeb
1502cbb3ec25SBjoern A. Zeeb /* reset airtime counters */
1503cbb3ec25SBjoern A. Zeeb mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band_idx),
1504cbb3ec25SBjoern A. Zeeb MT_WF_RMAC_MIB_RXTIME_CLR);
1505cbb3ec25SBjoern A. Zeeb
1506cbb3ec25SBjoern A. Zeeb mt7996_mcu_get_chan_mib_info(phy, true);
1507cbb3ec25SBjoern A. Zeeb }
1508cbb3ec25SBjoern A. Zeeb
mt7996_mac_set_coverage_class(struct mt7996_phy * phy)1509cbb3ec25SBjoern A. Zeeb void mt7996_mac_set_coverage_class(struct mt7996_phy *phy)
1510cbb3ec25SBjoern A. Zeeb {
1511cbb3ec25SBjoern A. Zeeb s16 coverage_class = phy->coverage_class;
1512cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev;
1513cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy2 = mt7996_phy2(dev);
1514cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy3 = mt7996_phy3(dev);
1515cbb3ec25SBjoern A. Zeeb u32 reg_offset;
1516cbb3ec25SBjoern A. Zeeb u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
1517cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
1518cbb3ec25SBjoern A. Zeeb u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
1519cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
1520cbb3ec25SBjoern A. Zeeb u8 band_idx = phy->mt76->band_idx;
1521cbb3ec25SBjoern A. Zeeb int offset;
1522cbb3ec25SBjoern A. Zeeb
1523cbb3ec25SBjoern A. Zeeb if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
1524cbb3ec25SBjoern A. Zeeb return;
1525cbb3ec25SBjoern A. Zeeb
1526cbb3ec25SBjoern A. Zeeb if (phy2)
1527cbb3ec25SBjoern A. Zeeb coverage_class = max_t(s16, dev->phy.coverage_class,
1528cbb3ec25SBjoern A. Zeeb phy2->coverage_class);
1529cbb3ec25SBjoern A. Zeeb
1530cbb3ec25SBjoern A. Zeeb if (phy3)
1531cbb3ec25SBjoern A. Zeeb coverage_class = max_t(s16, coverage_class,
1532cbb3ec25SBjoern A. Zeeb phy3->coverage_class);
1533cbb3ec25SBjoern A. Zeeb
1534cbb3ec25SBjoern A. Zeeb offset = 3 * coverage_class;
1535cbb3ec25SBjoern A. Zeeb reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
1536cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
1537cbb3ec25SBjoern A. Zeeb
1538cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset);
1539cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset);
1540cbb3ec25SBjoern A. Zeeb }
1541cbb3ec25SBjoern A. Zeeb
mt7996_mac_enable_nf(struct mt7996_dev * dev,u8 band)1542cbb3ec25SBjoern A. Zeeb void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band)
1543cbb3ec25SBjoern A. Zeeb {
1544cbb3ec25SBjoern A. Zeeb mt76_set(dev, MT_WF_PHYRX_CSD_BAND_RXTD12(band),
1545cbb3ec25SBjoern A. Zeeb MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY |
1546cbb3ec25SBjoern A. Zeeb MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR);
1547cbb3ec25SBjoern A. Zeeb
1548cbb3ec25SBjoern A. Zeeb mt76_set(dev, MT_WF_PHYRX_BAND_RX_CTRL1(band),
1549cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN, 0x5));
1550cbb3ec25SBjoern A. Zeeb }
1551cbb3ec25SBjoern A. Zeeb
1552cbb3ec25SBjoern A. Zeeb static u8
mt7996_phy_get_nf(struct mt7996_phy * phy,u8 band_idx)1553cbb3ec25SBjoern A. Zeeb mt7996_phy_get_nf(struct mt7996_phy *phy, u8 band_idx)
1554cbb3ec25SBjoern A. Zeeb {
1555cbb3ec25SBjoern A. Zeeb static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 };
1556cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev;
1557cbb3ec25SBjoern A. Zeeb u32 val, sum = 0, n = 0;
1558cbb3ec25SBjoern A. Zeeb int ant, i;
1559cbb3ec25SBjoern A. Zeeb
1560cbb3ec25SBjoern A. Zeeb for (ant = 0; ant < hweight8(phy->mt76->antenna_mask); ant++) {
1561cbb3ec25SBjoern A. Zeeb u32 reg = MT_WF_PHYRX_CSD_IRPI(band_idx, ant);
1562cbb3ec25SBjoern A. Zeeb
1563cbb3ec25SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) {
1564cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, reg);
1565cbb3ec25SBjoern A. Zeeb sum += val * nf_power[i];
1566cbb3ec25SBjoern A. Zeeb n += val;
1567cbb3ec25SBjoern A. Zeeb }
1568cbb3ec25SBjoern A. Zeeb }
1569cbb3ec25SBjoern A. Zeeb
1570cbb3ec25SBjoern A. Zeeb return n ? sum / n : 0;
1571cbb3ec25SBjoern A. Zeeb }
1572cbb3ec25SBjoern A. Zeeb
mt7996_update_channel(struct mt76_phy * mphy)1573cbb3ec25SBjoern A. Zeeb void mt7996_update_channel(struct mt76_phy *mphy)
1574cbb3ec25SBjoern A. Zeeb {
1575*8ba4d145SBjoern A. Zeeb struct mt7996_phy *phy = mphy->priv;
1576cbb3ec25SBjoern A. Zeeb struct mt76_channel_state *state = mphy->chan_state;
1577cbb3ec25SBjoern A. Zeeb int nf;
1578cbb3ec25SBjoern A. Zeeb
1579cbb3ec25SBjoern A. Zeeb mt7996_mcu_get_chan_mib_info(phy, false);
1580cbb3ec25SBjoern A. Zeeb
1581cbb3ec25SBjoern A. Zeeb nf = mt7996_phy_get_nf(phy, mphy->band_idx);
1582cbb3ec25SBjoern A. Zeeb if (!phy->noise)
1583cbb3ec25SBjoern A. Zeeb phy->noise = nf << 4;
1584cbb3ec25SBjoern A. Zeeb else if (nf)
1585cbb3ec25SBjoern A. Zeeb phy->noise += nf - (phy->noise >> 4);
1586cbb3ec25SBjoern A. Zeeb
1587cbb3ec25SBjoern A. Zeeb state->noise = -(phy->noise >> 4);
1588cbb3ec25SBjoern A. Zeeb }
1589cbb3ec25SBjoern A. Zeeb
1590cbb3ec25SBjoern A. Zeeb static bool
mt7996_wait_reset_state(struct mt7996_dev * dev,u32 state)1591cbb3ec25SBjoern A. Zeeb mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state)
1592cbb3ec25SBjoern A. Zeeb {
1593cbb3ec25SBjoern A. Zeeb bool ret;
1594cbb3ec25SBjoern A. Zeeb
1595cbb3ec25SBjoern A. Zeeb ret = wait_event_timeout(dev->reset_wait,
1596cbb3ec25SBjoern A. Zeeb (READ_ONCE(dev->recovery.state) & state),
1597cbb3ec25SBjoern A. Zeeb MT7996_RESET_TIMEOUT);
1598cbb3ec25SBjoern A. Zeeb
1599cbb3ec25SBjoern A. Zeeb WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
1600cbb3ec25SBjoern A. Zeeb return ret;
1601cbb3ec25SBjoern A. Zeeb }
1602cbb3ec25SBjoern A. Zeeb
1603cbb3ec25SBjoern A. Zeeb static void
mt7996_update_vif_beacon(void * priv,u8 * mac,struct ieee80211_vif * vif)1604cbb3ec25SBjoern A. Zeeb mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
1605cbb3ec25SBjoern A. Zeeb {
1606cbb3ec25SBjoern A. Zeeb struct ieee80211_hw *hw = priv;
1607cbb3ec25SBjoern A. Zeeb
1608cbb3ec25SBjoern A. Zeeb switch (vif->type) {
1609cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT:
1610cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_ADHOC:
1611cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_AP:
1612*8ba4d145SBjoern A. Zeeb mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf);
1613cbb3ec25SBjoern A. Zeeb break;
1614cbb3ec25SBjoern A. Zeeb default:
1615cbb3ec25SBjoern A. Zeeb break;
1616cbb3ec25SBjoern A. Zeeb }
1617cbb3ec25SBjoern A. Zeeb }
1618cbb3ec25SBjoern A. Zeeb
1619cbb3ec25SBjoern A. Zeeb static void
mt7996_update_beacons(struct mt7996_dev * dev)1620cbb3ec25SBjoern A. Zeeb mt7996_update_beacons(struct mt7996_dev *dev)
1621cbb3ec25SBjoern A. Zeeb {
1622cbb3ec25SBjoern A. Zeeb struct mt76_phy *phy2, *phy3;
1623cbb3ec25SBjoern A. Zeeb
1624cbb3ec25SBjoern A. Zeeb ieee80211_iterate_active_interfaces(dev->mt76.hw,
1625cbb3ec25SBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL,
1626cbb3ec25SBjoern A. Zeeb mt7996_update_vif_beacon, dev->mt76.hw);
1627cbb3ec25SBjoern A. Zeeb
1628cbb3ec25SBjoern A. Zeeb phy2 = dev->mt76.phys[MT_BAND1];
1629cbb3ec25SBjoern A. Zeeb if (!phy2)
1630cbb3ec25SBjoern A. Zeeb return;
1631cbb3ec25SBjoern A. Zeeb
1632cbb3ec25SBjoern A. Zeeb ieee80211_iterate_active_interfaces(phy2->hw,
1633cbb3ec25SBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL,
1634cbb3ec25SBjoern A. Zeeb mt7996_update_vif_beacon, phy2->hw);
1635cbb3ec25SBjoern A. Zeeb
1636cbb3ec25SBjoern A. Zeeb phy3 = dev->mt76.phys[MT_BAND2];
1637cbb3ec25SBjoern A. Zeeb if (!phy3)
1638cbb3ec25SBjoern A. Zeeb return;
1639cbb3ec25SBjoern A. Zeeb
1640cbb3ec25SBjoern A. Zeeb ieee80211_iterate_active_interfaces(phy3->hw,
1641cbb3ec25SBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL,
1642cbb3ec25SBjoern A. Zeeb mt7996_update_vif_beacon, phy3->hw);
1643cbb3ec25SBjoern A. Zeeb }
1644cbb3ec25SBjoern A. Zeeb
mt7996_tx_token_put(struct mt7996_dev * dev)1645cbb3ec25SBjoern A. Zeeb void mt7996_tx_token_put(struct mt7996_dev *dev)
1646cbb3ec25SBjoern A. Zeeb {
1647cbb3ec25SBjoern A. Zeeb struct mt76_txwi_cache *txwi;
1648cbb3ec25SBjoern A. Zeeb int id;
1649cbb3ec25SBjoern A. Zeeb
1650cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.token_lock);
1651cbb3ec25SBjoern A. Zeeb idr_for_each_entry(&dev->mt76.token, txwi, id) {
1652cbb3ec25SBjoern A. Zeeb mt7996_txwi_free(dev, txwi, NULL, NULL);
1653cbb3ec25SBjoern A. Zeeb dev->mt76.token_count--;
1654cbb3ec25SBjoern A. Zeeb }
1655cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.token_lock);
1656cbb3ec25SBjoern A. Zeeb idr_destroy(&dev->mt76.token);
1657cbb3ec25SBjoern A. Zeeb }
1658cbb3ec25SBjoern A. Zeeb
1659cbb3ec25SBjoern A. Zeeb static int
mt7996_mac_restart(struct mt7996_dev * dev)1660cbb3ec25SBjoern A. Zeeb mt7996_mac_restart(struct mt7996_dev *dev)
1661cbb3ec25SBjoern A. Zeeb {
1662cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy2, *phy3;
1663cbb3ec25SBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76;
1664cbb3ec25SBjoern A. Zeeb int i, ret;
1665cbb3ec25SBjoern A. Zeeb
1666cbb3ec25SBjoern A. Zeeb phy2 = mt7996_phy2(dev);
1667cbb3ec25SBjoern A. Zeeb phy3 = mt7996_phy3(dev);
1668cbb3ec25SBjoern A. Zeeb
1669cbb3ec25SBjoern A. Zeeb if (dev->hif2) {
1670cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
1671cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
1672cbb3ec25SBjoern A. Zeeb }
1673cbb3ec25SBjoern A. Zeeb
1674cbb3ec25SBjoern A. Zeeb if (dev_is_pci(mdev->dev)) {
1675cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
1676cbb3ec25SBjoern A. Zeeb if (dev->hif2)
1677cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
1678cbb3ec25SBjoern A. Zeeb }
1679cbb3ec25SBjoern A. Zeeb
1680cbb3ec25SBjoern A. Zeeb set_bit(MT76_RESET, &dev->mphy.state);
1681cbb3ec25SBjoern A. Zeeb set_bit(MT76_MCU_RESET, &dev->mphy.state);
1682cbb3ec25SBjoern A. Zeeb wake_up(&dev->mt76.mcu.wait);
1683*8ba4d145SBjoern A. Zeeb if (phy2)
1684cbb3ec25SBjoern A. Zeeb set_bit(MT76_RESET, &phy2->mt76->state);
1685*8ba4d145SBjoern A. Zeeb if (phy3)
1686cbb3ec25SBjoern A. Zeeb set_bit(MT76_RESET, &phy3->mt76->state);
1687cbb3ec25SBjoern A. Zeeb
1688cbb3ec25SBjoern A. Zeeb /* lock/unlock all queues to ensure that no tx is pending */
1689cbb3ec25SBjoern A. Zeeb mt76_txq_schedule_all(&dev->mphy);
1690cbb3ec25SBjoern A. Zeeb if (phy2)
1691cbb3ec25SBjoern A. Zeeb mt76_txq_schedule_all(phy2->mt76);
1692cbb3ec25SBjoern A. Zeeb if (phy3)
1693cbb3ec25SBjoern A. Zeeb mt76_txq_schedule_all(phy3->mt76);
1694cbb3ec25SBjoern A. Zeeb
1695cbb3ec25SBjoern A. Zeeb /* disable all tx/rx napi */
1696cbb3ec25SBjoern A. Zeeb mt76_worker_disable(&dev->mt76.tx_worker);
1697cbb3ec25SBjoern A. Zeeb mt76_for_each_q_rx(mdev, i) {
1698*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
1699*8ba4d145SBjoern A. Zeeb mt76_queue_is_wed_rro(&mdev->q_rx[i]))
1700*8ba4d145SBjoern A. Zeeb continue;
1701*8ba4d145SBjoern A. Zeeb
1702cbb3ec25SBjoern A. Zeeb if (mdev->q_rx[i].ndesc)
1703cbb3ec25SBjoern A. Zeeb napi_disable(&dev->mt76.napi[i]);
1704cbb3ec25SBjoern A. Zeeb }
1705cbb3ec25SBjoern A. Zeeb napi_disable(&dev->mt76.tx_napi);
1706cbb3ec25SBjoern A. Zeeb
1707cbb3ec25SBjoern A. Zeeb /* token reinit */
1708cbb3ec25SBjoern A. Zeeb mt7996_tx_token_put(dev);
1709cbb3ec25SBjoern A. Zeeb idr_init(&dev->mt76.token);
1710cbb3ec25SBjoern A. Zeeb
1711cbb3ec25SBjoern A. Zeeb mt7996_dma_reset(dev, true);
1712cbb3ec25SBjoern A. Zeeb
1713cbb3ec25SBjoern A. Zeeb mt76_for_each_q_rx(mdev, i) {
1714*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
1715*8ba4d145SBjoern A. Zeeb mt76_queue_is_wed_rro(&mdev->q_rx[i]))
1716*8ba4d145SBjoern A. Zeeb continue;
1717*8ba4d145SBjoern A. Zeeb
1718cbb3ec25SBjoern A. Zeeb if (mdev->q_rx[i].ndesc) {
1719cbb3ec25SBjoern A. Zeeb napi_enable(&dev->mt76.napi[i]);
1720*8ba4d145SBjoern A. Zeeb local_bh_disable();
1721cbb3ec25SBjoern A. Zeeb napi_schedule(&dev->mt76.napi[i]);
1722cbb3ec25SBjoern A. Zeeb local_bh_enable();
1723*8ba4d145SBjoern A. Zeeb }
1724*8ba4d145SBjoern A. Zeeb }
1725cbb3ec25SBjoern A. Zeeb clear_bit(MT76_MCU_RESET, &dev->mphy.state);
1726cbb3ec25SBjoern A. Zeeb clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
1727cbb3ec25SBjoern A. Zeeb
1728cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
1729cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
1730cbb3ec25SBjoern A. Zeeb if (dev->hif2) {
1731cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask);
1732cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
1733cbb3ec25SBjoern A. Zeeb }
1734cbb3ec25SBjoern A. Zeeb if (dev_is_pci(mdev->dev)) {
1735cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
1736cbb3ec25SBjoern A. Zeeb if (dev->hif2)
1737cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
1738cbb3ec25SBjoern A. Zeeb }
1739cbb3ec25SBjoern A. Zeeb
1740cbb3ec25SBjoern A. Zeeb /* load firmware */
1741cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_init_firmware(dev);
1742cbb3ec25SBjoern A. Zeeb if (ret)
1743cbb3ec25SBjoern A. Zeeb goto out;
1744cbb3ec25SBjoern A. Zeeb
1745cbb3ec25SBjoern A. Zeeb /* set the necessary init items */
1746cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_set_eeprom(dev);
1747cbb3ec25SBjoern A. Zeeb if (ret)
1748cbb3ec25SBjoern A. Zeeb goto out;
1749cbb3ec25SBjoern A. Zeeb
1750cbb3ec25SBjoern A. Zeeb mt7996_mac_init(dev);
1751*8ba4d145SBjoern A. Zeeb mt7996_init_txpower(&dev->phy);
1752*8ba4d145SBjoern A. Zeeb mt7996_init_txpower(phy2);
1753*8ba4d145SBjoern A. Zeeb mt7996_init_txpower(phy3);
1754cbb3ec25SBjoern A. Zeeb ret = mt7996_txbf_init(dev);
1755cbb3ec25SBjoern A. Zeeb
1756cbb3ec25SBjoern A. Zeeb if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
1757*8ba4d145SBjoern A. Zeeb ret = mt7996_run(&dev->phy);
1758cbb3ec25SBjoern A. Zeeb if (ret)
1759cbb3ec25SBjoern A. Zeeb goto out;
1760cbb3ec25SBjoern A. Zeeb }
1761cbb3ec25SBjoern A. Zeeb
1762cbb3ec25SBjoern A. Zeeb if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) {
1763*8ba4d145SBjoern A. Zeeb ret = mt7996_run(phy2);
1764cbb3ec25SBjoern A. Zeeb if (ret)
1765cbb3ec25SBjoern A. Zeeb goto out;
1766cbb3ec25SBjoern A. Zeeb }
1767cbb3ec25SBjoern A. Zeeb
1768cbb3ec25SBjoern A. Zeeb if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) {
1769*8ba4d145SBjoern A. Zeeb ret = mt7996_run(phy3);
1770cbb3ec25SBjoern A. Zeeb if (ret)
1771cbb3ec25SBjoern A. Zeeb goto out;
1772cbb3ec25SBjoern A. Zeeb }
1773cbb3ec25SBjoern A. Zeeb
1774cbb3ec25SBjoern A. Zeeb out:
1775cbb3ec25SBjoern A. Zeeb /* reset done */
1776cbb3ec25SBjoern A. Zeeb clear_bit(MT76_RESET, &dev->mphy.state);
1777cbb3ec25SBjoern A. Zeeb if (phy2)
1778cbb3ec25SBjoern A. Zeeb clear_bit(MT76_RESET, &phy2->mt76->state);
1779cbb3ec25SBjoern A. Zeeb if (phy3)
1780cbb3ec25SBjoern A. Zeeb clear_bit(MT76_RESET, &phy3->mt76->state);
1781cbb3ec25SBjoern A. Zeeb
1782cbb3ec25SBjoern A. Zeeb napi_enable(&dev->mt76.tx_napi);
1783*8ba4d145SBjoern A. Zeeb local_bh_disable();
1784cbb3ec25SBjoern A. Zeeb napi_schedule(&dev->mt76.tx_napi);
1785cbb3ec25SBjoern A. Zeeb local_bh_enable();
1786cbb3ec25SBjoern A. Zeeb
1787cbb3ec25SBjoern A. Zeeb mt76_worker_enable(&dev->mt76.tx_worker);
1788cbb3ec25SBjoern A. Zeeb return ret;
1789cbb3ec25SBjoern A. Zeeb }
1790cbb3ec25SBjoern A. Zeeb
1791cbb3ec25SBjoern A. Zeeb static void
mt7996_mac_full_reset(struct mt7996_dev * dev)1792cbb3ec25SBjoern A. Zeeb mt7996_mac_full_reset(struct mt7996_dev *dev)
1793cbb3ec25SBjoern A. Zeeb {
1794cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy2, *phy3;
1795cbb3ec25SBjoern A. Zeeb int i;
1796cbb3ec25SBjoern A. Zeeb
1797cbb3ec25SBjoern A. Zeeb phy2 = mt7996_phy2(dev);
1798cbb3ec25SBjoern A. Zeeb phy3 = mt7996_phy3(dev);
1799cbb3ec25SBjoern A. Zeeb dev->recovery.hw_full_reset = true;
1800cbb3ec25SBjoern A. Zeeb
1801cbb3ec25SBjoern A. Zeeb wake_up(&dev->mt76.mcu.wait);
1802cbb3ec25SBjoern A. Zeeb ieee80211_stop_queues(mt76_hw(dev));
1803cbb3ec25SBjoern A. Zeeb if (phy2)
1804cbb3ec25SBjoern A. Zeeb ieee80211_stop_queues(phy2->mt76->hw);
1805cbb3ec25SBjoern A. Zeeb if (phy3)
1806cbb3ec25SBjoern A. Zeeb ieee80211_stop_queues(phy3->mt76->hw);
1807cbb3ec25SBjoern A. Zeeb
1808*8ba4d145SBjoern A. Zeeb cancel_work_sync(&dev->wed_rro.work);
1809cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&dev->mphy.mac_work);
1810cbb3ec25SBjoern A. Zeeb if (phy2)
1811cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&phy2->mt76->mac_work);
1812cbb3ec25SBjoern A. Zeeb if (phy3)
1813cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&phy3->mt76->mac_work);
1814cbb3ec25SBjoern A. Zeeb
1815cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
1816cbb3ec25SBjoern A. Zeeb for (i = 0; i < 10; i++) {
1817cbb3ec25SBjoern A. Zeeb if (!mt7996_mac_restart(dev))
1818cbb3ec25SBjoern A. Zeeb break;
1819cbb3ec25SBjoern A. Zeeb }
1820cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
1821cbb3ec25SBjoern A. Zeeb
1822cbb3ec25SBjoern A. Zeeb if (i == 10)
1823cbb3ec25SBjoern A. Zeeb dev_err(dev->mt76.dev, "chip full reset failed\n");
1824cbb3ec25SBjoern A. Zeeb
1825cbb3ec25SBjoern A. Zeeb ieee80211_restart_hw(mt76_hw(dev));
1826cbb3ec25SBjoern A. Zeeb if (phy2)
1827cbb3ec25SBjoern A. Zeeb ieee80211_restart_hw(phy2->mt76->hw);
1828cbb3ec25SBjoern A. Zeeb if (phy3)
1829cbb3ec25SBjoern A. Zeeb ieee80211_restart_hw(phy3->mt76->hw);
1830cbb3ec25SBjoern A. Zeeb
1831cbb3ec25SBjoern A. Zeeb ieee80211_wake_queues(mt76_hw(dev));
1832cbb3ec25SBjoern A. Zeeb if (phy2)
1833cbb3ec25SBjoern A. Zeeb ieee80211_wake_queues(phy2->mt76->hw);
1834cbb3ec25SBjoern A. Zeeb if (phy3)
1835cbb3ec25SBjoern A. Zeeb ieee80211_wake_queues(phy3->mt76->hw);
1836cbb3ec25SBjoern A. Zeeb
1837cbb3ec25SBjoern A. Zeeb dev->recovery.hw_full_reset = false;
1838cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(mt76_hw(dev),
1839cbb3ec25SBjoern A. Zeeb &dev->mphy.mac_work,
1840cbb3ec25SBjoern A. Zeeb MT7996_WATCHDOG_TIME);
1841cbb3ec25SBjoern A. Zeeb if (phy2)
1842cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(phy2->mt76->hw,
1843cbb3ec25SBjoern A. Zeeb &phy2->mt76->mac_work,
1844cbb3ec25SBjoern A. Zeeb MT7996_WATCHDOG_TIME);
1845cbb3ec25SBjoern A. Zeeb if (phy3)
1846cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(phy3->mt76->hw,
1847cbb3ec25SBjoern A. Zeeb &phy3->mt76->mac_work,
1848cbb3ec25SBjoern A. Zeeb MT7996_WATCHDOG_TIME);
1849cbb3ec25SBjoern A. Zeeb }
1850cbb3ec25SBjoern A. Zeeb
mt7996_mac_reset_work(struct work_struct * work)1851cbb3ec25SBjoern A. Zeeb void mt7996_mac_reset_work(struct work_struct *work)
1852cbb3ec25SBjoern A. Zeeb {
1853cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy2, *phy3;
1854cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev;
1855cbb3ec25SBjoern A. Zeeb int i;
1856cbb3ec25SBjoern A. Zeeb
1857cbb3ec25SBjoern A. Zeeb dev = container_of(work, struct mt7996_dev, reset_work);
1858cbb3ec25SBjoern A. Zeeb phy2 = mt7996_phy2(dev);
1859cbb3ec25SBjoern A. Zeeb phy3 = mt7996_phy3(dev);
1860cbb3ec25SBjoern A. Zeeb
1861cbb3ec25SBjoern A. Zeeb /* chip full reset */
1862cbb3ec25SBjoern A. Zeeb if (dev->recovery.restart) {
1863cbb3ec25SBjoern A. Zeeb /* disable WA/WM WDT */
1864cbb3ec25SBjoern A. Zeeb mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA,
1865cbb3ec25SBjoern A. Zeeb MT_MCU_CMD_WDT_MASK);
1866cbb3ec25SBjoern A. Zeeb
1867cbb3ec25SBjoern A. Zeeb if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
1868cbb3ec25SBjoern A. Zeeb dev->recovery.wa_reset_count++;
1869cbb3ec25SBjoern A. Zeeb else
1870cbb3ec25SBjoern A. Zeeb dev->recovery.wm_reset_count++;
1871cbb3ec25SBjoern A. Zeeb
1872cbb3ec25SBjoern A. Zeeb mt7996_mac_full_reset(dev);
1873cbb3ec25SBjoern A. Zeeb
1874cbb3ec25SBjoern A. Zeeb /* enable mcu irq */
1875cbb3ec25SBjoern A. Zeeb mt7996_irq_enable(dev, MT_INT_MCU_CMD);
1876cbb3ec25SBjoern A. Zeeb mt7996_irq_disable(dev, 0);
1877cbb3ec25SBjoern A. Zeeb
1878cbb3ec25SBjoern A. Zeeb /* enable WA/WM WDT */
1879cbb3ec25SBjoern A. Zeeb mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
1880cbb3ec25SBjoern A. Zeeb
1881cbb3ec25SBjoern A. Zeeb dev->recovery.state = MT_MCU_CMD_NORMAL_STATE;
1882cbb3ec25SBjoern A. Zeeb dev->recovery.restart = false;
1883cbb3ec25SBjoern A. Zeeb return;
1884cbb3ec25SBjoern A. Zeeb }
1885cbb3ec25SBjoern A. Zeeb
1886cbb3ec25SBjoern A. Zeeb if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
1887cbb3ec25SBjoern A. Zeeb return;
1888cbb3ec25SBjoern A. Zeeb
1889cbb3ec25SBjoern A. Zeeb dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
1890cbb3ec25SBjoern A. Zeeb wiphy_name(dev->mt76.hw->wiphy));
1891*8ba4d145SBjoern A. Zeeb
1892*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
1893*8ba4d145SBjoern A. Zeeb mtk_wed_device_stop(&dev->mt76.mmio.wed_hif2);
1894*8ba4d145SBjoern A. Zeeb
1895*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed))
1896*8ba4d145SBjoern A. Zeeb mtk_wed_device_stop(&dev->mt76.mmio.wed);
1897*8ba4d145SBjoern A. Zeeb
1898cbb3ec25SBjoern A. Zeeb ieee80211_stop_queues(mt76_hw(dev));
1899cbb3ec25SBjoern A. Zeeb if (phy2)
1900cbb3ec25SBjoern A. Zeeb ieee80211_stop_queues(phy2->mt76->hw);
1901cbb3ec25SBjoern A. Zeeb if (phy3)
1902cbb3ec25SBjoern A. Zeeb ieee80211_stop_queues(phy3->mt76->hw);
1903cbb3ec25SBjoern A. Zeeb
1904cbb3ec25SBjoern A. Zeeb set_bit(MT76_RESET, &dev->mphy.state);
1905cbb3ec25SBjoern A. Zeeb set_bit(MT76_MCU_RESET, &dev->mphy.state);
1906cbb3ec25SBjoern A. Zeeb wake_up(&dev->mt76.mcu.wait);
1907*8ba4d145SBjoern A. Zeeb
1908*8ba4d145SBjoern A. Zeeb cancel_work_sync(&dev->wed_rro.work);
1909cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&dev->mphy.mac_work);
1910cbb3ec25SBjoern A. Zeeb if (phy2) {
1911cbb3ec25SBjoern A. Zeeb set_bit(MT76_RESET, &phy2->mt76->state);
1912cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&phy2->mt76->mac_work);
1913cbb3ec25SBjoern A. Zeeb }
1914cbb3ec25SBjoern A. Zeeb if (phy3) {
1915cbb3ec25SBjoern A. Zeeb set_bit(MT76_RESET, &phy3->mt76->state);
1916cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&phy3->mt76->mac_work);
1917cbb3ec25SBjoern A. Zeeb }
1918cbb3ec25SBjoern A. Zeeb mt76_worker_disable(&dev->mt76.tx_worker);
1919*8ba4d145SBjoern A. Zeeb mt76_for_each_q_rx(&dev->mt76, i) {
1920*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
1921*8ba4d145SBjoern A. Zeeb mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
1922*8ba4d145SBjoern A. Zeeb continue;
1923*8ba4d145SBjoern A. Zeeb
1924cbb3ec25SBjoern A. Zeeb napi_disable(&dev->mt76.napi[i]);
1925*8ba4d145SBjoern A. Zeeb }
1926cbb3ec25SBjoern A. Zeeb napi_disable(&dev->mt76.tx_napi);
1927cbb3ec25SBjoern A. Zeeb
1928cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
1929cbb3ec25SBjoern A. Zeeb
1930cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
1931cbb3ec25SBjoern A. Zeeb
1932cbb3ec25SBjoern A. Zeeb if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
1933cbb3ec25SBjoern A. Zeeb mt7996_dma_reset(dev, false);
1934cbb3ec25SBjoern A. Zeeb
1935cbb3ec25SBjoern A. Zeeb mt7996_tx_token_put(dev);
1936cbb3ec25SBjoern A. Zeeb idr_init(&dev->mt76.token);
1937cbb3ec25SBjoern A. Zeeb
1938cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT);
1939cbb3ec25SBjoern A. Zeeb mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
1940cbb3ec25SBjoern A. Zeeb }
1941cbb3ec25SBjoern A. Zeeb
1942cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
1943cbb3ec25SBjoern A. Zeeb mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
1944cbb3ec25SBjoern A. Zeeb
1945cbb3ec25SBjoern A. Zeeb /* enable DMA Tx/Tx and interrupt */
1946*8ba4d145SBjoern A. Zeeb mt7996_dma_start(dev, false, false);
1947*8ba4d145SBjoern A. Zeeb
1948*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
1949*8ba4d145SBjoern A. Zeeb u32 wed_irq_mask = MT_INT_RRO_RX_DONE | MT_INT_TX_DONE_BAND2 |
1950*8ba4d145SBjoern A. Zeeb dev->mt76.mmio.irqmask;
1951*8ba4d145SBjoern A. Zeeb
1952*8ba4d145SBjoern A. Zeeb if (mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
1953*8ba4d145SBjoern A. Zeeb wed_irq_mask &= ~MT_INT_RX_DONE_RRO_IND;
1954*8ba4d145SBjoern A. Zeeb
1955*8ba4d145SBjoern A. Zeeb mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
1956*8ba4d145SBjoern A. Zeeb
1957*8ba4d145SBjoern A. Zeeb mtk_wed_device_start_hw_rro(&dev->mt76.mmio.wed, wed_irq_mask,
1958*8ba4d145SBjoern A. Zeeb true);
1959*8ba4d145SBjoern A. Zeeb mt7996_irq_enable(dev, wed_irq_mask);
1960*8ba4d145SBjoern A. Zeeb mt7996_irq_disable(dev, 0);
1961*8ba4d145SBjoern A. Zeeb }
1962*8ba4d145SBjoern A. Zeeb
1963*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) {
1964*8ba4d145SBjoern A. Zeeb mt76_wr(dev, MT_INT_PCIE1_MASK_CSR, MT_INT_TX_RX_DONE_EXT);
1965*8ba4d145SBjoern A. Zeeb mtk_wed_device_start(&dev->mt76.mmio.wed_hif2,
1966*8ba4d145SBjoern A. Zeeb MT_INT_TX_RX_DONE_EXT);
1967*8ba4d145SBjoern A. Zeeb }
1968cbb3ec25SBjoern A. Zeeb
1969cbb3ec25SBjoern A. Zeeb clear_bit(MT76_MCU_RESET, &dev->mphy.state);
1970cbb3ec25SBjoern A. Zeeb clear_bit(MT76_RESET, &dev->mphy.state);
1971cbb3ec25SBjoern A. Zeeb if (phy2)
1972cbb3ec25SBjoern A. Zeeb clear_bit(MT76_RESET, &phy2->mt76->state);
1973cbb3ec25SBjoern A. Zeeb if (phy3)
1974cbb3ec25SBjoern A. Zeeb clear_bit(MT76_RESET, &phy3->mt76->state);
1975cbb3ec25SBjoern A. Zeeb
1976cbb3ec25SBjoern A. Zeeb mt76_for_each_q_rx(&dev->mt76, i) {
1977*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
1978*8ba4d145SBjoern A. Zeeb mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
1979*8ba4d145SBjoern A. Zeeb continue;
1980*8ba4d145SBjoern A. Zeeb
1981cbb3ec25SBjoern A. Zeeb napi_enable(&dev->mt76.napi[i]);
1982*8ba4d145SBjoern A. Zeeb local_bh_disable();
1983cbb3ec25SBjoern A. Zeeb napi_schedule(&dev->mt76.napi[i]);
1984cbb3ec25SBjoern A. Zeeb local_bh_enable();
1985*8ba4d145SBjoern A. Zeeb }
1986cbb3ec25SBjoern A. Zeeb
1987cbb3ec25SBjoern A. Zeeb tasklet_schedule(&dev->mt76.irq_tasklet);
1988cbb3ec25SBjoern A. Zeeb
1989cbb3ec25SBjoern A. Zeeb mt76_worker_enable(&dev->mt76.tx_worker);
1990cbb3ec25SBjoern A. Zeeb
1991cbb3ec25SBjoern A. Zeeb napi_enable(&dev->mt76.tx_napi);
1992*8ba4d145SBjoern A. Zeeb local_bh_disable();
1993cbb3ec25SBjoern A. Zeeb napi_schedule(&dev->mt76.tx_napi);
1994cbb3ec25SBjoern A. Zeeb local_bh_enable();
1995cbb3ec25SBjoern A. Zeeb
1996cbb3ec25SBjoern A. Zeeb ieee80211_wake_queues(mt76_hw(dev));
1997cbb3ec25SBjoern A. Zeeb if (phy2)
1998cbb3ec25SBjoern A. Zeeb ieee80211_wake_queues(phy2->mt76->hw);
1999cbb3ec25SBjoern A. Zeeb if (phy3)
2000cbb3ec25SBjoern A. Zeeb ieee80211_wake_queues(phy3->mt76->hw);
2001cbb3ec25SBjoern A. Zeeb
2002cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
2003cbb3ec25SBjoern A. Zeeb
2004cbb3ec25SBjoern A. Zeeb mt7996_update_beacons(dev);
2005cbb3ec25SBjoern A. Zeeb
2006cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
2007cbb3ec25SBjoern A. Zeeb MT7996_WATCHDOG_TIME);
2008cbb3ec25SBjoern A. Zeeb if (phy2)
2009cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(phy2->mt76->hw,
2010cbb3ec25SBjoern A. Zeeb &phy2->mt76->mac_work,
2011cbb3ec25SBjoern A. Zeeb MT7996_WATCHDOG_TIME);
2012cbb3ec25SBjoern A. Zeeb if (phy3)
2013cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(phy3->mt76->hw,
2014cbb3ec25SBjoern A. Zeeb &phy3->mt76->mac_work,
2015cbb3ec25SBjoern A. Zeeb MT7996_WATCHDOG_TIME);
2016cbb3ec25SBjoern A. Zeeb dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.",
2017cbb3ec25SBjoern A. Zeeb wiphy_name(dev->mt76.hw->wiphy));
2018cbb3ec25SBjoern A. Zeeb }
2019cbb3ec25SBjoern A. Zeeb
2020cbb3ec25SBjoern A. Zeeb /* firmware coredump */
mt7996_mac_dump_work(struct work_struct * work)2021cbb3ec25SBjoern A. Zeeb void mt7996_mac_dump_work(struct work_struct *work)
2022cbb3ec25SBjoern A. Zeeb {
2023cbb3ec25SBjoern A. Zeeb const struct mt7996_mem_region *mem_region;
2024cbb3ec25SBjoern A. Zeeb struct mt7996_crash_data *crash_data;
2025cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev;
2026cbb3ec25SBjoern A. Zeeb struct mt7996_mem_hdr *hdr;
2027cbb3ec25SBjoern A. Zeeb size_t buf_len;
2028cbb3ec25SBjoern A. Zeeb int i;
2029cbb3ec25SBjoern A. Zeeb u32 num;
2030cbb3ec25SBjoern A. Zeeb u8 *buf;
2031cbb3ec25SBjoern A. Zeeb
2032cbb3ec25SBjoern A. Zeeb dev = container_of(work, struct mt7996_dev, dump_work);
2033cbb3ec25SBjoern A. Zeeb
2034cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->dump_mutex);
2035cbb3ec25SBjoern A. Zeeb
2036cbb3ec25SBjoern A. Zeeb crash_data = mt7996_coredump_new(dev);
2037cbb3ec25SBjoern A. Zeeb if (!crash_data) {
2038cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->dump_mutex);
2039cbb3ec25SBjoern A. Zeeb goto skip_coredump;
2040cbb3ec25SBjoern A. Zeeb }
2041cbb3ec25SBjoern A. Zeeb
2042cbb3ec25SBjoern A. Zeeb mem_region = mt7996_coredump_get_mem_layout(dev, &num);
2043cbb3ec25SBjoern A. Zeeb if (!mem_region || !crash_data->memdump_buf_len) {
2044cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->dump_mutex);
2045cbb3ec25SBjoern A. Zeeb goto skip_memdump;
2046cbb3ec25SBjoern A. Zeeb }
2047cbb3ec25SBjoern A. Zeeb
2048cbb3ec25SBjoern A. Zeeb buf = crash_data->memdump_buf;
2049cbb3ec25SBjoern A. Zeeb buf_len = crash_data->memdump_buf_len;
2050cbb3ec25SBjoern A. Zeeb
2051cbb3ec25SBjoern A. Zeeb /* dumping memory content... */
2052cbb3ec25SBjoern A. Zeeb memset(buf, 0, buf_len);
2053cbb3ec25SBjoern A. Zeeb for (i = 0; i < num; i++) {
2054cbb3ec25SBjoern A. Zeeb if (mem_region->len > buf_len) {
2055cbb3ec25SBjoern A. Zeeb dev_warn(dev->mt76.dev, "%s len %zu is too large\n",
2056cbb3ec25SBjoern A. Zeeb mem_region->name, mem_region->len);
2057cbb3ec25SBjoern A. Zeeb break;
2058cbb3ec25SBjoern A. Zeeb }
2059cbb3ec25SBjoern A. Zeeb
2060cbb3ec25SBjoern A. Zeeb /* reserve space for the header */
2061cbb3ec25SBjoern A. Zeeb hdr = (void *)buf;
2062cbb3ec25SBjoern A. Zeeb buf += sizeof(*hdr);
2063cbb3ec25SBjoern A. Zeeb buf_len -= sizeof(*hdr);
2064cbb3ec25SBjoern A. Zeeb
2065cbb3ec25SBjoern A. Zeeb mt7996_memcpy_fromio(dev, buf, mem_region->start,
2066cbb3ec25SBjoern A. Zeeb mem_region->len);
2067cbb3ec25SBjoern A. Zeeb
2068cbb3ec25SBjoern A. Zeeb hdr->start = mem_region->start;
2069cbb3ec25SBjoern A. Zeeb hdr->len = mem_region->len;
2070cbb3ec25SBjoern A. Zeeb
2071cbb3ec25SBjoern A. Zeeb if (!mem_region->len)
2072cbb3ec25SBjoern A. Zeeb /* note: the header remains, just with zero length */
2073cbb3ec25SBjoern A. Zeeb break;
2074cbb3ec25SBjoern A. Zeeb
2075cbb3ec25SBjoern A. Zeeb buf += mem_region->len;
2076cbb3ec25SBjoern A. Zeeb buf_len -= mem_region->len;
2077cbb3ec25SBjoern A. Zeeb
2078cbb3ec25SBjoern A. Zeeb mem_region++;
2079cbb3ec25SBjoern A. Zeeb }
2080cbb3ec25SBjoern A. Zeeb
2081cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->dump_mutex);
2082cbb3ec25SBjoern A. Zeeb
2083cbb3ec25SBjoern A. Zeeb skip_memdump:
2084cbb3ec25SBjoern A. Zeeb mt7996_coredump_submit(dev);
2085cbb3ec25SBjoern A. Zeeb skip_coredump:
2086cbb3ec25SBjoern A. Zeeb queue_work(dev->mt76.wq, &dev->reset_work);
2087cbb3ec25SBjoern A. Zeeb }
2088cbb3ec25SBjoern A. Zeeb
mt7996_reset(struct mt7996_dev * dev)2089cbb3ec25SBjoern A. Zeeb void mt7996_reset(struct mt7996_dev *dev)
2090cbb3ec25SBjoern A. Zeeb {
2091cbb3ec25SBjoern A. Zeeb if (!dev->recovery.hw_init_done)
2092cbb3ec25SBjoern A. Zeeb return;
2093cbb3ec25SBjoern A. Zeeb
2094cbb3ec25SBjoern A. Zeeb if (dev->recovery.hw_full_reset)
2095cbb3ec25SBjoern A. Zeeb return;
2096cbb3ec25SBjoern A. Zeeb
2097cbb3ec25SBjoern A. Zeeb /* wm/wa exception: do full recovery */
2098cbb3ec25SBjoern A. Zeeb if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) {
2099cbb3ec25SBjoern A. Zeeb dev->recovery.restart = true;
2100cbb3ec25SBjoern A. Zeeb dev_info(dev->mt76.dev,
2101cbb3ec25SBjoern A. Zeeb "%s indicated firmware crash, attempting recovery\n",
2102cbb3ec25SBjoern A. Zeeb wiphy_name(dev->mt76.hw->wiphy));
2103cbb3ec25SBjoern A. Zeeb
2104cbb3ec25SBjoern A. Zeeb mt7996_irq_disable(dev, MT_INT_MCU_CMD);
2105cbb3ec25SBjoern A. Zeeb queue_work(dev->mt76.wq, &dev->dump_work);
2106cbb3ec25SBjoern A. Zeeb return;
2107cbb3ec25SBjoern A. Zeeb }
2108cbb3ec25SBjoern A. Zeeb
2109cbb3ec25SBjoern A. Zeeb queue_work(dev->mt76.wq, &dev->reset_work);
2110cbb3ec25SBjoern A. Zeeb wake_up(&dev->reset_wait);
2111cbb3ec25SBjoern A. Zeeb }
2112cbb3ec25SBjoern A. Zeeb
mt7996_mac_update_stats(struct mt7996_phy * phy)2113cbb3ec25SBjoern A. Zeeb void mt7996_mac_update_stats(struct mt7996_phy *phy)
2114cbb3ec25SBjoern A. Zeeb {
2115cbb3ec25SBjoern A. Zeeb struct mt76_mib_stats *mib = &phy->mib;
2116cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev;
2117cbb3ec25SBjoern A. Zeeb u8 band_idx = phy->mt76->band_idx;
2118cbb3ec25SBjoern A. Zeeb u32 cnt;
2119cbb3ec25SBjoern A. Zeeb int i;
2120cbb3ec25SBjoern A. Zeeb
2121cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RSCR1(band_idx));
2122cbb3ec25SBjoern A. Zeeb mib->fcs_err_cnt += cnt;
2123cbb3ec25SBjoern A. Zeeb
2124cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RSCR33(band_idx));
2125cbb3ec25SBjoern A. Zeeb mib->rx_fifo_full_cnt += cnt;
2126cbb3ec25SBjoern A. Zeeb
2127cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RSCR31(band_idx));
2128cbb3ec25SBjoern A. Zeeb mib->rx_mpdu_cnt += cnt;
2129cbb3ec25SBjoern A. Zeeb
2130cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR6(band_idx));
2131cbb3ec25SBjoern A. Zeeb mib->channel_idle_cnt += FIELD_GET(MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK, cnt);
2132cbb3ec25SBjoern A. Zeeb
2133cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RVSR0(band_idx));
2134cbb3ec25SBjoern A. Zeeb mib->rx_vector_mismatch_cnt += cnt;
2135cbb3ec25SBjoern A. Zeeb
2136cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RSCR35(band_idx));
2137cbb3ec25SBjoern A. Zeeb mib->rx_delimiter_fail_cnt += cnt;
2138cbb3ec25SBjoern A. Zeeb
2139cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RSCR36(band_idx));
2140cbb3ec25SBjoern A. Zeeb mib->rx_len_mismatch_cnt += cnt;
2141cbb3ec25SBjoern A. Zeeb
2142cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_TSCR0(band_idx));
2143cbb3ec25SBjoern A. Zeeb mib->tx_ampdu_cnt += cnt;
2144cbb3ec25SBjoern A. Zeeb
2145cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_TSCR2(band_idx));
2146cbb3ec25SBjoern A. Zeeb mib->tx_stop_q_empty_cnt += cnt;
2147cbb3ec25SBjoern A. Zeeb
2148cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_TSCR3(band_idx));
2149cbb3ec25SBjoern A. Zeeb mib->tx_mpdu_attempts_cnt += cnt;
2150cbb3ec25SBjoern A. Zeeb
2151cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_TSCR4(band_idx));
2152cbb3ec25SBjoern A. Zeeb mib->tx_mpdu_success_cnt += cnt;
2153cbb3ec25SBjoern A. Zeeb
2154cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RSCR27(band_idx));
2155cbb3ec25SBjoern A. Zeeb mib->rx_ampdu_cnt += cnt;
2156cbb3ec25SBjoern A. Zeeb
2157cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RSCR28(band_idx));
2158cbb3ec25SBjoern A. Zeeb mib->rx_ampdu_bytes_cnt += cnt;
2159cbb3ec25SBjoern A. Zeeb
2160cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RSCR29(band_idx));
2161cbb3ec25SBjoern A. Zeeb mib->rx_ampdu_valid_subframe_cnt += cnt;
2162cbb3ec25SBjoern A. Zeeb
2163cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RSCR30(band_idx));
2164cbb3ec25SBjoern A. Zeeb mib->rx_ampdu_valid_subframe_bytes_cnt += cnt;
2165cbb3ec25SBjoern A. Zeeb
2166cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR27(band_idx));
2167cbb3ec25SBjoern A. Zeeb mib->tx_rwp_fail_cnt += FIELD_GET(MT_MIB_SDR27_TX_RWP_FAIL_CNT, cnt);
2168cbb3ec25SBjoern A. Zeeb
2169cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR28(band_idx));
2170cbb3ec25SBjoern A. Zeeb mib->tx_rwp_need_cnt += FIELD_GET(MT_MIB_SDR28_TX_RWP_NEED_CNT, cnt);
2171cbb3ec25SBjoern A. Zeeb
2172cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_UMIB_RPDCR(band_idx));
2173cbb3ec25SBjoern A. Zeeb mib->rx_pfdrop_cnt += cnt;
2174cbb3ec25SBjoern A. Zeeb
2175cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_RVSR1(band_idx));
2176cbb3ec25SBjoern A. Zeeb mib->rx_vec_queue_overflow_drop_cnt += cnt;
2177cbb3ec25SBjoern A. Zeeb
2178cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_TSCR1(band_idx));
2179cbb3ec25SBjoern A. Zeeb mib->rx_ba_cnt += cnt;
2180cbb3ec25SBjoern A. Zeeb
2181cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BSCR0(band_idx));
2182cbb3ec25SBjoern A. Zeeb mib->tx_bf_ebf_ppdu_cnt += cnt;
2183cbb3ec25SBjoern A. Zeeb
2184cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BSCR1(band_idx));
2185cbb3ec25SBjoern A. Zeeb mib->tx_bf_ibf_ppdu_cnt += cnt;
2186cbb3ec25SBjoern A. Zeeb
2187cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BSCR2(band_idx));
2188cbb3ec25SBjoern A. Zeeb mib->tx_mu_bf_cnt += cnt;
2189cbb3ec25SBjoern A. Zeeb
2190cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_TSCR5(band_idx));
2191cbb3ec25SBjoern A. Zeeb mib->tx_mu_mpdu_cnt += cnt;
2192cbb3ec25SBjoern A. Zeeb
2193cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_TSCR6(band_idx));
2194cbb3ec25SBjoern A. Zeeb mib->tx_mu_acked_mpdu_cnt += cnt;
2195cbb3ec25SBjoern A. Zeeb
2196cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_TSCR7(band_idx));
2197cbb3ec25SBjoern A. Zeeb mib->tx_su_acked_mpdu_cnt += cnt;
2198cbb3ec25SBjoern A. Zeeb
2199cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BSCR3(band_idx));
2200cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_ht_cnt += cnt;
2201cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_all_cnt += cnt;
2202cbb3ec25SBjoern A. Zeeb
2203cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BSCR4(band_idx));
2204cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_vht_cnt += cnt;
2205cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_all_cnt += cnt;
2206cbb3ec25SBjoern A. Zeeb
2207cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BSCR5(band_idx));
2208cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_he_cnt += cnt;
2209cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_all_cnt += cnt;
2210cbb3ec25SBjoern A. Zeeb
2211cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BSCR6(band_idx));
2212cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_eht_cnt += cnt;
2213cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_all_cnt += cnt;
2214cbb3ec25SBjoern A. Zeeb
2215cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(band_idx));
2216cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt);
2217cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt);
2218cbb3ec25SBjoern A. Zeeb mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt);
2219cbb3ec25SBjoern A. Zeeb
2220cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BSCR7(band_idx));
2221cbb3ec25SBjoern A. Zeeb mib->tx_bf_fb_trig_cnt += cnt;
2222cbb3ec25SBjoern A. Zeeb
2223cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BSCR17(band_idx));
2224cbb3ec25SBjoern A. Zeeb mib->tx_bf_fb_cpl_cnt += cnt;
2225cbb3ec25SBjoern A. Zeeb
2226cbb3ec25SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
2227cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
2228cbb3ec25SBjoern A. Zeeb mib->tx_amsdu[i] += cnt;
2229cbb3ec25SBjoern A. Zeeb mib->tx_amsdu_cnt += cnt;
2230cbb3ec25SBjoern A. Zeeb }
2231cbb3ec25SBjoern A. Zeeb
2232cbb3ec25SBjoern A. Zeeb /* rts count */
2233cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BTSCR5(band_idx));
2234cbb3ec25SBjoern A. Zeeb mib->rts_cnt += cnt;
2235cbb3ec25SBjoern A. Zeeb
2236cbb3ec25SBjoern A. Zeeb /* rts retry count */
2237cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BTSCR6(band_idx));
2238cbb3ec25SBjoern A. Zeeb mib->rts_retries_cnt += cnt;
2239cbb3ec25SBjoern A. Zeeb
2240cbb3ec25SBjoern A. Zeeb /* ba miss count */
2241cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BTSCR0(band_idx));
2242cbb3ec25SBjoern A. Zeeb mib->ba_miss_cnt += cnt;
2243cbb3ec25SBjoern A. Zeeb
2244cbb3ec25SBjoern A. Zeeb /* ack fail count */
2245cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BFTFCR(band_idx));
2246cbb3ec25SBjoern A. Zeeb mib->ack_fail_cnt += cnt;
2247cbb3ec25SBjoern A. Zeeb
2248cbb3ec25SBjoern A. Zeeb for (i = 0; i < 16; i++) {
2249cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_TX_AGG_CNT(band_idx, i));
2250cbb3ec25SBjoern A. Zeeb phy->mt76->aggr_stats[i] += cnt;
2251cbb3ec25SBjoern A. Zeeb }
2252cbb3ec25SBjoern A. Zeeb }
2253cbb3ec25SBjoern A. Zeeb
mt7996_mac_sta_rc_work(struct work_struct * work)2254cbb3ec25SBjoern A. Zeeb void mt7996_mac_sta_rc_work(struct work_struct *work)
2255cbb3ec25SBjoern A. Zeeb {
2256cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work);
2257cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta;
2258cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif;
2259cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta;
2260cbb3ec25SBjoern A. Zeeb u32 changed;
2261cbb3ec25SBjoern A. Zeeb LIST_HEAD(list);
2262cbb3ec25SBjoern A. Zeeb
2263cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock);
2264cbb3ec25SBjoern A. Zeeb list_splice_init(&dev->sta_rc_list, &list);
2265cbb3ec25SBjoern A. Zeeb
2266cbb3ec25SBjoern A. Zeeb while (!list_empty(&list)) {
2267cbb3ec25SBjoern A. Zeeb msta = list_first_entry(&list, struct mt7996_sta, rc_list);
2268cbb3ec25SBjoern A. Zeeb list_del_init(&msta->rc_list);
2269cbb3ec25SBjoern A. Zeeb changed = msta->changed;
2270cbb3ec25SBjoern A. Zeeb msta->changed = 0;
2271cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock);
2272cbb3ec25SBjoern A. Zeeb
2273cbb3ec25SBjoern A. Zeeb sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
2274cbb3ec25SBjoern A. Zeeb vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
2275cbb3ec25SBjoern A. Zeeb
2276cbb3ec25SBjoern A. Zeeb if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
2277cbb3ec25SBjoern A. Zeeb IEEE80211_RC_NSS_CHANGED |
2278cbb3ec25SBjoern A. Zeeb IEEE80211_RC_BW_CHANGED))
2279cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_rate_ctrl(dev, vif, sta, true);
2280cbb3ec25SBjoern A. Zeeb
2281*8ba4d145SBjoern A. Zeeb if (changed & IEEE80211_RC_SMPS_CHANGED)
2282*8ba4d145SBjoern A. Zeeb mt7996_mcu_set_fixed_field(dev, vif, sta, NULL,
2283*8ba4d145SBjoern A. Zeeb RATE_PARAM_MMPS_UPDATE);
2284cbb3ec25SBjoern A. Zeeb
2285cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock);
2286cbb3ec25SBjoern A. Zeeb }
2287cbb3ec25SBjoern A. Zeeb
2288cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock);
2289cbb3ec25SBjoern A. Zeeb }
2290cbb3ec25SBjoern A. Zeeb
mt7996_mac_work(struct work_struct * work)2291cbb3ec25SBjoern A. Zeeb void mt7996_mac_work(struct work_struct *work)
2292cbb3ec25SBjoern A. Zeeb {
2293cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy;
2294cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy;
2295cbb3ec25SBjoern A. Zeeb
2296cbb3ec25SBjoern A. Zeeb mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
2297cbb3ec25SBjoern A. Zeeb mac_work.work);
2298cbb3ec25SBjoern A. Zeeb phy = mphy->priv;
2299cbb3ec25SBjoern A. Zeeb
2300cbb3ec25SBjoern A. Zeeb mutex_lock(&mphy->dev->mutex);
2301cbb3ec25SBjoern A. Zeeb
2302cbb3ec25SBjoern A. Zeeb mt76_update_survey(mphy);
2303cbb3ec25SBjoern A. Zeeb if (++mphy->mac_work_count == 5) {
2304cbb3ec25SBjoern A. Zeeb mphy->mac_work_count = 0;
2305cbb3ec25SBjoern A. Zeeb
2306cbb3ec25SBjoern A. Zeeb mt7996_mac_update_stats(phy);
2307*8ba4d145SBjoern A. Zeeb
2308*8ba4d145SBjoern A. Zeeb mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_RATE);
2309*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
2310*8ba4d145SBjoern A. Zeeb mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
2311*8ba4d145SBjoern A. Zeeb mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
2312*8ba4d145SBjoern A. Zeeb }
2313cbb3ec25SBjoern A. Zeeb }
2314cbb3ec25SBjoern A. Zeeb
2315cbb3ec25SBjoern A. Zeeb mutex_unlock(&mphy->dev->mutex);
2316cbb3ec25SBjoern A. Zeeb
2317cbb3ec25SBjoern A. Zeeb mt76_tx_status_check(mphy->dev, false);
2318cbb3ec25SBjoern A. Zeeb
2319cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
2320cbb3ec25SBjoern A. Zeeb MT7996_WATCHDOG_TIME);
2321cbb3ec25SBjoern A. Zeeb }
2322cbb3ec25SBjoern A. Zeeb
mt7996_dfs_stop_radar_detector(struct mt7996_phy * phy)2323cbb3ec25SBjoern A. Zeeb static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy)
2324cbb3ec25SBjoern A. Zeeb {
2325cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev;
2326cbb3ec25SBjoern A. Zeeb
2327cbb3ec25SBjoern A. Zeeb if (phy->rdd_state & BIT(0))
2328cbb3ec25SBjoern A. Zeeb mt7996_mcu_rdd_cmd(dev, RDD_STOP, 0,
2329cbb3ec25SBjoern A. Zeeb MT_RX_SEL0, 0);
2330cbb3ec25SBjoern A. Zeeb if (phy->rdd_state & BIT(1))
2331cbb3ec25SBjoern A. Zeeb mt7996_mcu_rdd_cmd(dev, RDD_STOP, 1,
2332cbb3ec25SBjoern A. Zeeb MT_RX_SEL0, 0);
2333cbb3ec25SBjoern A. Zeeb }
2334cbb3ec25SBjoern A. Zeeb
mt7996_dfs_start_rdd(struct mt7996_dev * dev,int chain)2335cbb3ec25SBjoern A. Zeeb static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int chain)
2336cbb3ec25SBjoern A. Zeeb {
2337cbb3ec25SBjoern A. Zeeb int err, region;
2338cbb3ec25SBjoern A. Zeeb
2339cbb3ec25SBjoern A. Zeeb switch (dev->mt76.region) {
2340cbb3ec25SBjoern A. Zeeb case NL80211_DFS_ETSI:
2341cbb3ec25SBjoern A. Zeeb region = 0;
2342cbb3ec25SBjoern A. Zeeb break;
2343cbb3ec25SBjoern A. Zeeb case NL80211_DFS_JP:
2344cbb3ec25SBjoern A. Zeeb region = 2;
2345cbb3ec25SBjoern A. Zeeb break;
2346cbb3ec25SBjoern A. Zeeb case NL80211_DFS_FCC:
2347cbb3ec25SBjoern A. Zeeb default:
2348cbb3ec25SBjoern A. Zeeb region = 1;
2349cbb3ec25SBjoern A. Zeeb break;
2350cbb3ec25SBjoern A. Zeeb }
2351cbb3ec25SBjoern A. Zeeb
2352cbb3ec25SBjoern A. Zeeb err = mt7996_mcu_rdd_cmd(dev, RDD_START, chain,
2353cbb3ec25SBjoern A. Zeeb MT_RX_SEL0, region);
2354cbb3ec25SBjoern A. Zeeb if (err < 0)
2355cbb3ec25SBjoern A. Zeeb return err;
2356cbb3ec25SBjoern A. Zeeb
2357cbb3ec25SBjoern A. Zeeb return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, chain,
2358cbb3ec25SBjoern A. Zeeb MT_RX_SEL0, 1);
2359cbb3ec25SBjoern A. Zeeb }
2360cbb3ec25SBjoern A. Zeeb
mt7996_dfs_start_radar_detector(struct mt7996_phy * phy)2361cbb3ec25SBjoern A. Zeeb static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy)
2362cbb3ec25SBjoern A. Zeeb {
2363cbb3ec25SBjoern A. Zeeb struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
2364cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev;
2365cbb3ec25SBjoern A. Zeeb u8 band_idx = phy->mt76->band_idx;
2366cbb3ec25SBjoern A. Zeeb int err;
2367cbb3ec25SBjoern A. Zeeb
2368cbb3ec25SBjoern A. Zeeb /* start CAC */
2369cbb3ec25SBjoern A. Zeeb err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_START, band_idx,
2370cbb3ec25SBjoern A. Zeeb MT_RX_SEL0, 0);
2371cbb3ec25SBjoern A. Zeeb if (err < 0)
2372cbb3ec25SBjoern A. Zeeb return err;
2373cbb3ec25SBjoern A. Zeeb
2374cbb3ec25SBjoern A. Zeeb err = mt7996_dfs_start_rdd(dev, band_idx);
2375cbb3ec25SBjoern A. Zeeb if (err < 0)
2376cbb3ec25SBjoern A. Zeeb return err;
2377cbb3ec25SBjoern A. Zeeb
2378cbb3ec25SBjoern A. Zeeb phy->rdd_state |= BIT(band_idx);
2379cbb3ec25SBjoern A. Zeeb
2380cbb3ec25SBjoern A. Zeeb if (chandef->width == NL80211_CHAN_WIDTH_160 ||
2381cbb3ec25SBjoern A. Zeeb chandef->width == NL80211_CHAN_WIDTH_80P80) {
2382cbb3ec25SBjoern A. Zeeb err = mt7996_dfs_start_rdd(dev, 1);
2383cbb3ec25SBjoern A. Zeeb if (err < 0)
2384cbb3ec25SBjoern A. Zeeb return err;
2385cbb3ec25SBjoern A. Zeeb
2386cbb3ec25SBjoern A. Zeeb phy->rdd_state |= BIT(1);
2387cbb3ec25SBjoern A. Zeeb }
2388cbb3ec25SBjoern A. Zeeb
2389cbb3ec25SBjoern A. Zeeb return 0;
2390cbb3ec25SBjoern A. Zeeb }
2391cbb3ec25SBjoern A. Zeeb
2392cbb3ec25SBjoern A. Zeeb static int
mt7996_dfs_init_radar_specs(struct mt7996_phy * phy)2393cbb3ec25SBjoern A. Zeeb mt7996_dfs_init_radar_specs(struct mt7996_phy *phy)
2394cbb3ec25SBjoern A. Zeeb {
2395cbb3ec25SBjoern A. Zeeb const struct mt7996_dfs_radar_spec *radar_specs;
2396cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev;
2397cbb3ec25SBjoern A. Zeeb int err, i;
2398cbb3ec25SBjoern A. Zeeb
2399cbb3ec25SBjoern A. Zeeb switch (dev->mt76.region) {
2400cbb3ec25SBjoern A. Zeeb case NL80211_DFS_FCC:
2401cbb3ec25SBjoern A. Zeeb radar_specs = &fcc_radar_specs;
2402cbb3ec25SBjoern A. Zeeb err = mt7996_mcu_set_fcc5_lpn(dev, 8);
2403cbb3ec25SBjoern A. Zeeb if (err < 0)
2404cbb3ec25SBjoern A. Zeeb return err;
2405cbb3ec25SBjoern A. Zeeb break;
2406cbb3ec25SBjoern A. Zeeb case NL80211_DFS_ETSI:
2407cbb3ec25SBjoern A. Zeeb radar_specs = &etsi_radar_specs;
2408cbb3ec25SBjoern A. Zeeb break;
2409cbb3ec25SBjoern A. Zeeb case NL80211_DFS_JP:
2410cbb3ec25SBjoern A. Zeeb radar_specs = &jp_radar_specs;
2411cbb3ec25SBjoern A. Zeeb break;
2412cbb3ec25SBjoern A. Zeeb default:
2413cbb3ec25SBjoern A. Zeeb return -EINVAL;
2414cbb3ec25SBjoern A. Zeeb }
2415cbb3ec25SBjoern A. Zeeb
2416cbb3ec25SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) {
2417cbb3ec25SBjoern A. Zeeb err = mt7996_mcu_set_radar_th(dev, i,
2418cbb3ec25SBjoern A. Zeeb &radar_specs->radar_pattern[i]);
2419cbb3ec25SBjoern A. Zeeb if (err < 0)
2420cbb3ec25SBjoern A. Zeeb return err;
2421cbb3ec25SBjoern A. Zeeb }
2422cbb3ec25SBjoern A. Zeeb
2423cbb3ec25SBjoern A. Zeeb return mt7996_mcu_set_pulse_th(dev, &radar_specs->pulse_th);
2424cbb3ec25SBjoern A. Zeeb }
2425cbb3ec25SBjoern A. Zeeb
mt7996_dfs_init_radar_detector(struct mt7996_phy * phy)2426cbb3ec25SBjoern A. Zeeb int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy)
2427cbb3ec25SBjoern A. Zeeb {
2428cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev;
2429cbb3ec25SBjoern A. Zeeb enum mt76_dfs_state dfs_state, prev_state;
2430cbb3ec25SBjoern A. Zeeb int err;
2431cbb3ec25SBjoern A. Zeeb
2432cbb3ec25SBjoern A. Zeeb prev_state = phy->mt76->dfs_state;
2433cbb3ec25SBjoern A. Zeeb dfs_state = mt76_phy_dfs_state(phy->mt76);
2434cbb3ec25SBjoern A. Zeeb
2435cbb3ec25SBjoern A. Zeeb if (prev_state == dfs_state)
2436cbb3ec25SBjoern A. Zeeb return 0;
2437cbb3ec25SBjoern A. Zeeb
2438cbb3ec25SBjoern A. Zeeb if (prev_state == MT_DFS_STATE_UNKNOWN)
2439cbb3ec25SBjoern A. Zeeb mt7996_dfs_stop_radar_detector(phy);
2440cbb3ec25SBjoern A. Zeeb
2441cbb3ec25SBjoern A. Zeeb if (dfs_state == MT_DFS_STATE_DISABLED)
2442cbb3ec25SBjoern A. Zeeb goto stop;
2443cbb3ec25SBjoern A. Zeeb
2444cbb3ec25SBjoern A. Zeeb if (prev_state <= MT_DFS_STATE_DISABLED) {
2445cbb3ec25SBjoern A. Zeeb err = mt7996_dfs_init_radar_specs(phy);
2446cbb3ec25SBjoern A. Zeeb if (err < 0)
2447cbb3ec25SBjoern A. Zeeb return err;
2448cbb3ec25SBjoern A. Zeeb
2449cbb3ec25SBjoern A. Zeeb err = mt7996_dfs_start_radar_detector(phy);
2450cbb3ec25SBjoern A. Zeeb if (err < 0)
2451cbb3ec25SBjoern A. Zeeb return err;
2452cbb3ec25SBjoern A. Zeeb
2453cbb3ec25SBjoern A. Zeeb phy->mt76->dfs_state = MT_DFS_STATE_CAC;
2454cbb3ec25SBjoern A. Zeeb }
2455cbb3ec25SBjoern A. Zeeb
2456cbb3ec25SBjoern A. Zeeb if (dfs_state == MT_DFS_STATE_CAC)
2457cbb3ec25SBjoern A. Zeeb return 0;
2458cbb3ec25SBjoern A. Zeeb
2459cbb3ec25SBjoern A. Zeeb err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_END,
2460cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx, MT_RX_SEL0, 0);
2461cbb3ec25SBjoern A. Zeeb if (err < 0) {
2462cbb3ec25SBjoern A. Zeeb phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;
2463cbb3ec25SBjoern A. Zeeb return err;
2464cbb3ec25SBjoern A. Zeeb }
2465cbb3ec25SBjoern A. Zeeb
2466cbb3ec25SBjoern A. Zeeb phy->mt76->dfs_state = MT_DFS_STATE_ACTIVE;
2467cbb3ec25SBjoern A. Zeeb return 0;
2468cbb3ec25SBjoern A. Zeeb
2469cbb3ec25SBjoern A. Zeeb stop:
2470cbb3ec25SBjoern A. Zeeb err = mt7996_mcu_rdd_cmd(dev, RDD_NORMAL_START,
2471cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx, MT_RX_SEL0, 0);
2472cbb3ec25SBjoern A. Zeeb if (err < 0)
2473cbb3ec25SBjoern A. Zeeb return err;
2474cbb3ec25SBjoern A. Zeeb
2475cbb3ec25SBjoern A. Zeeb mt7996_dfs_stop_radar_detector(phy);
2476cbb3ec25SBjoern A. Zeeb phy->mt76->dfs_state = MT_DFS_STATE_DISABLED;
2477cbb3ec25SBjoern A. Zeeb
2478cbb3ec25SBjoern A. Zeeb return 0;
2479cbb3ec25SBjoern A. Zeeb }
2480cbb3ec25SBjoern A. Zeeb
2481cbb3ec25SBjoern A. Zeeb static int
mt7996_mac_twt_duration_align(int duration)2482cbb3ec25SBjoern A. Zeeb mt7996_mac_twt_duration_align(int duration)
2483cbb3ec25SBjoern A. Zeeb {
2484cbb3ec25SBjoern A. Zeeb return duration << 8;
2485cbb3ec25SBjoern A. Zeeb }
2486cbb3ec25SBjoern A. Zeeb
2487cbb3ec25SBjoern A. Zeeb static u64
mt7996_mac_twt_sched_list_add(struct mt7996_dev * dev,struct mt7996_twt_flow * flow)2488cbb3ec25SBjoern A. Zeeb mt7996_mac_twt_sched_list_add(struct mt7996_dev *dev,
2489cbb3ec25SBjoern A. Zeeb struct mt7996_twt_flow *flow)
2490cbb3ec25SBjoern A. Zeeb {
2491cbb3ec25SBjoern A. Zeeb struct mt7996_twt_flow *iter, *iter_next;
2492cbb3ec25SBjoern A. Zeeb u32 duration = flow->duration << 8;
2493cbb3ec25SBjoern A. Zeeb u64 start_tsf;
2494cbb3ec25SBjoern A. Zeeb
2495cbb3ec25SBjoern A. Zeeb iter = list_first_entry_or_null(&dev->twt_list,
2496cbb3ec25SBjoern A. Zeeb struct mt7996_twt_flow, list);
2497cbb3ec25SBjoern A. Zeeb if (!iter || !iter->sched || iter->start_tsf > duration) {
2498cbb3ec25SBjoern A. Zeeb /* add flow as first entry in the list */
2499cbb3ec25SBjoern A. Zeeb list_add(&flow->list, &dev->twt_list);
2500cbb3ec25SBjoern A. Zeeb return 0;
2501cbb3ec25SBjoern A. Zeeb }
2502cbb3ec25SBjoern A. Zeeb
2503cbb3ec25SBjoern A. Zeeb list_for_each_entry_safe(iter, iter_next, &dev->twt_list, list) {
2504cbb3ec25SBjoern A. Zeeb start_tsf = iter->start_tsf +
2505cbb3ec25SBjoern A. Zeeb mt7996_mac_twt_duration_align(iter->duration);
2506cbb3ec25SBjoern A. Zeeb if (list_is_last(&iter->list, &dev->twt_list))
2507cbb3ec25SBjoern A. Zeeb break;
2508cbb3ec25SBjoern A. Zeeb
2509cbb3ec25SBjoern A. Zeeb if (!iter_next->sched ||
2510cbb3ec25SBjoern A. Zeeb iter_next->start_tsf > start_tsf + duration) {
2511cbb3ec25SBjoern A. Zeeb list_add(&flow->list, &iter->list);
2512cbb3ec25SBjoern A. Zeeb goto out;
2513cbb3ec25SBjoern A. Zeeb }
2514cbb3ec25SBjoern A. Zeeb }
2515cbb3ec25SBjoern A. Zeeb
2516cbb3ec25SBjoern A. Zeeb /* add flow as last entry in the list */
2517cbb3ec25SBjoern A. Zeeb list_add_tail(&flow->list, &dev->twt_list);
2518cbb3ec25SBjoern A. Zeeb out:
2519cbb3ec25SBjoern A. Zeeb return start_tsf;
2520cbb3ec25SBjoern A. Zeeb }
2521cbb3ec25SBjoern A. Zeeb
mt7996_mac_check_twt_req(struct ieee80211_twt_setup * twt)2522cbb3ec25SBjoern A. Zeeb static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt)
2523cbb3ec25SBjoern A. Zeeb {
2524cbb3ec25SBjoern A. Zeeb struct ieee80211_twt_params *twt_agrt;
2525cbb3ec25SBjoern A. Zeeb u64 interval, duration;
2526cbb3ec25SBjoern A. Zeeb u16 mantissa;
2527cbb3ec25SBjoern A. Zeeb u8 exp;
2528cbb3ec25SBjoern A. Zeeb
2529cbb3ec25SBjoern A. Zeeb /* only individual agreement supported */
2530cbb3ec25SBjoern A. Zeeb if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST)
2531cbb3ec25SBjoern A. Zeeb return -EOPNOTSUPP;
2532cbb3ec25SBjoern A. Zeeb
2533cbb3ec25SBjoern A. Zeeb /* only 256us unit supported */
2534cbb3ec25SBjoern A. Zeeb if (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT)
2535cbb3ec25SBjoern A. Zeeb return -EOPNOTSUPP;
2536cbb3ec25SBjoern A. Zeeb
2537cbb3ec25SBjoern A. Zeeb twt_agrt = (struct ieee80211_twt_params *)twt->params;
2538cbb3ec25SBjoern A. Zeeb
2539cbb3ec25SBjoern A. Zeeb /* explicit agreement not supported */
2540cbb3ec25SBjoern A. Zeeb if (!(twt_agrt->req_type & cpu_to_le16(IEEE80211_TWT_REQTYPE_IMPLICIT)))
2541cbb3ec25SBjoern A. Zeeb return -EOPNOTSUPP;
2542cbb3ec25SBjoern A. Zeeb
2543cbb3ec25SBjoern A. Zeeb exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP,
2544cbb3ec25SBjoern A. Zeeb le16_to_cpu(twt_agrt->req_type));
2545cbb3ec25SBjoern A. Zeeb mantissa = le16_to_cpu(twt_agrt->mantissa);
2546cbb3ec25SBjoern A. Zeeb duration = twt_agrt->min_twt_dur << 8;
2547cbb3ec25SBjoern A. Zeeb
2548cbb3ec25SBjoern A. Zeeb interval = (u64)mantissa << exp;
2549cbb3ec25SBjoern A. Zeeb if (interval < duration)
2550cbb3ec25SBjoern A. Zeeb return -EOPNOTSUPP;
2551cbb3ec25SBjoern A. Zeeb
2552cbb3ec25SBjoern A. Zeeb return 0;
2553cbb3ec25SBjoern A. Zeeb }
2554cbb3ec25SBjoern A. Zeeb
2555*8ba4d145SBjoern A. Zeeb static bool
mt7996_mac_twt_param_equal(struct mt7996_sta * msta,struct ieee80211_twt_params * twt_agrt)2556*8ba4d145SBjoern A. Zeeb mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
2557*8ba4d145SBjoern A. Zeeb struct ieee80211_twt_params *twt_agrt)
2558*8ba4d145SBjoern A. Zeeb {
2559*8ba4d145SBjoern A. Zeeb u16 type = le16_to_cpu(twt_agrt->req_type);
2560*8ba4d145SBjoern A. Zeeb u8 exp;
2561*8ba4d145SBjoern A. Zeeb int i;
2562*8ba4d145SBjoern A. Zeeb
2563*8ba4d145SBjoern A. Zeeb exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type);
2564*8ba4d145SBjoern A. Zeeb for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) {
2565*8ba4d145SBjoern A. Zeeb struct mt7996_twt_flow *f;
2566*8ba4d145SBjoern A. Zeeb
2567*8ba4d145SBjoern A. Zeeb if (!(msta->twt.flowid_mask & BIT(i)))
2568*8ba4d145SBjoern A. Zeeb continue;
2569*8ba4d145SBjoern A. Zeeb
2570*8ba4d145SBjoern A. Zeeb f = &msta->twt.flow[i];
2571*8ba4d145SBjoern A. Zeeb if (f->duration == twt_agrt->min_twt_dur &&
2572*8ba4d145SBjoern A. Zeeb f->mantissa == twt_agrt->mantissa &&
2573*8ba4d145SBjoern A. Zeeb f->exp == exp &&
2574*8ba4d145SBjoern A. Zeeb f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) &&
2575*8ba4d145SBjoern A. Zeeb f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) &&
2576*8ba4d145SBjoern A. Zeeb f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER))
2577*8ba4d145SBjoern A. Zeeb return true;
2578*8ba4d145SBjoern A. Zeeb }
2579*8ba4d145SBjoern A. Zeeb
2580*8ba4d145SBjoern A. Zeeb return false;
2581*8ba4d145SBjoern A. Zeeb }
2582*8ba4d145SBjoern A. Zeeb
mt7996_mac_add_twt_setup(struct ieee80211_hw * hw,struct ieee80211_sta * sta,struct ieee80211_twt_setup * twt)2583cbb3ec25SBjoern A. Zeeb void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
2584cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta,
2585cbb3ec25SBjoern A. Zeeb struct ieee80211_twt_setup *twt)
2586cbb3ec25SBjoern A. Zeeb {
2587cbb3ec25SBjoern A. Zeeb enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT;
2588cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
2589cbb3ec25SBjoern A. Zeeb struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
2590cbb3ec25SBjoern A. Zeeb u16 req_type = le16_to_cpu(twt_agrt->req_type);
2591cbb3ec25SBjoern A. Zeeb enum ieee80211_twt_setup_cmd sta_setup_cmd;
2592cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw);
2593cbb3ec25SBjoern A. Zeeb struct mt7996_twt_flow *flow;
2594*8ba4d145SBjoern A. Zeeb u8 flowid, table_id, exp;
2595cbb3ec25SBjoern A. Zeeb
2596cbb3ec25SBjoern A. Zeeb if (mt7996_mac_check_twt_req(twt))
2597cbb3ec25SBjoern A. Zeeb goto out;
2598cbb3ec25SBjoern A. Zeeb
2599cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
2600cbb3ec25SBjoern A. Zeeb
2601cbb3ec25SBjoern A. Zeeb if (dev->twt.n_agrt == MT7996_MAX_TWT_AGRT)
2602cbb3ec25SBjoern A. Zeeb goto unlock;
2603cbb3ec25SBjoern A. Zeeb
2604cbb3ec25SBjoern A. Zeeb if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
2605cbb3ec25SBjoern A. Zeeb goto unlock;
2606cbb3ec25SBjoern A. Zeeb
2607*8ba4d145SBjoern A. Zeeb if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) {
2608*8ba4d145SBjoern A. Zeeb setup_cmd = TWT_SETUP_CMD_DICTATE;
2609*8ba4d145SBjoern A. Zeeb twt_agrt->min_twt_dur = MT7996_MIN_TWT_DUR;
2610*8ba4d145SBjoern A. Zeeb goto unlock;
2611*8ba4d145SBjoern A. Zeeb }
2612*8ba4d145SBjoern A. Zeeb
2613*8ba4d145SBjoern A. Zeeb if (mt7996_mac_twt_param_equal(msta, twt_agrt))
2614*8ba4d145SBjoern A. Zeeb goto unlock;
2615*8ba4d145SBjoern A. Zeeb
2616cbb3ec25SBjoern A. Zeeb flowid = ffs(~msta->twt.flowid_mask) - 1;
2617*8ba4d145SBjoern A. Zeeb twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID);
2618*8ba4d145SBjoern A. Zeeb twt_agrt->req_type |= le16_encode_bits(flowid,
2619cbb3ec25SBjoern A. Zeeb IEEE80211_TWT_REQTYPE_FLOWID);
2620cbb3ec25SBjoern A. Zeeb
2621cbb3ec25SBjoern A. Zeeb table_id = ffs(~dev->twt.table_mask) - 1;
2622cbb3ec25SBjoern A. Zeeb exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type);
2623cbb3ec25SBjoern A. Zeeb sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type);
2624cbb3ec25SBjoern A. Zeeb
2625cbb3ec25SBjoern A. Zeeb flow = &msta->twt.flow[flowid];
2626cbb3ec25SBjoern A. Zeeb memset(flow, 0, sizeof(*flow));
2627cbb3ec25SBjoern A. Zeeb INIT_LIST_HEAD(&flow->list);
2628cbb3ec25SBjoern A. Zeeb flow->wcid = msta->wcid.idx;
2629cbb3ec25SBjoern A. Zeeb flow->table_id = table_id;
2630cbb3ec25SBjoern A. Zeeb flow->id = flowid;
2631cbb3ec25SBjoern A. Zeeb flow->duration = twt_agrt->min_twt_dur;
2632cbb3ec25SBjoern A. Zeeb flow->mantissa = twt_agrt->mantissa;
2633cbb3ec25SBjoern A. Zeeb flow->exp = exp;
2634cbb3ec25SBjoern A. Zeeb flow->protection = !!(req_type & IEEE80211_TWT_REQTYPE_PROTECTION);
2635cbb3ec25SBjoern A. Zeeb flow->flowtype = !!(req_type & IEEE80211_TWT_REQTYPE_FLOWTYPE);
2636cbb3ec25SBjoern A. Zeeb flow->trigger = !!(req_type & IEEE80211_TWT_REQTYPE_TRIGGER);
2637cbb3ec25SBjoern A. Zeeb
2638cbb3ec25SBjoern A. Zeeb if (sta_setup_cmd == TWT_SETUP_CMD_REQUEST ||
2639cbb3ec25SBjoern A. Zeeb sta_setup_cmd == TWT_SETUP_CMD_SUGGEST) {
2640cbb3ec25SBjoern A. Zeeb u64 interval = (u64)le16_to_cpu(twt_agrt->mantissa) << exp;
2641cbb3ec25SBjoern A. Zeeb u64 flow_tsf, curr_tsf;
2642cbb3ec25SBjoern A. Zeeb u32 rem;
2643cbb3ec25SBjoern A. Zeeb
2644cbb3ec25SBjoern A. Zeeb flow->sched = true;
2645cbb3ec25SBjoern A. Zeeb flow->start_tsf = mt7996_mac_twt_sched_list_add(dev, flow);
2646cbb3ec25SBjoern A. Zeeb curr_tsf = __mt7996_get_tsf(hw, msta->vif);
2647cbb3ec25SBjoern A. Zeeb div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem);
2648cbb3ec25SBjoern A. Zeeb flow_tsf = curr_tsf + interval - rem;
2649cbb3ec25SBjoern A. Zeeb twt_agrt->twt = cpu_to_le64(flow_tsf);
2650cbb3ec25SBjoern A. Zeeb } else {
2651cbb3ec25SBjoern A. Zeeb list_add_tail(&flow->list, &dev->twt_list);
2652cbb3ec25SBjoern A. Zeeb }
2653cbb3ec25SBjoern A. Zeeb flow->tsf = le64_to_cpu(twt_agrt->twt);
2654cbb3ec25SBjoern A. Zeeb
2655cbb3ec25SBjoern A. Zeeb if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD))
2656cbb3ec25SBjoern A. Zeeb goto unlock;
2657cbb3ec25SBjoern A. Zeeb
2658cbb3ec25SBjoern A. Zeeb setup_cmd = TWT_SETUP_CMD_ACCEPT;
2659cbb3ec25SBjoern A. Zeeb dev->twt.table_mask |= BIT(table_id);
2660cbb3ec25SBjoern A. Zeeb msta->twt.flowid_mask |= BIT(flowid);
2661cbb3ec25SBjoern A. Zeeb dev->twt.n_agrt++;
2662cbb3ec25SBjoern A. Zeeb
2663cbb3ec25SBjoern A. Zeeb unlock:
2664cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
2665cbb3ec25SBjoern A. Zeeb out:
2666*8ba4d145SBjoern A. Zeeb twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD);
2667*8ba4d145SBjoern A. Zeeb twt_agrt->req_type |=
2668*8ba4d145SBjoern A. Zeeb le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD);
2669*8ba4d145SBjoern A. Zeeb twt->control = twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED;
2670cbb3ec25SBjoern A. Zeeb }
2671cbb3ec25SBjoern A. Zeeb
mt7996_mac_twt_teardown_flow(struct mt7996_dev * dev,struct mt7996_sta * msta,u8 flowid)2672cbb3ec25SBjoern A. Zeeb void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
2673cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta,
2674cbb3ec25SBjoern A. Zeeb u8 flowid)
2675cbb3ec25SBjoern A. Zeeb {
2676cbb3ec25SBjoern A. Zeeb struct mt7996_twt_flow *flow;
2677cbb3ec25SBjoern A. Zeeb
2678cbb3ec25SBjoern A. Zeeb lockdep_assert_held(&dev->mt76.mutex);
2679cbb3ec25SBjoern A. Zeeb
2680cbb3ec25SBjoern A. Zeeb if (flowid >= ARRAY_SIZE(msta->twt.flow))
2681cbb3ec25SBjoern A. Zeeb return;
2682cbb3ec25SBjoern A. Zeeb
2683cbb3ec25SBjoern A. Zeeb if (!(msta->twt.flowid_mask & BIT(flowid)))
2684cbb3ec25SBjoern A. Zeeb return;
2685cbb3ec25SBjoern A. Zeeb
2686cbb3ec25SBjoern A. Zeeb flow = &msta->twt.flow[flowid];
2687cbb3ec25SBjoern A. Zeeb if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow,
2688cbb3ec25SBjoern A. Zeeb MCU_TWT_AGRT_DELETE))
2689cbb3ec25SBjoern A. Zeeb return;
2690cbb3ec25SBjoern A. Zeeb
2691cbb3ec25SBjoern A. Zeeb list_del_init(&flow->list);
2692cbb3ec25SBjoern A. Zeeb msta->twt.flowid_mask &= ~BIT(flowid);
2693cbb3ec25SBjoern A. Zeeb dev->twt.table_mask &= ~BIT(flow->table_id);
2694cbb3ec25SBjoern A. Zeeb dev->twt.n_agrt--;
2695cbb3ec25SBjoern A. Zeeb }
2696