1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | |
4 | Broadcom B43 wireless driver |
5 | |
6 | Transmission (TX/RX) related functions. |
7 | |
8 | Copyright (C) 2005 Martin Langer <martin-langer@gmx.de> |
9 | Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it> |
10 | Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch> |
11 | Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org> |
12 | Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> |
13 | |
14 | |
15 | */ |
16 | |
17 | #include "xmit.h" |
18 | #include "phy_common.h" |
19 | #include "dma.h" |
20 | #include "pio.h" |
21 | |
22 | static const struct b43_tx_legacy_rate_phy_ctl_entry b43_tx_legacy_rate_phy_ctl[] = { |
23 | { B43_CCK_RATE_1MB, 0x0, 0x0 }, |
24 | { B43_CCK_RATE_2MB, 0x0, 0x1 }, |
25 | { B43_CCK_RATE_5MB, 0x0, 0x2 }, |
26 | { B43_CCK_RATE_11MB, 0x0, 0x3 }, |
27 | { B43_OFDM_RATE_6MB, B43_TXH_PHY1_CRATE_1_2, B43_TXH_PHY1_MODUL_BPSK }, |
28 | { B43_OFDM_RATE_9MB, B43_TXH_PHY1_CRATE_3_4, B43_TXH_PHY1_MODUL_BPSK }, |
29 | { B43_OFDM_RATE_12MB, B43_TXH_PHY1_CRATE_1_2, B43_TXH_PHY1_MODUL_QPSK }, |
30 | { B43_OFDM_RATE_18MB, B43_TXH_PHY1_CRATE_3_4, B43_TXH_PHY1_MODUL_QPSK }, |
31 | { B43_OFDM_RATE_24MB, B43_TXH_PHY1_CRATE_1_2, B43_TXH_PHY1_MODUL_QAM16 }, |
32 | { B43_OFDM_RATE_36MB, B43_TXH_PHY1_CRATE_3_4, B43_TXH_PHY1_MODUL_QAM16 }, |
33 | { B43_OFDM_RATE_48MB, B43_TXH_PHY1_CRATE_2_3, B43_TXH_PHY1_MODUL_QAM64 }, |
34 | { B43_OFDM_RATE_54MB, B43_TXH_PHY1_CRATE_3_4, B43_TXH_PHY1_MODUL_QAM64 }, |
35 | }; |
36 | |
37 | static const struct b43_tx_legacy_rate_phy_ctl_entry * |
38 | b43_tx_legacy_rate_phy_ctl_ent(u8 bitrate) |
39 | { |
40 | const struct b43_tx_legacy_rate_phy_ctl_entry *e; |
41 | unsigned int i; |
42 | |
43 | for (i = 0; i < ARRAY_SIZE(b43_tx_legacy_rate_phy_ctl); i++) { |
44 | e = &(b43_tx_legacy_rate_phy_ctl[i]); |
45 | if (e->bitrate == bitrate) |
46 | return e; |
47 | } |
48 | |
49 | B43_WARN_ON(1); |
50 | return NULL; |
51 | } |
52 | |
53 | /* Extract the bitrate index out of a CCK PLCP header. */ |
54 | static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) |
55 | { |
56 | switch (plcp->raw[0]) { |
57 | case 0x0A: |
58 | return 0; |
59 | case 0x14: |
60 | return 1; |
61 | case 0x37: |
62 | return 2; |
63 | case 0x6E: |
64 | return 3; |
65 | } |
66 | return -1; |
67 | } |
68 | |
69 | /* Extract the bitrate index out of an OFDM PLCP header. */ |
70 | static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5) |
71 | { |
72 | /* For 2 GHz band first OFDM rate is at index 4, see main.c */ |
73 | int base = ghz5 ? 0 : 4; |
74 | |
75 | switch (plcp->raw[0] & 0xF) { |
76 | case 0xB: |
77 | return base + 0; |
78 | case 0xF: |
79 | return base + 1; |
80 | case 0xA: |
81 | return base + 2; |
82 | case 0xE: |
83 | return base + 3; |
84 | case 0x9: |
85 | return base + 4; |
86 | case 0xD: |
87 | return base + 5; |
88 | case 0x8: |
89 | return base + 6; |
90 | case 0xC: |
91 | return base + 7; |
92 | } |
93 | return -1; |
94 | } |
95 | |
96 | u8 b43_plcp_get_ratecode_cck(const u8 bitrate) |
97 | { |
98 | switch (bitrate) { |
99 | case B43_CCK_RATE_1MB: |
100 | return 0x0A; |
101 | case B43_CCK_RATE_2MB: |
102 | return 0x14; |
103 | case B43_CCK_RATE_5MB: |
104 | return 0x37; |
105 | case B43_CCK_RATE_11MB: |
106 | return 0x6E; |
107 | } |
108 | B43_WARN_ON(1); |
109 | return 0; |
110 | } |
111 | |
112 | u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate) |
113 | { |
114 | switch (bitrate) { |
115 | case B43_OFDM_RATE_6MB: |
116 | return 0xB; |
117 | case B43_OFDM_RATE_9MB: |
118 | return 0xF; |
119 | case B43_OFDM_RATE_12MB: |
120 | return 0xA; |
121 | case B43_OFDM_RATE_18MB: |
122 | return 0xE; |
123 | case B43_OFDM_RATE_24MB: |
124 | return 0x9; |
125 | case B43_OFDM_RATE_36MB: |
126 | return 0xD; |
127 | case B43_OFDM_RATE_48MB: |
128 | return 0x8; |
129 | case B43_OFDM_RATE_54MB: |
130 | return 0xC; |
131 | } |
132 | B43_WARN_ON(1); |
133 | return 0; |
134 | } |
135 | |
136 | void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, |
137 | const u16 octets, const u8 bitrate) |
138 | { |
139 | __u8 *raw = plcp->raw; |
140 | |
141 | if (b43_is_ofdm_rate(rate: bitrate)) { |
142 | u32 d; |
143 | |
144 | d = b43_plcp_get_ratecode_ofdm(bitrate); |
145 | B43_WARN_ON(octets & 0xF000); |
146 | d |= (octets << 5); |
147 | plcp->data = cpu_to_le32(d); |
148 | } else { |
149 | u32 plen; |
150 | |
151 | plen = octets * 16 / bitrate; |
152 | if ((octets * 16 % bitrate) > 0) { |
153 | plen++; |
154 | if ((bitrate == B43_CCK_RATE_11MB) |
155 | && ((octets * 8 % 11) < 4)) { |
156 | raw[1] = 0x84; |
157 | } else |
158 | raw[1] = 0x04; |
159 | } else |
160 | raw[1] = 0x04; |
161 | plcp->data |= cpu_to_le32(plen << 16); |
162 | raw[0] = b43_plcp_get_ratecode_cck(bitrate); |
163 | } |
164 | } |
165 | |
166 | /* TODO: verify if needed for SSLPN or LCN */ |
167 | static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate) |
168 | { |
169 | const struct b43_phy *phy = &dev->phy; |
170 | const struct b43_tx_legacy_rate_phy_ctl_entry *e; |
171 | u16 control = 0; |
172 | u16 bw; |
173 | |
174 | if (phy->type == B43_PHYTYPE_LP) |
175 | bw = B43_TXH_PHY1_BW_20; |
176 | else /* FIXME */ |
177 | bw = B43_TXH_PHY1_BW_20; |
178 | |
179 | if (0) { /* FIXME: MIMO */ |
180 | } else if (b43_is_cck_rate(rate: bitrate) && phy->type != B43_PHYTYPE_LP) { |
181 | control = bw; |
182 | } else { |
183 | control = bw; |
184 | e = b43_tx_legacy_rate_phy_ctl_ent(bitrate); |
185 | if (e) { |
186 | control |= e->coding_rate; |
187 | control |= e->modulation; |
188 | } |
189 | control |= B43_TXH_PHY1_MODE_SISO; |
190 | } |
191 | |
192 | return control; |
193 | } |
194 | |
195 | static u8 b43_calc_fallback_rate(u8 bitrate, int gmode) |
196 | { |
197 | switch (bitrate) { |
198 | case B43_CCK_RATE_1MB: |
199 | return B43_CCK_RATE_1MB; |
200 | case B43_CCK_RATE_2MB: |
201 | return B43_CCK_RATE_1MB; |
202 | case B43_CCK_RATE_5MB: |
203 | return B43_CCK_RATE_2MB; |
204 | case B43_CCK_RATE_11MB: |
205 | return B43_CCK_RATE_5MB; |
206 | /* |
207 | * Don't just fallback to CCK; it may be in 5GHz operation |
208 | * and falling back to CCK won't work out very well. |
209 | */ |
210 | case B43_OFDM_RATE_6MB: |
211 | if (gmode) |
212 | return B43_CCK_RATE_5MB; |
213 | else |
214 | return B43_OFDM_RATE_6MB; |
215 | case B43_OFDM_RATE_9MB: |
216 | return B43_OFDM_RATE_6MB; |
217 | case B43_OFDM_RATE_12MB: |
218 | return B43_OFDM_RATE_9MB; |
219 | case B43_OFDM_RATE_18MB: |
220 | return B43_OFDM_RATE_12MB; |
221 | case B43_OFDM_RATE_24MB: |
222 | return B43_OFDM_RATE_18MB; |
223 | case B43_OFDM_RATE_36MB: |
224 | return B43_OFDM_RATE_24MB; |
225 | case B43_OFDM_RATE_48MB: |
226 | return B43_OFDM_RATE_36MB; |
227 | case B43_OFDM_RATE_54MB: |
228 | return B43_OFDM_RATE_48MB; |
229 | } |
230 | B43_WARN_ON(1); |
231 | return 0; |
232 | } |
233 | |
234 | /* Generate a TX data header. */ |
235 | int b43_generate_txhdr(struct b43_wldev *dev, |
236 | u8 *_txhdr, |
237 | struct sk_buff *skb_frag, |
238 | struct ieee80211_tx_info *info, |
239 | u16 cookie) |
240 | { |
241 | const unsigned char *fragment_data = skb_frag->data; |
242 | unsigned int fragment_len = skb_frag->len; |
243 | struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; |
244 | const struct b43_phy *phy = &dev->phy; |
245 | const struct ieee80211_hdr *wlhdr = |
246 | (const struct ieee80211_hdr *)fragment_data; |
247 | int use_encryption = !!info->control.hw_key; |
248 | __le16 fctl = wlhdr->frame_control; |
249 | struct ieee80211_rate *fbrate; |
250 | u8 rate, rate_fb; |
251 | int rate_ofdm, rate_fb_ofdm; |
252 | unsigned int plcp_fragment_len; |
253 | u32 mac_ctl = 0; |
254 | u16 phy_ctl = 0; |
255 | bool fill_phy_ctl1 = (phy->type == B43_PHYTYPE_LP || |
256 | phy->type == B43_PHYTYPE_N || |
257 | phy->type == B43_PHYTYPE_HT); |
258 | u8 = 0; |
259 | struct ieee80211_rate *txrate; |
260 | struct ieee80211_tx_rate *rates; |
261 | |
262 | memset(txhdr, 0, sizeof(*txhdr)); |
263 | |
264 | txrate = ieee80211_get_tx_rate(hw: dev->wl->hw, c: info); |
265 | rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; |
266 | rate_ofdm = b43_is_ofdm_rate(rate); |
267 | fbrate = ieee80211_get_alt_retry_rate(hw: dev->wl->hw, c: info, idx: 0) ? : txrate; |
268 | rate_fb = fbrate->hw_value; |
269 | rate_fb_ofdm = b43_is_ofdm_rate(rate: rate_fb); |
270 | |
271 | if (rate_ofdm) |
272 | txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(bitrate: rate); |
273 | else |
274 | txhdr->phy_rate = b43_plcp_get_ratecode_cck(bitrate: rate); |
275 | txhdr->mac_frame_ctl = wlhdr->frame_control; |
276 | memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN); |
277 | |
278 | /* Calculate duration for fallback rate */ |
279 | if ((rate_fb == rate) || |
280 | (wlhdr->duration_id & cpu_to_le16(0x8000)) || |
281 | (wlhdr->duration_id == cpu_to_le16(0))) { |
282 | /* If the fallback rate equals the normal rate or the |
283 | * dur_id field contains an AID, CFP magic or 0, |
284 | * use the original dur_id field. */ |
285 | txhdr->dur_fb = wlhdr->duration_id; |
286 | } else { |
287 | txhdr->dur_fb = ieee80211_generic_frame_duration( |
288 | hw: dev->wl->hw, vif: info->control.vif, band: info->band, |
289 | frame_len: fragment_len, rate: fbrate); |
290 | } |
291 | |
292 | plcp_fragment_len = fragment_len + FCS_LEN; |
293 | if (use_encryption) { |
294 | u8 key_idx = info->control.hw_key->hw_key_idx; |
295 | struct b43_key *key; |
296 | int wlhdr_len; |
297 | size_t iv_len; |
298 | |
299 | B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key)); |
300 | key = &(dev->key[key_idx]); |
301 | |
302 | if (unlikely(!key->keyconf)) { |
303 | /* This key is invalid. This might only happen |
304 | * in a short timeframe after machine resume before |
305 | * we were able to reconfigure keys. |
306 | * Drop this packet completely. Do not transmit it |
307 | * unencrypted to avoid leaking information. */ |
308 | return -ENOKEY; |
309 | } |
310 | |
311 | /* Hardware appends ICV. */ |
312 | plcp_fragment_len += info->control.hw_key->icv_len; |
313 | |
314 | key_idx = b43_kidx_to_fw(dev, raw_kidx: key_idx); |
315 | mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & |
316 | B43_TXH_MAC_KEYIDX; |
317 | mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & |
318 | B43_TXH_MAC_KEYALG; |
319 | wlhdr_len = ieee80211_hdrlen(fc: fctl); |
320 | if (key->algorithm == B43_SEC_ALGO_TKIP) { |
321 | u16 phase1key[5]; |
322 | int i; |
323 | /* we give the phase1key and iv16 here, the key is stored in |
324 | * shm. With that the hardware can do phase 2 and encryption. |
325 | */ |
326 | ieee80211_get_tkip_p1k(keyconf: info->control.hw_key, skb: skb_frag, p1k: phase1key); |
327 | /* phase1key is in host endian. Copy to little-endian txhdr->iv. */ |
328 | for (i = 0; i < 5; i++) { |
329 | txhdr->iv[i * 2 + 0] = phase1key[i]; |
330 | txhdr->iv[i * 2 + 1] = phase1key[i] >> 8; |
331 | } |
332 | /* iv16 */ |
333 | memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3); |
334 | } else { |
335 | iv_len = min_t(size_t, info->control.hw_key->iv_len, |
336 | ARRAY_SIZE(txhdr->iv)); |
337 | memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); |
338 | } |
339 | } |
340 | switch (dev->fw.hdr_format) { |
341 | case B43_FW_HDR_598: |
342 | b43_generate_plcp_hdr(plcp: (struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp), |
343 | octets: plcp_fragment_len, bitrate: rate); |
344 | break; |
345 | case B43_FW_HDR_351: |
346 | b43_generate_plcp_hdr(plcp: (struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp), |
347 | octets: plcp_fragment_len, bitrate: rate); |
348 | break; |
349 | case B43_FW_HDR_410: |
350 | b43_generate_plcp_hdr(plcp: (struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp), |
351 | octets: plcp_fragment_len, bitrate: rate); |
352 | break; |
353 | } |
354 | b43_generate_plcp_hdr(plcp: (struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), |
355 | octets: plcp_fragment_len, bitrate: rate_fb); |
356 | |
357 | /* Extra Frame Types */ |
358 | if (rate_fb_ofdm) |
359 | extra_ft |= B43_TXH_EFT_FB_OFDM; |
360 | else |
361 | extra_ft |= B43_TXH_EFT_FB_CCK; |
362 | |
363 | /* Set channel radio code. Note that the micrcode ORs 0x100 to |
364 | * this value before comparing it to the value in SHM, if this |
365 | * is a 5Ghz packet. |
366 | */ |
367 | txhdr->chan_radio_code = phy->channel; |
368 | |
369 | /* PHY TX Control word */ |
370 | if (rate_ofdm) |
371 | phy_ctl |= B43_TXH_PHY_ENC_OFDM; |
372 | else |
373 | phy_ctl |= B43_TXH_PHY_ENC_CCK; |
374 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) |
375 | phy_ctl |= B43_TXH_PHY_SHORTPRMBL; |
376 | |
377 | switch (b43_ieee80211_antenna_sanitize(dev, antenna_nr: 0)) { |
378 | case 0: /* Default */ |
379 | phy_ctl |= B43_TXH_PHY_ANT01AUTO; |
380 | break; |
381 | case 1: /* Antenna 0 */ |
382 | phy_ctl |= B43_TXH_PHY_ANT0; |
383 | break; |
384 | case 2: /* Antenna 1 */ |
385 | phy_ctl |= B43_TXH_PHY_ANT1; |
386 | break; |
387 | case 3: /* Antenna 2 */ |
388 | phy_ctl |= B43_TXH_PHY_ANT2; |
389 | break; |
390 | case 4: /* Antenna 3 */ |
391 | phy_ctl |= B43_TXH_PHY_ANT3; |
392 | break; |
393 | default: |
394 | B43_WARN_ON(1); |
395 | } |
396 | |
397 | rates = info->control.rates; |
398 | /* MAC control */ |
399 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
400 | mac_ctl |= B43_TXH_MAC_ACK; |
401 | /* use hardware sequence counter as the non-TID counter */ |
402 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) |
403 | mac_ctl |= B43_TXH_MAC_HWSEQ; |
404 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
405 | mac_ctl |= B43_TXH_MAC_STMSDU; |
406 | if (!phy->gmode) |
407 | mac_ctl |= B43_TXH_MAC_5GHZ; |
408 | |
409 | /* Overwrite rates[0].count to make the retry calculation |
410 | * in the tx status easier. need the actual retry limit to |
411 | * detect whether the fallback rate was used. |
412 | */ |
413 | if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || |
414 | (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { |
415 | rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; |
416 | mac_ctl |= B43_TXH_MAC_LONGFRAME; |
417 | } else { |
418 | rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; |
419 | } |
420 | |
421 | /* Generate the RTS or CTS-to-self frame */ |
422 | if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || |
423 | (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { |
424 | unsigned int len; |
425 | struct ieee80211_hdr *hdr; |
426 | int rts_rate, rts_rate_fb; |
427 | int rts_rate_ofdm, rts_rate_fb_ofdm; |
428 | struct b43_plcp_hdr6 *plcp; |
429 | struct ieee80211_rate *rts_cts_rate; |
430 | |
431 | rts_cts_rate = ieee80211_get_rts_cts_rate(hw: dev->wl->hw, c: info); |
432 | |
433 | rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB; |
434 | rts_rate_ofdm = b43_is_ofdm_rate(rate: rts_rate); |
435 | rts_rate_fb = b43_calc_fallback_rate(bitrate: rts_rate, gmode: phy->gmode); |
436 | rts_rate_fb_ofdm = b43_is_ofdm_rate(rate: rts_rate_fb); |
437 | |
438 | if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
439 | struct ieee80211_cts *cts; |
440 | |
441 | switch (dev->fw.hdr_format) { |
442 | case B43_FW_HDR_598: |
443 | cts = (struct ieee80211_cts *) |
444 | (txhdr->format_598.rts_frame); |
445 | break; |
446 | case B43_FW_HDR_351: |
447 | cts = (struct ieee80211_cts *) |
448 | (txhdr->format_351.rts_frame); |
449 | break; |
450 | case B43_FW_HDR_410: |
451 | cts = (struct ieee80211_cts *) |
452 | (txhdr->format_410.rts_frame); |
453 | break; |
454 | } |
455 | ieee80211_ctstoself_get(hw: dev->wl->hw, vif: info->control.vif, |
456 | frame: fragment_data, frame_len: fragment_len, |
457 | frame_txctl: info, cts); |
458 | mac_ctl |= B43_TXH_MAC_SENDCTS; |
459 | len = sizeof(struct ieee80211_cts); |
460 | } else { |
461 | struct ieee80211_rts *rts; |
462 | |
463 | switch (dev->fw.hdr_format) { |
464 | case B43_FW_HDR_598: |
465 | rts = (struct ieee80211_rts *) |
466 | (txhdr->format_598.rts_frame); |
467 | break; |
468 | case B43_FW_HDR_351: |
469 | rts = (struct ieee80211_rts *) |
470 | (txhdr->format_351.rts_frame); |
471 | break; |
472 | case B43_FW_HDR_410: |
473 | rts = (struct ieee80211_rts *) |
474 | (txhdr->format_410.rts_frame); |
475 | break; |
476 | } |
477 | ieee80211_rts_get(hw: dev->wl->hw, vif: info->control.vif, |
478 | frame: fragment_data, frame_len: fragment_len, |
479 | frame_txctl: info, rts); |
480 | mac_ctl |= B43_TXH_MAC_SENDRTS; |
481 | len = sizeof(struct ieee80211_rts); |
482 | } |
483 | len += FCS_LEN; |
484 | |
485 | /* Generate the PLCP headers for the RTS/CTS frame */ |
486 | switch (dev->fw.hdr_format) { |
487 | case B43_FW_HDR_598: |
488 | plcp = &txhdr->format_598.rts_plcp; |
489 | break; |
490 | case B43_FW_HDR_351: |
491 | plcp = &txhdr->format_351.rts_plcp; |
492 | break; |
493 | case B43_FW_HDR_410: |
494 | plcp = &txhdr->format_410.rts_plcp; |
495 | break; |
496 | } |
497 | b43_generate_plcp_hdr(plcp: (struct b43_plcp_hdr4 *)plcp, |
498 | octets: len, bitrate: rts_rate); |
499 | plcp = &txhdr->rts_plcp_fb; |
500 | b43_generate_plcp_hdr(plcp: (struct b43_plcp_hdr4 *)plcp, |
501 | octets: len, bitrate: rts_rate_fb); |
502 | |
503 | switch (dev->fw.hdr_format) { |
504 | case B43_FW_HDR_598: |
505 | hdr = (struct ieee80211_hdr *) |
506 | (&txhdr->format_598.rts_frame); |
507 | break; |
508 | case B43_FW_HDR_351: |
509 | hdr = (struct ieee80211_hdr *) |
510 | (&txhdr->format_351.rts_frame); |
511 | break; |
512 | case B43_FW_HDR_410: |
513 | hdr = (struct ieee80211_hdr *) |
514 | (&txhdr->format_410.rts_frame); |
515 | break; |
516 | } |
517 | txhdr->rts_dur_fb = hdr->duration_id; |
518 | |
519 | if (rts_rate_ofdm) { |
520 | extra_ft |= B43_TXH_EFT_RTS_OFDM; |
521 | txhdr->phy_rate_rts = |
522 | b43_plcp_get_ratecode_ofdm(bitrate: rts_rate); |
523 | } else { |
524 | extra_ft |= B43_TXH_EFT_RTS_CCK; |
525 | txhdr->phy_rate_rts = |
526 | b43_plcp_get_ratecode_cck(bitrate: rts_rate); |
527 | } |
528 | if (rts_rate_fb_ofdm) |
529 | extra_ft |= B43_TXH_EFT_RTSFB_OFDM; |
530 | else |
531 | extra_ft |= B43_TXH_EFT_RTSFB_CCK; |
532 | |
533 | if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS && |
534 | fill_phy_ctl1) { |
535 | txhdr->phy_ctl1_rts = cpu_to_le16( |
536 | b43_generate_tx_phy_ctl1(dev, rts_rate)); |
537 | txhdr->phy_ctl1_rts_fb = cpu_to_le16( |
538 | b43_generate_tx_phy_ctl1(dev, rts_rate_fb)); |
539 | } |
540 | } |
541 | |
542 | /* Magic cookie */ |
543 | switch (dev->fw.hdr_format) { |
544 | case B43_FW_HDR_598: |
545 | txhdr->format_598.cookie = cpu_to_le16(cookie); |
546 | break; |
547 | case B43_FW_HDR_351: |
548 | txhdr->format_351.cookie = cpu_to_le16(cookie); |
549 | break; |
550 | case B43_FW_HDR_410: |
551 | txhdr->format_410.cookie = cpu_to_le16(cookie); |
552 | break; |
553 | } |
554 | |
555 | if (fill_phy_ctl1) { |
556 | txhdr->phy_ctl1 = |
557 | cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate)); |
558 | txhdr->phy_ctl1_fb = |
559 | cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate_fb)); |
560 | } |
561 | |
562 | /* Apply the bitfields */ |
563 | txhdr->mac_ctl = cpu_to_le32(mac_ctl); |
564 | txhdr->phy_ctl = cpu_to_le16(phy_ctl); |
565 | txhdr->extra_ft = extra_ft; |
566 | |
567 | return 0; |
568 | } |
569 | |
570 | static s8 (struct b43_wldev *dev, |
571 | u8 , int ofdm, |
572 | int adjust_2053, int adjust_2050) |
573 | { |
574 | struct b43_phy *phy = &dev->phy; |
575 | struct b43_phy_g *gphy = phy->g; |
576 | s32 tmp; |
577 | |
578 | switch (phy->radio_ver) { |
579 | case 0x2050: |
580 | if (ofdm) { |
581 | tmp = in_rssi; |
582 | if (tmp > 127) |
583 | tmp -= 256; |
584 | tmp *= 73; |
585 | tmp /= 64; |
586 | if (adjust_2050) |
587 | tmp += 25; |
588 | else |
589 | tmp -= 3; |
590 | } else { |
591 | if (dev->dev->bus_sprom-> |
592 | boardflags_lo & B43_BFL_RSSI) { |
593 | if (in_rssi > 63) |
594 | in_rssi = 63; |
595 | B43_WARN_ON(phy->type != B43_PHYTYPE_G); |
596 | tmp = gphy->nrssi_lt[in_rssi]; |
597 | tmp = 31 - tmp; |
598 | tmp *= -131; |
599 | tmp /= 128; |
600 | tmp -= 57; |
601 | } else { |
602 | tmp = in_rssi; |
603 | tmp = 31 - tmp; |
604 | tmp *= -149; |
605 | tmp /= 128; |
606 | tmp -= 68; |
607 | } |
608 | if (phy->type == B43_PHYTYPE_G && adjust_2050) |
609 | tmp += 25; |
610 | } |
611 | break; |
612 | case 0x2060: |
613 | if (in_rssi > 127) |
614 | tmp = in_rssi - 256; |
615 | else |
616 | tmp = in_rssi; |
617 | break; |
618 | default: |
619 | tmp = in_rssi; |
620 | tmp -= 11; |
621 | tmp *= 103; |
622 | tmp /= 64; |
623 | if (adjust_2053) |
624 | tmp -= 109; |
625 | else |
626 | tmp -= 83; |
627 | } |
628 | |
629 | return (s8) tmp; |
630 | } |
631 | |
632 | void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) |
633 | { |
634 | struct ieee80211_rx_status status; |
635 | struct b43_plcp_hdr6 *plcp; |
636 | struct ieee80211_hdr *wlhdr; |
637 | const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; |
638 | __le16 fctl; |
639 | u16 phystat0, phystat3; |
640 | u16 chanstat, mactime; |
641 | u32 macstat; |
642 | u16 chanid; |
643 | int padding, rate_idx; |
644 | |
645 | memset(&status, 0, sizeof(status)); |
646 | |
647 | /* Get metadata about the frame from the header. */ |
648 | phystat0 = le16_to_cpu(rxhdr->phy_status0); |
649 | phystat3 = le16_to_cpu(rxhdr->phy_status3); |
650 | switch (dev->fw.hdr_format) { |
651 | case B43_FW_HDR_598: |
652 | macstat = le32_to_cpu(rxhdr->format_598.mac_status); |
653 | mactime = le16_to_cpu(rxhdr->format_598.mac_time); |
654 | chanstat = le16_to_cpu(rxhdr->format_598.channel); |
655 | break; |
656 | case B43_FW_HDR_410: |
657 | case B43_FW_HDR_351: |
658 | macstat = le32_to_cpu(rxhdr->format_351.mac_status); |
659 | mactime = le16_to_cpu(rxhdr->format_351.mac_time); |
660 | chanstat = le16_to_cpu(rxhdr->format_351.channel); |
661 | break; |
662 | } |
663 | |
664 | if (unlikely(macstat & B43_RX_MAC_FCSERR)) { |
665 | dev->wl->ieee_stats.dot11FCSErrorCount++; |
666 | status.flag |= RX_FLAG_FAILED_FCS_CRC; |
667 | } |
668 | if (unlikely(phystat0 & (B43_RX_PHYST0_PLCPHCF | B43_RX_PHYST0_PLCPFV))) |
669 | status.flag |= RX_FLAG_FAILED_PLCP_CRC; |
670 | if (phystat0 & B43_RX_PHYST0_SHORTPRMBL) |
671 | status.enc_flags |= RX_ENC_FLAG_SHORTPRE; |
672 | if (macstat & B43_RX_MAC_DECERR) { |
673 | /* Decryption with the given key failed. |
674 | * Drop the packet. We also won't be able to decrypt it with |
675 | * the key in software. */ |
676 | goto drop; |
677 | } |
678 | |
679 | /* Skip PLCP and padding */ |
680 | padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0; |
681 | if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) { |
682 | b43dbg(wl: dev->wl, fmt: "RX: Packet size underrun (1)\n" ); |
683 | goto drop; |
684 | } |
685 | plcp = (struct b43_plcp_hdr6 *)(skb->data + padding); |
686 | skb_pull(skb, len: sizeof(struct b43_plcp_hdr6) + padding); |
687 | /* The skb contains the Wireless Header + payload data now */ |
688 | if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */ + FCS_LEN))) { |
689 | b43dbg(wl: dev->wl, fmt: "RX: Packet size underrun (2)\n" ); |
690 | goto drop; |
691 | } |
692 | wlhdr = (struct ieee80211_hdr *)(skb->data); |
693 | fctl = wlhdr->frame_control; |
694 | |
695 | if (macstat & B43_RX_MAC_DEC) { |
696 | unsigned int keyidx; |
697 | int wlhdr_len; |
698 | |
699 | keyidx = ((macstat & B43_RX_MAC_KEYIDX) |
700 | >> B43_RX_MAC_KEYIDX_SHIFT); |
701 | /* We must adjust the key index here. We want the "physical" |
702 | * key index, but the ucode passed it slightly different. |
703 | */ |
704 | keyidx = b43_kidx_to_raw(dev, firmware_kidx: keyidx); |
705 | B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key)); |
706 | |
707 | if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { |
708 | wlhdr_len = ieee80211_hdrlen(fc: fctl); |
709 | if (unlikely(skb->len < (wlhdr_len + 3))) { |
710 | b43dbg(wl: dev->wl, |
711 | fmt: "RX: Packet size underrun (3)\n" ); |
712 | goto drop; |
713 | } |
714 | status.flag |= RX_FLAG_DECRYPTED; |
715 | } |
716 | } |
717 | |
718 | /* Link quality statistics */ |
719 | switch (chanstat & B43_RX_CHAN_PHYTYPE) { |
720 | case B43_PHYTYPE_HT: |
721 | /* TODO: is max the right choice? */ |
722 | status.signal = max_t(__s8, |
723 | max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1), |
724 | rxhdr->phy_ht_power2); |
725 | break; |
726 | case B43_PHYTYPE_N: |
727 | /* Broadcom has code for min and avg, but always uses max */ |
728 | if (rxhdr->power0 == 16 || rxhdr->power0 == 32) |
729 | status.signal = max(rxhdr->power1, rxhdr->power2); |
730 | else |
731 | status.signal = max(rxhdr->power0, rxhdr->power1); |
732 | break; |
733 | case B43_PHYTYPE_B: |
734 | case B43_PHYTYPE_G: |
735 | case B43_PHYTYPE_LP: |
736 | status.signal = b43_rssi_postprocess(dev, in_rssi: rxhdr->jssi, |
737 | ofdm: (phystat0 & B43_RX_PHYST0_OFDM), |
738 | adjust_2053: (phystat0 & B43_RX_PHYST0_GAINCTL), |
739 | adjust_2050: (phystat3 & B43_RX_PHYST3_TRSTATE)); |
740 | break; |
741 | } |
742 | |
743 | if (phystat0 & B43_RX_PHYST0_OFDM) |
744 | rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, |
745 | ghz5: !!(chanstat & B43_RX_CHAN_5GHZ)); |
746 | else |
747 | rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); |
748 | if (unlikely(rate_idx == -1)) { |
749 | /* PLCP seems to be corrupted. |
750 | * Drop the frame, if we are not interested in corrupted frames. */ |
751 | if (!(dev->wl->filter_flags & FIF_PLCPFAIL)) |
752 | goto drop; |
753 | } |
754 | status.rate_idx = rate_idx; |
755 | status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); |
756 | |
757 | /* |
758 | * All frames on monitor interfaces and beacons always need a full |
759 | * 64-bit timestamp. Monitor interfaces need it for diagnostic |
760 | * purposes and beacons for IBSS merging. |
761 | * This code assumes we get to process the packet within 16 bits |
762 | * of timestamp, i.e. about 65 milliseconds after the PHY received |
763 | * the first symbol. |
764 | */ |
765 | if (ieee80211_is_beacon(fc: fctl) || dev->wl->radiotap_enabled) { |
766 | u16 low_mactime_now; |
767 | |
768 | b43_tsf_read(dev, tsf: &status.mactime); |
769 | low_mactime_now = status.mactime; |
770 | status.mactime = status.mactime & ~0xFFFFULL; |
771 | status.mactime += mactime; |
772 | if (low_mactime_now <= mactime) |
773 | status.mactime -= 0x10000; |
774 | status.flag |= RX_FLAG_MACTIME_START; |
775 | } |
776 | |
777 | chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; |
778 | switch (chanstat & B43_RX_CHAN_PHYTYPE) { |
779 | case B43_PHYTYPE_G: |
780 | status.band = NL80211_BAND_2GHZ; |
781 | /* Somewhere between 478.104 and 508.1084 firmware for G-PHY |
782 | * has been modified to be compatible with N-PHY and others. |
783 | */ |
784 | if (dev->fw.rev >= 508) |
785 | status.freq = ieee80211_channel_to_frequency(chan: chanid, band: status.band); |
786 | else |
787 | status.freq = chanid + 2400; |
788 | break; |
789 | case B43_PHYTYPE_N: |
790 | case B43_PHYTYPE_LP: |
791 | case B43_PHYTYPE_HT: |
792 | /* chanid is the SHM channel cookie. Which is the plain |
793 | * channel number in b43. */ |
794 | if (chanstat & B43_RX_CHAN_5GHZ) |
795 | status.band = NL80211_BAND_5GHZ; |
796 | else |
797 | status.band = NL80211_BAND_2GHZ; |
798 | status.freq = |
799 | ieee80211_channel_to_frequency(chan: chanid, band: status.band); |
800 | break; |
801 | default: |
802 | B43_WARN_ON(1); |
803 | goto drop; |
804 | } |
805 | |
806 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); |
807 | ieee80211_rx_ni(hw: dev->wl->hw, skb); |
808 | |
809 | #if B43_DEBUG |
810 | dev->rx_count++; |
811 | #endif |
812 | return; |
813 | drop: |
814 | dev_kfree_skb_any(skb); |
815 | } |
816 | |
817 | void b43_handle_txstatus(struct b43_wldev *dev, |
818 | const struct b43_txstatus *status) |
819 | { |
820 | b43_debugfs_log_txstat(dev, status); |
821 | |
822 | if (status->intermediate) |
823 | return; |
824 | if (status->for_ampdu) |
825 | return; |
826 | if (!status->acked) |
827 | dev->wl->ieee_stats.dot11ACKFailureCount++; |
828 | if (status->rts_count) { |
829 | if (status->rts_count == 0xF) //FIXME |
830 | dev->wl->ieee_stats.dot11RTSFailureCount++; |
831 | else |
832 | dev->wl->ieee_stats.dot11RTSSuccessCount++; |
833 | } |
834 | |
835 | if (b43_using_pio_transfers(dev)) |
836 | b43_pio_handle_txstatus(dev, status); |
837 | else |
838 | b43_dma_handle_txstatus(dev, status); |
839 | |
840 | b43_phy_txpower_check(dev, flags: 0); |
841 | } |
842 | |
843 | /* Fill out the mac80211 TXstatus report based on the b43-specific |
844 | * txstatus report data. This returns a boolean whether the frame was |
845 | * successfully transmitted. */ |
846 | bool b43_fill_txstatus_report(struct b43_wldev *dev, |
847 | struct ieee80211_tx_info *report, |
848 | const struct b43_txstatus *status) |
849 | { |
850 | bool frame_success = true; |
851 | int retry_limit; |
852 | |
853 | /* preserve the confiured retry limit before clearing the status |
854 | * The xmit function has overwritten the rc's value with the actual |
855 | * retry limit done by the hardware */ |
856 | retry_limit = report->status.rates[0].count; |
857 | ieee80211_tx_info_clear_status(info: report); |
858 | |
859 | if (status->acked) { |
860 | /* The frame was ACKed. */ |
861 | report->flags |= IEEE80211_TX_STAT_ACK; |
862 | } else { |
863 | /* The frame was not ACKed... */ |
864 | if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { |
865 | /* ...but we expected an ACK. */ |
866 | frame_success = false; |
867 | } |
868 | } |
869 | if (status->frame_count == 0) { |
870 | /* The frame was not transmitted at all. */ |
871 | report->status.rates[0].count = 0; |
872 | } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { |
873 | /* |
874 | * If the short retries (RTS, not data frame) have exceeded |
875 | * the limit, the hw will not have tried the selected rate, |
876 | * but will have used the fallback rate instead. |
877 | * Don't let the rate control count attempts for the selected |
878 | * rate in this case, otherwise the statistics will be off. |
879 | */ |
880 | report->status.rates[0].count = 0; |
881 | report->status.rates[1].count = status->frame_count; |
882 | } else { |
883 | if (status->frame_count > retry_limit) { |
884 | report->status.rates[0].count = retry_limit; |
885 | report->status.rates[1].count = status->frame_count - |
886 | retry_limit; |
887 | |
888 | } else { |
889 | report->status.rates[0].count = status->frame_count; |
890 | report->status.rates[1].idx = -1; |
891 | } |
892 | } |
893 | |
894 | return frame_success; |
895 | } |
896 | |
897 | /* Stop any TX operation on the device (suspend the hardware queues) */ |
898 | void b43_tx_suspend(struct b43_wldev *dev) |
899 | { |
900 | if (b43_using_pio_transfers(dev)) |
901 | b43_pio_tx_suspend(dev); |
902 | else |
903 | b43_dma_tx_suspend(dev); |
904 | } |
905 | |
906 | /* Resume any TX operation on the device (resume the hardware queues) */ |
907 | void b43_tx_resume(struct b43_wldev *dev) |
908 | { |
909 | if (b43_using_pio_transfers(dev)) |
910 | b43_pio_tx_resume(dev); |
911 | else |
912 | b43_dma_tx_resume(dev); |
913 | } |
914 | |