aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2014-02-03 05:45:51 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-04 15:30:07 -0500
commita243de48558397f438e299178cac29f6da8fc0ce (patch)
tree7a86e26b558acab2ec7ebc1bd30edd526034e46e /drivers/net
parent4fcfc7443d072582b5047b8b391d711590e5645c (diff)
ath9k_htc: avoid scheduling while atomic on sta_rc_update
mac80211 ->sta_rc_update() callback must be atomic. Since we have to take mutex and do other operations that can sleep when sending fimrware commands to device, the only option to satisfy atomicity requirement of ->sta_rc_update(), that I can see, is introduce work_struct and defer uploading new rates to that work. Tested-by: Oleksij Rempel <linux@rempel-privat.de> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c60
2 files changed, 40 insertions, 22 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 58da3468d1f0..99a203174f45 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -262,6 +262,8 @@ enum tid_aggr_state {
262struct ath9k_htc_sta { 262struct ath9k_htc_sta {
263 u8 index; 263 u8 index;
264 enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; 264 enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID];
265 struct work_struct rc_update_work;
266 struct ath9k_htc_priv *htc_priv;
265}; 267};
266 268
267#define ATH9K_HTC_RXBUF 256 269#define ATH9K_HTC_RXBUF 256
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index a57af9b96a39..c9254a61ca52 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1270,18 +1270,50 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
1270 mutex_unlock(&priv->mutex); 1270 mutex_unlock(&priv->mutex);
1271} 1271}
1272 1272
1273static void ath9k_htc_sta_rc_update_work(struct work_struct *work)
1274{
1275 struct ath9k_htc_sta *ista =
1276 container_of(work, struct ath9k_htc_sta, rc_update_work);
1277 struct ieee80211_sta *sta =
1278 container_of((void *)ista, struct ieee80211_sta, drv_priv);
1279 struct ath9k_htc_priv *priv = ista->htc_priv;
1280 struct ath_common *common = ath9k_hw_common(priv->ah);
1281 struct ath9k_htc_target_rate trate;
1282
1283 mutex_lock(&priv->mutex);
1284 ath9k_htc_ps_wakeup(priv);
1285
1286 memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
1287 ath9k_htc_setup_rate(priv, sta, &trate);
1288 if (!ath9k_htc_send_rate_cmd(priv, &trate))
1289 ath_dbg(common, CONFIG,
1290 "Supported rates for sta: %pM updated, rate caps: 0x%X\n",
1291 sta->addr, be32_to_cpu(trate.capflags));
1292 else
1293 ath_dbg(common, CONFIG,
1294 "Unable to update supported rates for sta: %pM\n",
1295 sta->addr);
1296
1297 ath9k_htc_ps_restore(priv);
1298 mutex_unlock(&priv->mutex);
1299}
1300
1273static int ath9k_htc_sta_add(struct ieee80211_hw *hw, 1301static int ath9k_htc_sta_add(struct ieee80211_hw *hw,
1274 struct ieee80211_vif *vif, 1302 struct ieee80211_vif *vif,
1275 struct ieee80211_sta *sta) 1303 struct ieee80211_sta *sta)
1276{ 1304{
1277 struct ath9k_htc_priv *priv = hw->priv; 1305 struct ath9k_htc_priv *priv = hw->priv;
1306 struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
1278 int ret; 1307 int ret;
1279 1308
1280 mutex_lock(&priv->mutex); 1309 mutex_lock(&priv->mutex);
1281 ath9k_htc_ps_wakeup(priv); 1310 ath9k_htc_ps_wakeup(priv);
1282 ret = ath9k_htc_add_station(priv, vif, sta); 1311 ret = ath9k_htc_add_station(priv, vif, sta);
1283 if (!ret) 1312 if (!ret) {
1313 INIT_WORK(&ista->rc_update_work, ath9k_htc_sta_rc_update_work);
1314 ista->htc_priv = priv;
1284 ath9k_htc_init_rate(priv, sta); 1315 ath9k_htc_init_rate(priv, sta);
1316 }
1285 ath9k_htc_ps_restore(priv); 1317 ath9k_htc_ps_restore(priv);
1286 mutex_unlock(&priv->mutex); 1318 mutex_unlock(&priv->mutex);
1287 1319
@@ -1293,12 +1325,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
1293 struct ieee80211_sta *sta) 1325 struct ieee80211_sta *sta)
1294{ 1326{
1295 struct ath9k_htc_priv *priv = hw->priv; 1327 struct ath9k_htc_priv *priv = hw->priv;
1296 struct ath9k_htc_sta *ista; 1328 struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
1297 int ret; 1329 int ret;
1298 1330
1331 cancel_work_sync(&ista->rc_update_work);
1332
1299 mutex_lock(&priv->mutex); 1333 mutex_lock(&priv->mutex);
1300 ath9k_htc_ps_wakeup(priv); 1334 ath9k_htc_ps_wakeup(priv);
1301 ista = (struct ath9k_htc_sta *) sta->drv_priv;
1302 htc_sta_drain(priv->htc, ista->index); 1335 htc_sta_drain(priv->htc, ista->index);
1303 ret = ath9k_htc_remove_station(priv, vif, sta); 1336 ret = ath9k_htc_remove_station(priv, vif, sta);
1304 ath9k_htc_ps_restore(priv); 1337 ath9k_htc_ps_restore(priv);
@@ -1311,29 +1344,12 @@ static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw,
1311 struct ieee80211_vif *vif, 1344 struct ieee80211_vif *vif,
1312 struct ieee80211_sta *sta, u32 changed) 1345 struct ieee80211_sta *sta, u32 changed)
1313{ 1346{
1314 struct ath9k_htc_priv *priv = hw->priv; 1347 struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
1315 struct ath_common *common = ath9k_hw_common(priv->ah);
1316 struct ath9k_htc_target_rate trate;
1317 1348
1318 if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED)) 1349 if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED))
1319 return; 1350 return;
1320 1351
1321 mutex_lock(&priv->mutex); 1352 schedule_work(&ista->rc_update_work);
1322 ath9k_htc_ps_wakeup(priv);
1323
1324 memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
1325 ath9k_htc_setup_rate(priv, sta, &trate);
1326 if (!ath9k_htc_send_rate_cmd(priv, &trate))
1327 ath_dbg(common, CONFIG,
1328 "Supported rates for sta: %pM updated, rate caps: 0x%X\n",
1329 sta->addr, be32_to_cpu(trate.capflags));
1330 else
1331 ath_dbg(common, CONFIG,
1332 "Unable to update supported rates for sta: %pM\n",
1333 sta->addr);
1334
1335 ath9k_htc_ps_restore(priv);
1336 mutex_unlock(&priv->mutex);
1337} 1353}
1338 1354
1339static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, 1355static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,