GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / net / wireless / ath / wcn36xx / txrx.c
1 /*
2  * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19 #include "txrx.h"
20
21 static inline int get_rssi0(struct wcn36xx_rx_bd *bd)
22 {
23         return 100 - ((bd->phy_stat0 >> 24) & 0xff);
24 }
25
26 static inline int get_snr(struct wcn36xx_rx_bd *bd)
27 {
28         return ((bd->phy_stat1 >> 24) & 0xff);
29 }
30
31 struct wcn36xx_rate {
32         u16 bitrate;
33         u16 mcs_or_legacy_index;
34         enum mac80211_rx_encoding encoding;
35         enum mac80211_rx_encoding_flags encoding_flags;
36         enum rate_info_bw bw;
37 };
38
39 /* Buffer descriptor rx_ch field is limited to 5-bit (4+1), a mapping is used
40  * for 11A Channels.
41  */
42 static const u8 ab_rx_ch_map[] = { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104,
43                                    108, 112, 116, 120, 124, 128, 132, 136, 140,
44                                    149, 153, 157, 161, 165, 144 };
45
46 static const struct wcn36xx_rate wcn36xx_rate_table[] = {
47         /* 11b rates */
48         {  10, 0, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
49         {  20, 1, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
50         {  55, 2, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
51         { 110, 3, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
52
53         /* 11b SP (short preamble) */
54         {  10, 0, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 },
55         {  20, 1, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 },
56         {  55, 2, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 },
57         { 110, 3, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 },
58
59         /* 11ag */
60         {  60, 4, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
61         {  90, 5, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
62         { 120, 6, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
63         { 180, 7, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
64         { 240, 8, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
65         { 360, 9, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
66         { 480, 10, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
67         { 540, 11, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
68
69         /* 11n */
70         {  65, 0, RX_ENC_HT, 0, RATE_INFO_BW_20 },
71         { 130, 1, RX_ENC_HT, 0, RATE_INFO_BW_20 },
72         { 195, 2, RX_ENC_HT, 0, RATE_INFO_BW_20 },
73         { 260, 3, RX_ENC_HT, 0, RATE_INFO_BW_20 },
74         { 390, 4, RX_ENC_HT, 0, RATE_INFO_BW_20 },
75         { 520, 5, RX_ENC_HT, 0, RATE_INFO_BW_20 },
76         { 585, 6, RX_ENC_HT, 0, RATE_INFO_BW_20 },
77         { 650, 7, RX_ENC_HT, 0, RATE_INFO_BW_20 },
78
79         /* 11n SGI */
80         {  72, 0, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
81         { 144, 1, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
82         { 217, 2, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
83         { 289, 3, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
84         { 434, 4, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
85         { 578, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
86         { 650, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
87         { 722, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
88
89         /* 11n GF (greenfield) */
90         {  65, 0, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
91         { 130, 1, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
92         { 195, 2, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
93         { 260, 3, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
94         { 390, 4, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
95         { 520, 5, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
96         { 585, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
97         { 650, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
98
99         /* 11n CB (channel bonding) */
100         { 135, 0, RX_ENC_HT, 0, RATE_INFO_BW_40 },
101         { 270, 1, RX_ENC_HT, 0, RATE_INFO_BW_40 },
102         { 405, 2, RX_ENC_HT, 0, RATE_INFO_BW_40 },
103         { 540, 3, RX_ENC_HT, 0, RATE_INFO_BW_40 },
104         { 810, 4, RX_ENC_HT, 0, RATE_INFO_BW_40 },
105         { 1080, 5, RX_ENC_HT, 0, RATE_INFO_BW_40 },
106         { 1215, 6, RX_ENC_HT, 0, RATE_INFO_BW_40 },
107         { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 },
108
109         /* 11n CB + SGI */
110         { 150, 0, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
111         { 300, 1, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
112         { 450, 2, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
113         { 600, 3, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
114         { 900, 4, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
115         { 1200, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
116         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
117         { 1500, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
118
119         /* 11n GF + CB */
120         { 135, 0, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
121         { 270, 1, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
122         { 405, 2, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
123         { 540, 3, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
124         { 810, 4, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
125         { 1080, 5, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
126         { 1215, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
127         { 1350, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
128
129         /* 11ac reserved indices */
130         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
131         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
132
133         /* 11ac 20 MHz 800ns GI MCS 0-8 */
134         {   65, 0, RX_ENC_HT, 0, RATE_INFO_BW_20 },
135         {  130, 1, RX_ENC_HT, 0, RATE_INFO_BW_20 },
136         {  195, 2, RX_ENC_HT, 0, RATE_INFO_BW_20 },
137         {  260, 3, RX_ENC_HT, 0, RATE_INFO_BW_20 },
138         {  390, 4, RX_ENC_HT, 0, RATE_INFO_BW_20 },
139         {  520, 5, RX_ENC_HT, 0, RATE_INFO_BW_20 },
140         {  585, 6, RX_ENC_HT, 0, RATE_INFO_BW_20 },
141         {  650, 7, RX_ENC_HT, 0, RATE_INFO_BW_20 },
142         {  780, 8, RX_ENC_HT, 0, RATE_INFO_BW_20 },
143
144         /* 11ac reserved indices */
145         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
146         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
147         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
148         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
149         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
150         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
151         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
152         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
153         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
154
155         /* 11ac 20 MHz 400ns SGI MCS 6-8 */
156         {  655, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
157         {  722, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
158         {  866, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
159
160         /* 11ac reserved indices */
161         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
162         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
163         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
164
165         /* 11ac 40 MHz 800ns GI MCS 0-9 */
166         {  135, 0, RX_ENC_HT, 0, RATE_INFO_BW_40 },
167         {  270, 1, RX_ENC_HT, 0, RATE_INFO_BW_40 },
168         {  405, 2, RX_ENC_HT, 0, RATE_INFO_BW_40 },
169         {  540, 3, RX_ENC_HT, 0, RATE_INFO_BW_40 },
170         {  810, 4, RX_ENC_HT, 0, RATE_INFO_BW_40 },
171         { 1080, 5, RX_ENC_HT, 0, RATE_INFO_BW_40 },
172         { 1215, 6, RX_ENC_HT, 0, RATE_INFO_BW_40 },
173         { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 },
174         { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 },
175         { 1620, 8, RX_ENC_HT, 0, RATE_INFO_BW_40 },
176         { 1800, 9, RX_ENC_HT, 0, RATE_INFO_BW_40 },
177
178         /* 11ac reserved indices */
179         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
180         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
181         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
182         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
183         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
184         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
185
186         /* 11ac 40 MHz 400ns SGI MCS 5-7 */
187         { 1200, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
188         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
189         { 1500, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
190
191         /* 11ac reserved index */
192         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
193
194         /* 11ac 40 MHz 400ns SGI MCS 5-7 */
195         { 1800, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
196         { 2000, 9, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
197
198         /* 11ac reserved index */
199         { 1350, 6, RX_ENC_HT,  RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
200
201         /* 11ac 80 MHz 800ns GI MCS 0-7 */
202         {  292, 0, RX_ENC_HT, 0, RATE_INFO_BW_80},
203         {  585, 1, RX_ENC_HT, 0, RATE_INFO_BW_80},
204         {  877, 2, RX_ENC_HT, 0, RATE_INFO_BW_80},
205         { 1170, 3, RX_ENC_HT, 0, RATE_INFO_BW_80},
206         { 1755, 4, RX_ENC_HT, 0, RATE_INFO_BW_80},
207         { 2340, 5, RX_ENC_HT, 0, RATE_INFO_BW_80},
208         { 2632, 6, RX_ENC_HT, 0, RATE_INFO_BW_80},
209         { 2925, 7, RX_ENC_HT, 0, RATE_INFO_BW_80},
210
211         /* 11 ac reserved index */
212         { 1350, 6, RX_ENC_HT,  RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
213
214         /* 11ac 80 MHz 800 ns GI MCS 8-9 */
215         { 3510, 8, RX_ENC_HT, 0, RATE_INFO_BW_80},
216         { 3900, 9, RX_ENC_HT, 0, RATE_INFO_BW_80},
217
218         /* 11 ac reserved indices */
219         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
220         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
221         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
222         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
223         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
224         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
225         { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
226
227         /* 11ac 80 MHz 400 ns SGI MCS 6-7 */
228         { 2925, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
229         { 3250, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
230
231         /* 11ac reserved index */
232         { 1350, 6, RX_ENC_HT,  RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
233
234         /* 11ac 80 MHz 400ns SGI MCS 8-9 */
235         { 3900, 8, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
236         { 4333, 9, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
237 };
238
239 static struct sk_buff *wcn36xx_unchain_msdu(struct sk_buff_head *amsdu)
240 {
241         struct sk_buff *skb, *first;
242         int total_len = 0;
243         int space;
244
245         first = __skb_dequeue(amsdu);
246
247         skb_queue_walk(amsdu, skb)
248                 total_len += skb->len;
249
250         space = total_len - skb_tailroom(first);
251         if (space > 0 && pskb_expand_head(first, 0, space, GFP_ATOMIC) < 0) {
252                 __skb_queue_head(amsdu, first);
253                 return NULL;
254         }
255
256         /* Walk list again, copying contents into msdu_head */
257         while ((skb = __skb_dequeue(amsdu))) {
258                 skb_copy_from_linear_data(skb, skb_put(first, skb->len),
259                                           skb->len);
260                 dev_kfree_skb_irq(skb);
261         }
262
263         return first;
264 }
265
266 static void __skb_queue_purge_irq(struct sk_buff_head *list)
267 {
268         struct sk_buff *skb;
269
270         while ((skb = __skb_dequeue(list)) != NULL)
271                 dev_kfree_skb_irq(skb);
272 }
273
274 static void wcn36xx_update_survey(struct wcn36xx *wcn, int rssi, int snr,
275                                   int band, int freq)
276 {
277         static struct ieee80211_channel *channel;
278         struct ieee80211_supported_band *sband;
279         int idx;
280         int i;
281
282         idx = 0;
283         if (band == NL80211_BAND_5GHZ)
284                 idx = wcn->hw->wiphy->bands[NL80211_BAND_2GHZ]->n_channels;
285
286         sband = wcn->hw->wiphy->bands[band];
287         channel = sband->channels;
288
289         for (i = 0; i < sband->n_channels; i++, channel++) {
290                 if (channel->center_freq == freq) {
291                         idx += i;
292                         break;
293                 }
294         }
295
296         spin_lock(&wcn->survey_lock);
297         wcn->chan_survey[idx].rssi = rssi;
298         wcn->chan_survey[idx].snr = snr;
299         spin_unlock(&wcn->survey_lock);
300 }
301
302 int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
303 {
304         struct ieee80211_rx_status status;
305         const struct wcn36xx_rate *rate;
306         struct ieee80211_hdr *hdr;
307         struct wcn36xx_rx_bd *bd;
308         u16 fc, sn;
309
310         /*
311          * All fields must be 0, otherwise it can lead to
312          * unexpected consequences.
313          */
314         memset(&status, 0, sizeof(status));
315
316         bd = (struct wcn36xx_rx_bd *)skb->data;
317         buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
318         wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP,
319                          "BD   <<< ", (char *)bd,
320                          sizeof(struct wcn36xx_rx_bd));
321
322         if (bd->pdu.mpdu_data_off <= bd->pdu.mpdu_header_off ||
323             bd->pdu.mpdu_len < bd->pdu.mpdu_header_len)
324                 goto drop;
325
326         if (bd->asf && !bd->esf) { /* chained A-MSDU chunks */
327                 /* Sanity check */
328                 if (bd->pdu.mpdu_data_off + bd->pdu.mpdu_len > WCN36XX_PKT_SIZE)
329                         goto drop;
330
331                 skb_put(skb, bd->pdu.mpdu_data_off + bd->pdu.mpdu_len);
332                 skb_pull(skb, bd->pdu.mpdu_data_off);
333
334                 /* Only set status for first chained BD (with mac header) */
335                 goto done;
336         }
337
338         if (bd->pdu.mpdu_header_off < sizeof(*bd) ||
339             bd->pdu.mpdu_header_off + bd->pdu.mpdu_len > WCN36XX_PKT_SIZE)
340                 goto drop;
341
342         skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len);
343         skb_pull(skb, bd->pdu.mpdu_header_off);
344
345         hdr = (struct ieee80211_hdr *) skb->data;
346         fc = __le16_to_cpu(hdr->frame_control);
347         sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl));
348
349         status.mactime = 10;
350         status.signal = -get_rssi0(bd);
351         status.antenna = 1;
352         status.flag = 0;
353         status.rx_flags = 0;
354         status.flag |= RX_FLAG_IV_STRIPPED |
355                        RX_FLAG_MMIC_STRIPPED |
356                        RX_FLAG_DECRYPTED;
357
358         wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag);
359
360         if (bd->scan_learn) {
361                 /* If packet originate from hardware scanning, extract the
362                  * band/channel from bd descriptor.
363                  */
364                 u8 hwch = (bd->reserved0 << 4) + bd->rx_ch;
365
366                 if (bd->rf_band != 1 && hwch <= sizeof(ab_rx_ch_map) && hwch >= 1) {
367                         status.band = NL80211_BAND_5GHZ;
368                         status.freq = ieee80211_channel_to_frequency(ab_rx_ch_map[hwch - 1],
369                                                                      status.band);
370                 } else {
371                         status.band = NL80211_BAND_2GHZ;
372                         status.freq = ieee80211_channel_to_frequency(hwch, status.band);
373                 }
374         } else {
375                 status.band = WCN36XX_BAND(wcn);
376                 status.freq = WCN36XX_CENTER_FREQ(wcn);
377         }
378
379         wcn36xx_update_survey(wcn, status.signal, get_snr(bd),
380                               status.band, status.freq);
381
382         if (bd->rate_id < ARRAY_SIZE(wcn36xx_rate_table)) {
383                 rate = &wcn36xx_rate_table[bd->rate_id];
384                 status.encoding = rate->encoding;
385                 status.enc_flags = rate->encoding_flags;
386                 status.bw = rate->bw;
387                 status.rate_idx = rate->mcs_or_legacy_index;
388                 status.nss = 1;
389
390                 if (status.band == NL80211_BAND_5GHZ &&
391                     status.encoding == RX_ENC_LEGACY &&
392                     status.rate_idx >= 4) {
393                         /* no dsss rates in 5Ghz rates table */
394                         status.rate_idx -= 4;
395                 }
396         } else {
397                 status.encoding = 0;
398                 status.bw = 0;
399                 status.enc_flags = 0;
400                 status.rate_idx = 0;
401         }
402
403         if (ieee80211_is_beacon(hdr->frame_control) ||
404             ieee80211_is_probe_resp(hdr->frame_control))
405                 status.boottime_ns = ktime_get_boottime_ns();
406
407         memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
408
409         if (ieee80211_is_beacon(hdr->frame_control)) {
410                 wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n",
411                             skb, skb->len, fc, sn);
412                 wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP, "SKB <<< ",
413                                  (char *)skb->data, skb->len);
414         } else {
415                 wcn36xx_dbg(WCN36XX_DBG_RX, "rx skb %p len %d fc %04x sn %d\n",
416                             skb, skb->len, fc, sn);
417                 wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, "SKB <<< ",
418                                  (char *)skb->data, skb->len);
419         }
420
421 done:
422         /*  Chained AMSDU ? slow path */
423         if (unlikely(bd->asf && !(bd->lsf && bd->esf))) {
424                 if (bd->esf && !skb_queue_empty(&wcn->amsdu)) {
425                         wcn36xx_err("Discarding non complete chain");
426                         __skb_queue_purge_irq(&wcn->amsdu);
427                 }
428
429                 __skb_queue_tail(&wcn->amsdu, skb);
430
431                 if (!bd->lsf)
432                         return 0; /* Not the last AMSDU, wait for more */
433
434                 skb = wcn36xx_unchain_msdu(&wcn->amsdu);
435                 if (!skb)
436                         goto drop;
437         }
438
439         ieee80211_rx_irqsafe(wcn->hw, skb);
440
441         return 0;
442
443 drop: /* drop everything */
444         wcn36xx_err("Drop frame! skb:%p len:%u hoff:%u doff:%u asf=%u esf=%u lsf=%u\n",
445                     skb, bd->pdu.mpdu_len, bd->pdu.mpdu_header_off,
446                     bd->pdu.mpdu_data_off, bd->asf, bd->esf, bd->lsf);
447
448         dev_kfree_skb_irq(skb);
449         __skb_queue_purge_irq(&wcn->amsdu);
450
451         return -EINVAL;
452 }
453
454 static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd,
455                                u32 mpdu_header_len,
456                                u32 len,
457                                u16 tid)
458 {
459         bd->pdu.mpdu_header_len = mpdu_header_len;
460         bd->pdu.mpdu_header_off = sizeof(*bd);
461         bd->pdu.mpdu_data_off = bd->pdu.mpdu_header_len +
462                 bd->pdu.mpdu_header_off;
463         bd->pdu.mpdu_len = len;
464         bd->pdu.tid = tid;
465 }
466
467 static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn,
468                                                   u8 *addr)
469 {
470         struct wcn36xx_vif *vif_priv = NULL;
471         struct ieee80211_vif *vif = NULL;
472         list_for_each_entry(vif_priv, &wcn->vif_list, list) {
473                         vif = wcn36xx_priv_to_vif(vif_priv);
474                         if (memcmp(vif->addr, addr, ETH_ALEN) == 0)
475                                 return vif_priv;
476         }
477         wcn36xx_warn("vif %pM not found\n", addr);
478         return NULL;
479 }
480
481 static void wcn36xx_tx_start_ampdu(struct wcn36xx *wcn,
482                                    struct wcn36xx_sta *sta_priv,
483                                    struct sk_buff *skb)
484 {
485         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
486         struct ieee80211_sta *sta;
487         u8 *qc, tid;
488
489         if (!conf_is_ht(&wcn->hw->conf))
490                 return;
491
492         sta = wcn36xx_priv_to_sta(sta_priv);
493
494         if (WARN_ON(!ieee80211_is_data_qos(hdr->frame_control)))
495                 return;
496
497         if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
498                 return;
499
500         qc = ieee80211_get_qos_ctl(hdr);
501         tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
502
503         spin_lock(&sta_priv->ampdu_lock);
504         if (sta_priv->ampdu_state[tid] != WCN36XX_AMPDU_NONE)
505                 goto out_unlock;
506
507         if (sta_priv->non_agg_frame_ct++ >= WCN36XX_AMPDU_START_THRESH) {
508                 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
509                 sta_priv->non_agg_frame_ct = 0;
510                 ieee80211_start_tx_ba_session(sta, tid, 0);
511         }
512 out_unlock:
513         spin_unlock(&sta_priv->ampdu_lock);
514 }
515
516 static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
517                                 struct wcn36xx *wcn,
518                                 struct wcn36xx_vif **vif_priv,
519                                 struct wcn36xx_sta *sta_priv,
520                                 struct sk_buff *skb,
521                                 bool bcast)
522 {
523         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
524         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
525         struct ieee80211_vif *vif = NULL;
526         struct wcn36xx_vif *__vif_priv = NULL;
527         bool is_data_qos = ieee80211_is_data_qos(hdr->frame_control);
528         u16 tid = 0;
529
530         bd->bd_rate = WCN36XX_BD_RATE_DATA;
531
532         /*
533          * For not unicast frames mac80211 will not set sta pointer so use
534          * self_sta_index instead.
535          */
536         if (sta_priv) {
537                 __vif_priv = sta_priv->vif;
538                 vif = wcn36xx_priv_to_vif(__vif_priv);
539
540                 bd->dpu_sign = sta_priv->ucast_dpu_sign;
541                 if (vif->type == NL80211_IFTYPE_STATION) {
542                         bd->sta_index = sta_priv->bss_sta_index;
543                         bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index;
544                 } else if (vif->type == NL80211_IFTYPE_AP ||
545                            vif->type == NL80211_IFTYPE_ADHOC ||
546                            vif->type == NL80211_IFTYPE_MESH_POINT) {
547                         bd->sta_index = sta_priv->sta_index;
548                         bd->dpu_desc_idx = sta_priv->dpu_desc_index;
549                 }
550         } else {
551                 __vif_priv = get_vif_by_addr(wcn, hdr->addr2);
552                 bd->sta_index = __vif_priv->self_sta_index;
553                 bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
554                 bd->dpu_sign = __vif_priv->self_ucast_dpu_sign;
555         }
556
557         if (is_data_qos) {
558                 tid = ieee80211_get_tid(hdr);
559                 /* TID->QID is one-to-one mapping */
560                 bd->queue_id = tid;
561                 bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS;
562         } else {
563                 bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS;
564         }
565
566         if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT ||
567             (sta_priv && !sta_priv->is_data_encrypted)) {
568                 bd->dpu_ne = 1;
569         }
570
571         if (ieee80211_is_any_nullfunc(hdr->frame_control)) {
572                 /* Don't use a regular queue for null packet (no ampdu) */
573                 bd->queue_id = WCN36XX_TX_U_WQ_ID;
574                 bd->bd_rate = WCN36XX_BD_RATE_CTRL;
575                 if (ieee80211_is_qos_nullfunc(hdr->frame_control))
576                         bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST;
577         }
578
579         if (bcast) {
580                 bd->ub = 1;
581                 bd->ack_policy = 1;
582         }
583         *vif_priv = __vif_priv;
584
585         wcn36xx_set_tx_pdu(bd,
586                            is_data_qos ?
587                            sizeof(struct ieee80211_qos_hdr) :
588                            sizeof(struct ieee80211_hdr_3addr),
589                            skb->len, tid);
590
591         if (sta_priv && is_data_qos)
592                 wcn36xx_tx_start_ampdu(wcn, sta_priv, skb);
593 }
594
595 static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd,
596                                 struct wcn36xx *wcn,
597                                 struct wcn36xx_vif **vif_priv,
598                                 struct sk_buff *skb,
599                                 bool bcast)
600 {
601         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
602         struct wcn36xx_vif *__vif_priv =
603                 get_vif_by_addr(wcn, hdr->addr2);
604         bd->sta_index = __vif_priv->self_sta_index;
605         bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
606         bd->dpu_ne = 1;
607
608         /* default rate for unicast */
609         if (ieee80211_is_mgmt(hdr->frame_control))
610                 bd->bd_rate = (WCN36XX_BAND(wcn) == NL80211_BAND_5GHZ) ?
611                         WCN36XX_BD_RATE_CTRL :
612                         WCN36XX_BD_RATE_MGMT;
613         else if (ieee80211_is_ctl(hdr->frame_control))
614                 bd->bd_rate = WCN36XX_BD_RATE_CTRL;
615         else
616                 wcn36xx_warn("frame control type unknown\n");
617
618         /*
619          * In joining state trick hardware that probe is sent as
620          * unicast even if address is broadcast.
621          */
622         if (__vif_priv->is_joining &&
623             ieee80211_is_probe_req(hdr->frame_control))
624                 bcast = false;
625
626         if (bcast) {
627                 /* broadcast */
628                 bd->ub = 1;
629                 /* No ack needed not unicast */
630                 bd->ack_policy = 1;
631                 bd->queue_id = WCN36XX_TX_B_WQ_ID;
632         } else
633                 bd->queue_id = WCN36XX_TX_U_WQ_ID;
634         *vif_priv = __vif_priv;
635
636         bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS;
637
638         wcn36xx_set_tx_pdu(bd,
639                            ieee80211_is_data_qos(hdr->frame_control) ?
640                            sizeof(struct ieee80211_qos_hdr) :
641                            sizeof(struct ieee80211_hdr_3addr),
642                            skb->len, WCN36XX_TID);
643 }
644
645 int wcn36xx_start_tx(struct wcn36xx *wcn,
646                      struct wcn36xx_sta *sta_priv,
647                      struct sk_buff *skb)
648 {
649         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
650         struct wcn36xx_vif *vif_priv = NULL;
651         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
652         bool is_low = ieee80211_is_data(hdr->frame_control);
653         bool bcast = is_broadcast_ether_addr(hdr->addr1) ||
654                 is_multicast_ether_addr(hdr->addr1);
655         bool ack_ind = (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) &&
656                                         !(info->flags & IEEE80211_TX_CTL_NO_ACK);
657         struct wcn36xx_tx_bd bd;
658         int ret;
659
660         memset(&bd, 0, sizeof(bd));
661
662         wcn36xx_dbg(WCN36XX_DBG_TX,
663                     "tx skb %p len %d fc %04x sn %d %s %s\n",
664                     skb, skb->len, __le16_to_cpu(hdr->frame_control),
665                     IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)),
666                     is_low ? "low" : "high", bcast ? "bcast" : "ucast");
667
668         wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len);
669
670         bd.dpu_rf = WCN36XX_BMU_WQ_TX;
671
672         if (unlikely(ack_ind)) {
673                 wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n");
674
675                 /* Only one at a time is supported by fw. Stop the TX queues
676                  * until the ack status gets back.
677                  */
678                 ieee80211_stop_queues(wcn->hw);
679
680                 /* Request ack indication from the firmware */
681                 bd.tx_comp = 1;
682         }
683
684         /* Data frames served first*/
685         if (is_low)
686                 wcn36xx_set_tx_data(&bd, wcn, &vif_priv, sta_priv, skb, bcast);
687         else
688                 /* MGMT and CTRL frames are handeld here*/
689                 wcn36xx_set_tx_mgmt(&bd, wcn, &vif_priv, skb, bcast);
690
691         buff_to_be((u32 *)&bd, sizeof(bd)/sizeof(u32));
692         bd.tx_bd_sign = 0xbdbdbdbd;
693
694         ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low);
695         if (unlikely(ret && ack_ind)) {
696                 /* If the skb has not been transmitted, resume TX queue */
697                 ieee80211_wake_queues(wcn->hw);
698         }
699
700         return ret;
701 }
702
703 void wcn36xx_process_tx_rate(struct ani_global_class_a_stats_info *stats, struct rate_info *info)
704 {
705         /* tx_rate is in units of 500kbps; mac80211 wants them in 100kbps */
706         if (stats->tx_rate_flags & HAL_TX_RATE_LEGACY)
707                 info->legacy = stats->tx_rate * 5;
708
709         info->flags = 0;
710         info->mcs = stats->mcs_index;
711         info->nss = 1;
712
713         if (stats->tx_rate_flags & (HAL_TX_RATE_HT20 | HAL_TX_RATE_HT40))
714                 info->flags |= RATE_INFO_FLAGS_MCS;
715
716         if (stats->tx_rate_flags & (HAL_TX_RATE_VHT20 | HAL_TX_RATE_VHT40 | HAL_TX_RATE_VHT80))
717                 info->flags |= RATE_INFO_FLAGS_VHT_MCS;
718
719         if (stats->tx_rate_flags & HAL_TX_RATE_SGI)
720                 info->flags |= RATE_INFO_FLAGS_SHORT_GI;
721
722         if (stats->tx_rate_flags & (HAL_TX_RATE_HT20 | HAL_TX_RATE_VHT20))
723                 info->bw = RATE_INFO_BW_20;
724
725         if (stats->tx_rate_flags & (HAL_TX_RATE_HT40 | HAL_TX_RATE_VHT40))
726                 info->bw = RATE_INFO_BW_40;
727
728         if (stats->tx_rate_flags & HAL_TX_RATE_VHT80)
729                 info->bw = RATE_INFO_BW_80;
730 }