diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/recv.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 780 | 
1 files changed, 22 insertions, 758 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index e1fcc68124d..12aca02228c 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -20,43 +20,6 @@  #define SKB_CB_ATHBUF(__skb)	(*((struct ath_buf **)__skb->cb)) -static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, -					       int mindelta, int main_rssi_avg, -					       int alt_rssi_avg, int pkt_count) -{ -	return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && -		(alt_rssi_avg > main_rssi_avg + maxdelta)) || -		(alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); -} - -static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, -					int curr_main_set, int curr_alt_set, -					int alt_rssi_avg, int main_rssi_avg) -{ -	bool result = false; -	switch (div_group) { -	case 0: -		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) -			result = true; -		break; -	case 1: -	case 2: -		if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && -			(curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && -				(alt_rssi_avg >= (main_rssi_avg - 5))) || -			((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && -			(curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && -				(alt_rssi_avg >= (main_rssi_avg - 2)))) && -							(alt_rssi_avg >= 4)) -			result = true; -		else -			result = false; -		break; -	} - -	return result; -} -  static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)  {  	return sc->ps_enabled && @@ -303,7 +266,7 @@ static void ath_edma_start_recv(struct ath_softc *sc)  	ath_opmode_init(sc); -	ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); +	ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));  	spin_unlock_bh(&sc->rx.rxbuflock);  } @@ -322,8 +285,8 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)  	int error = 0;  	spin_lock_init(&sc->sc_pcu_lock); -	sc->sc_flags &= ~SC_OP_RXFLUSH;  	spin_lock_init(&sc->rx.rxbuflock); +	clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);  	common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +  			     sc->sc_ah->caps.rx_status_len; @@ -467,6 +430,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc)  		rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;  	} +	if (AR_SREV_9550(sc->sc_ah)) +		rfilt |= ATH9K_RX_FILTER_4ADDRESS; +  	return rfilt;  } @@ -500,7 +466,7 @@ int ath_startrecv(struct ath_softc *sc)  start_recv:  	ath_opmode_init(sc); -	ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); +	ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));  	spin_unlock_bh(&sc->rx.rxbuflock); @@ -535,11 +501,11 @@ bool ath_stoprecv(struct ath_softc *sc)  void ath_flushrecv(struct ath_softc *sc)  { -	sc->sc_flags |= SC_OP_RXFLUSH; +	set_bit(SC_OP_RXFLUSH, &sc->sc_flags);  	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)  		ath_rx_tasklet(sc, 1, true);  	ath_rx_tasklet(sc, 1, false); -	sc->sc_flags &= ~SC_OP_RXFLUSH; +	clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);  }  static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) @@ -587,7 +553,7 @@ 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 timestamp from the AP\n"); -		ath_set_beacon(sc); +		ath9k_set_beacon(sc);  	}  	if (ath_beacon_dtim_pending_cab(skb)) { @@ -624,13 +590,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)  	/* Process Beacon and CAB receive in PS state */  	if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) -	    && mybeacon) +	    && mybeacon) {  		ath_rx_ps_beacon(sc, skb); -	else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && -		 (ieee80211_is_data(hdr->frame_control) || -		  ieee80211_is_action(hdr->frame_control)) && -		 is_multicast_ether_addr(hdr->addr1) && -		 !ieee80211_has_moredata(hdr->frame_control)) { +	} else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && +		   (ieee80211_is_data(hdr->frame_control) || +		    ieee80211_is_action(hdr->frame_control)) && +		   is_multicast_ether_addr(hdr->addr1) && +		   !ieee80211_has_moredata(hdr->frame_control)) {  		/*  		 * No more broadcast/multicast frames to be received at this  		 * point. @@ -695,9 +661,9 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,  			__skb_unlink(skb, &rx_edma->rx_fifo);  			list_add_tail(&bf->list, &sc->rx.rxbuf);  			ath_rx_edma_buf_link(sc, qtype); -		} else { -			bf = NULL;  		} + +		bf = NULL;  	}  	*dest = bf; @@ -822,7 +788,8 @@ static bool ath9k_rx_accept(struct ath_common *common,  	 * descriptor does contain a valid key index. This has been observed  	 * mostly with CCMP encryption.  	 */ -	if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID) +	if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID || +	    !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))  		rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;  	if (!rx_stats->rs_datalen) { @@ -1067,709 +1034,6 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,  		rxs->flag &= ~RX_FLAG_DECRYPTED;  } -static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, -				      struct ath_hw_antcomb_conf ant_conf, -				      int main_rssi_avg) -{ -	antcomb->quick_scan_cnt = 0; - -	if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) -		antcomb->rssi_lna2 = main_rssi_avg; -	else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) -		antcomb->rssi_lna1 = main_rssi_avg; - -	switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { -	case 0x10: /* LNA2 A-B */ -		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; -		antcomb->first_quick_scan_conf = -			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; -		break; -	case 0x20: /* LNA1 A-B */ -		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; -		antcomb->first_quick_scan_conf = -			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; -		break; -	case 0x21: /* LNA1 LNA2 */ -		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; -		antcomb->first_quick_scan_conf = -			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; -		antcomb->second_quick_scan_conf = -			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -		break; -	case 0x12: /* LNA2 LNA1 */ -		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; -		antcomb->first_quick_scan_conf = -			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; -		antcomb->second_quick_scan_conf = -			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -		break; -	case 0x13: /* LNA2 A+B */ -		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -		antcomb->first_quick_scan_conf = -			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; -		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; -		break; -	case 0x23: /* LNA1 A+B */ -		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -		antcomb->first_quick_scan_conf = -			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; -		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; -		break; -	default: -		break; -	} -} - -static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, -				struct ath_hw_antcomb_conf *div_ant_conf, -				int main_rssi_avg, int alt_rssi_avg, -				int alt_ratio) -{ -	/* alt_good */ -	switch (antcomb->quick_scan_cnt) { -	case 0: -		/* set alt to main, and alt to first conf */ -		div_ant_conf->main_lna_conf = antcomb->main_conf; -		div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; -		break; -	case 1: -		/* set alt to main, and alt to first conf */ -		div_ant_conf->main_lna_conf = antcomb->main_conf; -		div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; -		antcomb->rssi_first = main_rssi_avg; -		antcomb->rssi_second = alt_rssi_avg; - -		if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { -			/* main is LNA1 */ -			if (ath_is_alt_ant_ratio_better(alt_ratio, -						ATH_ANT_DIV_COMB_LNA1_DELTA_HI, -						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, -						main_rssi_avg, alt_rssi_avg, -						antcomb->total_pkt_count)) -				antcomb->first_ratio = true; -			else -				antcomb->first_ratio = false; -		} else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { -			if (ath_is_alt_ant_ratio_better(alt_ratio, -						ATH_ANT_DIV_COMB_LNA1_DELTA_MID, -						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, -						main_rssi_avg, alt_rssi_avg, -						antcomb->total_pkt_count)) -				antcomb->first_ratio = true; -			else -				antcomb->first_ratio = false; -		} else { -			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && -			    (alt_rssi_avg > main_rssi_avg + -			    ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || -			    (alt_rssi_avg > main_rssi_avg)) && -			    (antcomb->total_pkt_count > 50)) -				antcomb->first_ratio = true; -			else -				antcomb->first_ratio = false; -		} -		break; -	case 2: -		antcomb->alt_good = false; -		antcomb->scan_not_start = false; -		antcomb->scan = false; -		antcomb->rssi_first = main_rssi_avg; -		antcomb->rssi_third = alt_rssi_avg; - -		if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) -			antcomb->rssi_lna1 = alt_rssi_avg; -		else if (antcomb->second_quick_scan_conf == -			 ATH_ANT_DIV_COMB_LNA2) -			antcomb->rssi_lna2 = alt_rssi_avg; -		else if (antcomb->second_quick_scan_conf == -			 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { -			if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) -				antcomb->rssi_lna2 = main_rssi_avg; -			else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) -				antcomb->rssi_lna1 = main_rssi_avg; -		} - -		if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + -		    ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) -			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; -		else -			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; - -		if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { -			if (ath_is_alt_ant_ratio_better(alt_ratio, -						ATH_ANT_DIV_COMB_LNA1_DELTA_HI, -						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, -						main_rssi_avg, alt_rssi_avg, -						antcomb->total_pkt_count)) -				antcomb->second_ratio = true; -			else -				antcomb->second_ratio = false; -		} else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { -			if (ath_is_alt_ant_ratio_better(alt_ratio, -						ATH_ANT_DIV_COMB_LNA1_DELTA_MID, -						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, -						main_rssi_avg, alt_rssi_avg, -						antcomb->total_pkt_count)) -				antcomb->second_ratio = true; -			else -				antcomb->second_ratio = false; -		} else { -			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && -			    (alt_rssi_avg > main_rssi_avg + -			    ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || -			    (alt_rssi_avg > main_rssi_avg)) && -			    (antcomb->total_pkt_count > 50)) -				antcomb->second_ratio = true; -			else -				antcomb->second_ratio = false; -		} - -		/* set alt to the conf with maximun ratio */ -		if (antcomb->first_ratio && antcomb->second_ratio) { -			if (antcomb->rssi_second > antcomb->rssi_third) { -				/* first alt*/ -				if ((antcomb->first_quick_scan_conf == -				    ATH_ANT_DIV_COMB_LNA1) || -				    (antcomb->first_quick_scan_conf == -				    ATH_ANT_DIV_COMB_LNA2)) -					/* Set alt LNA1 or LNA2*/ -					if (div_ant_conf->main_lna_conf == -					    ATH_ANT_DIV_COMB_LNA2) -						div_ant_conf->alt_lna_conf = -							ATH_ANT_DIV_COMB_LNA1; -					else -						div_ant_conf->alt_lna_conf = -							ATH_ANT_DIV_COMB_LNA2; -				else -					/* Set alt to A+B or A-B */ -					div_ant_conf->alt_lna_conf = -						antcomb->first_quick_scan_conf; -			} else if ((antcomb->second_quick_scan_conf == -				   ATH_ANT_DIV_COMB_LNA1) || -				   (antcomb->second_quick_scan_conf == -				   ATH_ANT_DIV_COMB_LNA2)) { -				/* Set alt LNA1 or LNA2 */ -				if (div_ant_conf->main_lna_conf == -				    ATH_ANT_DIV_COMB_LNA2) -					div_ant_conf->alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -				else -					div_ant_conf->alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; -			} else { -				/* Set alt to A+B or A-B */ -				div_ant_conf->alt_lna_conf = -					antcomb->second_quick_scan_conf; -			} -		} else if (antcomb->first_ratio) { -			/* first alt */ -			if ((antcomb->first_quick_scan_conf == -			    ATH_ANT_DIV_COMB_LNA1) || -			    (antcomb->first_quick_scan_conf == -			    ATH_ANT_DIV_COMB_LNA2)) -					/* Set alt LNA1 or LNA2 */ -				if (div_ant_conf->main_lna_conf == -				    ATH_ANT_DIV_COMB_LNA2) -					div_ant_conf->alt_lna_conf = -							ATH_ANT_DIV_COMB_LNA1; -				else -					div_ant_conf->alt_lna_conf = -							ATH_ANT_DIV_COMB_LNA2; -			else -				/* Set alt to A+B or A-B */ -				div_ant_conf->alt_lna_conf = -						antcomb->first_quick_scan_conf; -		} else if (antcomb->second_ratio) { -				/* second alt */ -			if ((antcomb->second_quick_scan_conf == -			    ATH_ANT_DIV_COMB_LNA1) || -			    (antcomb->second_quick_scan_conf == -			    ATH_ANT_DIV_COMB_LNA2)) -				/* Set alt LNA1 or LNA2 */ -				if (div_ant_conf->main_lna_conf == -				    ATH_ANT_DIV_COMB_LNA2) -					div_ant_conf->alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -				else -					div_ant_conf->alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; -			else -				/* Set alt to A+B or A-B */ -				div_ant_conf->alt_lna_conf = -						antcomb->second_quick_scan_conf; -		} else { -			/* main is largest */ -			if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || -			    (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) -				/* Set alt LNA1 or LNA2 */ -				if (div_ant_conf->main_lna_conf == -				    ATH_ANT_DIV_COMB_LNA2) -					div_ant_conf->alt_lna_conf = -							ATH_ANT_DIV_COMB_LNA1; -				else -					div_ant_conf->alt_lna_conf = -							ATH_ANT_DIV_COMB_LNA2; -			else -				/* Set alt to A+B or A-B */ -				div_ant_conf->alt_lna_conf = antcomb->main_conf; -		} -		break; -	default: -		break; -	} -} - -static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, -		struct ath_ant_comb *antcomb, int alt_ratio) -{ -	if (ant_conf->div_group == 0) { -		/* Adjust the fast_div_bias based on main and alt lna conf */ -		switch ((ant_conf->main_lna_conf << 4) | -				ant_conf->alt_lna_conf) { -		case 0x01: /* A-B LNA2 */ -			ant_conf->fast_div_bias = 0x3b; -			break; -		case 0x02: /* A-B LNA1 */ -			ant_conf->fast_div_bias = 0x3d; -			break; -		case 0x03: /* A-B A+B */ -			ant_conf->fast_div_bias = 0x1; -			break; -		case 0x10: /* LNA2 A-B */ -			ant_conf->fast_div_bias = 0x7; -			break; -		case 0x12: /* LNA2 LNA1 */ -			ant_conf->fast_div_bias = 0x2; -			break; -		case 0x13: /* LNA2 A+B */ -			ant_conf->fast_div_bias = 0x7; -			break; -		case 0x20: /* LNA1 A-B */ -			ant_conf->fast_div_bias = 0x6; -			break; -		case 0x21: /* LNA1 LNA2 */ -			ant_conf->fast_div_bias = 0x0; -			break; -		case 0x23: /* LNA1 A+B */ -			ant_conf->fast_div_bias = 0x6; -			break; -		case 0x30: /* A+B A-B */ -			ant_conf->fast_div_bias = 0x1; -			break; -		case 0x31: /* A+B LNA2 */ -			ant_conf->fast_div_bias = 0x3b; -			break; -		case 0x32: /* A+B LNA1 */ -			ant_conf->fast_div_bias = 0x3d; -			break; -		default: -			break; -		} -	} else if (ant_conf->div_group == 1) { -		/* Adjust the fast_div_bias based on main and alt_lna_conf */ -		switch ((ant_conf->main_lna_conf << 4) | -			ant_conf->alt_lna_conf) { -		case 0x01: /* A-B LNA2 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x02: /* A-B LNA1 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x03: /* A-B A+B */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x10: /* LNA2 A-B */ -			if (!(antcomb->scan) && -			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) -				ant_conf->fast_div_bias = 0x3f; -			else -				ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x12: /* LNA2 LNA1 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x13: /* LNA2 A+B */ -			if (!(antcomb->scan) && -			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) -				ant_conf->fast_div_bias = 0x3f; -			else -				ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x20: /* LNA1 A-B */ -			if (!(antcomb->scan) && -			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) -				ant_conf->fast_div_bias = 0x3f; -			else -				ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x21: /* LNA1 LNA2 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x23: /* LNA1 A+B */ -			if (!(antcomb->scan) && -			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) -				ant_conf->fast_div_bias = 0x3f; -			else -				ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x30: /* A+B A-B */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x31: /* A+B LNA2 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x32: /* A+B LNA1 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		default: -			break; -		} -	} else if (ant_conf->div_group == 2) { -		/* Adjust the fast_div_bias based on main and alt_lna_conf */ -		switch ((ant_conf->main_lna_conf << 4) | -				ant_conf->alt_lna_conf) { -		case 0x01: /* A-B LNA2 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x02: /* A-B LNA1 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x03: /* A-B A+B */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x10: /* LNA2 A-B */ -			if (!(antcomb->scan) && -				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) -				ant_conf->fast_div_bias = 0x1; -			else -				ant_conf->fast_div_bias = 0x2; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x12: /* LNA2 LNA1 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x13: /* LNA2 A+B */ -			if (!(antcomb->scan) && -				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) -				ant_conf->fast_div_bias = 0x1; -			else -				ant_conf->fast_div_bias = 0x2; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x20: /* LNA1 A-B */ -			if (!(antcomb->scan) && -				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) -				ant_conf->fast_div_bias = 0x1; -			else -				ant_conf->fast_div_bias = 0x2; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x21: /* LNA1 LNA2 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x23: /* LNA1 A+B */ -			if (!(antcomb->scan) && -				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) -				ant_conf->fast_div_bias = 0x1; -			else -				ant_conf->fast_div_bias = 0x2; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x30: /* A+B A-B */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x31: /* A+B LNA2 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		case 0x32: /* A+B LNA1 */ -			ant_conf->fast_div_bias = 0x1; -			ant_conf->main_gaintb = 0; -			ant_conf->alt_gaintb = 0; -			break; -		default: -			break; -		} -	} -} - -/* Antenna diversity and combining */ -static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) -{ -	struct ath_hw_antcomb_conf div_ant_conf; -	struct ath_ant_comb *antcomb = &sc->ant_comb; -	int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; -	int curr_main_set; -	int main_rssi = rs->rs_rssi_ctl0; -	int alt_rssi = rs->rs_rssi_ctl1; -	int rx_ant_conf,  main_ant_conf; -	bool short_scan = false; - -	rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & -		       ATH_ANT_RX_MASK; -	main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & -			 ATH_ANT_RX_MASK; - -	/* Record packet only when both main_rssi and  alt_rssi is positive */ -	if (main_rssi > 0 && alt_rssi > 0) { -		antcomb->total_pkt_count++; -		antcomb->main_total_rssi += main_rssi; -		antcomb->alt_total_rssi  += alt_rssi; -		if (main_ant_conf == rx_ant_conf) -			antcomb->main_recv_cnt++; -		else -			antcomb->alt_recv_cnt++; -	} - -	/* Short scan check */ -	if (antcomb->scan && antcomb->alt_good) { -		if (time_after(jiffies, antcomb->scan_start_time + -		    msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) -			short_scan = true; -		else -			if (antcomb->total_pkt_count == -			    ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { -				alt_ratio = ((antcomb->alt_recv_cnt * 100) / -					    antcomb->total_pkt_count); -				if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) -					short_scan = true; -			} -	} - -	if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || -	    rs->rs_moreaggr) && !short_scan) -		return; - -	if (antcomb->total_pkt_count) { -		alt_ratio = ((antcomb->alt_recv_cnt * 100) / -			     antcomb->total_pkt_count); -		main_rssi_avg = (antcomb->main_total_rssi / -				 antcomb->total_pkt_count); -		alt_rssi_avg = (antcomb->alt_total_rssi / -				 antcomb->total_pkt_count); -	} - - -	ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); -	curr_alt_set = div_ant_conf.alt_lna_conf; -	curr_main_set = div_ant_conf.main_lna_conf; - -	antcomb->count++; - -	if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { -		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { -			ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, -						  main_rssi_avg); -			antcomb->alt_good = true; -		} else { -			antcomb->alt_good = false; -		} - -		antcomb->count = 0; -		antcomb->scan = true; -		antcomb->scan_not_start = true; -	} - -	if (!antcomb->scan) { -		if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, -					alt_ratio, curr_main_set, curr_alt_set, -					alt_rssi_avg, main_rssi_avg)) { -			if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { -				/* Switch main and alt LNA */ -				div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; -				div_ant_conf.alt_lna_conf  = -						ATH_ANT_DIV_COMB_LNA1; -			} else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { -				div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -				div_ant_conf.alt_lna_conf  = -						ATH_ANT_DIV_COMB_LNA2; -			} - -			goto div_comb_done; -		} else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && -			   (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { -			/* Set alt to another LNA */ -			if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) -				div_ant_conf.alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -			else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) -				div_ant_conf.alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; - -			goto div_comb_done; -		} - -		if ((alt_rssi_avg < (main_rssi_avg + -						div_ant_conf.lna1_lna2_delta))) -			goto div_comb_done; -	} - -	if (!antcomb->scan_not_start) { -		switch (curr_alt_set) { -		case ATH_ANT_DIV_COMB_LNA2: -			antcomb->rssi_lna2 = alt_rssi_avg; -			antcomb->rssi_lna1 = main_rssi_avg; -			antcomb->scan = true; -			/* set to A+B */ -			div_ant_conf.main_lna_conf = -				ATH_ANT_DIV_COMB_LNA1; -			div_ant_conf.alt_lna_conf  = -				ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -			break; -		case ATH_ANT_DIV_COMB_LNA1: -			antcomb->rssi_lna1 = alt_rssi_avg; -			antcomb->rssi_lna2 = main_rssi_avg; -			antcomb->scan = true; -			/* set to A+B */ -			div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; -			div_ant_conf.alt_lna_conf  = -				ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -			break; -		case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: -			antcomb->rssi_add = alt_rssi_avg; -			antcomb->scan = true; -			/* set to A-B */ -			div_ant_conf.alt_lna_conf = -				ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; -			break; -		case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: -			antcomb->rssi_sub = alt_rssi_avg; -			antcomb->scan = false; -			if (antcomb->rssi_lna2 > -			    (antcomb->rssi_lna1 + -			    ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { -				/* use LNA2 as main LNA */ -				if ((antcomb->rssi_add > antcomb->rssi_lna1) && -				    (antcomb->rssi_add > antcomb->rssi_sub)) { -					/* set to A+B */ -					div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; -					div_ant_conf.alt_lna_conf  = -						ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -				} else if (antcomb->rssi_sub > -					   antcomb->rssi_lna1) { -					/* set to A-B */ -					div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; -					div_ant_conf.alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; -				} else { -					/* set to LNA1 */ -					div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; -					div_ant_conf.alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -				} -			} else { -				/* use LNA1 as main LNA */ -				if ((antcomb->rssi_add > antcomb->rssi_lna2) && -				    (antcomb->rssi_add > antcomb->rssi_sub)) { -					/* set to A+B */ -					div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -					div_ant_conf.alt_lna_conf  = -						ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; -				} else if (antcomb->rssi_sub > -					   antcomb->rssi_lna1) { -					/* set to A-B */ -					div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -					div_ant_conf.alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; -				} else { -					/* set to LNA2 */ -					div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -					div_ant_conf.alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; -				} -			} -			break; -		default: -			break; -		} -	} else { -		if (!antcomb->alt_good) { -			antcomb->scan_not_start = false; -			/* Set alt to another LNA */ -			if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { -				div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; -				div_ant_conf.alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -			} else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { -				div_ant_conf.main_lna_conf = -						ATH_ANT_DIV_COMB_LNA1; -				div_ant_conf.alt_lna_conf = -						ATH_ANT_DIV_COMB_LNA2; -			} -			goto div_comb_done; -		} -	} - -	ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, -					   main_rssi_avg, alt_rssi_avg, -					   alt_ratio); - -	antcomb->quick_scan_cnt++; - -div_comb_done: -	ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); -	ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); - -	antcomb->scan_start_time = jiffies; -	antcomb->total_pkt_count = 0; -	antcomb->main_total_rssi = 0; -	antcomb->alt_total_rssi = 0; -	antcomb->main_recv_cnt = 0; -	antcomb->alt_recv_cnt = 0; -} -  int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  {  	struct ath_buf *bf; @@ -1803,7 +1067,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  	do {  		/* If handling rx interrupt and flush is in progress => exit */ -		if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) +		if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0))  			break;  		memset(&rs, 0, sizeof(rs)); @@ -1841,13 +1105,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  		else  			rs.is_mybeacon = false; +		sc->rx.num_pkts++;  		ath_debug_stat_rx(sc, &rs);  		/*  		 * If we're asked to flush receive queue, directly  		 * chain it back at the queue without processing it.  		 */ -		if (sc->sc_flags & SC_OP_RXFLUSH) { +		if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) {  			RX_STAT_INC(rx_drop_rxflush);  			goto requeue_drop_frag;  		} @@ -1968,7 +1233,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  			skb_trim(skb, skb->len - 8);  		spin_lock_irqsave(&sc->sc_pm_lock, flags); -  		if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |  				     PS_WAIT_FOR_CAB |  				     PS_WAIT_FOR_PSPOLL_DATA)) ||  |