2 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
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.
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.
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 #include <linux/random.h>
22 static inline int get_rssi0(struct wcn36xx_rx_bd
*bd
)
24 return 100 - ((bd
->phy_stat0
>> 24) & 0xff);
27 static inline int get_snr(struct wcn36xx_rx_bd
*bd
)
29 return ((bd
->phy_stat1
>> 24) & 0xff);
34 u16 mcs_or_legacy_index
;
35 enum mac80211_rx_encoding encoding
;
36 enum mac80211_rx_encoding_flags encoding_flags
;
40 /* Buffer descriptor rx_ch field is limited to 5-bit (4+1), a mapping is used
43 static const u8 ab_rx_ch_map
[] = { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104,
44 108, 112, 116, 120, 124, 128, 132, 136, 140,
45 149, 153, 157, 161, 165, 144 };
47 static const struct wcn36xx_rate wcn36xx_rate_table
[] = {
49 { 10, 0, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
50 { 20, 1, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
51 { 55, 2, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
52 { 110, 3, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
54 /* 11b SP (short preamble) */
55 { 10, 0, RX_ENC_LEGACY
, RX_ENC_FLAG_SHORTPRE
, RATE_INFO_BW_20
},
56 { 20, 1, RX_ENC_LEGACY
, RX_ENC_FLAG_SHORTPRE
, RATE_INFO_BW_20
},
57 { 55, 2, RX_ENC_LEGACY
, RX_ENC_FLAG_SHORTPRE
, RATE_INFO_BW_20
},
58 { 110, 3, RX_ENC_LEGACY
, RX_ENC_FLAG_SHORTPRE
, RATE_INFO_BW_20
},
61 { 60, 4, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
62 { 90, 5, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
63 { 120, 6, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
64 { 180, 7, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
65 { 240, 8, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
66 { 360, 9, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
67 { 480, 10, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
68 { 540, 11, RX_ENC_LEGACY
, 0, RATE_INFO_BW_20
},
71 { 65, 0, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
72 { 130, 1, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
73 { 195, 2, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
74 { 260, 3, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
75 { 390, 4, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
76 { 520, 5, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
77 { 585, 6, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
78 { 650, 7, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
81 { 72, 0, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
82 { 144, 1, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
83 { 217, 2, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
84 { 289, 3, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
85 { 434, 4, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
86 { 578, 5, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
87 { 650, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
88 { 722, 7, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
90 /* 11n GF (greenfield) */
91 { 65, 0, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_20
},
92 { 130, 1, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_20
},
93 { 195, 2, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_20
},
94 { 260, 3, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_20
},
95 { 390, 4, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_20
},
96 { 520, 5, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_20
},
97 { 585, 6, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_20
},
98 { 650, 7, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_20
},
100 /* 11n CB (channel bonding) */
101 { 135, 0, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
102 { 270, 1, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
103 { 405, 2, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
104 { 540, 3, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
105 { 810, 4, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
106 { 1080, 5, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
107 { 1215, 6, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
108 { 1350, 7, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
111 { 150, 0, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
112 { 300, 1, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
113 { 450, 2, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
114 { 600, 3, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
115 { 900, 4, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
116 { 1200, 5, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
117 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
118 { 1500, 7, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
121 { 135, 0, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_40
},
122 { 270, 1, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_40
},
123 { 405, 2, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_40
},
124 { 540, 3, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_40
},
125 { 810, 4, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_40
},
126 { 1080, 5, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_40
},
127 { 1215, 6, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_40
},
128 { 1350, 7, RX_ENC_HT
, RX_ENC_FLAG_HT_GF
, RATE_INFO_BW_40
},
130 /* 11ac reserved indices */
131 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
132 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
134 /* 11ac 20 MHz 800ns GI MCS 0-8 */
135 { 65, 0, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
136 { 130, 1, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
137 { 195, 2, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
138 { 260, 3, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
139 { 390, 4, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
140 { 520, 5, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
141 { 585, 6, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
142 { 650, 7, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
143 { 780, 8, RX_ENC_HT
, 0, RATE_INFO_BW_20
},
145 /* 11ac reserved indices */
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 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
156 /* 11ac 20 MHz 400ns SGI MCS 6-8 */
157 { 655, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
158 { 722, 7, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
159 { 866, 8, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_20
},
161 /* 11ac reserved indices */
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 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
166 /* 11ac 40 MHz 800ns GI MCS 0-9 */
167 { 135, 0, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
168 { 270, 1, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
169 { 405, 2, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
170 { 540, 3, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
171 { 810, 4, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
172 { 1080, 5, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
173 { 1215, 6, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
174 { 1350, 7, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
175 { 1350, 7, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
176 { 1620, 8, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
177 { 1800, 9, RX_ENC_HT
, 0, RATE_INFO_BW_40
},
179 /* 11ac reserved indices */
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 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
187 /* 11ac 40 MHz 400ns SGI MCS 5-7 */
188 { 1200, 5, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
189 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
190 { 1500, 7, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
192 /* 11ac reserved index */
193 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
195 /* 11ac 40 MHz 400ns SGI MCS 5-7 */
196 { 1800, 8, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
197 { 2000, 9, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
199 /* 11ac reserved index */
200 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
202 /* 11ac 80 MHz 800ns GI MCS 0-7 */
203 { 292, 0, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
204 { 585, 1, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
205 { 877, 2, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
206 { 1170, 3, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
207 { 1755, 4, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
208 { 2340, 5, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
209 { 2632, 6, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
210 { 2925, 7, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
212 /* 11 ac reserved index */
213 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
215 /* 11ac 80 MHz 800 ns GI MCS 8-9 */
216 { 3510, 8, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
217 { 3900, 9, RX_ENC_HT
, 0, RATE_INFO_BW_80
},
219 /* 11 ac reserved indices */
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 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
228 /* 11ac 80 MHz 400 ns SGI MCS 6-7 */
229 { 2925, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_80
},
230 { 3250, 7, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_80
},
232 /* 11ac reserved index */
233 { 1350, 6, RX_ENC_HT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_40
},
235 /* 11ac 80 MHz 400ns SGI MCS 8-9 */
236 { 3900, 8, RX_ENC_VHT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_80
},
237 { 4333, 9, RX_ENC_VHT
, RX_ENC_FLAG_SHORT_GI
, RATE_INFO_BW_80
},
240 static struct sk_buff
*wcn36xx_unchain_msdu(struct sk_buff_head
*amsdu
)
242 struct sk_buff
*skb
, *first
;
246 first
= __skb_dequeue(amsdu
);
248 skb_queue_walk(amsdu
, skb
)
249 total_len
+= skb
->len
;
251 space
= total_len
- skb_tailroom(first
);
252 if (space
> 0 && pskb_expand_head(first
, 0, space
, GFP_ATOMIC
) < 0) {
253 __skb_queue_head(amsdu
, first
);
257 /* Walk list again, copying contents into msdu_head */
258 while ((skb
= __skb_dequeue(amsdu
))) {
259 skb_copy_from_linear_data(skb
, skb_put(first
, skb
->len
),
261 dev_kfree_skb_irq(skb
);
267 static void __skb_queue_purge_irq(struct sk_buff_head
*list
)
271 while ((skb
= __skb_dequeue(list
)) != NULL
)
272 dev_kfree_skb_irq(skb
);
275 static void wcn36xx_update_survey(struct wcn36xx
*wcn
, int rssi
, int snr
,
278 static struct ieee80211_channel
*channel
;
279 struct ieee80211_supported_band
*sband
;
282 u8 snr_sample
= snr
& 0xff;
285 if (band
== NL80211_BAND_5GHZ
)
286 idx
= wcn
->hw
->wiphy
->bands
[NL80211_BAND_2GHZ
]->n_channels
;
288 sband
= wcn
->hw
->wiphy
->bands
[band
];
289 channel
= sband
->channels
;
291 for (i
= 0; i
< sband
->n_channels
; i
++, channel
++) {
292 if (channel
->center_freq
== freq
) {
298 spin_lock(&wcn
->survey_lock
);
299 wcn
->chan_survey
[idx
].rssi
= rssi
;
300 wcn
->chan_survey
[idx
].snr
= snr
;
301 spin_unlock(&wcn
->survey_lock
);
303 add_device_randomness(&snr_sample
, sizeof(snr_sample
));
306 int wcn36xx_rx_skb(struct wcn36xx
*wcn
, struct sk_buff
*skb
)
308 struct ieee80211_rx_status status
;
309 const struct wcn36xx_rate
*rate
;
310 struct ieee80211_hdr
*hdr
;
311 struct wcn36xx_rx_bd
*bd
;
315 * All fields must be 0, otherwise it can lead to
316 * unexpected consequences.
318 memset(&status
, 0, sizeof(status
));
320 bd
= (struct wcn36xx_rx_bd
*)skb
->data
;
321 buff_to_be(bd
, sizeof(*bd
)/sizeof(u32
));
322 wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP
,
323 "BD <<< ", (char *)bd
,
324 sizeof(struct wcn36xx_rx_bd
));
326 if (bd
->pdu
.mpdu_data_off
<= bd
->pdu
.mpdu_header_off
||
327 bd
->pdu
.mpdu_len
< bd
->pdu
.mpdu_header_len
)
330 if (bd
->asf
&& !bd
->esf
) { /* chained A-MSDU chunks */
332 if (bd
->pdu
.mpdu_data_off
+ bd
->pdu
.mpdu_len
> WCN36XX_PKT_SIZE
)
335 skb_put(skb
, bd
->pdu
.mpdu_data_off
+ bd
->pdu
.mpdu_len
);
336 skb_pull(skb
, bd
->pdu
.mpdu_data_off
);
338 /* Only set status for first chained BD (with mac header) */
342 if (bd
->pdu
.mpdu_header_off
< sizeof(*bd
) ||
343 bd
->pdu
.mpdu_header_off
+ bd
->pdu
.mpdu_len
> WCN36XX_PKT_SIZE
)
346 skb_put(skb
, bd
->pdu
.mpdu_header_off
+ bd
->pdu
.mpdu_len
);
347 skb_pull(skb
, bd
->pdu
.mpdu_header_off
);
349 hdr
= (struct ieee80211_hdr
*) skb
->data
;
350 fc
= __le16_to_cpu(hdr
->frame_control
);
351 sn
= IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr
->seq_ctrl
));
354 status
.signal
= -get_rssi0(bd
);
358 status
.flag
|= RX_FLAG_IV_STRIPPED
|
359 RX_FLAG_MMIC_STRIPPED
|
362 wcn36xx_dbg(WCN36XX_DBG_RX
, "status.flags=%x\n", status
.flag
);
364 if (bd
->scan_learn
) {
365 /* If packet originate from hardware scanning, extract the
366 * band/channel from bd descriptor.
368 u8 hwch
= (bd
->reserved0
<< 4) + bd
->rx_ch
;
370 if (bd
->rf_band
!= 1 && hwch
<= sizeof(ab_rx_ch_map
) && hwch
>= 1) {
371 status
.band
= NL80211_BAND_5GHZ
;
372 status
.freq
= ieee80211_channel_to_frequency(ab_rx_ch_map
[hwch
- 1],
375 status
.band
= NL80211_BAND_2GHZ
;
376 status
.freq
= ieee80211_channel_to_frequency(hwch
, status
.band
);
379 status
.band
= WCN36XX_BAND(wcn
);
380 status
.freq
= WCN36XX_CENTER_FREQ(wcn
);
383 wcn36xx_update_survey(wcn
, status
.signal
, get_snr(bd
),
384 status
.band
, status
.freq
);
386 if (bd
->rate_id
< ARRAY_SIZE(wcn36xx_rate_table
)) {
387 rate
= &wcn36xx_rate_table
[bd
->rate_id
];
388 status
.encoding
= rate
->encoding
;
389 status
.enc_flags
= rate
->encoding_flags
;
390 status
.bw
= rate
->bw
;
391 status
.rate_idx
= rate
->mcs_or_legacy_index
;
394 if (status
.band
== NL80211_BAND_5GHZ
&&
395 status
.encoding
== RX_ENC_LEGACY
&&
396 status
.rate_idx
>= 4) {
397 /* no dsss rates in 5Ghz rates table */
398 status
.rate_idx
-= 4;
403 status
.enc_flags
= 0;
407 if (ieee80211_is_beacon(hdr
->frame_control
) ||
408 ieee80211_is_probe_resp(hdr
->frame_control
))
409 status
.boottime_ns
= ktime_get_boottime_ns();
411 memcpy(IEEE80211_SKB_RXCB(skb
), &status
, sizeof(status
));
413 if (ieee80211_is_beacon(hdr
->frame_control
)) {
414 wcn36xx_dbg(WCN36XX_DBG_BEACON
, "beacon skb %p len %d fc %04x sn %d\n",
415 skb
, skb
->len
, fc
, sn
);
416 wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP
, "SKB <<< ",
417 (char *)skb
->data
, skb
->len
);
419 wcn36xx_dbg(WCN36XX_DBG_RX
, "rx skb %p len %d fc %04x sn %d\n",
420 skb
, skb
->len
, fc
, sn
);
421 wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP
, "SKB <<< ",
422 (char *)skb
->data
, skb
->len
);
426 /* Chained AMSDU ? slow path */
427 if (unlikely(bd
->asf
&& !(bd
->lsf
&& bd
->esf
))) {
428 if (bd
->esf
&& !skb_queue_empty(&wcn
->amsdu
)) {
429 wcn36xx_err("Discarding non complete chain");
430 __skb_queue_purge_irq(&wcn
->amsdu
);
433 __skb_queue_tail(&wcn
->amsdu
, skb
);
436 return 0; /* Not the last AMSDU, wait for more */
438 skb
= wcn36xx_unchain_msdu(&wcn
->amsdu
);
443 ieee80211_rx_irqsafe(wcn
->hw
, skb
);
447 drop
: /* drop everything */
448 wcn36xx_err("Drop frame! skb:%p len:%u hoff:%u doff:%u asf=%u esf=%u lsf=%u\n",
449 skb
, bd
->pdu
.mpdu_len
, bd
->pdu
.mpdu_header_off
,
450 bd
->pdu
.mpdu_data_off
, bd
->asf
, bd
->esf
, bd
->lsf
);
452 dev_kfree_skb_irq(skb
);
453 __skb_queue_purge_irq(&wcn
->amsdu
);
458 static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd
*bd
,
463 bd
->pdu
.mpdu_header_len
= mpdu_header_len
;
464 bd
->pdu
.mpdu_header_off
= sizeof(*bd
);
465 bd
->pdu
.mpdu_data_off
= bd
->pdu
.mpdu_header_len
+
466 bd
->pdu
.mpdu_header_off
;
467 bd
->pdu
.mpdu_len
= len
;
471 static inline struct wcn36xx_vif
*get_vif_by_addr(struct wcn36xx
*wcn
,
474 struct wcn36xx_vif
*vif_priv
= NULL
;
475 struct ieee80211_vif
*vif
= NULL
;
476 list_for_each_entry(vif_priv
, &wcn
->vif_list
, list
) {
477 vif
= wcn36xx_priv_to_vif(vif_priv
);
478 if (memcmp(vif
->addr
, addr
, ETH_ALEN
) == 0)
481 wcn36xx_warn("vif %pM not found\n", addr
);
485 static void wcn36xx_tx_start_ampdu(struct wcn36xx
*wcn
,
486 struct wcn36xx_sta
*sta_priv
,
489 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*)skb
->data
;
490 struct ieee80211_sta
*sta
;
493 if (!conf_is_ht(&wcn
->hw
->conf
))
496 sta
= wcn36xx_priv_to_sta(sta_priv
);
498 if (WARN_ON(!ieee80211_is_data_qos(hdr
->frame_control
)))
501 if (skb_get_queue_mapping(skb
) == IEEE80211_AC_VO
)
504 qc
= ieee80211_get_qos_ctl(hdr
);
505 tid
= qc
[0] & IEEE80211_QOS_CTL_TID_MASK
;
507 spin_lock(&sta_priv
->ampdu_lock
);
508 if (sta_priv
->ampdu_state
[tid
] != WCN36XX_AMPDU_NONE
)
511 if (sta_priv
->non_agg_frame_ct
++ >= WCN36XX_AMPDU_START_THRESH
) {
512 sta_priv
->ampdu_state
[tid
] = WCN36XX_AMPDU_START
;
513 sta_priv
->non_agg_frame_ct
= 0;
514 ieee80211_start_tx_ba_session(sta
, tid
, 0);
517 spin_unlock(&sta_priv
->ampdu_lock
);
520 static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd
*bd
,
522 struct wcn36xx_vif
**vif_priv
,
523 struct wcn36xx_sta
*sta_priv
,
527 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*)skb
->data
;
528 struct ieee80211_tx_info
*info
= IEEE80211_SKB_CB(skb
);
529 struct ieee80211_vif
*vif
= NULL
;
530 struct wcn36xx_vif
*__vif_priv
= NULL
;
531 bool is_data_qos
= ieee80211_is_data_qos(hdr
->frame_control
);
534 bd
->bd_rate
= WCN36XX_BD_RATE_DATA
;
537 * For not unicast frames mac80211 will not set sta pointer so use
538 * self_sta_index instead.
541 __vif_priv
= sta_priv
->vif
;
542 vif
= wcn36xx_priv_to_vif(__vif_priv
);
544 bd
->dpu_sign
= sta_priv
->ucast_dpu_sign
;
545 if (vif
->type
== NL80211_IFTYPE_STATION
) {
546 bd
->sta_index
= sta_priv
->bss_sta_index
;
547 bd
->dpu_desc_idx
= sta_priv
->bss_dpu_desc_index
;
548 } else if (vif
->type
== NL80211_IFTYPE_AP
||
549 vif
->type
== NL80211_IFTYPE_ADHOC
||
550 vif
->type
== NL80211_IFTYPE_MESH_POINT
) {
551 bd
->sta_index
= sta_priv
->sta_index
;
552 bd
->dpu_desc_idx
= sta_priv
->dpu_desc_index
;
555 __vif_priv
= get_vif_by_addr(wcn
, hdr
->addr2
);
556 bd
->sta_index
= __vif_priv
->self_sta_index
;
557 bd
->dpu_desc_idx
= __vif_priv
->self_dpu_desc_index
;
558 bd
->dpu_sign
= __vif_priv
->self_ucast_dpu_sign
;
562 tid
= ieee80211_get_tid(hdr
);
563 /* TID->QID is one-to-one mapping */
565 bd
->pdu
.bd_ssn
= WCN36XX_TXBD_SSN_FILL_DPU_QOS
;
567 bd
->pdu
.bd_ssn
= WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS
;
570 if (info
->flags
& IEEE80211_TX_INTFL_DONT_ENCRYPT
||
571 (sta_priv
&& !sta_priv
->is_data_encrypted
)) {
575 if (ieee80211_is_any_nullfunc(hdr
->frame_control
)) {
576 /* Don't use a regular queue for null packet (no ampdu) */
577 bd
->queue_id
= WCN36XX_TX_U_WQ_ID
;
578 bd
->bd_rate
= WCN36XX_BD_RATE_CTRL
;
579 if (ieee80211_is_qos_nullfunc(hdr
->frame_control
))
580 bd
->pdu
.bd_ssn
= WCN36XX_TXBD_SSN_FILL_HOST
;
587 *vif_priv
= __vif_priv
;
589 wcn36xx_set_tx_pdu(bd
,
591 sizeof(struct ieee80211_qos_hdr
) :
592 sizeof(struct ieee80211_hdr_3addr
),
595 if (sta_priv
&& is_data_qos
)
596 wcn36xx_tx_start_ampdu(wcn
, sta_priv
, skb
);
599 static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd
*bd
,
601 struct wcn36xx_vif
**vif_priv
,
605 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*)skb
->data
;
606 struct wcn36xx_vif
*__vif_priv
=
607 get_vif_by_addr(wcn
, hdr
->addr2
);
608 bd
->sta_index
= __vif_priv
->self_sta_index
;
609 bd
->dpu_desc_idx
= __vif_priv
->self_dpu_desc_index
;
612 /* default rate for unicast */
613 if (ieee80211_is_mgmt(hdr
->frame_control
))
614 bd
->bd_rate
= (WCN36XX_BAND(wcn
) == NL80211_BAND_5GHZ
) ?
615 WCN36XX_BD_RATE_CTRL
:
616 WCN36XX_BD_RATE_MGMT
;
617 else if (ieee80211_is_ctl(hdr
->frame_control
))
618 bd
->bd_rate
= WCN36XX_BD_RATE_CTRL
;
620 wcn36xx_warn("frame control type unknown\n");
623 * In joining state trick hardware that probe is sent as
624 * unicast even if address is broadcast.
626 if (__vif_priv
->is_joining
&&
627 ieee80211_is_probe_req(hdr
->frame_control
))
633 /* No ack needed not unicast */
635 bd
->queue_id
= WCN36XX_TX_B_WQ_ID
;
637 bd
->queue_id
= WCN36XX_TX_U_WQ_ID
;
638 *vif_priv
= __vif_priv
;
640 bd
->pdu
.bd_ssn
= WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS
;
642 wcn36xx_set_tx_pdu(bd
,
643 ieee80211_is_data_qos(hdr
->frame_control
) ?
644 sizeof(struct ieee80211_qos_hdr
) :
645 sizeof(struct ieee80211_hdr_3addr
),
646 skb
->len
, WCN36XX_TID
);
649 int wcn36xx_start_tx(struct wcn36xx
*wcn
,
650 struct wcn36xx_sta
*sta_priv
,
653 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*)skb
->data
;
654 struct wcn36xx_vif
*vif_priv
= NULL
;
655 struct ieee80211_tx_info
*info
= IEEE80211_SKB_CB(skb
);
656 bool is_low
= ieee80211_is_data(hdr
->frame_control
);
657 bool bcast
= is_broadcast_ether_addr(hdr
->addr1
) ||
658 is_multicast_ether_addr(hdr
->addr1
);
659 bool ack_ind
= (info
->flags
& IEEE80211_TX_CTL_REQ_TX_STATUS
) &&
660 !(info
->flags
& IEEE80211_TX_CTL_NO_ACK
);
661 struct wcn36xx_tx_bd bd
;
664 memset(&bd
, 0, sizeof(bd
));
666 wcn36xx_dbg(WCN36XX_DBG_TX
,
667 "tx skb %p len %d fc %04x sn %d %s %s\n",
668 skb
, skb
->len
, __le16_to_cpu(hdr
->frame_control
),
669 IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr
->seq_ctrl
)),
670 is_low
? "low" : "high", bcast
? "bcast" : "ucast");
672 wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP
, "", skb
->data
, skb
->len
);
674 bd
.dpu_rf
= WCN36XX_BMU_WQ_TX
;
676 if (unlikely(ack_ind
)) {
677 wcn36xx_dbg(WCN36XX_DBG_DXE
, "TX_ACK status requested\n");
679 /* Only one at a time is supported by fw. Stop the TX queues
680 * until the ack status gets back.
682 ieee80211_stop_queues(wcn
->hw
);
684 /* Request ack indication from the firmware */
688 /* Data frames served first*/
690 wcn36xx_set_tx_data(&bd
, wcn
, &vif_priv
, sta_priv
, skb
, bcast
);
692 /* MGMT and CTRL frames are handeld here*/
693 wcn36xx_set_tx_mgmt(&bd
, wcn
, &vif_priv
, skb
, bcast
);
695 buff_to_be(&bd
, sizeof(bd
)/sizeof(u32
));
696 bd
.tx_bd_sign
= 0xbdbdbdbd;
698 ret
= wcn36xx_dxe_tx_frame(wcn
, vif_priv
, &bd
, skb
, is_low
);
699 if (unlikely(ret
&& ack_ind
)) {
700 /* If the skb has not been transmitted, resume TX queue */
701 ieee80211_wake_queues(wcn
->hw
);
707 void wcn36xx_process_tx_rate(struct ani_global_class_a_stats_info
*stats
, struct rate_info
*info
)
709 /* tx_rate is in units of 500kbps; mac80211 wants them in 100kbps */
710 if (stats
->tx_rate_flags
& HAL_TX_RATE_LEGACY
)
711 info
->legacy
= stats
->tx_rate
* 5;
714 info
->mcs
= stats
->mcs_index
;
717 if (stats
->tx_rate_flags
& (HAL_TX_RATE_HT20
| HAL_TX_RATE_HT40
))
718 info
->flags
|= RATE_INFO_FLAGS_MCS
;
720 if (stats
->tx_rate_flags
& (HAL_TX_RATE_VHT20
| HAL_TX_RATE_VHT40
| HAL_TX_RATE_VHT80
))
721 info
->flags
|= RATE_INFO_FLAGS_VHT_MCS
;
723 if (stats
->tx_rate_flags
& HAL_TX_RATE_SGI
)
724 info
->flags
|= RATE_INFO_FLAGS_SHORT_GI
;
726 if (stats
->tx_rate_flags
& (HAL_TX_RATE_HT20
| HAL_TX_RATE_VHT20
))
727 info
->bw
= RATE_INFO_BW_20
;
729 if (stats
->tx_rate_flags
& (HAL_TX_RATE_HT40
| HAL_TX_RATE_VHT40
))
730 info
->bw
= RATE_INFO_BW_40
;
732 if (stats
->tx_rate_flags
& HAL_TX_RATE_VHT80
)
733 info
->bw
= RATE_INFO_BW_80
;