1*8ba4d145SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2*8ba4d145SBjoern A. Zeeb /* Copyright (C) 2023 MediaTek Inc. */
3*8ba4d145SBjoern A. Zeeb
4*8ba4d145SBjoern A. Zeeb #include <linux/devcoredump.h>
5*8ba4d145SBjoern A. Zeeb #include <linux/etherdevice.h>
6*8ba4d145SBjoern A. Zeeb #include <linux/timekeeping.h>
7*8ba4d145SBjoern A. Zeeb #include "mt7925.h"
8*8ba4d145SBjoern A. Zeeb #include "../dma.h"
9*8ba4d145SBjoern A. Zeeb #include "mac.h"
10*8ba4d145SBjoern A. Zeeb #include "mcu.h"
11*8ba4d145SBjoern A. Zeeb
mt7925_mac_wtbl_update(struct mt792x_dev * dev,int idx,u32 mask)12*8ba4d145SBjoern A. Zeeb bool mt7925_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask)
13*8ba4d145SBjoern A. Zeeb {
14*8ba4d145SBjoern A. Zeeb mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
15*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask);
16*8ba4d145SBjoern A. Zeeb
17*8ba4d145SBjoern A. Zeeb return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY,
18*8ba4d145SBjoern A. Zeeb 0, 5000);
19*8ba4d145SBjoern A. Zeeb }
20*8ba4d145SBjoern A. Zeeb
mt7925_mac_sta_poll(struct mt792x_dev * dev)21*8ba4d145SBjoern A. Zeeb static void mt7925_mac_sta_poll(struct mt792x_dev *dev)
22*8ba4d145SBjoern A. Zeeb {
23*8ba4d145SBjoern A. Zeeb static const u8 ac_to_tid[] = {
24*8ba4d145SBjoern A. Zeeb [IEEE80211_AC_BE] = 0,
25*8ba4d145SBjoern A. Zeeb [IEEE80211_AC_BK] = 1,
26*8ba4d145SBjoern A. Zeeb [IEEE80211_AC_VI] = 4,
27*8ba4d145SBjoern A. Zeeb [IEEE80211_AC_VO] = 6
28*8ba4d145SBjoern A. Zeeb };
29*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta;
30*8ba4d145SBjoern A. Zeeb struct mt792x_sta *msta;
31*8ba4d145SBjoern A. Zeeb struct mt792x_link_sta *mlink;
32*8ba4d145SBjoern A. Zeeb u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
33*8ba4d145SBjoern A. Zeeb LIST_HEAD(sta_poll_list);
34*8ba4d145SBjoern A. Zeeb struct rate_info *rate;
35*8ba4d145SBjoern A. Zeeb s8 rssi[4];
36*8ba4d145SBjoern A. Zeeb int i;
37*8ba4d145SBjoern A. Zeeb
38*8ba4d145SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock);
39*8ba4d145SBjoern A. Zeeb list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
40*8ba4d145SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock);
41*8ba4d145SBjoern A. Zeeb
42*8ba4d145SBjoern A. Zeeb while (true) {
43*8ba4d145SBjoern A. Zeeb bool clear = false;
44*8ba4d145SBjoern A. Zeeb u32 addr, val;
45*8ba4d145SBjoern A. Zeeb u16 idx;
46*8ba4d145SBjoern A. Zeeb u8 bw;
47*8ba4d145SBjoern A. Zeeb
48*8ba4d145SBjoern A. Zeeb if (list_empty(&sta_poll_list))
49*8ba4d145SBjoern A. Zeeb break;
50*8ba4d145SBjoern A. Zeeb mlink = list_first_entry(&sta_poll_list,
51*8ba4d145SBjoern A. Zeeb struct mt792x_link_sta, wcid.poll_list);
52*8ba4d145SBjoern A. Zeeb msta = mlink->sta;
53*8ba4d145SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock);
54*8ba4d145SBjoern A. Zeeb list_del_init(&mlink->wcid.poll_list);
55*8ba4d145SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock);
56*8ba4d145SBjoern A. Zeeb
57*8ba4d145SBjoern A. Zeeb idx = mlink->wcid.idx;
58*8ba4d145SBjoern A. Zeeb addr = mt7925_mac_wtbl_lmac_addr(dev, idx, MT_WTBL_AC0_CTT_OFFSET);
59*8ba4d145SBjoern A. Zeeb
60*8ba4d145SBjoern A. Zeeb for (i = 0; i < IEEE80211_NUM_ACS; i++) {
61*8ba4d145SBjoern A. Zeeb u32 tx_last = mlink->airtime_ac[i];
62*8ba4d145SBjoern A. Zeeb u32 rx_last = mlink->airtime_ac[i + 4];
63*8ba4d145SBjoern A. Zeeb
64*8ba4d145SBjoern A. Zeeb mlink->airtime_ac[i] = mt76_rr(dev, addr);
65*8ba4d145SBjoern A. Zeeb mlink->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
66*8ba4d145SBjoern A. Zeeb
67*8ba4d145SBjoern A. Zeeb tx_time[i] = mlink->airtime_ac[i] - tx_last;
68*8ba4d145SBjoern A. Zeeb rx_time[i] = mlink->airtime_ac[i + 4] - rx_last;
69*8ba4d145SBjoern A. Zeeb
70*8ba4d145SBjoern A. Zeeb if ((tx_last | rx_last) & BIT(30))
71*8ba4d145SBjoern A. Zeeb clear = true;
72*8ba4d145SBjoern A. Zeeb
73*8ba4d145SBjoern A. Zeeb addr += 8;
74*8ba4d145SBjoern A. Zeeb }
75*8ba4d145SBjoern A. Zeeb
76*8ba4d145SBjoern A. Zeeb if (clear) {
77*8ba4d145SBjoern A. Zeeb mt7925_mac_wtbl_update(dev, idx,
78*8ba4d145SBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
79*8ba4d145SBjoern A. Zeeb memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac));
80*8ba4d145SBjoern A. Zeeb }
81*8ba4d145SBjoern A. Zeeb
82*8ba4d145SBjoern A. Zeeb if (!mlink->wcid.sta)
83*8ba4d145SBjoern A. Zeeb continue;
84*8ba4d145SBjoern A. Zeeb
85*8ba4d145SBjoern A. Zeeb sta = container_of((void *)msta, struct ieee80211_sta,
86*8ba4d145SBjoern A. Zeeb drv_priv);
87*8ba4d145SBjoern A. Zeeb for (i = 0; i < IEEE80211_NUM_ACS; i++) {
88*8ba4d145SBjoern A. Zeeb u8 q = mt76_connac_lmac_mapping(i);
89*8ba4d145SBjoern A. Zeeb u32 tx_cur = tx_time[q];
90*8ba4d145SBjoern A. Zeeb u32 rx_cur = rx_time[q];
91*8ba4d145SBjoern A. Zeeb u8 tid = ac_to_tid[i];
92*8ba4d145SBjoern A. Zeeb
93*8ba4d145SBjoern A. Zeeb if (!tx_cur && !rx_cur)
94*8ba4d145SBjoern A. Zeeb continue;
95*8ba4d145SBjoern A. Zeeb
96*8ba4d145SBjoern A. Zeeb ieee80211_sta_register_airtime(sta, tid, tx_cur,
97*8ba4d145SBjoern A. Zeeb rx_cur);
98*8ba4d145SBjoern A. Zeeb }
99*8ba4d145SBjoern A. Zeeb
100*8ba4d145SBjoern A. Zeeb /* We don't support reading GI info from txs packets.
101*8ba4d145SBjoern A. Zeeb * For accurate tx status reporting and AQL improvement,
102*8ba4d145SBjoern A. Zeeb * we need to make sure that flags match so polling GI
103*8ba4d145SBjoern A. Zeeb * from per-sta counters directly.
104*8ba4d145SBjoern A. Zeeb */
105*8ba4d145SBjoern A. Zeeb rate = &mlink->wcid.rate;
106*8ba4d145SBjoern A. Zeeb
107*8ba4d145SBjoern A. Zeeb switch (rate->bw) {
108*8ba4d145SBjoern A. Zeeb case RATE_INFO_BW_160:
109*8ba4d145SBjoern A. Zeeb bw = IEEE80211_STA_RX_BW_160;
110*8ba4d145SBjoern A. Zeeb break;
111*8ba4d145SBjoern A. Zeeb case RATE_INFO_BW_80:
112*8ba4d145SBjoern A. Zeeb bw = IEEE80211_STA_RX_BW_80;
113*8ba4d145SBjoern A. Zeeb break;
114*8ba4d145SBjoern A. Zeeb case RATE_INFO_BW_40:
115*8ba4d145SBjoern A. Zeeb bw = IEEE80211_STA_RX_BW_40;
116*8ba4d145SBjoern A. Zeeb break;
117*8ba4d145SBjoern A. Zeeb default:
118*8ba4d145SBjoern A. Zeeb bw = IEEE80211_STA_RX_BW_20;
119*8ba4d145SBjoern A. Zeeb break;
120*8ba4d145SBjoern A. Zeeb }
121*8ba4d145SBjoern A. Zeeb
122*8ba4d145SBjoern A. Zeeb addr = mt7925_mac_wtbl_lmac_addr(dev, idx, 6);
123*8ba4d145SBjoern A. Zeeb val = mt76_rr(dev, addr);
124*8ba4d145SBjoern A. Zeeb if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) {
125*8ba4d145SBjoern A. Zeeb addr = mt7925_mac_wtbl_lmac_addr(dev, idx, 5);
126*8ba4d145SBjoern A. Zeeb val = mt76_rr(dev, addr);
127*8ba4d145SBjoern A. Zeeb rate->eht_gi = FIELD_GET(GENMASK(25, 24), val);
128*8ba4d145SBjoern A. Zeeb } else if (rate->flags & RATE_INFO_FLAGS_HE_MCS) {
129*8ba4d145SBjoern A. Zeeb u8 offs = MT_WTBL_TXRX_RATE_G2_HE + 2 * bw;
130*8ba4d145SBjoern A. Zeeb
131*8ba4d145SBjoern A. Zeeb rate->he_gi = (val & (0x3 << offs)) >> offs;
132*8ba4d145SBjoern A. Zeeb } else if (rate->flags &
133*8ba4d145SBjoern A. Zeeb (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) {
134*8ba4d145SBjoern A. Zeeb if (val & BIT(MT_WTBL_TXRX_RATE_G2 + bw))
135*8ba4d145SBjoern A. Zeeb rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
136*8ba4d145SBjoern A. Zeeb else
137*8ba4d145SBjoern A. Zeeb rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI;
138*8ba4d145SBjoern A. Zeeb }
139*8ba4d145SBjoern A. Zeeb
140*8ba4d145SBjoern A. Zeeb /* get signal strength of resp frames (CTS/BA/ACK) */
141*8ba4d145SBjoern A. Zeeb addr = mt7925_mac_wtbl_lmac_addr(dev, idx, 34);
142*8ba4d145SBjoern A. Zeeb val = mt76_rr(dev, addr);
143*8ba4d145SBjoern A. Zeeb
144*8ba4d145SBjoern A. Zeeb rssi[0] = to_rssi(GENMASK(7, 0), val);
145*8ba4d145SBjoern A. Zeeb rssi[1] = to_rssi(GENMASK(15, 8), val);
146*8ba4d145SBjoern A. Zeeb rssi[2] = to_rssi(GENMASK(23, 16), val);
147*8ba4d145SBjoern A. Zeeb rssi[3] = to_rssi(GENMASK(31, 14), val);
148*8ba4d145SBjoern A. Zeeb
149*8ba4d145SBjoern A. Zeeb mlink->ack_signal =
150*8ba4d145SBjoern A. Zeeb mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi);
151*8ba4d145SBjoern A. Zeeb
152*8ba4d145SBjoern A. Zeeb ewma_avg_signal_add(&mlink->avg_ack_signal, -mlink->ack_signal);
153*8ba4d145SBjoern A. Zeeb }
154*8ba4d145SBjoern A. Zeeb }
155*8ba4d145SBjoern A. Zeeb
mt7925_mac_set_fixed_rate_table(struct mt792x_dev * dev,u8 tbl_idx,u16 rate_idx)156*8ba4d145SBjoern A. Zeeb void mt7925_mac_set_fixed_rate_table(struct mt792x_dev *dev,
157*8ba4d145SBjoern A. Zeeb u8 tbl_idx, u16 rate_idx)
158*8ba4d145SBjoern A. Zeeb {
159*8ba4d145SBjoern A. Zeeb u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx;
160*8ba4d145SBjoern A. Zeeb
161*8ba4d145SBjoern A. Zeeb mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
162*8ba4d145SBjoern A. Zeeb /* use wtbl spe idx */
163*8ba4d145SBjoern A. Zeeb mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
164*8ba4d145SBjoern A. Zeeb mt76_wr(dev, MT_WTBL_ITCR, ctrl);
165*8ba4d145SBjoern A. Zeeb }
166*8ba4d145SBjoern A. Zeeb
167*8ba4d145SBjoern A. Zeeb /* The HW does not translate the mac header to 802.3 for mesh point */
mt7925_reverse_frag0_hdr_trans(struct sk_buff * skb,u16 hdr_gap)168*8ba4d145SBjoern A. Zeeb static int mt7925_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
169*8ba4d145SBjoern A. Zeeb {
170*8ba4d145SBjoern A. Zeeb struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
171*8ba4d145SBjoern A. Zeeb struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap);
172*8ba4d145SBjoern A. Zeeb struct mt792x_sta *msta = (struct mt792x_sta *)status->wcid;
173*8ba4d145SBjoern A. Zeeb __le32 *rxd = (__le32 *)skb->data;
174*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta;
175*8ba4d145SBjoern A. Zeeb struct ieee80211_vif *vif;
176*8ba4d145SBjoern A. Zeeb struct ieee80211_hdr hdr;
177*8ba4d145SBjoern A. Zeeb u16 frame_control;
178*8ba4d145SBjoern A. Zeeb
179*8ba4d145SBjoern A. Zeeb if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
180*8ba4d145SBjoern A. Zeeb MT_RXD3_NORMAL_U2M)
181*8ba4d145SBjoern A. Zeeb return -EINVAL;
182*8ba4d145SBjoern A. Zeeb
183*8ba4d145SBjoern A. Zeeb if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4))
184*8ba4d145SBjoern A. Zeeb return -EINVAL;
185*8ba4d145SBjoern A. Zeeb
186*8ba4d145SBjoern A. Zeeb if (!msta || !msta->vif)
187*8ba4d145SBjoern A. Zeeb return -EINVAL;
188*8ba4d145SBjoern A. Zeeb
189*8ba4d145SBjoern A. Zeeb sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
190*8ba4d145SBjoern A. Zeeb vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
191*8ba4d145SBjoern A. Zeeb
192*8ba4d145SBjoern A. Zeeb /* store the info from RXD and ethhdr to avoid being overridden */
193*8ba4d145SBjoern A. Zeeb frame_control = le32_get_bits(rxd[8], MT_RXD8_FRAME_CONTROL);
194*8ba4d145SBjoern A. Zeeb hdr.frame_control = cpu_to_le16(frame_control);
195*8ba4d145SBjoern A. Zeeb hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_SEQ_CTRL));
196*8ba4d145SBjoern A. Zeeb hdr.duration_id = 0;
197*8ba4d145SBjoern A. Zeeb
198*8ba4d145SBjoern A. Zeeb ether_addr_copy(hdr.addr1, vif->addr);
199*8ba4d145SBjoern A. Zeeb ether_addr_copy(hdr.addr2, sta->addr);
200*8ba4d145SBjoern A. Zeeb switch (frame_control & (IEEE80211_FCTL_TODS |
201*8ba4d145SBjoern A. Zeeb IEEE80211_FCTL_FROMDS)) {
202*8ba4d145SBjoern A. Zeeb case 0:
203*8ba4d145SBjoern A. Zeeb ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);
204*8ba4d145SBjoern A. Zeeb break;
205*8ba4d145SBjoern A. Zeeb case IEEE80211_FCTL_FROMDS:
206*8ba4d145SBjoern A. Zeeb ether_addr_copy(hdr.addr3, eth_hdr->h_source);
207*8ba4d145SBjoern A. Zeeb break;
208*8ba4d145SBjoern A. Zeeb case IEEE80211_FCTL_TODS:
209*8ba4d145SBjoern A. Zeeb ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
210*8ba4d145SBjoern A. Zeeb break;
211*8ba4d145SBjoern A. Zeeb case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS:
212*8ba4d145SBjoern A. Zeeb ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
213*8ba4d145SBjoern A. Zeeb ether_addr_copy(hdr.addr4, eth_hdr->h_source);
214*8ba4d145SBjoern A. Zeeb break;
215*8ba4d145SBjoern A. Zeeb default:
216*8ba4d145SBjoern A. Zeeb break;
217*8ba4d145SBjoern A. Zeeb }
218*8ba4d145SBjoern A. Zeeb
219*8ba4d145SBjoern A. Zeeb skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2);
220*8ba4d145SBjoern A. Zeeb if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||
221*8ba4d145SBjoern A. Zeeb eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))
222*8ba4d145SBjoern A. Zeeb ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);
223*8ba4d145SBjoern A. Zeeb else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)
224*8ba4d145SBjoern A. Zeeb ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);
225*8ba4d145SBjoern A. Zeeb else
226*8ba4d145SBjoern A. Zeeb skb_pull(skb, 2);
227*8ba4d145SBjoern A. Zeeb
228*8ba4d145SBjoern A. Zeeb if (ieee80211_has_order(hdr.frame_control))
229*8ba4d145SBjoern A. Zeeb memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[11],
230*8ba4d145SBjoern A. Zeeb IEEE80211_HT_CTL_LEN);
231*8ba4d145SBjoern A. Zeeb if (ieee80211_is_data_qos(hdr.frame_control)) {
232*8ba4d145SBjoern A. Zeeb __le16 qos_ctrl;
233*8ba4d145SBjoern A. Zeeb
234*8ba4d145SBjoern A. Zeeb qos_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_QOS_CTL));
235*8ba4d145SBjoern A. Zeeb memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,
236*8ba4d145SBjoern A. Zeeb IEEE80211_QOS_CTL_LEN);
237*8ba4d145SBjoern A. Zeeb }
238*8ba4d145SBjoern A. Zeeb
239*8ba4d145SBjoern A. Zeeb if (ieee80211_has_a4(hdr.frame_control))
240*8ba4d145SBjoern A. Zeeb memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
241*8ba4d145SBjoern A. Zeeb else
242*8ba4d145SBjoern A. Zeeb memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6);
243*8ba4d145SBjoern A. Zeeb
244*8ba4d145SBjoern A. Zeeb return 0;
245*8ba4d145SBjoern A. Zeeb }
246*8ba4d145SBjoern A. Zeeb
247*8ba4d145SBjoern A. Zeeb static int
mt7925_mac_fill_rx_rate(struct mt792x_dev * dev,struct mt76_rx_status * status,struct ieee80211_supported_band * sband,__le32 * rxv,u8 * mode)248*8ba4d145SBjoern A. Zeeb mt7925_mac_fill_rx_rate(struct mt792x_dev *dev,
249*8ba4d145SBjoern A. Zeeb struct mt76_rx_status *status,
250*8ba4d145SBjoern A. Zeeb struct ieee80211_supported_band *sband,
251*8ba4d145SBjoern A. Zeeb __le32 *rxv, u8 *mode)
252*8ba4d145SBjoern A. Zeeb {
253*8ba4d145SBjoern A. Zeeb u32 v0, v2;
254*8ba4d145SBjoern A. Zeeb u8 stbc, gi, bw, dcm, nss;
255*8ba4d145SBjoern A. Zeeb int i, idx;
256*8ba4d145SBjoern A. Zeeb bool cck = false;
257*8ba4d145SBjoern A. Zeeb
258*8ba4d145SBjoern A. Zeeb v0 = le32_to_cpu(rxv[0]);
259*8ba4d145SBjoern A. Zeeb v2 = le32_to_cpu(rxv[2]);
260*8ba4d145SBjoern A. Zeeb
261*8ba4d145SBjoern A. Zeeb idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
262*8ba4d145SBjoern A. Zeeb i = idx;
263*8ba4d145SBjoern A. Zeeb nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
264*8ba4d145SBjoern A. Zeeb
265*8ba4d145SBjoern A. Zeeb stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
266*8ba4d145SBjoern A. Zeeb gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
267*8ba4d145SBjoern A. Zeeb *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
268*8ba4d145SBjoern A. Zeeb dcm = FIELD_GET(MT_PRXV_DCM, v2);
269*8ba4d145SBjoern A. Zeeb bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
270*8ba4d145SBjoern A. Zeeb
271*8ba4d145SBjoern A. Zeeb switch (*mode) {
272*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_CCK:
273*8ba4d145SBjoern A. Zeeb cck = true;
274*8ba4d145SBjoern A. Zeeb fallthrough;
275*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_OFDM:
276*8ba4d145SBjoern A. Zeeb i = mt76_get_rate(&dev->mt76, sband, i, cck);
277*8ba4d145SBjoern A. Zeeb break;
278*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HT_GF:
279*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HT:
280*8ba4d145SBjoern A. Zeeb status->encoding = RX_ENC_HT;
281*8ba4d145SBjoern A. Zeeb if (gi)
282*8ba4d145SBjoern A. Zeeb status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
283*8ba4d145SBjoern A. Zeeb if (i > 31)
284*8ba4d145SBjoern A. Zeeb return -EINVAL;
285*8ba4d145SBjoern A. Zeeb break;
286*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_VHT:
287*8ba4d145SBjoern A. Zeeb status->nss = nss;
288*8ba4d145SBjoern A. Zeeb status->encoding = RX_ENC_VHT;
289*8ba4d145SBjoern A. Zeeb if (gi)
290*8ba4d145SBjoern A. Zeeb status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
291*8ba4d145SBjoern A. Zeeb if (i > 11)
292*8ba4d145SBjoern A. Zeeb return -EINVAL;
293*8ba4d145SBjoern A. Zeeb break;
294*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HE_MU:
295*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HE_SU:
296*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HE_EXT_SU:
297*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HE_TB:
298*8ba4d145SBjoern A. Zeeb status->nss = nss;
299*8ba4d145SBjoern A. Zeeb status->encoding = RX_ENC_HE;
300*8ba4d145SBjoern A. Zeeb i &= GENMASK(3, 0);
301*8ba4d145SBjoern A. Zeeb
302*8ba4d145SBjoern A. Zeeb if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
303*8ba4d145SBjoern A. Zeeb status->he_gi = gi;
304*8ba4d145SBjoern A. Zeeb
305*8ba4d145SBjoern A. Zeeb status->he_dcm = dcm;
306*8ba4d145SBjoern A. Zeeb break;
307*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_EHT_SU:
308*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_EHT_TRIG:
309*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_EHT_MU:
310*8ba4d145SBjoern A. Zeeb status->nss = nss;
311*8ba4d145SBjoern A. Zeeb status->encoding = RX_ENC_EHT;
312*8ba4d145SBjoern A. Zeeb i &= GENMASK(3, 0);
313*8ba4d145SBjoern A. Zeeb
314*8ba4d145SBjoern A. Zeeb if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
315*8ba4d145SBjoern A. Zeeb status->eht.gi = gi;
316*8ba4d145SBjoern A. Zeeb break;
317*8ba4d145SBjoern A. Zeeb default:
318*8ba4d145SBjoern A. Zeeb return -EINVAL;
319*8ba4d145SBjoern A. Zeeb }
320*8ba4d145SBjoern A. Zeeb status->rate_idx = i;
321*8ba4d145SBjoern A. Zeeb
322*8ba4d145SBjoern A. Zeeb switch (bw) {
323*8ba4d145SBjoern A. Zeeb case IEEE80211_STA_RX_BW_20:
324*8ba4d145SBjoern A. Zeeb break;
325*8ba4d145SBjoern A. Zeeb case IEEE80211_STA_RX_BW_40:
326*8ba4d145SBjoern A. Zeeb if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
327*8ba4d145SBjoern A. Zeeb (idx & MT_PRXV_TX_ER_SU_106T)) {
328*8ba4d145SBjoern A. Zeeb status->bw = RATE_INFO_BW_HE_RU;
329*8ba4d145SBjoern A. Zeeb status->he_ru =
330*8ba4d145SBjoern A. Zeeb NL80211_RATE_INFO_HE_RU_ALLOC_106;
331*8ba4d145SBjoern A. Zeeb } else {
332*8ba4d145SBjoern A. Zeeb status->bw = RATE_INFO_BW_40;
333*8ba4d145SBjoern A. Zeeb }
334*8ba4d145SBjoern A. Zeeb break;
335*8ba4d145SBjoern A. Zeeb case IEEE80211_STA_RX_BW_80:
336*8ba4d145SBjoern A. Zeeb status->bw = RATE_INFO_BW_80;
337*8ba4d145SBjoern A. Zeeb break;
338*8ba4d145SBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
339*8ba4d145SBjoern A. Zeeb status->bw = RATE_INFO_BW_160;
340*8ba4d145SBjoern A. Zeeb break;
341*8ba4d145SBjoern A. Zeeb default:
342*8ba4d145SBjoern A. Zeeb return -EINVAL;
343*8ba4d145SBjoern A. Zeeb }
344*8ba4d145SBjoern A. Zeeb
345*8ba4d145SBjoern A. Zeeb status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
346*8ba4d145SBjoern A. Zeeb if (*mode < MT_PHY_TYPE_HE_SU && gi)
347*8ba4d145SBjoern A. Zeeb status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
348*8ba4d145SBjoern A. Zeeb
349*8ba4d145SBjoern A. Zeeb return 0;
350*8ba4d145SBjoern A. Zeeb }
351*8ba4d145SBjoern A. Zeeb
352*8ba4d145SBjoern A. Zeeb static int
mt7925_mac_fill_rx(struct mt792x_dev * dev,struct sk_buff * skb)353*8ba4d145SBjoern A. Zeeb mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
354*8ba4d145SBjoern A. Zeeb {
355*8ba4d145SBjoern A. Zeeb u32 csum_mask = MT_RXD3_NORMAL_IP_SUM | MT_RXD3_NORMAL_UDP_TCP_SUM;
356*8ba4d145SBjoern A. Zeeb struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
357*8ba4d145SBjoern A. Zeeb bool hdr_trans, unicast, insert_ccmp_hdr = false;
358*8ba4d145SBjoern A. Zeeb u8 chfreq, qos_ctl = 0, remove_pad, amsdu_info;
359*8ba4d145SBjoern A. Zeeb u16 hdr_gap;
360*8ba4d145SBjoern A. Zeeb __le32 *rxv = NULL, *rxd = (__le32 *)skb->data;
361*8ba4d145SBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
362*8ba4d145SBjoern A. Zeeb struct mt792x_phy *phy = &dev->phy;
363*8ba4d145SBjoern A. Zeeb struct ieee80211_supported_band *sband;
364*8ba4d145SBjoern A. Zeeb u32 csum_status = *(u32 *)skb->cb;
365*8ba4d145SBjoern A. Zeeb u32 rxd1 = le32_to_cpu(rxd[1]);
366*8ba4d145SBjoern A. Zeeb u32 rxd2 = le32_to_cpu(rxd[2]);
367*8ba4d145SBjoern A. Zeeb u32 rxd3 = le32_to_cpu(rxd[3]);
368*8ba4d145SBjoern A. Zeeb u32 rxd4 = le32_to_cpu(rxd[4]);
369*8ba4d145SBjoern A. Zeeb struct mt792x_link_sta *mlink;
370*8ba4d145SBjoern A. Zeeb u8 mode = 0; /* , band_idx; */
371*8ba4d145SBjoern A. Zeeb u16 seq_ctrl = 0;
372*8ba4d145SBjoern A. Zeeb __le16 fc = 0;
373*8ba4d145SBjoern A. Zeeb int idx;
374*8ba4d145SBjoern A. Zeeb
375*8ba4d145SBjoern A. Zeeb memset(status, 0, sizeof(*status));
376*8ba4d145SBjoern A. Zeeb
377*8ba4d145SBjoern A. Zeeb if (!test_bit(MT76_STATE_RUNNING, &mphy->state))
378*8ba4d145SBjoern A. Zeeb return -EINVAL;
379*8ba4d145SBjoern A. Zeeb
380*8ba4d145SBjoern A. Zeeb if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
381*8ba4d145SBjoern A. Zeeb return -EINVAL;
382*8ba4d145SBjoern A. Zeeb
383*8ba4d145SBjoern A. Zeeb hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
384*8ba4d145SBjoern A. Zeeb if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM))
385*8ba4d145SBjoern A. Zeeb return -EINVAL;
386*8ba4d145SBjoern A. Zeeb
387*8ba4d145SBjoern A. Zeeb /* ICV error or CCMP/BIP/WPI MIC error */
388*8ba4d145SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_ICV_ERR)
389*8ba4d145SBjoern A. Zeeb status->flag |= RX_FLAG_ONLY_MONITOR;
390*8ba4d145SBjoern A. Zeeb
391*8ba4d145SBjoern A. Zeeb chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3);
392*8ba4d145SBjoern A. Zeeb unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
393*8ba4d145SBjoern A. Zeeb idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
394*8ba4d145SBjoern A. Zeeb status->wcid = mt792x_rx_get_wcid(dev, idx, unicast);
395*8ba4d145SBjoern A. Zeeb
396*8ba4d145SBjoern A. Zeeb if (status->wcid) {
397*8ba4d145SBjoern A. Zeeb mlink = container_of(status->wcid, struct mt792x_link_sta, wcid);
398*8ba4d145SBjoern A. Zeeb mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
399*8ba4d145SBjoern A. Zeeb }
400*8ba4d145SBjoern A. Zeeb
401*8ba4d145SBjoern A. Zeeb mt792x_get_status_freq_info(status, chfreq);
402*8ba4d145SBjoern A. Zeeb
403*8ba4d145SBjoern A. Zeeb switch (status->band) {
404*8ba4d145SBjoern A. Zeeb case NL80211_BAND_5GHZ:
405*8ba4d145SBjoern A. Zeeb sband = &mphy->sband_5g.sband;
406*8ba4d145SBjoern A. Zeeb break;
407*8ba4d145SBjoern A. Zeeb case NL80211_BAND_6GHZ:
408*8ba4d145SBjoern A. Zeeb sband = &mphy->sband_6g.sband;
409*8ba4d145SBjoern A. Zeeb break;
410*8ba4d145SBjoern A. Zeeb default:
411*8ba4d145SBjoern A. Zeeb sband = &mphy->sband_2g.sband;
412*8ba4d145SBjoern A. Zeeb break;
413*8ba4d145SBjoern A. Zeeb }
414*8ba4d145SBjoern A. Zeeb
415*8ba4d145SBjoern A. Zeeb if (!sband->channels)
416*8ba4d145SBjoern A. Zeeb return -EINVAL;
417*8ba4d145SBjoern A. Zeeb
418*8ba4d145SBjoern A. Zeeb if (mt76_is_mmio(&dev->mt76) && (rxd3 & csum_mask) == csum_mask &&
419*8ba4d145SBjoern A. Zeeb !(csum_status & (BIT(0) | BIT(2) | BIT(3))))
420*8ba4d145SBjoern A. Zeeb skb->ip_summed = CHECKSUM_UNNECESSARY;
421*8ba4d145SBjoern A. Zeeb
422*8ba4d145SBjoern A. Zeeb if (rxd3 & MT_RXD3_NORMAL_FCS_ERR)
423*8ba4d145SBjoern A. Zeeb status->flag |= RX_FLAG_FAILED_FCS_CRC;
424*8ba4d145SBjoern A. Zeeb
425*8ba4d145SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR)
426*8ba4d145SBjoern A. Zeeb status->flag |= RX_FLAG_MMIC_ERROR;
427*8ba4d145SBjoern A. Zeeb
428*8ba4d145SBjoern A. Zeeb if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 &&
429*8ba4d145SBjoern A. Zeeb !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) {
430*8ba4d145SBjoern A. Zeeb status->flag |= RX_FLAG_DECRYPTED;
431*8ba4d145SBjoern A. Zeeb status->flag |= RX_FLAG_IV_STRIPPED;
432*8ba4d145SBjoern A. Zeeb status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
433*8ba4d145SBjoern A. Zeeb }
434*8ba4d145SBjoern A. Zeeb
435*8ba4d145SBjoern A. Zeeb remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2);
436*8ba4d145SBjoern A. Zeeb
437*8ba4d145SBjoern A. Zeeb if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
438*8ba4d145SBjoern A. Zeeb return -EINVAL;
439*8ba4d145SBjoern A. Zeeb
440*8ba4d145SBjoern A. Zeeb rxd += 8;
441*8ba4d145SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_4) {
442*8ba4d145SBjoern A. Zeeb u32 v0 = le32_to_cpu(rxd[0]);
443*8ba4d145SBjoern A. Zeeb u32 v2 = le32_to_cpu(rxd[2]);
444*8ba4d145SBjoern A. Zeeb
445*8ba4d145SBjoern A. Zeeb /* TODO: need to map rxd address */
446*8ba4d145SBjoern A. Zeeb fc = cpu_to_le16(FIELD_GET(MT_RXD8_FRAME_CONTROL, v0));
447*8ba4d145SBjoern A. Zeeb seq_ctrl = FIELD_GET(MT_RXD10_SEQ_CTRL, v2);
448*8ba4d145SBjoern A. Zeeb qos_ctl = FIELD_GET(MT_RXD10_QOS_CTL, v2);
449*8ba4d145SBjoern A. Zeeb
450*8ba4d145SBjoern A. Zeeb rxd += 4;
451*8ba4d145SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
452*8ba4d145SBjoern A. Zeeb return -EINVAL;
453*8ba4d145SBjoern A. Zeeb }
454*8ba4d145SBjoern A. Zeeb
455*8ba4d145SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_1) {
456*8ba4d145SBjoern A. Zeeb u8 *data = (u8 *)rxd;
457*8ba4d145SBjoern A. Zeeb
458*8ba4d145SBjoern A. Zeeb if (status->flag & RX_FLAG_DECRYPTED) {
459*8ba4d145SBjoern A. Zeeb switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) {
460*8ba4d145SBjoern A. Zeeb case MT_CIPHER_AES_CCMP:
461*8ba4d145SBjoern A. Zeeb case MT_CIPHER_CCMP_CCX:
462*8ba4d145SBjoern A. Zeeb case MT_CIPHER_CCMP_256:
463*8ba4d145SBjoern A. Zeeb insert_ccmp_hdr =
464*8ba4d145SBjoern A. Zeeb FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
465*8ba4d145SBjoern A. Zeeb fallthrough;
466*8ba4d145SBjoern A. Zeeb case MT_CIPHER_TKIP:
467*8ba4d145SBjoern A. Zeeb case MT_CIPHER_TKIP_NO_MIC:
468*8ba4d145SBjoern A. Zeeb case MT_CIPHER_GCMP:
469*8ba4d145SBjoern A. Zeeb case MT_CIPHER_GCMP_256:
470*8ba4d145SBjoern A. Zeeb status->iv[0] = data[5];
471*8ba4d145SBjoern A. Zeeb status->iv[1] = data[4];
472*8ba4d145SBjoern A. Zeeb status->iv[2] = data[3];
473*8ba4d145SBjoern A. Zeeb status->iv[3] = data[2];
474*8ba4d145SBjoern A. Zeeb status->iv[4] = data[1];
475*8ba4d145SBjoern A. Zeeb status->iv[5] = data[0];
476*8ba4d145SBjoern A. Zeeb break;
477*8ba4d145SBjoern A. Zeeb default:
478*8ba4d145SBjoern A. Zeeb break;
479*8ba4d145SBjoern A. Zeeb }
480*8ba4d145SBjoern A. Zeeb }
481*8ba4d145SBjoern A. Zeeb rxd += 4;
482*8ba4d145SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
483*8ba4d145SBjoern A. Zeeb return -EINVAL;
484*8ba4d145SBjoern A. Zeeb }
485*8ba4d145SBjoern A. Zeeb
486*8ba4d145SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_2) {
487*8ba4d145SBjoern A. Zeeb status->timestamp = le32_to_cpu(rxd[0]);
488*8ba4d145SBjoern A. Zeeb status->flag |= RX_FLAG_MACTIME_START;
489*8ba4d145SBjoern A. Zeeb
490*8ba4d145SBjoern A. Zeeb if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) {
491*8ba4d145SBjoern A. Zeeb status->flag |= RX_FLAG_AMPDU_DETAILS;
492*8ba4d145SBjoern A. Zeeb
493*8ba4d145SBjoern A. Zeeb /* all subframes of an A-MPDU have the same timestamp */
494*8ba4d145SBjoern A. Zeeb if (phy->rx_ampdu_ts != status->timestamp) {
495*8ba4d145SBjoern A. Zeeb if (!++phy->ampdu_ref)
496*8ba4d145SBjoern A. Zeeb phy->ampdu_ref++;
497*8ba4d145SBjoern A. Zeeb }
498*8ba4d145SBjoern A. Zeeb phy->rx_ampdu_ts = status->timestamp;
499*8ba4d145SBjoern A. Zeeb
500*8ba4d145SBjoern A. Zeeb status->ampdu_ref = phy->ampdu_ref;
501*8ba4d145SBjoern A. Zeeb }
502*8ba4d145SBjoern A. Zeeb
503*8ba4d145SBjoern A. Zeeb rxd += 4;
504*8ba4d145SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
505*8ba4d145SBjoern A. Zeeb return -EINVAL;
506*8ba4d145SBjoern A. Zeeb }
507*8ba4d145SBjoern A. Zeeb
508*8ba4d145SBjoern A. Zeeb /* RXD Group 3 - P-RXV */
509*8ba4d145SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
510*8ba4d145SBjoern A. Zeeb u32 v3;
511*8ba4d145SBjoern A. Zeeb int ret;
512*8ba4d145SBjoern A. Zeeb
513*8ba4d145SBjoern A. Zeeb rxv = rxd;
514*8ba4d145SBjoern A. Zeeb rxd += 4;
515*8ba4d145SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
516*8ba4d145SBjoern A. Zeeb return -EINVAL;
517*8ba4d145SBjoern A. Zeeb
518*8ba4d145SBjoern A. Zeeb v3 = le32_to_cpu(rxv[3]);
519*8ba4d145SBjoern A. Zeeb
520*8ba4d145SBjoern A. Zeeb status->chains = mphy->antenna_mask;
521*8ba4d145SBjoern A. Zeeb status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v3);
522*8ba4d145SBjoern A. Zeeb status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v3);
523*8ba4d145SBjoern A. Zeeb status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v3);
524*8ba4d145SBjoern A. Zeeb status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v3);
525*8ba4d145SBjoern A. Zeeb
526*8ba4d145SBjoern A. Zeeb /* RXD Group 5 - C-RXV */
527*8ba4d145SBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
528*8ba4d145SBjoern A. Zeeb rxd += 24;
529*8ba4d145SBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len)
530*8ba4d145SBjoern A. Zeeb return -EINVAL;
531*8ba4d145SBjoern A. Zeeb }
532*8ba4d145SBjoern A. Zeeb
533*8ba4d145SBjoern A. Zeeb ret = mt7925_mac_fill_rx_rate(dev, status, sband, rxv, &mode);
534*8ba4d145SBjoern A. Zeeb if (ret < 0)
535*8ba4d145SBjoern A. Zeeb return ret;
536*8ba4d145SBjoern A. Zeeb }
537*8ba4d145SBjoern A. Zeeb
538*8ba4d145SBjoern A. Zeeb amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4);
539*8ba4d145SBjoern A. Zeeb status->amsdu = !!amsdu_info;
540*8ba4d145SBjoern A. Zeeb if (status->amsdu) {
541*8ba4d145SBjoern A. Zeeb status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME;
542*8ba4d145SBjoern A. Zeeb status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME;
543*8ba4d145SBjoern A. Zeeb }
544*8ba4d145SBjoern A. Zeeb
545*8ba4d145SBjoern A. Zeeb hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad;
546*8ba4d145SBjoern A. Zeeb if (hdr_trans && ieee80211_has_morefrags(fc)) {
547*8ba4d145SBjoern A. Zeeb if (mt7925_reverse_frag0_hdr_trans(skb, hdr_gap))
548*8ba4d145SBjoern A. Zeeb return -EINVAL;
549*8ba4d145SBjoern A. Zeeb hdr_trans = false;
550*8ba4d145SBjoern A. Zeeb } else {
551*8ba4d145SBjoern A. Zeeb int pad_start = 0;
552*8ba4d145SBjoern A. Zeeb
553*8ba4d145SBjoern A. Zeeb skb_pull(skb, hdr_gap);
554*8ba4d145SBjoern A. Zeeb if (!hdr_trans && status->amsdu) {
555*8ba4d145SBjoern A. Zeeb pad_start = ieee80211_get_hdrlen_from_skb(skb);
556*8ba4d145SBjoern A. Zeeb } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) {
557*8ba4d145SBjoern A. Zeeb /* When header translation failure is indicated,
558*8ba4d145SBjoern A. Zeeb * the hardware will insert an extra 2-byte field
559*8ba4d145SBjoern A. Zeeb * containing the data length after the protocol
560*8ba4d145SBjoern A. Zeeb * type field.
561*8ba4d145SBjoern A. Zeeb */
562*8ba4d145SBjoern A. Zeeb pad_start = 12;
563*8ba4d145SBjoern A. Zeeb if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q)
564*8ba4d145SBjoern A. Zeeb pad_start += 4;
565*8ba4d145SBjoern A. Zeeb else
566*8ba4d145SBjoern A. Zeeb pad_start = 0;
567*8ba4d145SBjoern A. Zeeb }
568*8ba4d145SBjoern A. Zeeb
569*8ba4d145SBjoern A. Zeeb if (pad_start) {
570*8ba4d145SBjoern A. Zeeb memmove(skb->data + 2, skb->data, pad_start);
571*8ba4d145SBjoern A. Zeeb skb_pull(skb, 2);
572*8ba4d145SBjoern A. Zeeb }
573*8ba4d145SBjoern A. Zeeb }
574*8ba4d145SBjoern A. Zeeb
575*8ba4d145SBjoern A. Zeeb if (!hdr_trans) {
576*8ba4d145SBjoern A. Zeeb struct ieee80211_hdr *hdr;
577*8ba4d145SBjoern A. Zeeb
578*8ba4d145SBjoern A. Zeeb if (insert_ccmp_hdr) {
579*8ba4d145SBjoern A. Zeeb u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
580*8ba4d145SBjoern A. Zeeb
581*8ba4d145SBjoern A. Zeeb mt76_insert_ccmp_hdr(skb, key_id);
582*8ba4d145SBjoern A. Zeeb }
583*8ba4d145SBjoern A. Zeeb
584*8ba4d145SBjoern A. Zeeb hdr = mt76_skb_get_hdr(skb);
585*8ba4d145SBjoern A. Zeeb fc = hdr->frame_control;
586*8ba4d145SBjoern A. Zeeb if (ieee80211_is_data_qos(fc)) {
587*8ba4d145SBjoern A. Zeeb seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
588*8ba4d145SBjoern A. Zeeb qos_ctl = *ieee80211_get_qos_ctl(hdr);
589*8ba4d145SBjoern A. Zeeb }
590*8ba4d145SBjoern A. Zeeb skb_set_mac_header(skb, (unsigned char *)hdr - skb->data);
591*8ba4d145SBjoern A. Zeeb } else {
592*8ba4d145SBjoern A. Zeeb status->flag |= RX_FLAG_8023;
593*8ba4d145SBjoern A. Zeeb }
594*8ba4d145SBjoern A. Zeeb
595*8ba4d145SBjoern A. Zeeb mt792x_mac_assoc_rssi(dev, skb);
596*8ba4d145SBjoern A. Zeeb
597*8ba4d145SBjoern A. Zeeb if (rxv && !(status->flag & RX_FLAG_8023)) {
598*8ba4d145SBjoern A. Zeeb switch (status->encoding) {
599*8ba4d145SBjoern A. Zeeb case RX_ENC_EHT:
600*8ba4d145SBjoern A. Zeeb mt76_connac3_mac_decode_eht_radiotap(skb, rxv, mode);
601*8ba4d145SBjoern A. Zeeb break;
602*8ba4d145SBjoern A. Zeeb case RX_ENC_HE:
603*8ba4d145SBjoern A. Zeeb mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
604*8ba4d145SBjoern A. Zeeb break;
605*8ba4d145SBjoern A. Zeeb default:
606*8ba4d145SBjoern A. Zeeb break;
607*8ba4d145SBjoern A. Zeeb }
608*8ba4d145SBjoern A. Zeeb }
609*8ba4d145SBjoern A. Zeeb
610*8ba4d145SBjoern A. Zeeb if (!status->wcid || !ieee80211_is_data_qos(fc))
611*8ba4d145SBjoern A. Zeeb return 0;
612*8ba4d145SBjoern A. Zeeb
613*8ba4d145SBjoern A. Zeeb status->aggr = unicast && !ieee80211_is_qos_nullfunc(fc);
614*8ba4d145SBjoern A. Zeeb status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);
615*8ba4d145SBjoern A. Zeeb status->qos_ctl = qos_ctl;
616*8ba4d145SBjoern A. Zeeb
617*8ba4d145SBjoern A. Zeeb return 0;
618*8ba4d145SBjoern A. Zeeb }
619*8ba4d145SBjoern A. Zeeb
620*8ba4d145SBjoern A. Zeeb static void
mt7925_mac_write_txwi_8023(__le32 * txwi,struct sk_buff * skb,struct mt76_wcid * wcid)621*8ba4d145SBjoern A. Zeeb mt7925_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb,
622*8ba4d145SBjoern A. Zeeb struct mt76_wcid *wcid)
623*8ba4d145SBjoern A. Zeeb {
624*8ba4d145SBjoern A. Zeeb u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
625*8ba4d145SBjoern A. Zeeb u8 fc_type, fc_stype;
626*8ba4d145SBjoern A. Zeeb u16 ethertype;
627*8ba4d145SBjoern A. Zeeb bool wmm = false;
628*8ba4d145SBjoern A. Zeeb u32 val;
629*8ba4d145SBjoern A. Zeeb
630*8ba4d145SBjoern A. Zeeb if (wcid->sta) {
631*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta;
632*8ba4d145SBjoern A. Zeeb
633*8ba4d145SBjoern A. Zeeb sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
634*8ba4d145SBjoern A. Zeeb wmm = sta->wme;
635*8ba4d145SBjoern A. Zeeb }
636*8ba4d145SBjoern A. Zeeb
637*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
638*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD1_TID, tid);
639*8ba4d145SBjoern A. Zeeb
640*8ba4d145SBjoern A. Zeeb ethertype = get_unaligned_be16(&skb->data[12]);
641*8ba4d145SBjoern A. Zeeb if (ethertype >= ETH_P_802_3_MIN)
642*8ba4d145SBjoern A. Zeeb val |= MT_TXD1_ETH_802_3;
643*8ba4d145SBjoern A. Zeeb
644*8ba4d145SBjoern A. Zeeb txwi[1] |= cpu_to_le32(val);
645*8ba4d145SBjoern A. Zeeb
646*8ba4d145SBjoern A. Zeeb fc_type = IEEE80211_FTYPE_DATA >> 2;
647*8ba4d145SBjoern A. Zeeb fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
648*8ba4d145SBjoern A. Zeeb
649*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
650*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
651*8ba4d145SBjoern A. Zeeb
652*8ba4d145SBjoern A. Zeeb txwi[2] |= cpu_to_le32(val);
653*8ba4d145SBjoern A. Zeeb }
654*8ba4d145SBjoern A. Zeeb
655*8ba4d145SBjoern A. Zeeb static void
mt7925_mac_write_txwi_80211(struct mt76_dev * dev,__le32 * txwi,struct sk_buff * skb,struct ieee80211_key_conf * key)656*8ba4d145SBjoern A. Zeeb mt7925_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi,
657*8ba4d145SBjoern A. Zeeb struct sk_buff *skb,
658*8ba4d145SBjoern A. Zeeb struct ieee80211_key_conf *key)
659*8ba4d145SBjoern A. Zeeb {
660*8ba4d145SBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
661*8ba4d145SBjoern A. Zeeb struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
662*8ba4d145SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
663*8ba4d145SBjoern A. Zeeb bool multicast = is_multicast_ether_addr(hdr->addr1);
664*8ba4d145SBjoern A. Zeeb u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
665*8ba4d145SBjoern A. Zeeb __le16 fc = hdr->frame_control;
666*8ba4d145SBjoern A. Zeeb u8 fc_type, fc_stype;
667*8ba4d145SBjoern A. Zeeb u32 val;
668*8ba4d145SBjoern A. Zeeb
669*8ba4d145SBjoern A. Zeeb if (ieee80211_is_action(fc) &&
670*8ba4d145SBjoern A. Zeeb mgmt->u.action.category == WLAN_CATEGORY_BACK &&
671*8ba4d145SBjoern A. Zeeb mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)
672*8ba4d145SBjoern A. Zeeb tid = MT_TX_ADDBA;
673*8ba4d145SBjoern A. Zeeb else if (ieee80211_is_mgmt(hdr->frame_control))
674*8ba4d145SBjoern A. Zeeb tid = MT_TX_NORMAL;
675*8ba4d145SBjoern A. Zeeb
676*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
677*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD1_HDR_INFO,
678*8ba4d145SBjoern A. Zeeb ieee80211_get_hdrlen_from_skb(skb) / 2) |
679*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD1_TID, tid);
680*8ba4d145SBjoern A. Zeeb
681*8ba4d145SBjoern A. Zeeb if (!ieee80211_is_data(fc) || multicast ||
682*8ba4d145SBjoern A. Zeeb info->flags & IEEE80211_TX_CTL_USE_MINRATE)
683*8ba4d145SBjoern A. Zeeb val |= MT_TXD1_FIXED_RATE;
684*8ba4d145SBjoern A. Zeeb
685*8ba4d145SBjoern A. Zeeb if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
686*8ba4d145SBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
687*8ba4d145SBjoern A. Zeeb val |= MT_TXD1_BIP;
688*8ba4d145SBjoern A. Zeeb txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
689*8ba4d145SBjoern A. Zeeb }
690*8ba4d145SBjoern A. Zeeb
691*8ba4d145SBjoern A. Zeeb txwi[1] |= cpu_to_le32(val);
692*8ba4d145SBjoern A. Zeeb
693*8ba4d145SBjoern A. Zeeb fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
694*8ba4d145SBjoern A. Zeeb fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
695*8ba4d145SBjoern A. Zeeb
696*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
697*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
698*8ba4d145SBjoern A. Zeeb
699*8ba4d145SBjoern A. Zeeb txwi[2] |= cpu_to_le32(val);
700*8ba4d145SBjoern A. Zeeb
701*8ba4d145SBjoern A. Zeeb txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast));
702*8ba4d145SBjoern A. Zeeb if (ieee80211_is_beacon(fc))
703*8ba4d145SBjoern A. Zeeb txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
704*8ba4d145SBjoern A. Zeeb
705*8ba4d145SBjoern A. Zeeb if (info->flags & IEEE80211_TX_CTL_INJECTED) {
706*8ba4d145SBjoern A. Zeeb u16 seqno = le16_to_cpu(hdr->seq_ctrl);
707*8ba4d145SBjoern A. Zeeb
708*8ba4d145SBjoern A. Zeeb if (ieee80211_is_back_req(hdr->frame_control)) {
709*8ba4d145SBjoern A. Zeeb struct ieee80211_bar *bar;
710*8ba4d145SBjoern A. Zeeb
711*8ba4d145SBjoern A. Zeeb bar = (struct ieee80211_bar *)skb->data;
712*8ba4d145SBjoern A. Zeeb seqno = le16_to_cpu(bar->start_seq_num);
713*8ba4d145SBjoern A. Zeeb }
714*8ba4d145SBjoern A. Zeeb
715*8ba4d145SBjoern A. Zeeb val = MT_TXD3_SN_VALID |
716*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
717*8ba4d145SBjoern A. Zeeb txwi[3] |= cpu_to_le32(val);
718*8ba4d145SBjoern A. Zeeb txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
719*8ba4d145SBjoern A. Zeeb }
720*8ba4d145SBjoern A. Zeeb }
721*8ba4d145SBjoern A. Zeeb
722*8ba4d145SBjoern A. Zeeb void
mt7925_mac_write_txwi(struct mt76_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)723*8ba4d145SBjoern A. Zeeb mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
724*8ba4d145SBjoern A. Zeeb struct sk_buff *skb, struct mt76_wcid *wcid,
725*8ba4d145SBjoern A. Zeeb struct ieee80211_key_conf *key, int pid,
726*8ba4d145SBjoern A. Zeeb enum mt76_txq_id qid, u32 changed)
727*8ba4d145SBjoern A. Zeeb {
728*8ba4d145SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
729*8ba4d145SBjoern A. Zeeb struct ieee80211_vif *vif = info->control.vif;
730*8ba4d145SBjoern A. Zeeb u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0, band_idx = 0;
731*8ba4d145SBjoern A. Zeeb u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE;
732*8ba4d145SBjoern A. Zeeb bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
733*8ba4d145SBjoern A. Zeeb struct mt76_vif_link *mvif;
734*8ba4d145SBjoern A. Zeeb bool beacon = !!(changed & (BSS_CHANGED_BEACON |
735*8ba4d145SBjoern A. Zeeb BSS_CHANGED_BEACON_ENABLED));
736*8ba4d145SBjoern A. Zeeb bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
737*8ba4d145SBjoern A. Zeeb BSS_CHANGED_FILS_DISCOVERY));
738*8ba4d145SBjoern A. Zeeb struct mt792x_bss_conf *mconf;
739*8ba4d145SBjoern A. Zeeb
740*8ba4d145SBjoern A. Zeeb mconf = vif ? mt792x_vif_to_link((struct mt792x_vif *)vif->drv_priv,
741*8ba4d145SBjoern A. Zeeb wcid->link_id) : NULL;
742*8ba4d145SBjoern A. Zeeb mvif = mconf ? (struct mt76_vif_link *)&mconf->mt76 : NULL;
743*8ba4d145SBjoern A. Zeeb
744*8ba4d145SBjoern A. Zeeb if (mvif) {
745*8ba4d145SBjoern A. Zeeb omac_idx = mvif->omac_idx;
746*8ba4d145SBjoern A. Zeeb wmm_idx = mvif->wmm_idx;
747*8ba4d145SBjoern A. Zeeb band_idx = mvif->band_idx;
748*8ba4d145SBjoern A. Zeeb }
749*8ba4d145SBjoern A. Zeeb
750*8ba4d145SBjoern A. Zeeb if (inband_disc) {
751*8ba4d145SBjoern A. Zeeb p_fmt = MT_TX_TYPE_FW;
752*8ba4d145SBjoern A. Zeeb q_idx = MT_LMAC_ALTX0;
753*8ba4d145SBjoern A. Zeeb } else if (beacon) {
754*8ba4d145SBjoern A. Zeeb p_fmt = MT_TX_TYPE_FW;
755*8ba4d145SBjoern A. Zeeb q_idx = MT_LMAC_BCN0;
756*8ba4d145SBjoern A. Zeeb } else if (qid >= MT_TXQ_PSD) {
757*8ba4d145SBjoern A. Zeeb p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
758*8ba4d145SBjoern A. Zeeb q_idx = MT_LMAC_ALTX0;
759*8ba4d145SBjoern A. Zeeb } else {
760*8ba4d145SBjoern A. Zeeb p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
761*8ba4d145SBjoern A. Zeeb q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
762*8ba4d145SBjoern A. Zeeb mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
763*8ba4d145SBjoern A. Zeeb
764*8ba4d145SBjoern A. Zeeb /* counting non-offloading skbs */
765*8ba4d145SBjoern A. Zeeb wcid->stats.tx_bytes += skb->len;
766*8ba4d145SBjoern A. Zeeb wcid->stats.tx_packets++;
767*8ba4d145SBjoern A. Zeeb }
768*8ba4d145SBjoern A. Zeeb
769*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
770*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
771*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
772*8ba4d145SBjoern A. Zeeb txwi[0] = cpu_to_le32(val);
773*8ba4d145SBjoern A. Zeeb
774*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
775*8ba4d145SBjoern A. Zeeb FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
776*8ba4d145SBjoern A. Zeeb
777*8ba4d145SBjoern A. Zeeb if (band_idx)
778*8ba4d145SBjoern A. Zeeb val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
779*8ba4d145SBjoern A. Zeeb
780*8ba4d145SBjoern A. Zeeb txwi[1] = cpu_to_le32(val);
781*8ba4d145SBjoern A. Zeeb txwi[2] = 0;
782*8ba4d145SBjoern A. Zeeb
783*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15);
784*8ba4d145SBjoern A. Zeeb
785*8ba4d145SBjoern A. Zeeb if (key)
786*8ba4d145SBjoern A. Zeeb val |= MT_TXD3_PROTECT_FRAME;
787*8ba4d145SBjoern A. Zeeb if (info->flags & IEEE80211_TX_CTL_NO_ACK)
788*8ba4d145SBjoern A. Zeeb val |= MT_TXD3_NO_ACK;
789*8ba4d145SBjoern A. Zeeb if (wcid->amsdu)
790*8ba4d145SBjoern A. Zeeb val |= MT_TXD3_HW_AMSDU;
791*8ba4d145SBjoern A. Zeeb
792*8ba4d145SBjoern A. Zeeb txwi[3] = cpu_to_le32(val);
793*8ba4d145SBjoern A. Zeeb txwi[4] = 0;
794*8ba4d145SBjoern A. Zeeb
795*8ba4d145SBjoern A. Zeeb val = FIELD_PREP(MT_TXD5_PID, pid);
796*8ba4d145SBjoern A. Zeeb if (pid >= MT_PACKET_ID_FIRST) {
797*8ba4d145SBjoern A. Zeeb val |= MT_TXD5_TX_STATUS_HOST;
798*8ba4d145SBjoern A. Zeeb txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
799*8ba4d145SBjoern A. Zeeb txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
800*8ba4d145SBjoern A. Zeeb }
801*8ba4d145SBjoern A. Zeeb
802*8ba4d145SBjoern A. Zeeb txwi[5] = cpu_to_le32(val);
803*8ba4d145SBjoern A. Zeeb
804*8ba4d145SBjoern A. Zeeb val = MT_TXD6_DAS | FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
805*8ba4d145SBjoern A. Zeeb if (!ieee80211_vif_is_mld(vif) ||
806*8ba4d145SBjoern A. Zeeb (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0))
807*8ba4d145SBjoern A. Zeeb val |= MT_TXD6_DIS_MAT;
808*8ba4d145SBjoern A. Zeeb txwi[6] = cpu_to_le32(val);
809*8ba4d145SBjoern A. Zeeb txwi[7] = 0;
810*8ba4d145SBjoern A. Zeeb
811*8ba4d145SBjoern A. Zeeb if (is_8023)
812*8ba4d145SBjoern A. Zeeb mt7925_mac_write_txwi_8023(txwi, skb, wcid);
813*8ba4d145SBjoern A. Zeeb else
814*8ba4d145SBjoern A. Zeeb mt7925_mac_write_txwi_80211(dev, txwi, skb, key);
815*8ba4d145SBjoern A. Zeeb
816*8ba4d145SBjoern A. Zeeb if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
817*8ba4d145SBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
818*8ba4d145SBjoern A. Zeeb bool mcast = ieee80211_is_data(hdr->frame_control) &&
819*8ba4d145SBjoern A. Zeeb is_multicast_ether_addr(hdr->addr1);
820*8ba4d145SBjoern A. Zeeb u8 idx = MT792x_BASIC_RATES_TBL;
821*8ba4d145SBjoern A. Zeeb
822*8ba4d145SBjoern A. Zeeb if (mvif) {
823*8ba4d145SBjoern A. Zeeb if (mcast && mvif->mcast_rates_idx)
824*8ba4d145SBjoern A. Zeeb idx = mvif->mcast_rates_idx;
825*8ba4d145SBjoern A. Zeeb else if (beacon && mvif->beacon_rates_idx)
826*8ba4d145SBjoern A. Zeeb idx = mvif->beacon_rates_idx;
827*8ba4d145SBjoern A. Zeeb else
828*8ba4d145SBjoern A. Zeeb idx = mvif->basic_rates_idx;
829*8ba4d145SBjoern A. Zeeb }
830*8ba4d145SBjoern A. Zeeb
831*8ba4d145SBjoern A. Zeeb txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx));
832*8ba4d145SBjoern A. Zeeb txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
833*8ba4d145SBjoern A. Zeeb }
834*8ba4d145SBjoern A. Zeeb }
835*8ba4d145SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7925_mac_write_txwi);
836*8ba4d145SBjoern A. Zeeb
mt7925_tx_check_aggr(struct ieee80211_sta * sta,struct sk_buff * skb,struct mt76_wcid * wcid)837*8ba4d145SBjoern A. Zeeb static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb,
838*8ba4d145SBjoern A. Zeeb struct mt76_wcid *wcid)
839*8ba4d145SBjoern A. Zeeb {
840*8ba4d145SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
841*8ba4d145SBjoern A. Zeeb struct ieee80211_link_sta *link_sta;
842*8ba4d145SBjoern A. Zeeb struct mt792x_link_sta *mlink;
843*8ba4d145SBjoern A. Zeeb struct mt792x_sta *msta;
844*8ba4d145SBjoern A. Zeeb bool is_8023;
845*8ba4d145SBjoern A. Zeeb u16 fc, tid;
846*8ba4d145SBjoern A. Zeeb
847*8ba4d145SBjoern A. Zeeb link_sta = rcu_dereference(sta->link[wcid->link_id]);
848*8ba4d145SBjoern A. Zeeb if (!link_sta)
849*8ba4d145SBjoern A. Zeeb return;
850*8ba4d145SBjoern A. Zeeb
851*8ba4d145SBjoern A. Zeeb if (!sta || !(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
852*8ba4d145SBjoern A. Zeeb return;
853*8ba4d145SBjoern A. Zeeb
854*8ba4d145SBjoern A. Zeeb tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
855*8ba4d145SBjoern A. Zeeb is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
856*8ba4d145SBjoern A. Zeeb
857*8ba4d145SBjoern A. Zeeb if (is_8023) {
858*8ba4d145SBjoern A. Zeeb fc = IEEE80211_FTYPE_DATA |
859*8ba4d145SBjoern A. Zeeb (sta->wme ? IEEE80211_STYPE_QOS_DATA :
860*8ba4d145SBjoern A. Zeeb IEEE80211_STYPE_DATA);
861*8ba4d145SBjoern A. Zeeb } else {
862*8ba4d145SBjoern A. Zeeb /* No need to get precise TID for Action/Management Frame,
863*8ba4d145SBjoern A. Zeeb * since it will not meet the following Frame Control
864*8ba4d145SBjoern A. Zeeb * condition anyway.
865*8ba4d145SBjoern A. Zeeb */
866*8ba4d145SBjoern A. Zeeb
867*8ba4d145SBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
868*8ba4d145SBjoern A. Zeeb
869*8ba4d145SBjoern A. Zeeb fc = le16_to_cpu(hdr->frame_control) &
870*8ba4d145SBjoern A. Zeeb (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
871*8ba4d145SBjoern A. Zeeb }
872*8ba4d145SBjoern A. Zeeb
873*8ba4d145SBjoern A. Zeeb if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
874*8ba4d145SBjoern A. Zeeb return;
875*8ba4d145SBjoern A. Zeeb
876*8ba4d145SBjoern A. Zeeb msta = (struct mt792x_sta *)sta->drv_priv;
877*8ba4d145SBjoern A. Zeeb
878*8ba4d145SBjoern A. Zeeb if (sta->mlo && msta->deflink_id != IEEE80211_LINK_UNSPECIFIED)
879*8ba4d145SBjoern A. Zeeb mlink = rcu_dereference(msta->link[msta->deflink_id]);
880*8ba4d145SBjoern A. Zeeb else
881*8ba4d145SBjoern A. Zeeb mlink = &msta->deflink;
882*8ba4d145SBjoern A. Zeeb
883*8ba4d145SBjoern A. Zeeb if (!test_and_set_bit(tid, &mlink->wcid.ampdu_state))
884*8ba4d145SBjoern A. Zeeb ieee80211_start_tx_ba_session(sta, tid, 0);
885*8ba4d145SBjoern A. Zeeb }
886*8ba4d145SBjoern A. Zeeb
887*8ba4d145SBjoern A. Zeeb static bool
mt7925_mac_add_txs_skb(struct mt792x_dev * dev,struct mt76_wcid * wcid,int pid,__le32 * txs_data)888*8ba4d145SBjoern A. Zeeb mt7925_mac_add_txs_skb(struct mt792x_dev *dev, struct mt76_wcid *wcid,
889*8ba4d145SBjoern A. Zeeb int pid, __le32 *txs_data)
890*8ba4d145SBjoern A. Zeeb {
891*8ba4d145SBjoern A. Zeeb struct mt76_sta_stats *stats = &wcid->stats;
892*8ba4d145SBjoern A. Zeeb struct ieee80211_supported_band *sband;
893*8ba4d145SBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76;
894*8ba4d145SBjoern A. Zeeb struct mt76_phy *mphy;
895*8ba4d145SBjoern A. Zeeb struct ieee80211_tx_info *info;
896*8ba4d145SBjoern A. Zeeb struct sk_buff_head list;
897*8ba4d145SBjoern A. Zeeb struct rate_info rate = {};
898*8ba4d145SBjoern A. Zeeb struct sk_buff *skb;
899*8ba4d145SBjoern A. Zeeb bool cck = false;
900*8ba4d145SBjoern A. Zeeb u32 txrate, txs, mode, stbc;
901*8ba4d145SBjoern A. Zeeb
902*8ba4d145SBjoern A. Zeeb mt76_tx_status_lock(mdev, &list);
903*8ba4d145SBjoern A. Zeeb skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
904*8ba4d145SBjoern A. Zeeb if (!skb)
905*8ba4d145SBjoern A. Zeeb goto out_no_skb;
906*8ba4d145SBjoern A. Zeeb
907*8ba4d145SBjoern A. Zeeb txs = le32_to_cpu(txs_data[0]);
908*8ba4d145SBjoern A. Zeeb
909*8ba4d145SBjoern A. Zeeb info = IEEE80211_SKB_CB(skb);
910*8ba4d145SBjoern A. Zeeb if (!(txs & MT_TXS0_ACK_ERROR_MASK))
911*8ba4d145SBjoern A. Zeeb info->flags |= IEEE80211_TX_STAT_ACK;
912*8ba4d145SBjoern A. Zeeb
913*8ba4d145SBjoern A. Zeeb info->status.ampdu_len = 1;
914*8ba4d145SBjoern A. Zeeb info->status.ampdu_ack_len = !!(info->flags &
915*8ba4d145SBjoern A. Zeeb IEEE80211_TX_STAT_ACK);
916*8ba4d145SBjoern A. Zeeb
917*8ba4d145SBjoern A. Zeeb info->status.rates[0].idx = -1;
918*8ba4d145SBjoern A. Zeeb
919*8ba4d145SBjoern A. Zeeb txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
920*8ba4d145SBjoern A. Zeeb
921*8ba4d145SBjoern A. Zeeb rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
922*8ba4d145SBjoern A. Zeeb rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
923*8ba4d145SBjoern A. Zeeb stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
924*8ba4d145SBjoern A. Zeeb
925*8ba4d145SBjoern A. Zeeb if (stbc && rate.nss > 1)
926*8ba4d145SBjoern A. Zeeb rate.nss >>= 1;
927*8ba4d145SBjoern A. Zeeb
928*8ba4d145SBjoern A. Zeeb if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
929*8ba4d145SBjoern A. Zeeb stats->tx_nss[rate.nss - 1]++;
930*8ba4d145SBjoern A. Zeeb if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
931*8ba4d145SBjoern A. Zeeb stats->tx_mcs[rate.mcs]++;
932*8ba4d145SBjoern A. Zeeb
933*8ba4d145SBjoern A. Zeeb mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
934*8ba4d145SBjoern A. Zeeb switch (mode) {
935*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_CCK:
936*8ba4d145SBjoern A. Zeeb cck = true;
937*8ba4d145SBjoern A. Zeeb fallthrough;
938*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_OFDM:
939*8ba4d145SBjoern A. Zeeb mphy = mt76_dev_phy(mdev, wcid->phy_idx);
940*8ba4d145SBjoern A. Zeeb
941*8ba4d145SBjoern A. Zeeb if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
942*8ba4d145SBjoern A. Zeeb sband = &mphy->sband_5g.sband;
943*8ba4d145SBjoern A. Zeeb else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
944*8ba4d145SBjoern A. Zeeb sband = &mphy->sband_6g.sband;
945*8ba4d145SBjoern A. Zeeb else
946*8ba4d145SBjoern A. Zeeb sband = &mphy->sband_2g.sband;
947*8ba4d145SBjoern A. Zeeb
948*8ba4d145SBjoern A. Zeeb rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck);
949*8ba4d145SBjoern A. Zeeb rate.legacy = sband->bitrates[rate.mcs].bitrate;
950*8ba4d145SBjoern A. Zeeb break;
951*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HT:
952*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HT_GF:
953*8ba4d145SBjoern A. Zeeb if (rate.mcs > 31)
954*8ba4d145SBjoern A. Zeeb goto out;
955*8ba4d145SBjoern A. Zeeb
956*8ba4d145SBjoern A. Zeeb rate.flags = RATE_INFO_FLAGS_MCS;
957*8ba4d145SBjoern A. Zeeb if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
958*8ba4d145SBjoern A. Zeeb rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
959*8ba4d145SBjoern A. Zeeb break;
960*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_VHT:
961*8ba4d145SBjoern A. Zeeb if (rate.mcs > 9)
962*8ba4d145SBjoern A. Zeeb goto out;
963*8ba4d145SBjoern A. Zeeb
964*8ba4d145SBjoern A. Zeeb rate.flags = RATE_INFO_FLAGS_VHT_MCS;
965*8ba4d145SBjoern A. Zeeb break;
966*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HE_SU:
967*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HE_EXT_SU:
968*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HE_TB:
969*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_HE_MU:
970*8ba4d145SBjoern A. Zeeb if (rate.mcs > 11)
971*8ba4d145SBjoern A. Zeeb goto out;
972*8ba4d145SBjoern A. Zeeb
973*8ba4d145SBjoern A. Zeeb rate.he_gi = wcid->rate.he_gi;
974*8ba4d145SBjoern A. Zeeb rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
975*8ba4d145SBjoern A. Zeeb rate.flags = RATE_INFO_FLAGS_HE_MCS;
976*8ba4d145SBjoern A. Zeeb break;
977*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_EHT_SU:
978*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_EHT_TRIG:
979*8ba4d145SBjoern A. Zeeb case MT_PHY_TYPE_EHT_MU:
980*8ba4d145SBjoern A. Zeeb if (rate.mcs > 13)
981*8ba4d145SBjoern A. Zeeb goto out;
982*8ba4d145SBjoern A. Zeeb
983*8ba4d145SBjoern A. Zeeb rate.eht_gi = wcid->rate.eht_gi;
984*8ba4d145SBjoern A. Zeeb rate.flags = RATE_INFO_FLAGS_EHT_MCS;
985*8ba4d145SBjoern A. Zeeb break;
986*8ba4d145SBjoern A. Zeeb default:
987*8ba4d145SBjoern A. Zeeb goto out;
988*8ba4d145SBjoern A. Zeeb }
989*8ba4d145SBjoern A. Zeeb
990*8ba4d145SBjoern A. Zeeb stats->tx_mode[mode]++;
991*8ba4d145SBjoern A. Zeeb
992*8ba4d145SBjoern A. Zeeb switch (FIELD_GET(MT_TXS0_BW, txs)) {
993*8ba4d145SBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
994*8ba4d145SBjoern A. Zeeb rate.bw = RATE_INFO_BW_160;
995*8ba4d145SBjoern A. Zeeb stats->tx_bw[3]++;
996*8ba4d145SBjoern A. Zeeb break;
997*8ba4d145SBjoern A. Zeeb case IEEE80211_STA_RX_BW_80:
998*8ba4d145SBjoern A. Zeeb rate.bw = RATE_INFO_BW_80;
999*8ba4d145SBjoern A. Zeeb stats->tx_bw[2]++;
1000*8ba4d145SBjoern A. Zeeb break;
1001*8ba4d145SBjoern A. Zeeb case IEEE80211_STA_RX_BW_40:
1002*8ba4d145SBjoern A. Zeeb rate.bw = RATE_INFO_BW_40;
1003*8ba4d145SBjoern A. Zeeb stats->tx_bw[1]++;
1004*8ba4d145SBjoern A. Zeeb break;
1005*8ba4d145SBjoern A. Zeeb default:
1006*8ba4d145SBjoern A. Zeeb rate.bw = RATE_INFO_BW_20;
1007*8ba4d145SBjoern A. Zeeb stats->tx_bw[0]++;
1008*8ba4d145SBjoern A. Zeeb break;
1009*8ba4d145SBjoern A. Zeeb }
1010*8ba4d145SBjoern A. Zeeb wcid->rate = rate;
1011*8ba4d145SBjoern A. Zeeb
1012*8ba4d145SBjoern A. Zeeb out:
1013*8ba4d145SBjoern A. Zeeb mt76_tx_status_skb_done(mdev, skb, &list);
1014*8ba4d145SBjoern A. Zeeb
1015*8ba4d145SBjoern A. Zeeb out_no_skb:
1016*8ba4d145SBjoern A. Zeeb mt76_tx_status_unlock(mdev, &list);
1017*8ba4d145SBjoern A. Zeeb
1018*8ba4d145SBjoern A. Zeeb return !!skb;
1019*8ba4d145SBjoern A. Zeeb }
1020*8ba4d145SBjoern A. Zeeb
mt7925_mac_add_txs(struct mt792x_dev * dev,void * data)1021*8ba4d145SBjoern A. Zeeb void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data)
1022*8ba4d145SBjoern A. Zeeb {
1023*8ba4d145SBjoern A. Zeeb struct mt792x_link_sta *mlink = NULL;
1024*8ba4d145SBjoern A. Zeeb struct mt76_wcid *wcid;
1025*8ba4d145SBjoern A. Zeeb __le32 *txs_data = data;
1026*8ba4d145SBjoern A. Zeeb u16 wcidx;
1027*8ba4d145SBjoern A. Zeeb u8 pid;
1028*8ba4d145SBjoern A. Zeeb
1029*8ba4d145SBjoern A. Zeeb if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
1030*8ba4d145SBjoern A. Zeeb return;
1031*8ba4d145SBjoern A. Zeeb
1032*8ba4d145SBjoern A. Zeeb wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
1033*8ba4d145SBjoern A. Zeeb pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
1034*8ba4d145SBjoern A. Zeeb
1035*8ba4d145SBjoern A. Zeeb if (pid < MT_PACKET_ID_FIRST)
1036*8ba4d145SBjoern A. Zeeb return;
1037*8ba4d145SBjoern A. Zeeb
1038*8ba4d145SBjoern A. Zeeb if (wcidx >= MT792x_WTBL_SIZE)
1039*8ba4d145SBjoern A. Zeeb return;
1040*8ba4d145SBjoern A. Zeeb
1041*8ba4d145SBjoern A. Zeeb rcu_read_lock();
1042*8ba4d145SBjoern A. Zeeb
1043*8ba4d145SBjoern A. Zeeb wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
1044*8ba4d145SBjoern A. Zeeb if (!wcid)
1045*8ba4d145SBjoern A. Zeeb goto out;
1046*8ba4d145SBjoern A. Zeeb
1047*8ba4d145SBjoern A. Zeeb mlink = container_of(wcid, struct mt792x_link_sta, wcid);
1048*8ba4d145SBjoern A. Zeeb
1049*8ba4d145SBjoern A. Zeeb mt7925_mac_add_txs_skb(dev, wcid, pid, txs_data);
1050*8ba4d145SBjoern A. Zeeb if (!wcid->sta)
1051*8ba4d145SBjoern A. Zeeb goto out;
1052*8ba4d145SBjoern A. Zeeb
1053*8ba4d145SBjoern A. Zeeb mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
1054*8ba4d145SBjoern A. Zeeb
1055*8ba4d145SBjoern A. Zeeb out:
1056*8ba4d145SBjoern A. Zeeb rcu_read_unlock();
1057*8ba4d145SBjoern A. Zeeb }
1058*8ba4d145SBjoern A. Zeeb
mt7925_txwi_free(struct mt792x_dev * dev,struct mt76_txwi_cache * t,struct ieee80211_sta * sta,struct mt76_wcid * wcid,struct list_head * free_list)1059*8ba4d145SBjoern A. Zeeb void mt7925_txwi_free(struct mt792x_dev *dev, struct mt76_txwi_cache *t,
1060*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta, struct mt76_wcid *wcid,
1061*8ba4d145SBjoern A. Zeeb struct list_head *free_list)
1062*8ba4d145SBjoern A. Zeeb {
1063*8ba4d145SBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76;
1064*8ba4d145SBjoern A. Zeeb __le32 *txwi;
1065*8ba4d145SBjoern A. Zeeb u16 wcid_idx;
1066*8ba4d145SBjoern A. Zeeb
1067*8ba4d145SBjoern A. Zeeb mt76_connac_txp_skb_unmap(mdev, t);
1068*8ba4d145SBjoern A. Zeeb if (!t->skb)
1069*8ba4d145SBjoern A. Zeeb goto out;
1070*8ba4d145SBjoern A. Zeeb
1071*8ba4d145SBjoern A. Zeeb txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
1072*8ba4d145SBjoern A. Zeeb if (sta) {
1073*8ba4d145SBjoern A. Zeeb if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
1074*8ba4d145SBjoern A. Zeeb mt7925_tx_check_aggr(sta, t->skb, wcid);
1075*8ba4d145SBjoern A. Zeeb
1076*8ba4d145SBjoern A. Zeeb wcid_idx = wcid->idx;
1077*8ba4d145SBjoern A. Zeeb } else {
1078*8ba4d145SBjoern A. Zeeb wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
1079*8ba4d145SBjoern A. Zeeb }
1080*8ba4d145SBjoern A. Zeeb
1081*8ba4d145SBjoern A. Zeeb __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
1082*8ba4d145SBjoern A. Zeeb out:
1083*8ba4d145SBjoern A. Zeeb t->skb = NULL;
1084*8ba4d145SBjoern A. Zeeb mt76_put_txwi(mdev, t);
1085*8ba4d145SBjoern A. Zeeb }
1086*8ba4d145SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7925_txwi_free);
1087*8ba4d145SBjoern A. Zeeb
1088*8ba4d145SBjoern A. Zeeb static void
mt7925_mac_tx_free(struct mt792x_dev * dev,void * data,int len)1089*8ba4d145SBjoern A. Zeeb mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
1090*8ba4d145SBjoern A. Zeeb {
1091*8ba4d145SBjoern A. Zeeb __le32 *tx_free = (__le32 *)data, *cur_info;
1092*8ba4d145SBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76;
1093*8ba4d145SBjoern A. Zeeb struct mt76_txwi_cache *txwi;
1094*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta = NULL;
1095*8ba4d145SBjoern A. Zeeb struct mt76_wcid *wcid = NULL;
1096*8ba4d145SBjoern A. Zeeb LIST_HEAD(free_list);
1097*8ba4d145SBjoern A. Zeeb struct sk_buff *skb, *tmp;
1098*8ba4d145SBjoern A. Zeeb #if defined(__linux__)
1099*8ba4d145SBjoern A. Zeeb void *end = data + len;
1100*8ba4d145SBjoern A. Zeeb #elif defined(__FreeBSD__)
1101*8ba4d145SBjoern A. Zeeb void *end = (u8 *)data + len;
1102*8ba4d145SBjoern A. Zeeb #endif
1103*8ba4d145SBjoern A. Zeeb bool wake = false;
1104*8ba4d145SBjoern A. Zeeb u16 total, count = 0;
1105*8ba4d145SBjoern A. Zeeb
1106*8ba4d145SBjoern A. Zeeb /* clean DMA queues and unmap buffers first */
1107*8ba4d145SBjoern A. Zeeb mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
1108*8ba4d145SBjoern A. Zeeb mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
1109*8ba4d145SBjoern A. Zeeb
1110*8ba4d145SBjoern A. Zeeb if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4))
1111*8ba4d145SBjoern A. Zeeb return;
1112*8ba4d145SBjoern A. Zeeb
1113*8ba4d145SBjoern A. Zeeb total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT);
1114*8ba4d145SBjoern A. Zeeb for (cur_info = &tx_free[2]; count < total; cur_info++) {
1115*8ba4d145SBjoern A. Zeeb u32 msdu, info;
1116*8ba4d145SBjoern A. Zeeb u8 i;
1117*8ba4d145SBjoern A. Zeeb
1118*8ba4d145SBjoern A. Zeeb if (WARN_ON_ONCE((void *)cur_info >= end))
1119*8ba4d145SBjoern A. Zeeb return;
1120*8ba4d145SBjoern A. Zeeb /* 1'b1: new wcid pair.
1121*8ba4d145SBjoern A. Zeeb * 1'b0: msdu_id with the same 'wcid pair' as above.
1122*8ba4d145SBjoern A. Zeeb */
1123*8ba4d145SBjoern A. Zeeb info = le32_to_cpu(*cur_info);
1124*8ba4d145SBjoern A. Zeeb if (info & MT_TXFREE_INFO_PAIR) {
1125*8ba4d145SBjoern A. Zeeb struct mt792x_link_sta *mlink;
1126*8ba4d145SBjoern A. Zeeb u16 idx;
1127*8ba4d145SBjoern A. Zeeb
1128*8ba4d145SBjoern A. Zeeb idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
1129*8ba4d145SBjoern A. Zeeb wcid = rcu_dereference(dev->mt76.wcid[idx]);
1130*8ba4d145SBjoern A. Zeeb sta = wcid_to_sta(wcid);
1131*8ba4d145SBjoern A. Zeeb if (!sta)
1132*8ba4d145SBjoern A. Zeeb continue;
1133*8ba4d145SBjoern A. Zeeb
1134*8ba4d145SBjoern A. Zeeb mlink = container_of(wcid, struct mt792x_link_sta, wcid);
1135*8ba4d145SBjoern A. Zeeb mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
1136*8ba4d145SBjoern A. Zeeb continue;
1137*8ba4d145SBjoern A. Zeeb }
1138*8ba4d145SBjoern A. Zeeb
1139*8ba4d145SBjoern A. Zeeb if (info & MT_TXFREE_INFO_HEADER) {
1140*8ba4d145SBjoern A. Zeeb if (wcid) {
1141*8ba4d145SBjoern A. Zeeb wcid->stats.tx_retries +=
1142*8ba4d145SBjoern A. Zeeb FIELD_GET(MT_TXFREE_INFO_COUNT, info) - 1;
1143*8ba4d145SBjoern A. Zeeb wcid->stats.tx_failed +=
1144*8ba4d145SBjoern A. Zeeb !!FIELD_GET(MT_TXFREE_INFO_STAT, info);
1145*8ba4d145SBjoern A. Zeeb }
1146*8ba4d145SBjoern A. Zeeb continue;
1147*8ba4d145SBjoern A. Zeeb }
1148*8ba4d145SBjoern A. Zeeb
1149*8ba4d145SBjoern A. Zeeb for (i = 0; i < 2; i++) {
1150*8ba4d145SBjoern A. Zeeb msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID;
1151*8ba4d145SBjoern A. Zeeb if (msdu == MT_TXFREE_INFO_MSDU_ID)
1152*8ba4d145SBjoern A. Zeeb continue;
1153*8ba4d145SBjoern A. Zeeb
1154*8ba4d145SBjoern A. Zeeb count++;
1155*8ba4d145SBjoern A. Zeeb txwi = mt76_token_release(mdev, msdu, &wake);
1156*8ba4d145SBjoern A. Zeeb if (!txwi)
1157*8ba4d145SBjoern A. Zeeb continue;
1158*8ba4d145SBjoern A. Zeeb
1159*8ba4d145SBjoern A. Zeeb mt7925_txwi_free(dev, txwi, sta, wcid, &free_list);
1160*8ba4d145SBjoern A. Zeeb }
1161*8ba4d145SBjoern A. Zeeb }
1162*8ba4d145SBjoern A. Zeeb
1163*8ba4d145SBjoern A. Zeeb mt7925_mac_sta_poll(dev);
1164*8ba4d145SBjoern A. Zeeb
1165*8ba4d145SBjoern A. Zeeb if (wake)
1166*8ba4d145SBjoern A. Zeeb mt76_set_tx_blocked(&dev->mt76, false);
1167*8ba4d145SBjoern A. Zeeb
1168*8ba4d145SBjoern A. Zeeb mt76_worker_schedule(&dev->mt76.tx_worker);
1169*8ba4d145SBjoern A. Zeeb
1170*8ba4d145SBjoern A. Zeeb list_for_each_entry_safe(skb, tmp, &free_list, list) {
1171*8ba4d145SBjoern A. Zeeb skb_list_del_init(skb);
1172*8ba4d145SBjoern A. Zeeb napi_consume_skb(skb, 1);
1173*8ba4d145SBjoern A. Zeeb }
1174*8ba4d145SBjoern A. Zeeb }
1175*8ba4d145SBjoern A. Zeeb
mt7925_rx_check(struct mt76_dev * mdev,void * data,int len)1176*8ba4d145SBjoern A. Zeeb bool mt7925_rx_check(struct mt76_dev *mdev, void *data, int len)
1177*8ba4d145SBjoern A. Zeeb {
1178*8ba4d145SBjoern A. Zeeb struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
1179*8ba4d145SBjoern A. Zeeb __le32 *rxd = (__le32 *)data;
1180*8ba4d145SBjoern A. Zeeb __le32 *end = (__le32 *)&rxd[len / 4];
1181*8ba4d145SBjoern A. Zeeb enum rx_pkt_type type;
1182*8ba4d145SBjoern A. Zeeb
1183*8ba4d145SBjoern A. Zeeb type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
1184*8ba4d145SBjoern A. Zeeb if (type != PKT_TYPE_NORMAL) {
1185*8ba4d145SBjoern A. Zeeb u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK);
1186*8ba4d145SBjoern A. Zeeb
1187*8ba4d145SBjoern A. Zeeb if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) ==
1188*8ba4d145SBjoern A. Zeeb MT_RXD0_SW_PKT_TYPE_FRAME))
1189*8ba4d145SBjoern A. Zeeb return true;
1190*8ba4d145SBjoern A. Zeeb }
1191*8ba4d145SBjoern A. Zeeb
1192*8ba4d145SBjoern A. Zeeb switch (type) {
1193*8ba4d145SBjoern A. Zeeb case PKT_TYPE_TXRX_NOTIFY:
1194*8ba4d145SBjoern A. Zeeb /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */
1195*8ba4d145SBjoern A. Zeeb mt7925_mac_tx_free(dev, data, len); /* mmio */
1196*8ba4d145SBjoern A. Zeeb return false;
1197*8ba4d145SBjoern A. Zeeb case PKT_TYPE_TXS:
1198*8ba4d145SBjoern A. Zeeb for (rxd += 4; rxd + 12 <= end; rxd += 12)
1199*8ba4d145SBjoern A. Zeeb mt7925_mac_add_txs(dev, rxd);
1200*8ba4d145SBjoern A. Zeeb return false;
1201*8ba4d145SBjoern A. Zeeb default:
1202*8ba4d145SBjoern A. Zeeb return true;
1203*8ba4d145SBjoern A. Zeeb }
1204*8ba4d145SBjoern A. Zeeb }
1205*8ba4d145SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7925_rx_check);
1206*8ba4d145SBjoern A. Zeeb
mt7925_queue_rx_skb(struct mt76_dev * mdev,enum mt76_rxq_id q,struct sk_buff * skb,u32 * info)1207*8ba4d145SBjoern A. Zeeb void mt7925_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
1208*8ba4d145SBjoern A. Zeeb struct sk_buff *skb, u32 *info)
1209*8ba4d145SBjoern A. Zeeb {
1210*8ba4d145SBjoern A. Zeeb struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
1211*8ba4d145SBjoern A. Zeeb __le32 *rxd = (__le32 *)skb->data;
1212*8ba4d145SBjoern A. Zeeb __le32 *end = (__le32 *)&skb->data[skb->len];
1213*8ba4d145SBjoern A. Zeeb enum rx_pkt_type type;
1214*8ba4d145SBjoern A. Zeeb u16 flag;
1215*8ba4d145SBjoern A. Zeeb
1216*8ba4d145SBjoern A. Zeeb type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
1217*8ba4d145SBjoern A. Zeeb flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG);
1218*8ba4d145SBjoern A. Zeeb if (type != PKT_TYPE_NORMAL) {
1219*8ba4d145SBjoern A. Zeeb u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK);
1220*8ba4d145SBjoern A. Zeeb
1221*8ba4d145SBjoern A. Zeeb if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) ==
1222*8ba4d145SBjoern A. Zeeb MT_RXD0_SW_PKT_TYPE_FRAME))
1223*8ba4d145SBjoern A. Zeeb type = PKT_TYPE_NORMAL;
1224*8ba4d145SBjoern A. Zeeb }
1225*8ba4d145SBjoern A. Zeeb
1226*8ba4d145SBjoern A. Zeeb if (type == PKT_TYPE_RX_EVENT && flag == 0x1)
1227*8ba4d145SBjoern A. Zeeb type = PKT_TYPE_NORMAL_MCU;
1228*8ba4d145SBjoern A. Zeeb
1229*8ba4d145SBjoern A. Zeeb switch (type) {
1230*8ba4d145SBjoern A. Zeeb case PKT_TYPE_TXRX_NOTIFY:
1231*8ba4d145SBjoern A. Zeeb /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */
1232*8ba4d145SBjoern A. Zeeb mt7925_mac_tx_free(dev, skb->data, skb->len);
1233*8ba4d145SBjoern A. Zeeb napi_consume_skb(skb, 1);
1234*8ba4d145SBjoern A. Zeeb break;
1235*8ba4d145SBjoern A. Zeeb case PKT_TYPE_RX_EVENT:
1236*8ba4d145SBjoern A. Zeeb mt7925_mcu_rx_event(dev, skb);
1237*8ba4d145SBjoern A. Zeeb break;
1238*8ba4d145SBjoern A. Zeeb case PKT_TYPE_TXS:
1239*8ba4d145SBjoern A. Zeeb for (rxd += 2; rxd + 8 <= end; rxd += 8)
1240*8ba4d145SBjoern A. Zeeb mt7925_mac_add_txs(dev, rxd);
1241*8ba4d145SBjoern A. Zeeb dev_kfree_skb(skb);
1242*8ba4d145SBjoern A. Zeeb break;
1243*8ba4d145SBjoern A. Zeeb case PKT_TYPE_NORMAL_MCU:
1244*8ba4d145SBjoern A. Zeeb case PKT_TYPE_NORMAL:
1245*8ba4d145SBjoern A. Zeeb if (!mt7925_mac_fill_rx(dev, skb)) {
1246*8ba4d145SBjoern A. Zeeb mt76_rx(&dev->mt76, q, skb);
1247*8ba4d145SBjoern A. Zeeb return;
1248*8ba4d145SBjoern A. Zeeb }
1249*8ba4d145SBjoern A. Zeeb fallthrough;
1250*8ba4d145SBjoern A. Zeeb default:
1251*8ba4d145SBjoern A. Zeeb dev_kfree_skb(skb);
1252*8ba4d145SBjoern A. Zeeb break;
1253*8ba4d145SBjoern A. Zeeb }
1254*8ba4d145SBjoern A. Zeeb }
1255*8ba4d145SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7925_queue_rx_skb);
1256*8ba4d145SBjoern A. Zeeb
1257*8ba4d145SBjoern A. Zeeb static void
mt7925_vif_connect_iter(void * priv,u8 * mac,struct ieee80211_vif * vif)1258*8ba4d145SBjoern A. Zeeb mt7925_vif_connect_iter(void *priv, u8 *mac,
1259*8ba4d145SBjoern A. Zeeb struct ieee80211_vif *vif)
1260*8ba4d145SBjoern A. Zeeb {
1261*8ba4d145SBjoern A. Zeeb struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
1262*8ba4d145SBjoern A. Zeeb unsigned long valid = ieee80211_vif_is_mld(vif) ?
1263*8ba4d145SBjoern A. Zeeb mvif->valid_links : BIT(0);
1264*8ba4d145SBjoern A. Zeeb struct mt792x_dev *dev = mvif->phy->dev;
1265*8ba4d145SBjoern A. Zeeb struct ieee80211_hw *hw = mt76_hw(dev);
1266*8ba4d145SBjoern A. Zeeb struct ieee80211_bss_conf *bss_conf;
1267*8ba4d145SBjoern A. Zeeb struct mt792x_bss_conf *mconf;
1268*8ba4d145SBjoern A. Zeeb int i;
1269*8ba4d145SBjoern A. Zeeb
1270*8ba4d145SBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_STATION)
1271*8ba4d145SBjoern A. Zeeb ieee80211_disconnect(vif, true);
1272*8ba4d145SBjoern A. Zeeb
1273*8ba4d145SBjoern A. Zeeb for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
1274*8ba4d145SBjoern A. Zeeb bss_conf = mt792x_vif_to_bss_conf(vif, i);
1275*8ba4d145SBjoern A. Zeeb mconf = mt792x_vif_to_link(mvif, i);
1276*8ba4d145SBjoern A. Zeeb
1277*8ba4d145SBjoern A. Zeeb mt76_connac_mcu_uni_add_dev(&dev->mphy, bss_conf, &mconf->mt76,
1278*8ba4d145SBjoern A. Zeeb &mvif->sta.deflink.wcid, true);
1279*8ba4d145SBjoern A. Zeeb mt7925_mcu_set_tx(dev, bss_conf);
1280*8ba4d145SBjoern A. Zeeb }
1281*8ba4d145SBjoern A. Zeeb
1282*8ba4d145SBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_AP) {
1283*8ba4d145SBjoern A. Zeeb mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.deflink.wcid,
1284*8ba4d145SBjoern A. Zeeb true, NULL);
1285*8ba4d145SBjoern A. Zeeb mt7925_mcu_sta_update(dev, NULL, vif, true,
1286*8ba4d145SBjoern A. Zeeb MT76_STA_INFO_STATE_NONE);
1287*8ba4d145SBjoern A. Zeeb mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true);
1288*8ba4d145SBjoern A. Zeeb }
1289*8ba4d145SBjoern A. Zeeb }
1290*8ba4d145SBjoern A. Zeeb
1291*8ba4d145SBjoern A. Zeeb /* system error recovery */
mt7925_mac_reset_work(struct work_struct * work)1292*8ba4d145SBjoern A. Zeeb void mt7925_mac_reset_work(struct work_struct *work)
1293*8ba4d145SBjoern A. Zeeb {
1294*8ba4d145SBjoern A. Zeeb struct mt792x_dev *dev = container_of(work, struct mt792x_dev,
1295*8ba4d145SBjoern A. Zeeb reset_work);
1296*8ba4d145SBjoern A. Zeeb struct ieee80211_hw *hw = mt76_hw(dev);
1297*8ba4d145SBjoern A. Zeeb struct mt76_connac_pm *pm = &dev->pm;
1298*8ba4d145SBjoern A. Zeeb int i, ret;
1299*8ba4d145SBjoern A. Zeeb
1300*8ba4d145SBjoern A. Zeeb dev_dbg(dev->mt76.dev, "chip reset\n");
1301*8ba4d145SBjoern A. Zeeb dev->hw_full_reset = true;
1302*8ba4d145SBjoern A. Zeeb ieee80211_stop_queues(hw);
1303*8ba4d145SBjoern A. Zeeb
1304*8ba4d145SBjoern A. Zeeb cancel_delayed_work_sync(&dev->mphy.mac_work);
1305*8ba4d145SBjoern A. Zeeb cancel_delayed_work_sync(&pm->ps_work);
1306*8ba4d145SBjoern A. Zeeb cancel_work_sync(&pm->wake_work);
1307*8ba4d145SBjoern A. Zeeb dev->sar_inited = false;
1308*8ba4d145SBjoern A. Zeeb
1309*8ba4d145SBjoern A. Zeeb for (i = 0; i < 10; i++) {
1310*8ba4d145SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
1311*8ba4d145SBjoern A. Zeeb ret = mt792x_dev_reset(dev);
1312*8ba4d145SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
1313*8ba4d145SBjoern A. Zeeb
1314*8ba4d145SBjoern A. Zeeb if (!ret)
1315*8ba4d145SBjoern A. Zeeb break;
1316*8ba4d145SBjoern A. Zeeb }
1317*8ba4d145SBjoern A. Zeeb
1318*8ba4d145SBjoern A. Zeeb if (i == 10)
1319*8ba4d145SBjoern A. Zeeb dev_err(dev->mt76.dev, "chip reset failed\n");
1320*8ba4d145SBjoern A. Zeeb
1321*8ba4d145SBjoern A. Zeeb if (test_and_clear_bit(MT76_HW_SCANNING, &dev->mphy.state)) {
1322*8ba4d145SBjoern A. Zeeb struct cfg80211_scan_info info = {
1323*8ba4d145SBjoern A. Zeeb .aborted = true,
1324*8ba4d145SBjoern A. Zeeb };
1325*8ba4d145SBjoern A. Zeeb
1326*8ba4d145SBjoern A. Zeeb ieee80211_scan_completed(dev->mphy.hw, &info);
1327*8ba4d145SBjoern A. Zeeb }
1328*8ba4d145SBjoern A. Zeeb
1329*8ba4d145SBjoern A. Zeeb dev->hw_full_reset = false;
1330*8ba4d145SBjoern A. Zeeb pm->suspended = false;
1331*8ba4d145SBjoern A. Zeeb ieee80211_wake_queues(hw);
1332*8ba4d145SBjoern A. Zeeb ieee80211_iterate_active_interfaces(hw,
1333*8ba4d145SBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL,
1334*8ba4d145SBjoern A. Zeeb mt7925_vif_connect_iter, NULL);
1335*8ba4d145SBjoern A. Zeeb mt76_connac_power_save_sched(&dev->mt76.phy, pm);
1336*8ba4d145SBjoern A. Zeeb }
1337*8ba4d145SBjoern A. Zeeb
mt7925_coredump_work(struct work_struct * work)1338*8ba4d145SBjoern A. Zeeb void mt7925_coredump_work(struct work_struct *work)
1339*8ba4d145SBjoern A. Zeeb {
1340*8ba4d145SBjoern A. Zeeb struct mt792x_dev *dev;
1341*8ba4d145SBjoern A. Zeeb char *dump, *data;
1342*8ba4d145SBjoern A. Zeeb
1343*8ba4d145SBjoern A. Zeeb dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev,
1344*8ba4d145SBjoern A. Zeeb coredump.work.work);
1345*8ba4d145SBjoern A. Zeeb
1346*8ba4d145SBjoern A. Zeeb if (time_is_after_jiffies(dev->coredump.last_activity +
1347*8ba4d145SBjoern A. Zeeb 4 * MT76_CONNAC_COREDUMP_TIMEOUT)) {
1348*8ba4d145SBjoern A. Zeeb queue_delayed_work(dev->mt76.wq, &dev->coredump.work,
1349*8ba4d145SBjoern A. Zeeb MT76_CONNAC_COREDUMP_TIMEOUT);
1350*8ba4d145SBjoern A. Zeeb return;
1351*8ba4d145SBjoern A. Zeeb }
1352*8ba4d145SBjoern A. Zeeb
1353*8ba4d145SBjoern A. Zeeb dump = vzalloc(MT76_CONNAC_COREDUMP_SZ);
1354*8ba4d145SBjoern A. Zeeb data = dump;
1355*8ba4d145SBjoern A. Zeeb
1356*8ba4d145SBjoern A. Zeeb while (true) {
1357*8ba4d145SBjoern A. Zeeb struct sk_buff *skb;
1358*8ba4d145SBjoern A. Zeeb
1359*8ba4d145SBjoern A. Zeeb spin_lock_bh(&dev->mt76.lock);
1360*8ba4d145SBjoern A. Zeeb skb = __skb_dequeue(&dev->coredump.msg_list);
1361*8ba4d145SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.lock);
1362*8ba4d145SBjoern A. Zeeb
1363*8ba4d145SBjoern A. Zeeb if (!skb)
1364*8ba4d145SBjoern A. Zeeb break;
1365*8ba4d145SBjoern A. Zeeb
1366*8ba4d145SBjoern A. Zeeb skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 8);
1367*8ba4d145SBjoern A. Zeeb if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
1368*8ba4d145SBjoern A. Zeeb dev_kfree_skb(skb);
1369*8ba4d145SBjoern A. Zeeb continue;
1370*8ba4d145SBjoern A. Zeeb }
1371*8ba4d145SBjoern A. Zeeb
1372*8ba4d145SBjoern A. Zeeb memcpy(data, skb->data, skb->len);
1373*8ba4d145SBjoern A. Zeeb data += skb->len;
1374*8ba4d145SBjoern A. Zeeb
1375*8ba4d145SBjoern A. Zeeb dev_kfree_skb(skb);
1376*8ba4d145SBjoern A. Zeeb }
1377*8ba4d145SBjoern A. Zeeb
1378*8ba4d145SBjoern A. Zeeb if (dump)
1379*8ba4d145SBjoern A. Zeeb dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
1380*8ba4d145SBjoern A. Zeeb GFP_KERNEL);
1381*8ba4d145SBjoern A. Zeeb
1382*8ba4d145SBjoern A. Zeeb mt792x_reset(&dev->mt76);
1383*8ba4d145SBjoern A. Zeeb }
1384*8ba4d145SBjoern A. Zeeb
1385*8ba4d145SBjoern A. Zeeb /* usb_sdio */
1386*8ba4d145SBjoern A. Zeeb static void
mt7925_usb_sdio_write_txwi(struct mt792x_dev * dev,struct mt76_wcid * wcid,enum mt76_txq_id qid,struct ieee80211_sta * sta,struct ieee80211_key_conf * key,int pid,struct sk_buff * skb)1387*8ba4d145SBjoern A. Zeeb mt7925_usb_sdio_write_txwi(struct mt792x_dev *dev, struct mt76_wcid *wcid,
1388*8ba4d145SBjoern A. Zeeb enum mt76_txq_id qid, struct ieee80211_sta *sta,
1389*8ba4d145SBjoern A. Zeeb struct ieee80211_key_conf *key, int pid,
1390*8ba4d145SBjoern A. Zeeb struct sk_buff *skb)
1391*8ba4d145SBjoern A. Zeeb {
1392*8ba4d145SBjoern A. Zeeb __le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE);
1393*8ba4d145SBjoern A. Zeeb
1394*8ba4d145SBjoern A. Zeeb memset(txwi, 0, MT_SDIO_TXD_SIZE);
1395*8ba4d145SBjoern A. Zeeb mt7925_mac_write_txwi(&dev->mt76, txwi, skb, wcid, key, pid, qid, 0);
1396*8ba4d145SBjoern A. Zeeb skb_push(skb, MT_SDIO_TXD_SIZE);
1397*8ba4d145SBjoern A. Zeeb }
1398*8ba4d145SBjoern A. Zeeb
mt7925_usb_sdio_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)1399*8ba4d145SBjoern A. Zeeb int mt7925_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
1400*8ba4d145SBjoern A. Zeeb enum mt76_txq_id qid, struct mt76_wcid *wcid,
1401*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta,
1402*8ba4d145SBjoern A. Zeeb struct mt76_tx_info *tx_info)
1403*8ba4d145SBjoern A. Zeeb {
1404*8ba4d145SBjoern A. Zeeb struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
1405*8ba4d145SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
1406*8ba4d145SBjoern A. Zeeb struct ieee80211_key_conf *key = info->control.hw_key;
1407*8ba4d145SBjoern A. Zeeb struct sk_buff *skb = tx_info->skb;
1408*8ba4d145SBjoern A. Zeeb int err, pad, pktid;
1409*8ba4d145SBjoern A. Zeeb
1410*8ba4d145SBjoern A. Zeeb if (unlikely(tx_info->skb->len <= ETH_HLEN))
1411*8ba4d145SBjoern A. Zeeb return -EINVAL;
1412*8ba4d145SBjoern A. Zeeb
1413*8ba4d145SBjoern A. Zeeb if (!wcid)
1414*8ba4d145SBjoern A. Zeeb wcid = &dev->mt76.global_wcid;
1415*8ba4d145SBjoern A. Zeeb
1416*8ba4d145SBjoern A. Zeeb if (sta) {
1417*8ba4d145SBjoern A. Zeeb struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
1418*8ba4d145SBjoern A. Zeeb
1419*8ba4d145SBjoern A. Zeeb if (time_after(jiffies, msta->deflink.last_txs + HZ / 4)) {
1420*8ba4d145SBjoern A. Zeeb info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
1421*8ba4d145SBjoern A. Zeeb msta->deflink.last_txs = jiffies;
1422*8ba4d145SBjoern A. Zeeb }
1423*8ba4d145SBjoern A. Zeeb }
1424*8ba4d145SBjoern A. Zeeb
1425*8ba4d145SBjoern A. Zeeb pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
1426*8ba4d145SBjoern A. Zeeb mt7925_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb);
1427*8ba4d145SBjoern A. Zeeb
1428*8ba4d145SBjoern A. Zeeb mt792x_skb_add_usb_sdio_hdr(dev, skb, 0);
1429*8ba4d145SBjoern A. Zeeb pad = round_up(skb->len, 4) - skb->len;
1430*8ba4d145SBjoern A. Zeeb if (mt76_is_usb(mdev))
1431*8ba4d145SBjoern A. Zeeb pad += 4;
1432*8ba4d145SBjoern A. Zeeb
1433*8ba4d145SBjoern A. Zeeb err = mt76_skb_adjust_pad(skb, pad);
1434*8ba4d145SBjoern A. Zeeb if (err)
1435*8ba4d145SBjoern A. Zeeb /* Release pktid in case of error. */
1436*8ba4d145SBjoern A. Zeeb idr_remove(&wcid->pktid, pktid);
1437*8ba4d145SBjoern A. Zeeb
1438*8ba4d145SBjoern A. Zeeb return err;
1439*8ba4d145SBjoern A. Zeeb }
1440*8ba4d145SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7925_usb_sdio_tx_prepare_skb);
1441*8ba4d145SBjoern A. Zeeb
mt7925_usb_sdio_tx_complete_skb(struct mt76_dev * mdev,struct mt76_queue_entry * e)1442*8ba4d145SBjoern A. Zeeb void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
1443*8ba4d145SBjoern A. Zeeb struct mt76_queue_entry *e)
1444*8ba4d145SBjoern A. Zeeb {
1445*8ba4d145SBjoern A. Zeeb __le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE);
1446*8ba4d145SBjoern A. Zeeb unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
1447*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta;
1448*8ba4d145SBjoern A. Zeeb struct mt76_wcid *wcid;
1449*8ba4d145SBjoern A. Zeeb u16 idx;
1450*8ba4d145SBjoern A. Zeeb
1451*8ba4d145SBjoern A. Zeeb idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
1452*8ba4d145SBjoern A. Zeeb wcid = rcu_dereference(mdev->wcid[idx]);
1453*8ba4d145SBjoern A. Zeeb sta = wcid_to_sta(wcid);
1454*8ba4d145SBjoern A. Zeeb
1455*8ba4d145SBjoern A. Zeeb if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
1456*8ba4d145SBjoern A. Zeeb mt76_connac2_tx_check_aggr(sta, txwi);
1457*8ba4d145SBjoern A. Zeeb
1458*8ba4d145SBjoern A. Zeeb skb_pull(e->skb, headroom);
1459*8ba4d145SBjoern A. Zeeb mt76_tx_complete_skb(mdev, e->wcid, e->skb);
1460*8ba4d145SBjoern A. Zeeb }
1461*8ba4d145SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7925_usb_sdio_tx_complete_skb);
1462*8ba4d145SBjoern A. Zeeb
mt7925_usb_sdio_tx_status_data(struct mt76_dev * mdev,u8 * update)1463*8ba4d145SBjoern A. Zeeb bool mt7925_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)
1464*8ba4d145SBjoern A. Zeeb {
1465*8ba4d145SBjoern A. Zeeb struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
1466*8ba4d145SBjoern A. Zeeb
1467*8ba4d145SBjoern A. Zeeb mt792x_mutex_acquire(dev);
1468*8ba4d145SBjoern A. Zeeb mt7925_mac_sta_poll(dev);
1469*8ba4d145SBjoern A. Zeeb mt792x_mutex_release(dev);
1470*8ba4d145SBjoern A. Zeeb
1471*8ba4d145SBjoern A. Zeeb return false;
1472*8ba4d145SBjoern A. Zeeb }
1473*8ba4d145SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7925_usb_sdio_tx_status_data);
1474*8ba4d145SBjoern A. Zeeb
1475*8ba4d145SBjoern A. Zeeb #if IS_ENABLED(CONFIG_IPV6)
mt7925_set_ipv6_ns_work(struct work_struct * work)1476*8ba4d145SBjoern A. Zeeb void mt7925_set_ipv6_ns_work(struct work_struct *work)
1477*8ba4d145SBjoern A. Zeeb {
1478*8ba4d145SBjoern A. Zeeb struct mt792x_dev *dev = container_of(work, struct mt792x_dev,
1479*8ba4d145SBjoern A. Zeeb ipv6_ns_work);
1480*8ba4d145SBjoern A. Zeeb struct sk_buff *skb;
1481*8ba4d145SBjoern A. Zeeb int ret = 0;
1482*8ba4d145SBjoern A. Zeeb
1483*8ba4d145SBjoern A. Zeeb do {
1484*8ba4d145SBjoern A. Zeeb skb = skb_dequeue(&dev->ipv6_ns_list);
1485*8ba4d145SBjoern A. Zeeb
1486*8ba4d145SBjoern A. Zeeb if (!skb)
1487*8ba4d145SBjoern A. Zeeb break;
1488*8ba4d145SBjoern A. Zeeb
1489*8ba4d145SBjoern A. Zeeb mt792x_mutex_acquire(dev);
1490*8ba4d145SBjoern A. Zeeb ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
1491*8ba4d145SBjoern A. Zeeb MCU_UNI_CMD(OFFLOAD), true);
1492*8ba4d145SBjoern A. Zeeb mt792x_mutex_release(dev);
1493*8ba4d145SBjoern A. Zeeb
1494*8ba4d145SBjoern A. Zeeb } while (!ret);
1495*8ba4d145SBjoern A. Zeeb
1496*8ba4d145SBjoern A. Zeeb if (ret)
1497*8ba4d145SBjoern A. Zeeb skb_queue_purge(&dev->ipv6_ns_list);
1498*8ba4d145SBjoern A. Zeeb }
1499*8ba4d145SBjoern A. Zeeb #endif
1500