Commit | Line | Data |
---|---|---|
a84fab3c CL |
1 | /* |
2 | * Atheros CARL9170 driver | |
3 | * | |
4 | * 802.11 & command trap routines | |
5 | * | |
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | |
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; see the file COPYING. If not, see | |
21 | * http://www.gnu.org/licenses/. | |
22 | * | |
23 | * This file incorporates work covered by the following copyright and | |
24 | * permission notice: | |
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | |
26 | * | |
27 | * Permission to use, copy, modify, and/or distribute this software for any | |
28 | * purpose with or without fee is hereby granted, provided that the above | |
29 | * copyright notice and this permission notice appear in all copies. | |
30 | * | |
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
38 | */ | |
39 | ||
40 | #include <linux/init.h> | |
41 | #include <linux/slab.h> | |
42 | #include <linux/module.h> | |
43 | #include <linux/etherdevice.h> | |
44 | #include <linux/crc32.h> | |
45 | #include <net/mac80211.h> | |
46 | #include "carl9170.h" | |
47 | #include "hw.h" | |
48 | #include "cmd.h" | |
49 | ||
50 | static void carl9170_dbg_message(struct ar9170 *ar, const char *buf, u32 len) | |
51 | { | |
52 | bool restart = false; | |
53 | enum carl9170_restart_reasons reason = CARL9170_RR_NO_REASON; | |
54 | ||
55 | if (len > 3) { | |
56 | if (memcmp(buf, CARL9170_ERR_MAGIC, 3) == 0) { | |
57 | ar->fw.err_counter++; | |
58 | if (ar->fw.err_counter > 3) { | |
59 | restart = true; | |
60 | reason = CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS; | |
61 | } | |
62 | } | |
63 | ||
64 | if (memcmp(buf, CARL9170_BUG_MAGIC, 3) == 0) { | |
65 | ar->fw.bug_counter++; | |
66 | restart = true; | |
67 | reason = CARL9170_RR_FATAL_FIRMWARE_ERROR; | |
68 | } | |
69 | } | |
70 | ||
71 | wiphy_info(ar->hw->wiphy, "FW: %.*s\n", len, buf); | |
72 | ||
73 | if (restart) | |
74 | carl9170_restart(ar, reason); | |
75 | } | |
76 | ||
77 | static void carl9170_handle_ps(struct ar9170 *ar, struct carl9170_rsp *rsp) | |
78 | { | |
79 | u32 ps; | |
80 | bool new_ps; | |
81 | ||
82 | ps = le32_to_cpu(rsp->psm.state); | |
83 | ||
84 | new_ps = (ps & CARL9170_PSM_COUNTER) != CARL9170_PSM_WAKE; | |
85 | if (ar->ps.state != new_ps) { | |
86 | if (!new_ps) { | |
87 | ar->ps.sleep_ms = jiffies_to_msecs(jiffies - | |
88 | ar->ps.last_action); | |
89 | } | |
90 | ||
91 | ar->ps.last_action = jiffies; | |
92 | ||
93 | ar->ps.state = new_ps; | |
94 | } | |
95 | } | |
96 | ||
97 | static int carl9170_check_sequence(struct ar9170 *ar, unsigned int seq) | |
98 | { | |
99 | if (ar->cmd_seq < -1) | |
100 | return 0; | |
101 | ||
102 | /* | |
103 | * Initialize Counter | |
104 | */ | |
105 | if (ar->cmd_seq < 0) | |
106 | ar->cmd_seq = seq; | |
107 | ||
108 | /* | |
109 | * The sequence is strictly monotonic increasing and it never skips! | |
110 | * | |
111 | * Therefore we can safely assume that whenever we received an | |
112 | * unexpected sequence we have lost some valuable data. | |
113 | */ | |
114 | if (seq != ar->cmd_seq) { | |
115 | int count; | |
116 | ||
117 | count = (seq - ar->cmd_seq) % ar->fw.cmd_bufs; | |
118 | ||
119 | wiphy_err(ar->hw->wiphy, "lost %d command responses/traps! " | |
120 | "w:%d g:%d\n", count, ar->cmd_seq, seq); | |
121 | ||
122 | carl9170_restart(ar, CARL9170_RR_LOST_RSP); | |
123 | return -EIO; | |
124 | } | |
125 | ||
126 | ar->cmd_seq = (ar->cmd_seq + 1) % ar->fw.cmd_bufs; | |
127 | return 0; | |
128 | } | |
129 | ||
130 | static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) | |
131 | { | |
132 | /* | |
133 | * Some commands may have a variable response length | |
134 | * and we cannot predict the correct length in advance. | |
135 | * So we only check if we provided enough space for the data. | |
136 | */ | |
137 | if (unlikely(ar->readlen != (len - 4))) { | |
138 | dev_warn(&ar->udev->dev, "received invalid command response:" | |
139 | "got %d, instead of %d\n", len - 4, ar->readlen); | |
140 | print_hex_dump_bytes("carl9170 cmd:", DUMP_PREFIX_OFFSET, | |
141 | ar->cmd_buf, (ar->cmd.hdr.len + 4) & 0x3f); | |
142 | print_hex_dump_bytes("carl9170 rsp:", DUMP_PREFIX_OFFSET, | |
143 | buffer, len); | |
144 | /* | |
145 | * Do not complete. The command times out, | |
146 | * and we get a stack trace from there. | |
147 | */ | |
148 | carl9170_restart(ar, CARL9170_RR_INVALID_RSP); | |
149 | } | |
150 | ||
151 | spin_lock(&ar->cmd_lock); | |
152 | if (ar->readbuf) { | |
153 | if (len >= 4) | |
154 | memcpy(ar->readbuf, buffer + 4, len - 4); | |
155 | ||
156 | ar->readbuf = NULL; | |
157 | } | |
158 | complete(&ar->cmd_wait); | |
159 | spin_unlock(&ar->cmd_lock); | |
160 | } | |
161 | ||
162 | void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | |
163 | { | |
2c208890 | 164 | struct carl9170_rsp *cmd = buf; |
a84fab3c CL |
165 | struct ieee80211_vif *vif; |
166 | ||
a84fab3c CL |
167 | if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) { |
168 | if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG)) | |
169 | carl9170_cmd_callback(ar, len, buf); | |
170 | ||
171 | return; | |
172 | } | |
173 | ||
174 | if (unlikely(cmd->hdr.len != (len - 4))) { | |
175 | if (net_ratelimit()) { | |
176 | wiphy_err(ar->hw->wiphy, "FW: received over-/under" | |
177 | "sized event %x (%d, but should be %d).\n", | |
178 | cmd->hdr.cmd, cmd->hdr.len, len - 4); | |
179 | ||
180 | print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, | |
181 | buf, len); | |
182 | } | |
183 | ||
184 | return; | |
185 | } | |
186 | ||
187 | /* hardware event handlers */ | |
188 | switch (cmd->hdr.cmd) { | |
189 | case CARL9170_RSP_PRETBTT: | |
190 | /* pre-TBTT event */ | |
191 | rcu_read_lock(); | |
192 | vif = carl9170_get_main_vif(ar); | |
193 | ||
194 | if (!vif) { | |
195 | rcu_read_unlock(); | |
196 | break; | |
197 | } | |
198 | ||
199 | switch (vif->type) { | |
200 | case NL80211_IFTYPE_STATION: | |
201 | carl9170_handle_ps(ar, cmd); | |
202 | break; | |
203 | ||
204 | case NL80211_IFTYPE_AP: | |
205 | case NL80211_IFTYPE_ADHOC: | |
da93c26d | 206 | case NL80211_IFTYPE_MESH_POINT: |
a84fab3c CL |
207 | carl9170_update_beacon(ar, true); |
208 | break; | |
209 | ||
210 | default: | |
211 | break; | |
212 | } | |
213 | rcu_read_unlock(); | |
214 | ||
215 | break; | |
216 | ||
217 | ||
218 | case CARL9170_RSP_TXCOMP: | |
219 | /* TX status notification */ | |
220 | carl9170_tx_process_status(ar, cmd); | |
221 | break; | |
222 | ||
223 | case CARL9170_RSP_BEACON_CONFIG: | |
224 | /* | |
225 | * (IBSS) beacon send notification | |
226 | * bytes: 04 c2 XX YY B4 B3 B2 B1 | |
227 | * | |
228 | * XX always 80 | |
229 | * YY always 00 | |
230 | * B1-B4 "should" be the number of send out beacons. | |
231 | */ | |
232 | break; | |
233 | ||
234 | case CARL9170_RSP_ATIM: | |
235 | /* End of Atim Window */ | |
236 | break; | |
237 | ||
238 | case CARL9170_RSP_WATCHDOG: | |
239 | /* Watchdog Interrupt */ | |
240 | carl9170_restart(ar, CARL9170_RR_WATCHDOG); | |
241 | break; | |
242 | ||
243 | case CARL9170_RSP_TEXT: | |
244 | /* firmware debug */ | |
245 | carl9170_dbg_message(ar, (char *)buf + 4, len - 4); | |
246 | break; | |
247 | ||
248 | case CARL9170_RSP_HEXDUMP: | |
249 | wiphy_dbg(ar->hw->wiphy, "FW: HD %d\n", len - 4); | |
250 | print_hex_dump_bytes("FW:", DUMP_PREFIX_NONE, | |
251 | (char *)buf + 4, len - 4); | |
252 | break; | |
253 | ||
254 | case CARL9170_RSP_RADAR: | |
255 | if (!net_ratelimit()) | |
256 | break; | |
257 | ||
258 | wiphy_info(ar->hw->wiphy, "FW: RADAR! Please report this " | |
259 | "incident to linux-wireless@vger.kernel.org !\n"); | |
260 | break; | |
261 | ||
262 | case CARL9170_RSP_GPIO: | |
263 | #ifdef CONFIG_CARL9170_WPC | |
264 | if (ar->wps.pbc) { | |
265 | bool state = !!(cmd->gpio.gpio & cpu_to_le32( | |
266 | AR9170_GPIO_PORT_WPS_BUTTON_PRESSED)); | |
267 | ||
268 | if (state != ar->wps.pbc_state) { | |
269 | ar->wps.pbc_state = state; | |
270 | input_report_key(ar->wps.pbc, KEY_WPS_BUTTON, | |
271 | state); | |
272 | input_sync(ar->wps.pbc); | |
273 | } | |
274 | } | |
275 | #endif /* CONFIG_CARL9170_WPC */ | |
276 | break; | |
277 | ||
278 | case CARL9170_RSP_BOOT: | |
279 | complete(&ar->fw_boot_wait); | |
280 | break; | |
281 | ||
282 | default: | |
283 | wiphy_err(ar->hw->wiphy, "FW: received unhandled event %x\n", | |
284 | cmd->hdr.cmd); | |
285 | print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); | |
286 | break; | |
287 | } | |
288 | } | |
289 | ||
290 | static int carl9170_rx_mac_status(struct ar9170 *ar, | |
291 | struct ar9170_rx_head *head, struct ar9170_rx_macstatus *mac, | |
292 | struct ieee80211_rx_status *status) | |
293 | { | |
294 | struct ieee80211_channel *chan; | |
295 | u8 error, decrypt; | |
296 | ||
297 | BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); | |
298 | BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); | |
299 | ||
300 | error = mac->error; | |
301 | ||
302 | if (error & AR9170_RX_ERROR_WRONG_RA) { | |
303 | if (!ar->sniffer_enabled) | |
304 | return -EINVAL; | |
305 | } | |
306 | ||
307 | if (error & AR9170_RX_ERROR_PLCP) { | |
308 | if (!(ar->filter_state & FIF_PLCPFAIL)) | |
309 | return -EINVAL; | |
310 | ||
311 | status->flag |= RX_FLAG_FAILED_PLCP_CRC; | |
312 | } | |
313 | ||
314 | if (error & AR9170_RX_ERROR_FCS) { | |
315 | ar->tx_fcs_errors++; | |
316 | ||
317 | if (!(ar->filter_state & FIF_FCSFAIL)) | |
318 | return -EINVAL; | |
319 | ||
320 | status->flag |= RX_FLAG_FAILED_FCS_CRC; | |
321 | } | |
322 | ||
323 | decrypt = ar9170_get_decrypt_type(mac); | |
324 | if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && | |
325 | decrypt != AR9170_ENC_ALG_NONE) { | |
326 | if ((decrypt == AR9170_ENC_ALG_TKIP) && | |
327 | (error & AR9170_RX_ERROR_MMIC)) | |
328 | status->flag |= RX_FLAG_MMIC_ERROR; | |
329 | ||
330 | status->flag |= RX_FLAG_DECRYPTED; | |
331 | } | |
332 | ||
333 | if (error & AR9170_RX_ERROR_DECRYPT && !ar->sniffer_enabled) | |
334 | return -ENODATA; | |
335 | ||
336 | error &= ~(AR9170_RX_ERROR_MMIC | | |
337 | AR9170_RX_ERROR_FCS | | |
338 | AR9170_RX_ERROR_WRONG_RA | | |
339 | AR9170_RX_ERROR_DECRYPT | | |
340 | AR9170_RX_ERROR_PLCP); | |
341 | ||
342 | /* drop any other error frames */ | |
343 | if (unlikely(error)) { | |
344 | /* TODO: update netdevice's RX dropped/errors statistics */ | |
345 | ||
346 | if (net_ratelimit()) | |
347 | wiphy_dbg(ar->hw->wiphy, "received frame with " | |
348 | "suspicious error code (%#x).\n", error); | |
349 | ||
350 | return -EINVAL; | |
351 | } | |
352 | ||
353 | chan = ar->channel; | |
354 | if (chan) { | |
355 | status->band = chan->band; | |
356 | status->freq = chan->center_freq; | |
357 | } | |
358 | ||
359 | switch (mac->status & AR9170_RX_STATUS_MODULATION) { | |
360 | case AR9170_RX_STATUS_MODULATION_CCK: | |
361 | if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) | |
362 | status->flag |= RX_FLAG_SHORTPRE; | |
363 | switch (head->plcp[0]) { | |
364 | case AR9170_RX_PHY_RATE_CCK_1M: | |
365 | status->rate_idx = 0; | |
366 | break; | |
367 | case AR9170_RX_PHY_RATE_CCK_2M: | |
368 | status->rate_idx = 1; | |
369 | break; | |
370 | case AR9170_RX_PHY_RATE_CCK_5M: | |
371 | status->rate_idx = 2; | |
372 | break; | |
373 | case AR9170_RX_PHY_RATE_CCK_11M: | |
374 | status->rate_idx = 3; | |
375 | break; | |
376 | default: | |
377 | if (net_ratelimit()) { | |
378 | wiphy_err(ar->hw->wiphy, "invalid plcp cck " | |
379 | "rate (%x).\n", head->plcp[0]); | |
380 | } | |
381 | ||
382 | return -EINVAL; | |
383 | } | |
384 | break; | |
385 | ||
386 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | |
387 | case AR9170_RX_STATUS_MODULATION_OFDM: | |
388 | switch (head->plcp[0] & 0xf) { | |
389 | case AR9170_TXRX_PHY_RATE_OFDM_6M: | |
390 | status->rate_idx = 0; | |
391 | break; | |
392 | case AR9170_TXRX_PHY_RATE_OFDM_9M: | |
393 | status->rate_idx = 1; | |
394 | break; | |
395 | case AR9170_TXRX_PHY_RATE_OFDM_12M: | |
396 | status->rate_idx = 2; | |
397 | break; | |
398 | case AR9170_TXRX_PHY_RATE_OFDM_18M: | |
399 | status->rate_idx = 3; | |
400 | break; | |
401 | case AR9170_TXRX_PHY_RATE_OFDM_24M: | |
402 | status->rate_idx = 4; | |
403 | break; | |
404 | case AR9170_TXRX_PHY_RATE_OFDM_36M: | |
405 | status->rate_idx = 5; | |
406 | break; | |
407 | case AR9170_TXRX_PHY_RATE_OFDM_48M: | |
408 | status->rate_idx = 6; | |
409 | break; | |
410 | case AR9170_TXRX_PHY_RATE_OFDM_54M: | |
411 | status->rate_idx = 7; | |
412 | break; | |
413 | default: | |
414 | if (net_ratelimit()) { | |
415 | wiphy_err(ar->hw->wiphy, "invalid plcp ofdm " | |
416 | "rate (%x).\n", head->plcp[0]); | |
417 | } | |
418 | ||
419 | return -EINVAL; | |
420 | } | |
421 | if (status->band == IEEE80211_BAND_2GHZ) | |
422 | status->rate_idx += 4; | |
423 | break; | |
424 | ||
425 | case AR9170_RX_STATUS_MODULATION_HT: | |
426 | if (head->plcp[3] & 0x80) | |
427 | status->flag |= RX_FLAG_40MHZ; | |
428 | if (head->plcp[6] & 0x80) | |
429 | status->flag |= RX_FLAG_SHORT_GI; | |
430 | ||
431 | status->rate_idx = clamp(0, 75, head->plcp[3] & 0x7f); | |
432 | status->flag |= RX_FLAG_HT; | |
433 | break; | |
434 | ||
435 | default: | |
436 | BUG(); | |
437 | return -ENOSYS; | |
438 | } | |
439 | ||
440 | return 0; | |
441 | } | |
442 | ||
443 | static void carl9170_rx_phy_status(struct ar9170 *ar, | |
444 | struct ar9170_rx_phystatus *phy, struct ieee80211_rx_status *status) | |
445 | { | |
446 | int i; | |
447 | ||
448 | BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); | |
449 | ||
450 | for (i = 0; i < 3; i++) | |
451 | if (phy->rssi[i] != 0x80) | |
452 | status->antenna |= BIT(i); | |
453 | ||
454 | /* post-process RSSI */ | |
455 | for (i = 0; i < 7; i++) | |
456 | if (phy->rssi[i] & 0x80) | |
457 | phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; | |
458 | ||
459 | /* TODO: we could do something with phy_errors */ | |
460 | status->signal = ar->noise[0] + phy->rssi_combined; | |
461 | } | |
462 | ||
463 | static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len) | |
464 | { | |
465 | struct sk_buff *skb; | |
466 | int reserved = 0; | |
467 | struct ieee80211_hdr *hdr = (void *) buf; | |
468 | ||
469 | if (ieee80211_is_data_qos(hdr->frame_control)) { | |
470 | u8 *qc = ieee80211_get_qos_ctl(hdr); | |
471 | reserved += NET_IP_ALIGN; | |
472 | ||
04b7dcf9 | 473 | if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) |
a84fab3c CL |
474 | reserved += NET_IP_ALIGN; |
475 | } | |
476 | ||
477 | if (ieee80211_has_a4(hdr->frame_control)) | |
478 | reserved += NET_IP_ALIGN; | |
479 | ||
480 | reserved = 32 + (reserved & NET_IP_ALIGN); | |
481 | ||
482 | skb = dev_alloc_skb(len + reserved); | |
483 | if (likely(skb)) { | |
484 | skb_reserve(skb, reserved); | |
485 | memcpy(skb_put(skb, len), buf, len); | |
486 | } | |
487 | ||
488 | return skb; | |
489 | } | |
490 | ||
491 | static u8 *carl9170_find_ie(u8 *data, unsigned int len, u8 ie) | |
492 | { | |
493 | struct ieee80211_mgmt *mgmt = (void *)data; | |
494 | u8 *pos, *end; | |
495 | ||
496 | pos = (u8 *)mgmt->u.beacon.variable; | |
497 | end = data + len; | |
498 | while (pos < end) { | |
499 | if (pos + 2 + pos[1] > end) | |
500 | return NULL; | |
501 | ||
502 | if (pos[0] == ie) | |
503 | return pos; | |
504 | ||
505 | pos += 2 + pos[1]; | |
506 | } | |
507 | return NULL; | |
508 | } | |
509 | ||
510 | /* | |
511 | * NOTE: | |
512 | * | |
513 | * The firmware is in charge of waking up the device just before | |
514 | * the AP is expected to transmit the next beacon. | |
515 | * | |
516 | * This leaves the driver with the important task of deciding when | |
517 | * to set the PHY back to bed again. | |
518 | */ | |
519 | static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) | |
520 | { | |
2c208890 | 521 | struct ieee80211_hdr *hdr = data; |
a84fab3c CL |
522 | struct ieee80211_tim_ie *tim_ie; |
523 | u8 *tim; | |
524 | u8 tim_len; | |
525 | bool cam; | |
526 | ||
527 | if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS))) | |
528 | return; | |
529 | ||
530 | /* check if this really is a beacon */ | |
531 | if (!ieee80211_is_beacon(hdr->frame_control)) | |
532 | return; | |
533 | ||
534 | /* min. beacon length + FCS_LEN */ | |
535 | if (len <= 40 + FCS_LEN) | |
536 | return; | |
537 | ||
538 | /* and only beacons from the associated BSSID, please */ | |
2e42e474 | 539 | if (!ether_addr_equal(hdr->addr3, ar->common.curbssid) || |
a84fab3c CL |
540 | !ar->common.curaid) |
541 | return; | |
542 | ||
543 | ar->ps.last_beacon = jiffies; | |
544 | ||
545 | tim = carl9170_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); | |
546 | if (!tim) | |
547 | return; | |
548 | ||
549 | if (tim[1] < sizeof(*tim_ie)) | |
550 | return; | |
551 | ||
552 | tim_len = tim[1]; | |
553 | tim_ie = (struct ieee80211_tim_ie *) &tim[2]; | |
554 | ||
555 | if (!WARN_ON_ONCE(!ar->hw->conf.ps_dtim_period)) | |
556 | ar->ps.dtim_counter = (tim_ie->dtim_count - 1) % | |
557 | ar->hw->conf.ps_dtim_period; | |
558 | ||
559 | /* Check whenever the PHY can be turned off again. */ | |
560 | ||
561 | /* 1. What about buffered unicast traffic for our AID? */ | |
562 | cam = ieee80211_check_tim(tim_ie, tim_len, ar->common.curaid); | |
563 | ||
564 | /* 2. Maybe the AP wants to send multicast/broadcast data? */ | |
5820de53 | 565 | cam |= !!(tim_ie->bitmap_ctrl & 0x01); |
a84fab3c CL |
566 | |
567 | if (!cam) { | |
568 | /* back to low-power land. */ | |
569 | ar->ps.off_override &= ~PS_OFF_BCN; | |
570 | carl9170_ps_check(ar); | |
571 | } else { | |
572 | /* force CAM */ | |
573 | ar->ps.off_override |= PS_OFF_BCN; | |
574 | } | |
575 | } | |
576 | ||
c9122c0d CL |
577 | static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len) |
578 | { | |
579 | struct ieee80211_bar *bar = (void *) data; | |
580 | struct carl9170_bar_list_entry *entry; | |
581 | unsigned int queue; | |
582 | ||
583 | if (likely(!ieee80211_is_back(bar->frame_control))) | |
584 | return; | |
585 | ||
586 | if (len <= sizeof(*bar) + FCS_LEN) | |
587 | return; | |
588 | ||
589 | queue = TID_TO_WME_AC(((le16_to_cpu(bar->control) & | |
590 | IEEE80211_BAR_CTRL_TID_INFO_MASK) >> | |
591 | IEEE80211_BAR_CTRL_TID_INFO_SHIFT) & 7); | |
592 | ||
593 | rcu_read_lock(); | |
594 | list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) { | |
595 | struct sk_buff *entry_skb = entry->skb; | |
596 | struct _carl9170_tx_superframe *super = (void *)entry_skb->data; | |
597 | struct ieee80211_bar *entry_bar = (void *)super->frame_data; | |
598 | ||
599 | #define TID_CHECK(a, b) ( \ | |
600 | ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) == \ | |
601 | ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK))) \ | |
602 | ||
603 | if (bar->start_seq_num == entry_bar->start_seq_num && | |
604 | TID_CHECK(bar->control, entry_bar->control) && | |
605 | compare_ether_addr(bar->ra, entry_bar->ta) == 0 && | |
606 | compare_ether_addr(bar->ta, entry_bar->ra) == 0) { | |
607 | struct ieee80211_tx_info *tx_info; | |
608 | ||
609 | tx_info = IEEE80211_SKB_CB(entry_skb); | |
610 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | |
611 | ||
612 | spin_lock_bh(&ar->bar_list_lock[queue]); | |
613 | list_del_rcu(&entry->list); | |
614 | spin_unlock_bh(&ar->bar_list_lock[queue]); | |
615 | kfree_rcu(entry, head); | |
616 | break; | |
617 | } | |
618 | } | |
619 | rcu_read_unlock(); | |
620 | ||
621 | #undef TID_CHECK | |
622 | } | |
623 | ||
33dd7699 CL |
624 | static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms, |
625 | struct ieee80211_rx_status *rx_status) | |
8f236d1b CL |
626 | { |
627 | __le16 fc; | |
628 | ||
629 | if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE) { | |
630 | /* | |
631 | * This frame is not part of an aMPDU. | |
632 | * Therefore it is not subjected to any | |
633 | * of the following content restrictions. | |
634 | */ | |
635 | return true; | |
636 | } | |
637 | ||
33dd7699 CL |
638 | rx_status->flag |= RX_FLAG_AMPDU_DETAILS | RX_FLAG_AMPDU_LAST_KNOWN; |
639 | rx_status->ampdu_reference = ar->ampdu_ref; | |
640 | ||
8f236d1b CL |
641 | /* |
642 | * "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts | |
643 | * certain frame types can be part of an aMPDU. | |
644 | * | |
645 | * In order to keep the processing cost down, I opted for a | |
646 | * stateless filter solely based on the frame control field. | |
647 | */ | |
648 | ||
649 | fc = ((struct ieee80211_hdr *)buf)->frame_control; | |
650 | if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc)) | |
651 | return true; | |
652 | ||
653 | if (ieee80211_is_ack(fc) || ieee80211_is_back(fc) || | |
654 | ieee80211_is_back_req(fc)) | |
655 | return true; | |
656 | ||
657 | if (ieee80211_is_action(fc)) | |
658 | return true; | |
659 | ||
660 | return false; | |
661 | } | |
662 | ||
a84fab3c CL |
663 | /* |
664 | * If the frame alignment is right (or the kernel has | |
665 | * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there | |
666 | * is only a single MPDU in the USB frame, then we could | |
667 | * submit to mac80211 the SKB directly. However, since | |
668 | * there may be multiple packets in one SKB in stream | |
669 | * mode, and we need to observe the proper ordering, | |
670 | * this is non-trivial. | |
671 | */ | |
672 | ||
673 | static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) | |
674 | { | |
675 | struct ar9170_rx_head *head; | |
676 | struct ar9170_rx_macstatus *mac; | |
677 | struct ar9170_rx_phystatus *phy = NULL; | |
678 | struct ieee80211_rx_status status; | |
679 | struct sk_buff *skb; | |
680 | int mpdu_len; | |
8f236d1b | 681 | u8 mac_status; |
a84fab3c CL |
682 | |
683 | if (!IS_STARTED(ar)) | |
684 | return; | |
685 | ||
c8a16c68 CL |
686 | if (unlikely(len < sizeof(*mac))) |
687 | goto drop; | |
a84fab3c | 688 | |
33dd7699 CL |
689 | memset(&status, 0, sizeof(status)); |
690 | ||
a84fab3c CL |
691 | mpdu_len = len - sizeof(*mac); |
692 | ||
693 | mac = (void *)(buf + mpdu_len); | |
8f236d1b CL |
694 | mac_status = mac->status; |
695 | switch (mac_status & AR9170_RX_STATUS_MPDU) { | |
a84fab3c | 696 | case AR9170_RX_STATUS_MPDU_FIRST: |
33dd7699 | 697 | ar->ampdu_ref++; |
a84fab3c CL |
698 | /* Aggregated MPDUs start with an PLCP header */ |
699 | if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { | |
700 | head = (void *) buf; | |
701 | ||
702 | /* | |
703 | * The PLCP header needs to be cached for the | |
704 | * following MIDDLE + LAST A-MPDU packets. | |
705 | * | |
706 | * So, if you are wondering why all frames seem | |
707 | * to share a common RX status information, | |
708 | * then you have the answer right here... | |
709 | */ | |
710 | memcpy(&ar->rx_plcp, (void *) buf, | |
711 | sizeof(struct ar9170_rx_head)); | |
712 | ||
713 | mpdu_len -= sizeof(struct ar9170_rx_head); | |
714 | buf += sizeof(struct ar9170_rx_head); | |
715 | ||
716 | ar->rx_has_plcp = true; | |
717 | } else { | |
718 | if (net_ratelimit()) { | |
719 | wiphy_err(ar->hw->wiphy, "plcp info " | |
720 | "is clipped.\n"); | |
721 | } | |
722 | ||
c8a16c68 | 723 | goto drop; |
a84fab3c CL |
724 | } |
725 | break; | |
726 | ||
727 | case AR9170_RX_STATUS_MPDU_LAST: | |
33dd7699 CL |
728 | status.flag |= RX_FLAG_AMPDU_IS_LAST; |
729 | ||
a84fab3c CL |
730 | /* |
731 | * The last frame of an A-MPDU has an extra tail | |
732 | * which does contain the phy status of the whole | |
733 | * aggregate. | |
734 | */ | |
a84fab3c CL |
735 | if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { |
736 | mpdu_len -= sizeof(struct ar9170_rx_phystatus); | |
737 | phy = (void *)(buf + mpdu_len); | |
738 | } else { | |
739 | if (net_ratelimit()) { | |
740 | wiphy_err(ar->hw->wiphy, "frame tail " | |
741 | "is clipped.\n"); | |
742 | } | |
743 | ||
c8a16c68 | 744 | goto drop; |
a84fab3c CL |
745 | } |
746 | ||
747 | case AR9170_RX_STATUS_MPDU_MIDDLE: | |
748 | /* These are just data + mac status */ | |
749 | if (unlikely(!ar->rx_has_plcp)) { | |
750 | if (!net_ratelimit()) | |
751 | return; | |
752 | ||
753 | wiphy_err(ar->hw->wiphy, "rx stream does not start " | |
754 | "with a first_mpdu frame tag.\n"); | |
755 | ||
c8a16c68 | 756 | goto drop; |
a84fab3c CL |
757 | } |
758 | ||
759 | head = &ar->rx_plcp; | |
760 | break; | |
761 | ||
762 | case AR9170_RX_STATUS_MPDU_SINGLE: | |
763 | /* single mpdu has both: plcp (head) and phy status (tail) */ | |
764 | head = (void *) buf; | |
765 | ||
766 | mpdu_len -= sizeof(struct ar9170_rx_head); | |
767 | mpdu_len -= sizeof(struct ar9170_rx_phystatus); | |
768 | ||
769 | buf += sizeof(struct ar9170_rx_head); | |
770 | phy = (void *)(buf + mpdu_len); | |
771 | break; | |
772 | ||
773 | default: | |
774 | BUG_ON(1); | |
775 | break; | |
776 | } | |
777 | ||
778 | /* FC + DU + RA + FCS */ | |
c8a16c68 CL |
779 | if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN))) |
780 | goto drop; | |
a84fab3c | 781 | |
c8a16c68 CL |
782 | if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) |
783 | goto drop; | |
a84fab3c | 784 | |
33dd7699 | 785 | if (!carl9170_ampdu_check(ar, buf, mac_status, &status)) |
8f236d1b CL |
786 | goto drop; |
787 | ||
a84fab3c CL |
788 | if (phy) |
789 | carl9170_rx_phy_status(ar, phy, &status); | |
790 | ||
791 | carl9170_ps_beacon(ar, buf, mpdu_len); | |
792 | ||
c9122c0d CL |
793 | carl9170_ba_check(ar, buf, mpdu_len); |
794 | ||
a84fab3c | 795 | skb = carl9170_rx_copy_data(buf, mpdu_len); |
c8a16c68 CL |
796 | if (!skb) |
797 | goto drop; | |
798 | ||
799 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | |
800 | ieee80211_rx(ar->hw, skb); | |
801 | return; | |
802 | ||
803 | drop: | |
804 | ar->rx_dropped++; | |
a84fab3c CL |
805 | } |
806 | ||
807 | static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf, | |
808 | const unsigned int resplen) | |
809 | { | |
810 | struct carl9170_rsp *cmd; | |
811 | int i = 0; | |
812 | ||
813 | while (i < resplen) { | |
814 | cmd = (void *) &respbuf[i]; | |
815 | ||
816 | i += cmd->hdr.len + 4; | |
817 | if (unlikely(i > resplen)) | |
818 | break; | |
819 | ||
b4764c80 CL |
820 | if (carl9170_check_sequence(ar, cmd->hdr.seq)) |
821 | break; | |
822 | ||
a84fab3c CL |
823 | carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4); |
824 | } | |
825 | ||
826 | if (unlikely(i != resplen)) { | |
827 | if (!net_ratelimit()) | |
828 | return; | |
829 | ||
830 | wiphy_err(ar->hw->wiphy, "malformed firmware trap:\n"); | |
831 | print_hex_dump_bytes("rxcmd:", DUMP_PREFIX_OFFSET, | |
832 | respbuf, resplen); | |
833 | } | |
834 | } | |
835 | ||
836 | static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len) | |
837 | { | |
838 | unsigned int i = 0; | |
839 | ||
840 | /* weird thing, but this is the same in the original driver */ | |
841 | while (len > 2 && i < 12 && buf[0] == 0xff && buf[1] == 0xff) { | |
842 | i += 2; | |
843 | len -= 2; | |
844 | buf += 2; | |
845 | } | |
846 | ||
847 | if (unlikely(len < 4)) | |
848 | return; | |
849 | ||
850 | /* found the 6 * 0xffff marker? */ | |
851 | if (i == 12) | |
852 | carl9170_rx_untie_cmds(ar, buf, len); | |
853 | else | |
854 | carl9170_handle_mpdu(ar, buf, len); | |
855 | } | |
856 | ||
857 | static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) | |
858 | { | |
859 | unsigned int tlen, wlen = 0, clen = 0; | |
860 | struct ar9170_stream *rx_stream; | |
861 | u8 *tbuf; | |
862 | ||
863 | tbuf = buf; | |
864 | tlen = len; | |
865 | ||
866 | while (tlen >= 4) { | |
867 | rx_stream = (void *) tbuf; | |
868 | clen = le16_to_cpu(rx_stream->length); | |
869 | wlen = ALIGN(clen, 4); | |
870 | ||
871 | /* check if this is stream has a valid tag.*/ | |
872 | if (rx_stream->tag != cpu_to_le16(AR9170_RX_STREAM_TAG)) { | |
873 | /* | |
874 | * TODO: handle the highly unlikely event that the | |
875 | * corrupted stream has the TAG at the right position. | |
876 | */ | |
877 | ||
878 | /* check if the frame can be repaired. */ | |
879 | if (!ar->rx_failover_missing) { | |
880 | ||
881 | /* this is not "short read". */ | |
882 | if (net_ratelimit()) { | |
883 | wiphy_err(ar->hw->wiphy, | |
884 | "missing tag!\n"); | |
885 | } | |
886 | ||
887 | __carl9170_rx(ar, tbuf, tlen); | |
888 | return; | |
889 | } | |
890 | ||
891 | if (ar->rx_failover_missing > tlen) { | |
892 | if (net_ratelimit()) { | |
893 | wiphy_err(ar->hw->wiphy, | |
894 | "possible multi " | |
895 | "stream corruption!\n"); | |
896 | goto err_telluser; | |
897 | } else { | |
898 | goto err_silent; | |
899 | } | |
900 | } | |
901 | ||
902 | memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); | |
903 | ar->rx_failover_missing -= tlen; | |
904 | ||
905 | if (ar->rx_failover_missing <= 0) { | |
906 | /* | |
907 | * nested carl9170_rx_stream call! | |
908 | * | |
25985edc | 909 | * termination is guaranteed, even when the |
a84fab3c CL |
910 | * combined frame also have an element with |
911 | * a bad tag. | |
912 | */ | |
913 | ||
914 | ar->rx_failover_missing = 0; | |
915 | carl9170_rx_stream(ar, ar->rx_failover->data, | |
916 | ar->rx_failover->len); | |
917 | ||
918 | skb_reset_tail_pointer(ar->rx_failover); | |
919 | skb_trim(ar->rx_failover, 0); | |
920 | } | |
921 | ||
922 | return; | |
923 | } | |
924 | ||
925 | /* check if stream is clipped */ | |
926 | if (wlen > tlen - 4) { | |
927 | if (ar->rx_failover_missing) { | |
928 | /* TODO: handle double stream corruption. */ | |
929 | if (net_ratelimit()) { | |
930 | wiphy_err(ar->hw->wiphy, "double rx " | |
931 | "stream corruption!\n"); | |
932 | goto err_telluser; | |
933 | } else { | |
934 | goto err_silent; | |
935 | } | |
936 | } | |
937 | ||
938 | /* | |
939 | * save incomplete data set. | |
940 | * the firmware will resend the missing bits when | |
941 | * the rx - descriptor comes round again. | |
942 | */ | |
943 | ||
944 | memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); | |
945 | ar->rx_failover_missing = clen - tlen; | |
946 | return; | |
947 | } | |
948 | __carl9170_rx(ar, rx_stream->payload, clen); | |
949 | ||
950 | tbuf += wlen + 4; | |
951 | tlen -= wlen + 4; | |
952 | } | |
953 | ||
954 | if (tlen) { | |
955 | if (net_ratelimit()) { | |
956 | wiphy_err(ar->hw->wiphy, "%d bytes of unprocessed " | |
957 | "data left in rx stream!\n", tlen); | |
958 | } | |
959 | ||
960 | goto err_telluser; | |
961 | } | |
962 | ||
963 | return; | |
964 | ||
965 | err_telluser: | |
966 | wiphy_err(ar->hw->wiphy, "damaged RX stream data [want:%d, " | |
967 | "data:%d, rx:%d, pending:%d ]\n", clen, wlen, tlen, | |
968 | ar->rx_failover_missing); | |
969 | ||
970 | if (ar->rx_failover_missing) | |
971 | print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, | |
972 | ar->rx_failover->data, | |
973 | ar->rx_failover->len); | |
974 | ||
975 | print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, | |
976 | buf, len); | |
977 | ||
978 | wiphy_err(ar->hw->wiphy, "please check your hardware and cables, if " | |
979 | "you see this message frequently.\n"); | |
980 | ||
981 | err_silent: | |
982 | if (ar->rx_failover_missing) { | |
983 | skb_reset_tail_pointer(ar->rx_failover); | |
984 | skb_trim(ar->rx_failover, 0); | |
985 | ar->rx_failover_missing = 0; | |
986 | } | |
987 | } | |
988 | ||
989 | void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len) | |
990 | { | |
991 | if (ar->fw.rx_stream) | |
992 | carl9170_rx_stream(ar, buf, len); | |
993 | else | |
994 | __carl9170_rx(ar, buf, len); | |
995 | } |