aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-06-16 06:30:27 -0400
committerReinette Chatre <reinette.chatre@intel.com>2010-06-21 13:46:21 -0400
commit4620fefa59d8aeae400b21d60d9a86aa11ebffa7 (patch)
treede4e8f3b4526ca9c8b87c27737c47065e3630494 /drivers/net/wireless
parent543708be320d7df692d24b349ca01a947b340764 (diff)
iwlagn: use mutex for aggregation
Now that the ampdu_action callback can sleep, we can use the mutex to properly protect the aggregation data, and return useful errors if they should happen. Also, add some sleep and mutex debugging so we won't call any of the functions that now require being able to sleep and/or the mutex to be held in an invalid context. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Acked-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h2
5 files changed, 45 insertions, 27 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 83e6a42ca2da..fee276bc36fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1785,6 +1785,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1785{ 1785{
1786 unsigned long flags; 1786 unsigned long flags;
1787 u16 ra_tid; 1787 u16 ra_tid;
1788 int ret;
1788 1789
1789 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || 1790 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
1790 (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues 1791 (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -1800,7 +1801,9 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1800 ra_tid = BUILD_RAxTID(sta_id, tid); 1801 ra_tid = BUILD_RAxTID(sta_id, tid);
1801 1802
1802 /* Modify device's station table to Tx this TID */ 1803 /* Modify device's station table to Tx this TID */
1803 iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); 1804 ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
1805 if (ret)
1806 return ret;
1804 1807
1805 spin_lock_irqsave(&priv->lock, flags); 1808 spin_lock_irqsave(&priv->lock, flags);
1806 1809
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 84df7fca750d..2573234e4db1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -233,6 +233,7 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
233{ 233{
234 unsigned long flags; 234 unsigned long flags;
235 u16 ra_tid; 235 u16 ra_tid;
236 int ret;
236 237
237 if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || 238 if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
238 (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues 239 (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -248,7 +249,9 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
248 ra_tid = BUILD_RAxTID(sta_id, tid); 249 ra_tid = BUILD_RAxTID(sta_id, tid);
249 250
250 /* Modify device's station table to Tx this TID */ 251 /* Modify device's station table to Tx this TID */
251 iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); 252 ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
253 if (ret)
254 return ret;
252 255
253 spin_lock_irqsave(&priv->lock, flags); 256 spin_lock_irqsave(&priv->lock, flags);
254 257
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index d857f8496f69..294b7ed3c16a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3374,7 +3374,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3374 struct ieee80211_sta *sta, u16 tid, u16 *ssn) 3374 struct ieee80211_sta *sta, u16 tid, u16 *ssn)
3375{ 3375{
3376 struct iwl_priv *priv = hw->priv; 3376 struct iwl_priv *priv = hw->priv;
3377 int ret; 3377 int ret = -EINVAL;
3378 3378
3379 IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", 3379 IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
3380 sta->addr, tid); 3380 sta->addr, tid);
@@ -3382,17 +3382,19 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3382 if (!(priv->cfg->sku & IWL_SKU_N)) 3382 if (!(priv->cfg->sku & IWL_SKU_N))
3383 return -EACCES; 3383 return -EACCES;
3384 3384
3385 mutex_lock(&priv->mutex);
3386
3385 switch (action) { 3387 switch (action) {
3386 case IEEE80211_AMPDU_RX_START: 3388 case IEEE80211_AMPDU_RX_START:
3387 IWL_DEBUG_HT(priv, "start Rx\n"); 3389 IWL_DEBUG_HT(priv, "start Rx\n");
3388 return iwl_sta_rx_agg_start(priv, sta, tid, *ssn); 3390 ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
3391 break;
3389 case IEEE80211_AMPDU_RX_STOP: 3392 case IEEE80211_AMPDU_RX_STOP:
3390 IWL_DEBUG_HT(priv, "stop Rx\n"); 3393 IWL_DEBUG_HT(priv, "stop Rx\n");
3391 ret = iwl_sta_rx_agg_stop(priv, sta, tid); 3394 ret = iwl_sta_rx_agg_stop(priv, sta, tid);
3392 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3395 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3393 return 0; 3396 ret = 0;
3394 else 3397 break;
3395 return ret;
3396 case IEEE80211_AMPDU_TX_START: 3398 case IEEE80211_AMPDU_TX_START:
3397 IWL_DEBUG_HT(priv, "start Tx\n"); 3399 IWL_DEBUG_HT(priv, "start Tx\n");
3398 ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); 3400 ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
@@ -3401,7 +3403,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3401 IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", 3403 IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
3402 priv->_agn.agg_tids_count); 3404 priv->_agn.agg_tids_count);
3403 } 3405 }
3404 return ret; 3406 break;
3405 case IEEE80211_AMPDU_TX_STOP: 3407 case IEEE80211_AMPDU_TX_STOP:
3406 IWL_DEBUG_HT(priv, "stop Tx\n"); 3408 IWL_DEBUG_HT(priv, "stop Tx\n");
3407 ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); 3409 ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
@@ -3411,18 +3413,15 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3411 priv->_agn.agg_tids_count); 3413 priv->_agn.agg_tids_count);
3412 } 3414 }
3413 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3415 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3414 return 0; 3416 ret = 0;
3415 else 3417 break;
3416 return ret;
3417 case IEEE80211_AMPDU_TX_OPERATIONAL: 3418 case IEEE80211_AMPDU_TX_OPERATIONAL:
3418 /* do nothing */ 3419 /* do nothing, return value ignored */
3419 return -EOPNOTSUPP;
3420 default:
3421 IWL_DEBUG_HT(priv, "unknown\n");
3422 return -EINVAL;
3423 break; 3420 break;
3424 } 3421 }
3425 return 0; 3422 mutex_unlock(&priv->mutex);
3423
3424 return ret;
3426} 3425}
3427 3426
3428static void iwl_mac_sta_notify(struct ieee80211_hw *hw, 3427static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index d57df6c02db3..a62a03236ebb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -30,6 +30,7 @@
30#include <net/mac80211.h> 30#include <net/mac80211.h>
31#include <linux/etherdevice.h> 31#include <linux/etherdevice.h>
32#include <linux/sched.h> 32#include <linux/sched.h>
33#include <linux/lockdep.h>
33 34
34#include "iwl-dev.h" 35#include "iwl-dev.h"
35#include "iwl-core.h" 36#include "iwl-core.h"
@@ -145,8 +146,10 @@ int iwl_send_add_sta(struct iwl_priv *priv,
145 146
146 if (flags & CMD_ASYNC) 147 if (flags & CMD_ASYNC)
147 cmd.callback = iwl_add_sta_callback; 148 cmd.callback = iwl_add_sta_callback;
148 else 149 else {
149 cmd.flags |= CMD_WANT_SKB; 150 cmd.flags |= CMD_WANT_SKB;
151 might_sleep();
152 }
150 153
151 cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); 154 cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
152 ret = iwl_send_cmd(priv, &cmd); 155 ret = iwl_send_cmd(priv, &cmd);
@@ -1268,17 +1271,22 @@ EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station);
1268/** 1271/**
1269 * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table 1272 * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
1270 */ 1273 */
1271void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) 1274int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
1272{ 1275{
1273 unsigned long flags; 1276 unsigned long flags;
1277 struct iwl_addsta_cmd sta_cmd;
1278
1279 lockdep_assert_held(&priv->mutex);
1274 1280
1275 /* Remove "disable" flag, to enable Tx for this TID */ 1281 /* Remove "disable" flag, to enable Tx for this TID */
1276 spin_lock_irqsave(&priv->sta_lock, flags); 1282 spin_lock_irqsave(&priv->sta_lock, flags);
1277 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; 1283 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
1278 priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); 1284 priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
1279 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1285 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1280 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); 1286 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
1281 spin_unlock_irqrestore(&priv->sta_lock, flags); 1287 spin_unlock_irqrestore(&priv->sta_lock, flags);
1288
1289 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
1282} 1290}
1283EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); 1291EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
1284 1292
@@ -1287,6 +1295,9 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
1287{ 1295{
1288 unsigned long flags; 1296 unsigned long flags;
1289 int sta_id; 1297 int sta_id;
1298 struct iwl_addsta_cmd sta_cmd;
1299
1300 lockdep_assert_held(&priv->mutex);
1290 1301
1291 sta_id = iwl_sta_id(sta); 1302 sta_id = iwl_sta_id(sta);
1292 if (sta_id == IWL_INVALID_STATION) 1303 if (sta_id == IWL_INVALID_STATION)
@@ -1298,10 +1309,10 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
1298 priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; 1309 priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
1299 priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); 1310 priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
1300 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1311 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1312 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
1301 spin_unlock_irqrestore(&priv->sta_lock, flags); 1313 spin_unlock_irqrestore(&priv->sta_lock, flags);
1302 1314
1303 return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 1315 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
1304 CMD_ASYNC);
1305} 1316}
1306EXPORT_SYMBOL(iwl_sta_rx_agg_start); 1317EXPORT_SYMBOL(iwl_sta_rx_agg_start);
1307 1318
@@ -1309,7 +1320,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
1309 int tid) 1320 int tid)
1310{ 1321{
1311 unsigned long flags; 1322 unsigned long flags;
1312 int sta_id, ret; 1323 int sta_id;
1324 struct iwl_addsta_cmd sta_cmd;
1325
1326 lockdep_assert_held(&priv->mutex);
1313 1327
1314 sta_id = iwl_sta_id(sta); 1328 sta_id = iwl_sta_id(sta);
1315 if (sta_id == IWL_INVALID_STATION) { 1329 if (sta_id == IWL_INVALID_STATION) {
@@ -1322,11 +1336,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
1322 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; 1336 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
1323 priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; 1337 priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
1324 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1338 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1325 ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); 1339 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
1326 spin_unlock_irqrestore(&priv->sta_lock, flags); 1340 spin_unlock_irqrestore(&priv->sta_lock, flags);
1327 1341
1328 return ret; 1342 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
1329
1330} 1343}
1331EXPORT_SYMBOL(iwl_sta_rx_agg_stop); 1344EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
1332 1345
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 5b1b1e461eb6..619bb99d85cf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -73,7 +73,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
73 const u8 *addr); 73 const u8 *addr);
74int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 74int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
75 struct ieee80211_sta *sta); 75 struct ieee80211_sta *sta);
76void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); 76int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
77int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, 77int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
78 int tid, u16 ssn); 78 int tid, u16 ssn);
79int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, 79int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,