diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 14:43:13 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 14:43:13 -0700 | 
| commit | 951cc93a7493a81a47e20231441bc6cf17c98a37 (patch) | |
| tree | f53934f0f225e0215a85c8c59af4c6513e89e3f1 /drivers/net/wireless/ath/ath9k/main.c | |
| parent | a7e1aabb28e8154ce987b622fd78d80a1ca39361 (diff) | |
| parent | 415b3334a21aa67806c52d1acf4e72e14f7f402f (diff) | |
| download | olio-linux-3.10-951cc93a7493a81a47e20231441bc6cf17c98a37.tar.xz olio-linux-3.10-951cc93a7493a81a47e20231441bc6cf17c98a37.zip  | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1287 commits)
  icmp: Fix regression in nexthop resolution during replies.
  net: Fix ppc64 BPF JIT dependencies.
  acenic: include NET_SKB_PAD headroom to incoming skbs
  ixgbe: convert to ndo_fix_features
  ixgbe: only enable WoL for magic packet by default
  ixgbe: remove ifdef check for non-existent define
  ixgbe: Pass staterr instead of re-reading status and error bits from descriptor
  ixgbe: Move interrupt related values out of ring and into q_vector
  ixgbe: add structure for containing RX/TX rings to q_vector
  ixgbe: inline the ixgbe_maybe_stop_tx function
  ixgbe: Update ATR to use recorded TX queues instead of CPU for routing
  igb: Fix for DH89xxCC near end loopback test
  e1000: always call e1000_check_for_link() on e1000_ce4100 MACs.
  netxen: add fw version compatibility check
  be2net: request native mode each time the card is reset
  ipv4: Constrain UFO fragment sizes to multiples of 8 bytes
  virtio_net: Fix panic in virtnet_remove
  ipv6: make fragment identifications less predictable
  ipv6: unshare inetpeers
  can: make function can_get_bittiming static
  ...
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 179 | 
1 files changed, 101 insertions, 78 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2ca351fe6d3..9098aaad97a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -62,14 +62,12 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)  	if (txq->axq_depth || !list_empty(&txq->axq_acq))  		pending = true; -	else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) -		pending = !list_empty(&txq->txq_fifo_pending);  	spin_unlock_bh(&txq->axq_lock);  	return pending;  } -bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) +static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)  {  	unsigned long flags;  	bool ret; @@ -136,7 +134,7 @@ void ath9k_ps_restore(struct ath_softc *sc)  	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);  } -static void ath_start_ani(struct ath_common *common) +void ath_start_ani(struct ath_common *common)  {  	struct ath_hw *ah = common->ah;  	unsigned long timestamp = jiffies_to_msecs(jiffies); @@ -219,7 +217,7 @@ static int ath_update_survey_stats(struct ath_softc *sc)   * by reseting the chip.  To accomplish this we must first cleanup any pending   * DMA, then restart stuff.  */ -int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, +static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,  		    struct ath9k_channel *hchan)  {  	struct ath_hw *ah = sc->sc_ah; @@ -302,7 +300,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,  			ath_set_beacon(sc);  		ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);  		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); -		ath_start_ani(common); +		if (!common->disable_ani) +			ath_start_ani(common);  	}   ps_restore: @@ -361,7 +360,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int  	txctl.paprd = BIT(chain);  	if (ath_tx_start(hw, skb, &txctl) != 0) { -		ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n"); +		ath_dbg(common, ATH_DBG_CALIBRATE, "PAPRD TX failed\n");  		dev_kfree_skb_any(skb);  		return false;  	} @@ -370,7 +369,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int  			msecs_to_jiffies(ATH_PAPRD_TIMEOUT));  	if (!time_left) -		ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE, +		ath_dbg(common, ATH_DBG_CALIBRATE,  			"Timeout waiting for paprd training on TX chain %d\n",  			chain); @@ -394,12 +393,14 @@ void ath_paprd_calibrate(struct work_struct *work)  	if (!caldata)  		return; +	ath9k_ps_wakeup(sc); +  	if (ar9003_paprd_init_table(ah) < 0) -		return; +		goto fail_paprd;  	skb = alloc_skb(len, GFP_KERNEL);  	if (!skb) -		return; +		goto fail_paprd;  	skb_put(skb, len);  	memset(skb->data, 0, len); @@ -411,7 +412,6 @@ void ath_paprd_calibrate(struct work_struct *work)  	memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);  	memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); -	ath9k_ps_wakeup(sc);  	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {  		if (!(common->tx_chainmask & BIT(chain)))  			continue; @@ -431,11 +431,18 @@ void ath_paprd_calibrate(struct work_struct *work)  		if (!ath_paprd_send_frame(sc, skb, chain))  			goto fail_paprd; -		if (!ar9003_paprd_is_done(ah)) +		if (!ar9003_paprd_is_done(ah)) { +			ath_dbg(common, ATH_DBG_CALIBRATE, +				"PAPRD not yet done on chain %d\n", chain);  			break; +		} -		if (ar9003_paprd_create_curve(ah, caldata, chain) != 0) +		if (ar9003_paprd_create_curve(ah, caldata, chain)) { +			ath_dbg(common, ATH_DBG_CALIBRATE, +				"PAPRD create curve failed on chain %d\n", +								   chain);  			break; +		}  		chain_ok = 1;  	} @@ -515,24 +522,19 @@ void ath_ani_calibrate(unsigned long data)  		common->ani.checkani_timer = timestamp;  	} -	/* Skip all processing if there's nothing to do. */ -	if (longcal || shortcal || aniflag) { -		/* Call ANI routine if necessary */ -		if (aniflag) { -			spin_lock_irqsave(&common->cc_lock, flags); -			ath9k_hw_ani_monitor(ah, ah->curchan); -			ath_update_survey_stats(sc); -			spin_unlock_irqrestore(&common->cc_lock, flags); -		} +	/* Call ANI routine if necessary */ +	if (aniflag) { +		spin_lock_irqsave(&common->cc_lock, flags); +		ath9k_hw_ani_monitor(ah, ah->curchan); +		ath_update_survey_stats(sc); +		spin_unlock_irqrestore(&common->cc_lock, flags); +	} -		/* Perform calibration if necessary */ -		if (longcal || shortcal) { -			common->ani.caldone = -				ath9k_hw_calibrate(ah, -						   ah->curchan, -						   common->rx_chainmask, -						   longcal); -		} +	/* Perform calibration if necessary */ +	if (longcal || shortcal) { +		common->ani.caldone = +			ath9k_hw_calibrate(ah, ah->curchan, +						common->rx_chainmask, longcal);  	}  	ath9k_ps_restore(sc); @@ -615,8 +617,11 @@ void ath_hw_check(struct work_struct *work)  	ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "  		"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);  	if (busy >= 99) { -		if (++sc->hw_busy_count >= 3) +		if (++sc->hw_busy_count >= 3) { +			spin_lock_bh(&sc->sc_pcu_lock);  			ath_reset(sc, true); +			spin_unlock_bh(&sc->sc_pcu_lock); +		}  	} else if (busy >= 0)  		sc->hw_busy_count = 0; @@ -635,7 +640,9 @@ static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)  			/* Rx is hung for more than 500ms. Reset it */  			ath_dbg(common, ATH_DBG_RESET,  				"Possible RX hang, resetting"); +			spin_lock_bh(&sc->sc_pcu_lock);  			ath_reset(sc, true); +			spin_unlock_bh(&sc->sc_pcu_lock);  			count = 0;  		}  	} else @@ -672,7 +679,9 @@ void ath9k_tasklet(unsigned long data)  	if ((status & ATH9K_INT_FATAL) ||  	    (status & ATH9K_INT_BB_WATCHDOG)) { +		spin_lock(&sc->sc_pcu_lock);  		ath_reset(sc, true); +		spin_unlock(&sc->sc_pcu_lock);  		return;  	} @@ -868,7 +877,7 @@ chip_reset:  #undef SCHED_INTR  } -void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) +static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)  {  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah); @@ -974,10 +983,10 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)  	sc->hw_busy_count = 0;  	/* Stop ANI */ +  	del_timer_sync(&common->ani.timer);  	ath9k_ps_wakeup(sc); -	spin_lock_bh(&sc->sc_pcu_lock);  	ieee80211_stop_queues(hw); @@ -1020,10 +1029,11 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)  	}  	ieee80211_wake_queues(hw); -	spin_unlock_bh(&sc->sc_pcu_lock);  	/* Start ANI */ -	ath_start_ani(common); +	if (!common->disable_ani) +		ath_start_ani(common); +  	ath9k_ps_restore(sc);  	return r; @@ -1261,7 +1271,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)  	/* disable HAL and put h/w to sleep */  	ath9k_hw_disable(ah); -	ath9k_hw_configpcipowersave(ah, 1, 1);  	spin_unlock_bh(&sc->sc_pcu_lock); @@ -1412,10 +1421,14 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,  	ath9k_hw_set_interrupts(ah, ah->imask);  	/* Set up ANI */ -	if ((iter_data.naps + iter_data.nadhocs) > 0) { +	if (iter_data.naps > 0) {  		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; -		sc->sc_flags |= SC_OP_ANI_RUN; -		ath_start_ani(common); + +		if (!common->disable_ani) { +			sc->sc_flags |= SC_OP_ANI_RUN; +			ath_start_ani(common); +		} +  	} else {  		sc->sc_flags &= ~SC_OP_ANI_RUN;  		del_timer_sync(&common->ani.timer); @@ -1952,50 +1965,38 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)  	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;  	struct ath_vif *avp = (void *)vif->drv_priv; -	switch (sc->sc_ah->opmode) { -	case NL80211_IFTYPE_ADHOC: -		/* There can be only one vif available */ +	/* +	 * Skip iteration if primary station vif's bss info +	 * was not changed +	 */ +	if (sc->sc_flags & SC_OP_PRIM_STA_VIF) +		return; + +	if (bss_conf->assoc) { +		sc->sc_flags |= SC_OP_PRIM_STA_VIF; +		avp->primary_sta_vif = true;  		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);  		common->curaid = bss_conf->aid;  		ath9k_hw_write_associd(sc->sc_ah); -		/* configure beacon */ -		if (bss_conf->enable_beacon) -			ath_beacon_config(sc, vif); -		break; -	case NL80211_IFTYPE_STATION: -		/* -		 * Skip iteration if primary station vif's bss info -		 * was not changed -		 */ -		if (sc->sc_flags & SC_OP_PRIM_STA_VIF) -			break; - -		if (bss_conf->assoc) { -			sc->sc_flags |= SC_OP_PRIM_STA_VIF; -			avp->primary_sta_vif = true; -			memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); -			common->curaid = bss_conf->aid; -			ath9k_hw_write_associd(sc->sc_ah); -			ath_dbg(common, ATH_DBG_CONFIG, +		ath_dbg(common, ATH_DBG_CONFIG,  				"Bss Info ASSOC %d, bssid: %pM\n",  				bss_conf->aid, common->curbssid); -			ath_beacon_config(sc, vif); -			/* -			 * Request a re-configuration of Beacon related timers -			 * on the receipt of the first Beacon frame (i.e., -			 * after time sync with the AP). -			 */ -			sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; -			/* Reset rssi stats */ -			sc->last_rssi = ATH_RSSI_DUMMY_MARKER; -			sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; +		ath_beacon_config(sc, vif); +		/* +		 * Request a re-configuration of Beacon related timers +		 * on the receipt of the first Beacon frame (i.e., +		 * after time sync with the AP). +		 */ +		sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; +		/* Reset rssi stats */ +		sc->last_rssi = ATH_RSSI_DUMMY_MARKER; +		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; +		if (!common->disable_ani) {  			sc->sc_flags |= SC_OP_ANI_RUN;  			ath_start_ani(common);  		} -		break; -	default: -		break; +  	}  } @@ -2005,6 +2006,9 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)  	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;  	struct ath_vif *avp = (void *)vif->drv_priv; +	if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) +		return; +  	/* Reconfigure bss info */  	if (avp->primary_sta_vif && !bss_conf->assoc) {  		ath_dbg(common, ATH_DBG_CONFIG, @@ -2023,8 +2027,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)  	 * None of station vifs are associated.  	 * Clear bssid & aid  	 */ -	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && -	    !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) { +	if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {  		ath9k_hw_write_associd(sc->sc_ah);  		/* Stop ANI */  		sc->sc_flags &= ~SC_OP_ANI_RUN; @@ -2054,6 +2057,26 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,  			common->curbssid, common->curaid);  	} +	if (changed & BSS_CHANGED_IBSS) { +		/* There can be only one vif available */ +		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); +		common->curaid = bss_conf->aid; +		ath9k_hw_write_associd(sc->sc_ah); + +		if (bss_conf->ibss_joined) { +			sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; + +			if (!common->disable_ani) { +				sc->sc_flags |= SC_OP_ANI_RUN; +				ath_start_ani(common); +			} + +		} else { +			sc->sc_flags &= ~SC_OP_ANI_RUN; +			del_timer_sync(&common->ani.timer); +		} +	} +  	/* Enable transmission of beacons (AP, IBSS, MESH) */  	if ((changed & BSS_CHANGED_BEACON) ||  	    ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) { @@ -2308,9 +2331,9 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)  	ath9k_ps_wakeup(sc);  	spin_lock_bh(&sc->sc_pcu_lock);  	drain_txq = ath_drain_all_txq(sc, false); -	spin_unlock_bh(&sc->sc_pcu_lock);  	if (!drain_txq)  		ath_reset(sc, false); +	spin_unlock_bh(&sc->sc_pcu_lock);  	ath9k_ps_restore(sc);  	ieee80211_wake_queues(hw); @@ -2334,7 +2357,7 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)  	return false;  } -int ath9k_tx_last_beacon(struct ieee80211_hw *hw) +static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)  {  	struct ath_softc *sc = hw->priv;  	struct ath_hw *ah = sc->sc_ah;  |