Commit 3b95e9c0 authored by John W. Linville's avatar John W. Linville

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem
parents 5dc5503f 2a1e0fd1
...@@ -1827,7 +1827,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) ...@@ -1827,7 +1827,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
} }
/* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); if (AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
} }
/* /*
......
...@@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) ...@@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
if (mac->link_state != MAC80211_LINKED) if (mac->link_state != MAC80211_LINKED)
return; return;
spin_lock(&rtlpriv->locks.lps_lock); spin_lock_irq(&rtlpriv->locks.lps_lock);
/* Idle for a while if we connect to AP a while ago. */ /* Idle for a while if we connect to AP a while ago. */
if (mac->cnt_after_linked >= 2) { if (mac->cnt_after_linked >= 2) {
...@@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) ...@@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
} }
} }
spin_unlock(&rtlpriv->locks.lps_lock); spin_unlock_irq(&rtlpriv->locks.lps_lock);
} }
/*Leave the leisure power save mode.*/ /*Leave the leisure power save mode.*/
...@@ -416,8 +416,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw) ...@@ -416,8 +416,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
unsigned long flags;
spin_lock(&rtlpriv->locks.lps_lock); spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags);
if (ppsc->fwctrl_lps) { if (ppsc->fwctrl_lps) {
if (ppsc->dot11_psmode != EACTIVE) { if (ppsc->dot11_psmode != EACTIVE) {
...@@ -438,7 +439,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw) ...@@ -438,7 +439,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
rtl_lps_set_psmode(hw, EACTIVE); rtl_lps_set_psmode(hw, EACTIVE);
} }
} }
spin_unlock(&rtlpriv->locks.lps_lock); spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags);
} }
/* For sw LPS*/ /* For sw LPS*/
...@@ -539,9 +540,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw) ...@@ -539,9 +540,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
} }
spin_lock(&rtlpriv->locks.lps_lock); spin_lock_irq(&rtlpriv->locks.lps_lock);
rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
spin_unlock(&rtlpriv->locks.lps_lock); spin_unlock_irq(&rtlpriv->locks.lps_lock);
} }
void rtl_swlps_rfon_wq_callback(void *data) void rtl_swlps_rfon_wq_callback(void *data)
...@@ -574,9 +575,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) ...@@ -574,9 +575,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
if (rtlpriv->link_info.busytraffic) if (rtlpriv->link_info.busytraffic)
return; return;
spin_lock(&rtlpriv->locks.lps_lock); spin_lock_irq(&rtlpriv->locks.lps_lock);
rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
spin_unlock(&rtlpriv->locks.lps_lock); spin_unlock_irq(&rtlpriv->locks.lps_lock);
if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
!RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
......
...@@ -161,6 +161,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, ...@@ -161,6 +161,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
return -ENOENT; return -ENOENT;
} }
/* if we're already stopping ignore any new requests to stop */
if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
spin_unlock_bh(&sta->lock);
return -EALREADY;
}
if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
/* not even started yet! */ /* not even started yet! */
ieee80211_assign_tid_tx(sta, tid, NULL); ieee80211_assign_tid_tx(sta, tid, NULL);
...@@ -169,6 +175,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, ...@@ -169,6 +175,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
return 0; return 0;
} }
set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
...@@ -176,8 +184,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, ...@@ -176,8 +184,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
sta->sta.addr, tid); sta->sta.addr, tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */ #endif /* CONFIG_MAC80211_HT_DEBUG */
set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
del_timer_sync(&tid_tx->addba_resp_timer); del_timer_sync(&tid_tx->addba_resp_timer);
/* /*
...@@ -187,6 +193,20 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, ...@@ -187,6 +193,20 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
*/ */
clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
/*
* There might be a few packets being processed right now (on
* another CPU) that have already gotten past the aggregation
* check when it was still OPERATIONAL and consequently have
* IEEE80211_TX_CTL_AMPDU set. In that case, this code might
* call into the driver at the same time or even before the
* TX paths calls into it, which could confuse the driver.
*
* Wait for all currently running TX paths to finish before
* telling the driver. New packets will not go through since
* the aggregation session is no longer OPERATIONAL.
*/
synchronize_net();
tid_tx->stop_initiator = initiator; tid_tx->stop_initiator = initiator;
tid_tx->tx_stop = tx; tid_tx->tx_stop = tx;
...@@ -757,11 +777,27 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, ...@@ -757,11 +777,27 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
goto out; goto out;
} }
del_timer(&tid_tx->addba_resp_timer); del_timer_sync(&tid_tx->addba_resp_timer);
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid);
#endif #endif
/*
* addba_resp_timer may have fired before we got here, and
* caused WANT_STOP to be set. If the stop then was already
* processed further, STOPPING might be set.
*/
if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) ||
test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG
"got addBA resp for tid %d but we already gave up\n",
tid);
#endif
goto out;
}
/* /*
* IEEE 802.11-2007 7.3.1.14: * IEEE 802.11-2007 7.3.1.14:
* In an ADDBA Response frame, when the Status Code field * In an ADDBA Response frame, when the Status Code field
......
...@@ -89,8 +89,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { ...@@ -89,8 +89,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
[NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
[NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, [NL80211_ATTR_MAC] = { .len = ETH_ALEN },
[NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN }, [NL80211_ATTR_PREV_BSSID] = { .len = ETH_ALEN },
[NL80211_ATTR_KEY] = { .type = NLA_NESTED, }, [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
[NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment