diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2014-01-28 03:14:48 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-04 15:30:06 -0500 |
commit | 2fa4cb905605c863bf570027233af7afd8149ae4 (patch) | |
tree | d2891782e2e56d8a19474e8ea0c6334b16786b25 /drivers/net/wireless/ath/ath9k | |
parent | 235c0dc55aa52157bbaf2917e0a4bd8ae965c43a (diff) |
ath9k_htc: make ->sta_rc_update atomic for most calls
sta_rc_update() callback must be atomic, hence we can not take mutexes
or do other operations, which can sleep in ath9k_htc_sta_rc_update().
I think we can just return from ath9k_htc_sta_rc_update(), if it is
called without IEEE80211_RC_SUPP_RATES_CHANGED bit. That will help
with scheduling while atomic bug for most cases (except mesh and IBSS
modes).
For mesh and IBSS I do not see other solution like creating additional
workqueue, because sending firmware command require us to sleep, but
this can be done in additional patch.
Patch partially fixes bug:
https://bugzilla.redhat.com/show_bug.cgi?id=990955
Cc: stable@vger.kernel.org
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 608d739d1378..a57af9b96a39 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1315,21 +1315,22 @@ static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw, | |||
1315 | struct ath_common *common = ath9k_hw_common(priv->ah); | 1315 | struct ath_common *common = ath9k_hw_common(priv->ah); |
1316 | struct ath9k_htc_target_rate trate; | 1316 | struct ath9k_htc_target_rate trate; |
1317 | 1317 | ||
1318 | if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED)) | ||
1319 | return; | ||
1320 | |||
1318 | mutex_lock(&priv->mutex); | 1321 | mutex_lock(&priv->mutex); |
1319 | ath9k_htc_ps_wakeup(priv); | 1322 | ath9k_htc_ps_wakeup(priv); |
1320 | 1323 | ||
1321 | if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { | 1324 | memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); |
1322 | memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); | 1325 | ath9k_htc_setup_rate(priv, sta, &trate); |
1323 | ath9k_htc_setup_rate(priv, sta, &trate); | 1326 | if (!ath9k_htc_send_rate_cmd(priv, &trate)) |
1324 | if (!ath9k_htc_send_rate_cmd(priv, &trate)) | 1327 | ath_dbg(common, CONFIG, |
1325 | ath_dbg(common, CONFIG, | 1328 | "Supported rates for sta: %pM updated, rate caps: 0x%X\n", |
1326 | "Supported rates for sta: %pM updated, rate caps: 0x%X\n", | 1329 | sta->addr, be32_to_cpu(trate.capflags)); |
1327 | sta->addr, be32_to_cpu(trate.capflags)); | 1330 | else |
1328 | else | 1331 | ath_dbg(common, CONFIG, |
1329 | ath_dbg(common, CONFIG, | 1332 | "Unable to update supported rates for sta: %pM\n", |
1330 | "Unable to update supported rates for sta: %pM\n", | 1333 | sta->addr); |
1331 | sta->addr); | ||
1332 | } | ||
1333 | 1334 | ||
1334 | ath9k_htc_ps_restore(priv); | 1335 | ath9k_htc_ps_restore(priv); |
1335 | mutex_unlock(&priv->mutex); | 1336 | mutex_unlock(&priv->mutex); |