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