brintos

brintos / linux-shallow public Read only

0
0
Text · 24.1 KiB · 908c4c8 Raw
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