diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/recv.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 550 | 
1 files changed, 102 insertions, 448 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 4ee472a5a4e..9105a92364f 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -15,11 +15,10 @@   */  #include <linux/dma-mapping.h> -#include <linux/relay.h>  #include "ath9k.h"  #include "ar9003_mac.h" -#define SKB_CB_ATHBUF(__skb)	(*((struct ath_buf **)__skb->cb)) +#define SKB_CB_ATHBUF(__skb)	(*((struct ath_rxbuf **)__skb->cb))  static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)  { @@ -35,7 +34,8 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)   * buffer (or rx fifo). This can incorrectly acknowledge packets   * to a sender if last desc is self-linked.   */ -static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) +static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf, +			    bool flush)  {  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah); @@ -60,18 +60,19 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)  			     common->rx_bufsize,  			     0); -	if (sc->rx.rxlink == NULL) -		ath9k_hw_putrxbuf(ah, bf->bf_daddr); -	else +	if (sc->rx.rxlink)  		*sc->rx.rxlink = bf->bf_daddr; +	else if (!flush) +		ath9k_hw_putrxbuf(ah, bf->bf_daddr);  	sc->rx.rxlink = &ds->ds_link;  } -static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf) +static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf, +			      bool flush)  {  	if (sc->rx.buf_hold) -		ath_rx_buf_link(sc, sc->rx.buf_hold); +		ath_rx_buf_link(sc, sc->rx.buf_hold, flush);  	sc->rx.buf_hold = bf;  } @@ -112,13 +113,13 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,  	struct ath_hw *ah = sc->sc_ah;  	struct ath_rx_edma *rx_edma;  	struct sk_buff *skb; -	struct ath_buf *bf; +	struct ath_rxbuf *bf;  	rx_edma = &sc->rx.rx_edma[qtype];  	if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize)  		return false; -	bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); +	bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list);  	list_del_init(&bf->list);  	skb = bf->bf_mpdu; @@ -138,7 +139,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc,  				  enum ath9k_rx_qtype qtype)  {  	struct ath_common *common = ath9k_hw_common(sc->sc_ah); -	struct ath_buf *bf, *tbf; +	struct ath_rxbuf *bf, *tbf;  	if (list_empty(&sc->rx.rxbuf)) {  		ath_dbg(common, QUEUE, "No free rx buf available\n"); @@ -154,7 +155,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc,  static void ath_rx_remove_buffer(struct ath_softc *sc,  				 enum ath9k_rx_qtype qtype)  { -	struct ath_buf *bf; +	struct ath_rxbuf *bf;  	struct ath_rx_edma *rx_edma;  	struct sk_buff *skb; @@ -171,7 +172,7 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc)  {  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah); -	struct ath_buf *bf; +	struct ath_rxbuf *bf;  	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);  	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); @@ -199,7 +200,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)  	struct ath_common *common = ath9k_hw_common(sc->sc_ah);  	struct ath_hw *ah = sc->sc_ah;  	struct sk_buff *skb; -	struct ath_buf *bf; +	struct ath_rxbuf *bf;  	int error = 0, i;  	u32 size; @@ -211,7 +212,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)  	ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP],  			       ah->caps.rx_hp_qdepth); -	size = sizeof(struct ath_buf) * nbufs; +	size = sizeof(struct ath_rxbuf) * nbufs;  	bf = devm_kzalloc(sc->dev, size, GFP_KERNEL);  	if (!bf)  		return -ENOMEM; @@ -271,7 +272,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)  {  	struct ath_common *common = ath9k_hw_common(sc->sc_ah);  	struct sk_buff *skb; -	struct ath_buf *bf; +	struct ath_rxbuf *bf;  	int error = 0;  	spin_lock_init(&sc->sc_pcu_lock); @@ -332,7 +333,7 @@ void ath_rx_cleanup(struct ath_softc *sc)  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah);  	struct sk_buff *skb; -	struct ath_buf *bf; +	struct ath_rxbuf *bf;  	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {  		ath_rx_edma_cleanup(sc); @@ -375,6 +376,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc)  {  	u32 rfilt; +	if (config_enabled(CONFIG_ATH9K_TX99)) +		return 0; +  	rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST  		| ATH9K_RX_FILTER_MCAST; @@ -417,7 +421,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)  		rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;  	} -	if (AR_SREV_9550(sc->sc_ah)) +	if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah))  		rfilt |= ATH9K_RX_FILTER_4ADDRESS;  	return rfilt; @@ -427,7 +431,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)  int ath_startrecv(struct ath_softc *sc)  {  	struct ath_hw *ah = sc->sc_ah; -	struct ath_buf *bf, *tbf; +	struct ath_rxbuf *bf, *tbf;  	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {  		ath_edma_start_recv(sc); @@ -440,14 +444,14 @@ int ath_startrecv(struct ath_softc *sc)  	sc->rx.buf_hold = NULL;  	sc->rx.rxlink = NULL;  	list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) { -		ath_rx_buf_link(sc, bf); +		ath_rx_buf_link(sc, bf, false);  	}  	/* We could have deleted elements so the list may be empty now */  	if (list_empty(&sc->rx.rxbuf))  		goto start_recv; -	bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); +	bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list);  	ath9k_hw_putrxbuf(ah, bf->bf_daddr);  	ath9k_hw_rxena(ah); @@ -536,7 +540,10 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)  		sc->ps_flags &= ~PS_BEACON_SYNC;  		ath_dbg(common, PS,  			"Reconfigure beacon timers based on synchronized timestamp\n"); -		ath9k_set_beacon(sc); +		if (!(WARN_ON_ONCE(sc->cur_beacon_conf.beacon_interval == 0))) +			ath9k_set_beacon(sc); +		if (sc->p2p_ps_vif) +			ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif);  	}  	if (ath_beacon_dtim_pending_cab(skb)) { @@ -603,13 +610,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)  static bool ath_edma_get_buffers(struct ath_softc *sc,  				 enum ath9k_rx_qtype qtype,  				 struct ath_rx_status *rs, -				 struct ath_buf **dest) +				 struct ath_rxbuf **dest)  {  	struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah);  	struct sk_buff *skb; -	struct ath_buf *bf; +	struct ath_rxbuf *bf;  	int ret;  	skb = skb_peek(&rx_edma->rx_fifo); @@ -653,11 +660,11 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,  	return true;  } -static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc, +static struct ath_rxbuf *ath_edma_get_next_rx_buf(struct ath_softc *sc,  						struct ath_rx_status *rs,  						enum ath9k_rx_qtype qtype)  { -	struct ath_buf *bf = NULL; +	struct ath_rxbuf *bf = NULL;  	while (ath_edma_get_buffers(sc, qtype, rs, &bf)) {  		if (!bf) @@ -668,13 +675,13 @@ static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc,  	return NULL;  } -static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, +static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,  					   struct ath_rx_status *rs)  {  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah);  	struct ath_desc *ds; -	struct ath_buf *bf; +	struct ath_rxbuf *bf;  	int ret;  	if (list_empty(&sc->rx.rxbuf)) { @@ -682,7 +689,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,  		return NULL;  	} -	bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); +	bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list);  	if (bf == sc->rx.buf_hold)  		return NULL; @@ -702,7 +709,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,  	ret = ath9k_hw_rxprocdesc(ah, ds, rs);  	if (ret == -EINPROGRESS) {  		struct ath_rx_status trs; -		struct ath_buf *tbf; +		struct ath_rxbuf *tbf;  		struct ath_desc *tds;  		memset(&trs, 0, sizeof(trs)); @@ -711,7 +718,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,  			return NULL;  		} -		tbf = list_entry(bf->list.next, struct ath_buf, list); +		tbf = list_entry(bf->list.next, struct ath_rxbuf, list);  		/*  		 * On some hardware the descriptor status words could @@ -730,11 +737,18 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,  			return NULL;  		/* -		 * mark descriptor as zero-length and set the 'more' -		 * flag to ensure that both buffers get discarded +		 * Re-check previous descriptor, in case it has been filled +		 * in the mean time.  		 */ -		rs->rs_datalen = 0; -		rs->rs_more = true; +		ret = ath9k_hw_rxprocdesc(ah, ds, rs); +		if (ret == -EINPROGRESS) { +			/* +			 * mark descriptor as zero-length and set the 'more' +			 * flag to ensure that both buffers get discarded +			 */ +			rs->rs_datalen = 0; +			rs->rs_more = true; +		}  	}  	list_del(&bf->list); @@ -753,194 +767,6 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,  	return bf;  } -/* Assumes you've already done the endian to CPU conversion */ -static bool ath9k_rx_accept(struct ath_common *common, -			    struct ieee80211_hdr *hdr, -			    struct ieee80211_rx_status *rxs, -			    struct ath_rx_status *rx_stats, -			    bool *decrypt_error) -{ -	struct ath_softc *sc = (struct ath_softc *) common->priv; -	bool is_mc, is_valid_tkip, strip_mic, mic_error; -	struct ath_hw *ah = common->ah; -	__le16 fc; - -	fc = hdr->frame_control; - -	is_mc = !!is_multicast_ether_addr(hdr->addr1); -	is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && -		test_bit(rx_stats->rs_keyix, common->tkip_keymap); -	strip_mic = is_valid_tkip && ieee80211_is_data(fc) && -		ieee80211_has_protected(fc) && -		!(rx_stats->rs_status & -		(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC | -		 ATH9K_RXERR_KEYMISS)); - -	/* -	 * Key miss events are only relevant for pairwise keys where the -	 * descriptor does contain a valid key index. This has been observed -	 * mostly with CCMP encryption. -	 */ -	if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID || -	    !test_bit(rx_stats->rs_keyix, common->ccmp_keymap)) -		rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; - -	mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) && -		!ieee80211_has_morefrags(fc) && -		!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && -		(rx_stats->rs_status & ATH9K_RXERR_MIC); - -	/* -	 * The rx_stats->rs_status will not be set until the end of the -	 * chained descriptors so it can be ignored if rs_more is set. The -	 * rs_more will be false at the last element of the chained -	 * descriptors. -	 */ -	if (rx_stats->rs_status != 0) { -		u8 status_mask; - -		if (rx_stats->rs_status & ATH9K_RXERR_CRC) { -			rxs->flag |= RX_FLAG_FAILED_FCS_CRC; -			mic_error = false; -		} - -		if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) || -		    (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) { -			*decrypt_error = true; -			mic_error = false; -		} - -		/* -		 * Reject error frames with the exception of -		 * decryption and MIC failures. For monitor mode, -		 * we also ignore the CRC error. -		 */ -		status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | -			      ATH9K_RXERR_KEYMISS; - -		if (ah->is_monitoring && (sc->rx.rxfilter & FIF_FCSFAIL)) -			status_mask |= ATH9K_RXERR_CRC; - -		if (rx_stats->rs_status & ~status_mask) -			return false; -	} - -	/* -	 * For unicast frames the MIC error bit can have false positives, -	 * so all MIC error reports need to be validated in software. -	 * False negatives are not common, so skip software verification -	 * if the hardware considers the MIC valid. -	 */ -	if (strip_mic) -		rxs->flag |= RX_FLAG_MMIC_STRIPPED; -	else if (is_mc && mic_error) -		rxs->flag |= RX_FLAG_MMIC_ERROR; - -	return true; -} - -static int ath9k_process_rate(struct ath_common *common, -			      struct ieee80211_hw *hw, -			      struct ath_rx_status *rx_stats, -			      struct ieee80211_rx_status *rxs) -{ -	struct ieee80211_supported_band *sband; -	enum ieee80211_band band; -	unsigned int i = 0; -	struct ath_softc __maybe_unused *sc = common->priv; - -	band = hw->conf.chandef.chan->band; -	sband = hw->wiphy->bands[band]; - -	switch (hw->conf.chandef.width) { -	case NL80211_CHAN_WIDTH_5: -		rxs->flag |= RX_FLAG_5MHZ; -		break; -	case NL80211_CHAN_WIDTH_10: -		rxs->flag |= RX_FLAG_10MHZ; -		break; -	default: -		break; -	} - -	if (rx_stats->rs_rate & 0x80) { -		/* HT rate */ -		rxs->flag |= RX_FLAG_HT; -		rxs->flag |= rx_stats->flag; -		rxs->rate_idx = rx_stats->rs_rate & 0x7f; -		return 0; -	} - -	for (i = 0; i < sband->n_bitrates; i++) { -		if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { -			rxs->rate_idx = i; -			return 0; -		} -		if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { -			rxs->flag |= RX_FLAG_SHORTPRE; -			rxs->rate_idx = i; -			return 0; -		} -	} - -	/* -	 * No valid hardware bitrate found -- we should not get here -	 * because hardware has already validated this frame as OK. -	 */ -	ath_dbg(common, ANY, -		"unsupported hw bitrate detected 0x%02x using 1 Mbit\n", -		rx_stats->rs_rate); -	RX_STAT_INC(rx_rate_err); -	return -EINVAL; -} - -static void ath9k_process_rssi(struct ath_common *common, -			       struct ieee80211_hw *hw, -			       struct ath_rx_status *rx_stats, -			       struct ieee80211_rx_status *rxs) -{ -	struct ath_softc *sc = hw->priv; -	struct ath_hw *ah = common->ah; -	int last_rssi; -	int rssi = rx_stats->rs_rssi; - -	/* -	 * RSSI is not available for subframes in an A-MPDU. -	 */ -	if (rx_stats->rs_moreaggr) { -		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; -		return; -	} - -	/* -	 * Check if the RSSI for the last subframe in an A-MPDU -	 * or an unaggregated frame is valid. -	 */ -	if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) { -		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; -		return; -	} - -	/* -	 * Update Beacon RSSI, this is used by ANI. -	 */ -	if (rx_stats->is_mybeacon && -	    ((ah->opmode == NL80211_IFTYPE_STATION) || -	     (ah->opmode == NL80211_IFTYPE_ADHOC))) { -		ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); -		last_rssi = sc->last_rssi; - -		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) -			rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); -		if (rssi < 0) -			rssi = 0; - -		ah->stats.avgbrssi = rssi; -	} - -	rxs->signal = ah->noise + rx_stats->rs_rssi; -} -  static void ath9k_process_tsf(struct ath_rx_status *rs,  			      struct ieee80211_rx_status *rxs,  			      u64 tsf) @@ -957,131 +783,6 @@ static void ath9k_process_tsf(struct ath_rx_status *rs,  		rxs->mactime += 0x100000000ULL;  } -#ifdef CONFIG_ATH9K_DEBUGFS -static s8 fix_rssi_inv_only(u8 rssi_val) -{ -	if (rssi_val == 128) -		rssi_val = 0; -	return (s8) rssi_val; -} -#endif - -/* returns 1 if this was a spectral frame, even if not handled. */ -static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, -			   struct ath_rx_status *rs, u64 tsf) -{ -#ifdef CONFIG_ATH9K_DEBUGFS -	struct ath_hw *ah = sc->sc_ah; -	u8 bins[SPECTRAL_HT20_NUM_BINS]; -	u8 *vdata = (u8 *)hdr; -	struct fft_sample_ht20 fft_sample; -	struct ath_radar_info *radar_info; -	struct ath_ht20_mag_info *mag_info; -	int len = rs->rs_datalen; -	int dc_pos; -	u16 length, max_magnitude; - -	/* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer -	 * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT -	 * yet, but this is supposed to be possible as well. -	 */ -	if (rs->rs_phyerr != ATH9K_PHYERR_RADAR && -	    rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT && -	    rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL) -		return 0; - -	/* check if spectral scan bit is set. This does not have to be checked -	 * if received through a SPECTRAL phy error, but shouldn't hurt. -	 */ -	radar_info = ((struct ath_radar_info *)&vdata[len]) - 1; -	if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) -		return 0; - -	/* Variation in the data length is possible and will be fixed later. -	 * Note that we only support HT20 for now. -	 * -	 * TODO: add HT20_40 support as well. -	 */ -	if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) || -	    (len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1)) -		return 1; - -	fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20; -	length = sizeof(fft_sample) - sizeof(fft_sample.tlv); -	fft_sample.tlv.length = __cpu_to_be16(length); - -	fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq); -	fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); -	fft_sample.noise = ah->noise; - -	switch (len - SPECTRAL_HT20_TOTAL_DATA_LEN) { -	case 0: -		/* length correct, nothing to do. */ -		memcpy(bins, vdata, SPECTRAL_HT20_NUM_BINS); -		break; -	case -1: -		/* first byte missing, duplicate it. */ -		memcpy(&bins[1], vdata, SPECTRAL_HT20_NUM_BINS - 1); -		bins[0] = vdata[0]; -		break; -	case 2: -		/* MAC added 2 extra bytes at bin 30 and 32, remove them. */ -		memcpy(bins, vdata, 30); -		bins[30] = vdata[31]; -		memcpy(&bins[31], &vdata[33], SPECTRAL_HT20_NUM_BINS - 31); -		break; -	case 1: -		/* MAC added 2 extra bytes AND first byte is missing. */ -		bins[0] = vdata[0]; -		memcpy(&bins[0], vdata, 30); -		bins[31] = vdata[31]; -		memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32); -		break; -	default: -		return 1; -	} - -	/* DC value (value in the middle) is the blind spot of the spectral -	 * sample and invalid, interpolate it. -	 */ -	dc_pos = SPECTRAL_HT20_NUM_BINS / 2; -	bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; - -	/* mag data is at the end of the frame, in front of radar_info */ -	mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; - -	/* copy raw bins without scaling them */ -	memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS); -	fft_sample.max_exp = mag_info->max_exp & 0xf; - -	max_magnitude = spectral_max_magnitude(mag_info->all_bins); -	fft_sample.max_magnitude = __cpu_to_be16(max_magnitude); -	fft_sample.max_index = spectral_max_index(mag_info->all_bins); -	fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins); -	fft_sample.tsf = __cpu_to_be64(tsf); - -	ath_debug_send_fft_sample(sc, &fft_sample.tlv); -	return 1; -#else -	return 0; -#endif -} - -static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr) -{ -	struct ath_hw *ah = sc->sc_ah; -	struct ath_common *common = ath9k_hw_common(ah); - -	if (ieee80211_is_beacon(hdr->frame_control)) { -		RX_STAT_INC(rx_beacons); -		if (!is_zero_ether_addr(common->curbssid) && -		    ether_addr_equal(hdr->addr3, common->curbssid)) -			return true; -	} - -	return false; -} -  /*   * For Decrypt or Demic errors, we only mark packet status here and always push   * up the frame up to let mac80211 handle the actual error case, be it no @@ -1098,32 +799,32 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,  	struct ath_common *common = ath9k_hw_common(ah);  	struct ieee80211_hdr *hdr;  	bool discard_current = sc->rx.discard_next; -	int ret = 0;  	/*  	 * Discard corrupt descriptors which are marked in  	 * ath_get_next_rx_buf().  	 */ -	sc->rx.discard_next = rx_stats->rs_more;  	if (discard_current) -		return -EINVAL; +		goto corrupt; + +	sc->rx.discard_next = false;  	/*  	 * Discard zero-length packets.  	 */  	if (!rx_stats->rs_datalen) {  		RX_STAT_INC(rx_len_err); -		return -EINVAL; +		goto corrupt;  	} -        /* -         * rs_status follows rs_datalen so if rs_datalen is too large -         * we can take a hint that hardware corrupted it, so ignore -         * those frames. -         */ +	/* +	 * rs_status follows rs_datalen so if rs_datalen is too large +	 * we can take a hint that hardware corrupted it, so ignore +	 * those frames. +	 */  	if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {  		RX_STAT_INC(rx_len_err); -		return -EINVAL; +		goto corrupt;  	}  	/* Only use status info from the last fragment */ @@ -1137,10 +838,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,  	 * This is different from the other corrupt descriptor  	 * condition handled above.  	 */ -	if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) { -		ret = -EINVAL; -		goto exit; -	} +	if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) +		goto corrupt;  	hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len); @@ -1156,34 +855,42 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,  		if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))  			RX_STAT_INC(rx_spectral); -		ret = -EINVAL; -		goto exit; +		return -EINVAL;  	}  	/*  	 * everything but the rate is checked here, the rate check is done  	 * separately to avoid doing two lookups for a rate for each frame.  	 */ -	if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) { -		ret = -EINVAL; -		goto exit; -	} +	if (!ath9k_cmn_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error, sc->rx.rxfilter)) +		return -EINVAL; -	rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr); -	if (rx_stats->is_mybeacon) { -		sc->hw_busy_count = 0; -		ath_start_rx_poll(sc, 3); +	if (ath_is_mybeacon(common, hdr)) { +		RX_STAT_INC(rx_beacons); +		rx_stats->is_mybeacon = true;  	} -	if (ath9k_process_rate(common, hw, rx_stats, rx_status)) { -		ret =-EINVAL; -		goto exit; +	/* +	 * This shouldn't happen, but have a safety check anyway. +	 */ +	if (WARN_ON(!ah->curchan)) +		return -EINVAL; + +	if (ath9k_cmn_process_rate(common, hw, rx_stats, rx_status)) { +		/* +		 * No valid hardware bitrate found -- we should not get here +		 * because hardware has already validated this frame as OK. +		 */ +		ath_dbg(common, ANY, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", +			rx_stats->rs_rate); +		RX_STAT_INC(rx_rate_err); +		return -EINVAL;  	} -	ath9k_process_rssi(common, hw, rx_stats, rx_status); +	ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status); -	rx_status->band = hw->conf.chandef.chan->band; -	rx_status->freq = hw->conf.chandef.chan->center_freq; +	rx_status->band = ah->curchan->chan->band; +	rx_status->freq = ah->curchan->chan->center_freq;  	rx_status->antenna = rx_stats->rs_antenna;  	rx_status->flag |= RX_FLAG_MACTIME_END; @@ -1193,60 +900,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,  		sc->rx.num_pkts++;  #endif -exit: -	sc->rx.discard_next = false; -	return ret; -} - -static void ath9k_rx_skb_postprocess(struct ath_common *common, -				     struct sk_buff *skb, -				     struct ath_rx_status *rx_stats, -				     struct ieee80211_rx_status *rxs, -				     bool decrypt_error) -{ -	struct ath_hw *ah = common->ah; -	struct ieee80211_hdr *hdr; -	int hdrlen, padpos, padsize; -	u8 keyix; -	__le16 fc; - -	/* see if any padding is done by the hw and remove it */ -	hdr = (struct ieee80211_hdr *) skb->data; -	hdrlen = ieee80211_get_hdrlen_from_skb(skb); -	fc = hdr->frame_control; -	padpos = ieee80211_hdrlen(fc); - -	/* The MAC header is padded to have 32-bit boundary if the -	 * packet payload is non-zero. The general calculation for -	 * padsize would take into account odd header lengths: -	 * padsize = (4 - padpos % 4) % 4; However, since only -	 * even-length headers are used, padding can only be 0 or 2 -	 * bytes and we can optimize this a bit. In addition, we must -	 * not try to remove padding from short control frames that do -	 * not have payload. */ -	padsize = padpos & 3; -	if (padsize && skb->len>=padpos+padsize+FCS_LEN) { -		memmove(skb->data + padsize, skb->data, padpos); -		skb_pull(skb, padsize); -	} - -	keyix = rx_stats->rs_keyix; - -	if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && -	    ieee80211_has_protected(fc)) { -		rxs->flag |= RX_FLAG_DECRYPTED; -	} else if (ieee80211_has_protected(fc) -		   && !decrypt_error && skb->len >= hdrlen + 4) { -		keyix = skb->data[hdrlen + 3] >> 6; +	return 0; -		if (test_bit(keyix, common->keymap)) -			rxs->flag |= RX_FLAG_DECRYPTED; -	} -	if (ah->sw_mgmt_crypto && -	    (rxs->flag & RX_FLAG_DECRYPTED) && -	    ieee80211_is_mgmt(fc)) -		/* Use software decrypt for management frames. */ -		rxs->flag &= ~RX_FLAG_DECRYPTED; +corrupt: +	sc->rx.discard_next = rx_stats->rs_more; +	return -EINVAL;  }  /* @@ -1270,13 +928,6 @@ static void ath9k_antenna_check(struct ath_softc *sc,  		return;  	/* -	 * All MPDUs in an aggregate will use the same LNA -	 * as the first MPDU. -	 */ -	if (rs->rs_isaggr && !rs->rs_firstaggr) -		return; - -	/*  	 * Change the default rx antenna if rx diversity  	 * chooses the other antenna 3 times in a row.  	 */ @@ -1315,7 +966,7 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc,  int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  { -	struct ath_buf *bf; +	struct ath_rxbuf *bf;  	struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb;  	struct ieee80211_rx_status *rxs;  	struct ath_hw *ah = sc->sc_ah; @@ -1329,6 +980,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  	u64 tsf = 0;  	unsigned long flags;  	dma_addr_t new_buf_addr; +	unsigned int budget = 512;  	if (edma)  		dma_type = DMA_BIDIRECTIONAL; @@ -1405,8 +1057,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  			skb_pull(skb, ah->caps.rx_status_len);  		if (!rs.rs_more) -			ath9k_rx_skb_postprocess(common, hdr_skb, &rs, -						 rxs, decrypt_error); +			ath9k_cmn_rx_skb_postprocess(common, hdr_skb, &rs, +						     rxs, decrypt_error);  		if (rs.rs_more) {  			RX_STAT_INC(rx_frags); @@ -1455,8 +1107,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);  		ath9k_antenna_check(sc, &rs); -  		ath9k_apply_ampdu_details(sc, &rs, rxs); +		ath_debug_rate_stats(sc, &rs, skb);  		ieee80211_rx(hw, skb); @@ -1467,15 +1119,17 @@ requeue_drop_frag:  		}  requeue:  		list_add_tail(&bf->list, &sc->rx.rxbuf); -		if (flush) -			continue; -		if (edma) { +		if (!edma) { +			ath_rx_buf_relink(sc, bf, flush); +			if (!flush) +				ath9k_hw_rxena(ah); +		} else if (!flush) {  			ath_rx_edma_buf_link(sc, qtype); -		} else { -			ath_rx_buf_relink(sc, bf); -			ath9k_hw_rxena(ah);  		} + +		if (!budget--) +			break;  	} while (1);  	if (!(ah->imask & ATH9K_INT_RXEOL)) {  | 
