aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2011-08-26 02:11:31 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-29 15:33:01 -0400
commite20d434170c3a7f388d5e916825499c9c0738606 (patch)
tree64a4966a3847d46bae04762d3782740fe23759ac /drivers/net/wireless/iwlwifi
parentf22be624c29b7f714e5a82ad13dc33a0cd1443a2 (diff)
iwlagn: move the stop / wake queue logic to transport layer
priv->mac80211_registered and priv->hw needed to move to shared. stop_queue API was added in order to allow the upper layer to stop the SW queues for regulatory purposes. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tt.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h61
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-shared.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h61
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h8
9 files changed, 93 insertions, 74 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
index 495f9366474..92ba8cd0ecd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -209,7 +209,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
209{ 209{
210 if (stop) { 210 if (stop) {
211 IWL_DEBUG_TEMP(priv, "Stop all queues\n"); 211 IWL_DEBUG_TEMP(priv, "Stop all queues\n");
212 if (priv->mac80211_registered) 212 if (priv->shrd->mac80211_registered)
213 ieee80211_stop_queues(priv->hw); 213 ieee80211_stop_queues(priv->hw);
214 IWL_DEBUG_TEMP(priv, 214 IWL_DEBUG_TEMP(priv,
215 "Schedule 5 seconds CT_KILL Timer\n"); 215 "Schedule 5 seconds CT_KILL Timer\n");
@@ -217,7 +217,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
217 jiffies + CT_KILL_EXIT_DURATION * HZ); 217 jiffies + CT_KILL_EXIT_DURATION * HZ);
218 } else { 218 } else {
219 IWL_DEBUG_TEMP(priv, "Wake all queues\n"); 219 IWL_DEBUG_TEMP(priv, "Wake all queues\n");
220 if (priv->mac80211_registered) 220 if (priv->shrd->mac80211_registered)
221 ieee80211_wake_queues(priv->hw); 221 ieee80211_wake_queues(priv->hw);
222 } 222 }
223} 223}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index bc3268a0c75..009c35a8d20 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -803,7 +803,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
803 iwl_is_associated_ctx(ctx) && ctx->vif && 803 iwl_is_associated_ctx(ctx) && ctx->vif &&
804 ctx->vif->type == NL80211_IFTYPE_STATION) { 804 ctx->vif->type == NL80211_IFTYPE_STATION) {
805 ctx->last_tx_rejected = true; 805 ctx->last_tx_rejected = true;
806 iwl_stop_queue(priv, &priv->txq[txq_id]); 806 iwl_trans_stop_queue(trans(priv), txq_id);
807 807
808 IWL_DEBUG_TX_REPLY(priv, 808 IWL_DEBUG_TX_REPLY(priv,
809 "TXQ %d status %s (0x%08x) " 809 "TXQ %d status %s (0x%08x) "
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 5fdf9b10b47..a0cf486f762 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1519,7 +1519,7 @@ static void __iwl_down(struct iwl_priv *priv)
1519 if (!exit_pending) 1519 if (!exit_pending)
1520 clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); 1520 clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
1521 1521
1522 if (priv->mac80211_registered) 1522 if (priv->shrd->mac80211_registered)
1523 ieee80211_stop_queues(priv->hw); 1523 ieee80211_stop_queues(priv->hw);
1524 1524
1525 /* Clear out all status bits but a few that are stable across reset */ 1525 /* Clear out all status bits but a few that are stable across reset */
@@ -1863,7 +1863,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
1863 IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); 1863 IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
1864 return ret; 1864 return ret;
1865 } 1865 }
1866 priv->mac80211_registered = 1; 1866 priv->shrd->mac80211_registered = 1;
1867 1867
1868 return 0; 1868 return 0;
1869} 1869}
@@ -3243,6 +3243,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
3243 priv->shrd = &priv->_shrd; 3243 priv->shrd = &priv->_shrd;
3244 priv->shrd->bus = bus; 3244 priv->shrd->bus = bus;
3245 priv->shrd->priv = priv; 3245 priv->shrd->priv = priv;
3246 priv->shrd->hw = hw;
3246 bus_set_drv_data(priv->bus, priv->shrd); 3247 bus_set_drv_data(priv->bus, priv->shrd);
3247 3248
3248 priv->shrd->trans = trans_ops->alloc(priv->shrd); 3249 priv->shrd->trans = trans_ops->alloc(priv->shrd);
@@ -3418,9 +3419,9 @@ void __devexit iwl_remove(struct iwl_priv * priv)
3418 iwl_testmode_cleanup(priv); 3419 iwl_testmode_cleanup(priv);
3419 iwl_leds_exit(priv); 3420 iwl_leds_exit(priv);
3420 3421
3421 if (priv->mac80211_registered) { 3422 if (priv->shrd->mac80211_registered) {
3422 ieee80211_unregister_hw(priv->hw); 3423 ieee80211_unregister_hw(priv->hw);
3423 priv->mac80211_registered = 0; 3424 priv->shrd->mac80211_registered = 0;
3424 } 3425 }
3425 3426
3426 iwl_tt_exit(priv); 3427 iwl_tt_exit(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 2e75429f5ac..08e8e1bf483 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1181,8 +1181,6 @@ struct iwl_priv {
1181 /* Indication if ieee80211_ops->open has been called */ 1181 /* Indication if ieee80211_ops->open has been called */
1182 u8 is_open; 1182 u8 is_open;
1183 1183
1184 u8 mac80211_registered;
1185
1186 /* eeprom -- this is in the card's little endian byte order */ 1184 /* eeprom -- this is in the card's little endian byte order */
1187 u8 *eeprom; 1185 u8 *eeprom;
1188 int nvm_device_type; 1186 int nvm_device_type;
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 7f92d14083c..d3feac9e45b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -64,67 +64,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd)
64 return --index & (n_bd - 1); 64 return --index & (n_bd - 1);
65} 65}
66 66
67/*
68 * we have 8 bits used like this:
69 *
70 * 7 6 5 4 3 2 1 0
71 * | | | | | | | |
72 * | | | | | | +-+-------- AC queue (0-3)
73 * | | | | | |
74 * | +-+-+-+-+------------ HW queue ID
75 * |
76 * +---------------------- unused
77 */
78static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
79{
80 BUG_ON(ac > 3); /* only have 2 bits */
81 BUG_ON(hwq > 31); /* only use 5 bits */
82
83 txq->swq_id = (hwq << 2) | ac;
84}
85
86static inline void iwl_wake_queue(struct iwl_priv *priv,
87 struct iwl_tx_queue *txq)
88{
89 u8 queue = txq->swq_id;
90 u8 ac = queue & 3;
91 u8 hwq = (queue >> 2) & 0x1f;
92
93 if (unlikely(!priv->mac80211_registered))
94 return;
95
96 if (test_and_clear_bit(hwq, priv->queue_stopped))
97 if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0)
98 ieee80211_wake_queue(priv->hw, ac);
99}
100
101static inline void iwl_stop_queue(struct iwl_priv *priv,
102 struct iwl_tx_queue *txq)
103{
104 u8 queue = txq->swq_id;
105 u8 ac = queue & 3;
106 u8 hwq = (queue >> 2) & 0x1f;
107
108 if (unlikely(!priv->mac80211_registered))
109 return;
110
111 if (!test_and_set_bit(hwq, priv->queue_stopped))
112 if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0)
113 ieee80211_stop_queue(priv->hw, ac);
114}
115
116#ifdef ieee80211_stop_queue
117#undef ieee80211_stop_queue
118#endif
119
120#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
121
122#ifdef ieee80211_wake_queue
123#undef ieee80211_wake_queue
124#endif
125
126#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
127
128static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) 67static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
129{ 68{
130 IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); 69 IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h
index 17a02a76f8b..8b8cd54a32e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-shared.h
+++ b/drivers/net/wireless/iwlwifi/iwl-shared.h
@@ -243,6 +243,12 @@ struct iwl_shared {
243 spinlock_t sta_lock; 243 spinlock_t sta_lock;
244 struct mutex mutex; 244 struct mutex mutex;
245 245
246 /*these 2 shouldn't really be here, but they are needed for
247 * iwl_queue_stop, which is called from the upper layer too
248 */
249 u8 mac80211_registered;
250 struct ieee80211_hw *hw;
251
246 struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; 252 struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
247}; 253};
248 254
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
index abb2ce68dee..255b326bf0e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
@@ -240,4 +240,65 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
240 iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask); 240 iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask);
241} 241}
242 242
243/*
244 * we have 8 bits used like this:
245 *
246 * 7 6 5 4 3 2 1 0
247 * | | | | | | | |
248 * | | | | | | +-+-------- AC queue (0-3)
249 * | | | | | |
250 * | +-+-+-+-+------------ HW queue ID
251 * |
252 * +---------------------- unused
253 */
254static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
255{
256 BUG_ON(ac > 3); /* only have 2 bits */
257 BUG_ON(hwq > 31); /* only use 5 bits */
258
259 txq->swq_id = (hwq << 2) | ac;
260}
261
262static inline void iwl_wake_queue(struct iwl_trans *trans,
263 struct iwl_tx_queue *txq)
264{
265 u8 queue = txq->swq_id;
266 u8 ac = queue & 3;
267 u8 hwq = (queue >> 2) & 0x1f;
268
269 if (unlikely(!trans->shrd->mac80211_registered))
270 return;
271
272 if (test_and_clear_bit(hwq, priv(trans)->queue_stopped))
273 if (atomic_dec_return(&priv(trans)->queue_stop_count[ac]) <= 0)
274 ieee80211_wake_queue(trans->shrd->hw, ac);
275}
276
277static inline void iwl_stop_queue(struct iwl_trans *trans,
278 struct iwl_tx_queue *txq)
279{
280 u8 queue = txq->swq_id;
281 u8 ac = queue & 3;
282 u8 hwq = (queue >> 2) & 0x1f;
283
284 if (unlikely(!trans->shrd->mac80211_registered))
285 return;
286
287 if (!test_and_set_bit(hwq, priv(trans)->queue_stopped))
288 if (atomic_inc_return(&priv(trans)->queue_stop_count[ac]) > 0)
289 ieee80211_stop_queue(trans->shrd->hw, ac);
290}
291
292#ifdef ieee80211_stop_queue
293#undef ieee80211_stop_queue
294#endif
295
296#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
297
298#ifdef ieee80211_wake_queue
299#undef ieee80211_wake_queue
300#endif
301
302#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
303
243#endif /* __iwl_trans_int_pcie_h__ */ 304#endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index 646170400e1..cce57d53f61 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -1228,7 +1228,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
1228 txq->need_update = 1; 1228 txq->need_update = 1;
1229 iwl_txq_update_write_ptr(trans, txq); 1229 iwl_txq_update_write_ptr(trans, txq);
1230 } else { 1230 } else {
1231 iwl_stop_queue(priv(trans), txq); 1231 iwl_stop_queue(trans, txq);
1232 } 1232 }
1233 } 1233 }
1234 return 0; 1234 return 0;
@@ -1286,7 +1286,7 @@ static int iwlagn_txq_check_empty(struct iwl_trans *trans,
1286 iwl_stop_tx_ba_trans_ready(priv(trans), 1286 iwl_stop_tx_ba_trans_ready(priv(trans),
1287 NUM_IWL_RXON_CTX, 1287 NUM_IWL_RXON_CTX,
1288 sta_id, tid); 1288 sta_id, tid);
1289 iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]); 1289 iwl_wake_queue(trans, &priv(trans)->txq[txq_id]);
1290 } 1290 }
1291 break; 1291 break;
1292 case IWL_EMPTYING_HW_QUEUE_ADDBA: 1292 case IWL_EMPTYING_HW_QUEUE_ADDBA:
@@ -1345,7 +1345,7 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
1345 ssn , tfd_num, txq_id, txq->swq_id); 1345 ssn , tfd_num, txq_id, txq->swq_id);
1346 freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); 1346 freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
1347 if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond) 1347 if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
1348 iwl_wake_queue(priv(trans), txq); 1348 iwl_wake_queue(trans, txq);
1349 } 1349 }
1350 1350
1351 iwl_free_tfds_in_queue(trans, sta_id, tid, freed); 1351 iwl_free_tfds_in_queue(trans, sta_id, tid, freed);
@@ -1423,7 +1423,7 @@ static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans,
1423 ac, 1423 ac,
1424 (atomic_read(&priv(trans)->queue_stop_count[ac]) > 0) 1424 (atomic_read(&priv(trans)->queue_stop_count[ac]) > 0)
1425 ? "stopped" : "awake"); 1425 ? "stopped" : "awake");
1426 iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]); 1426 iwl_wake_queue(trans, &priv(trans)->txq[txq_id]);
1427 } 1427 }
1428} 1428}
1429 1429
@@ -1446,6 +1446,11 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd)
1446 return iwl_trans; 1446 return iwl_trans;
1447} 1447}
1448 1448
1449static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id)
1450{
1451 iwl_stop_queue(trans, &priv(trans)->txq[txq_id]);
1452}
1453
1449#define IWL_FLUSH_WAIT_MS 2000 1454#define IWL_FLUSH_WAIT_MS 2000
1450 1455
1451static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) 1456static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
@@ -2078,6 +2083,7 @@ const struct iwl_trans_ops trans_ops_pcie = {
2078 .kick_nic = iwl_trans_pcie_kick_nic, 2083 .kick_nic = iwl_trans_pcie_kick_nic,
2079 2084
2080 .free = iwl_trans_pcie_free, 2085 .free = iwl_trans_pcie_free,
2086 .stop_queue = iwl_trans_pcie_stop_queue,
2081 2087
2082 .dbgfs_register = iwl_trans_pcie_dbgfs_register, 2088 .dbgfs_register = iwl_trans_pcie_dbgfs_register,
2083 2089
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 6edf2e0dada..7a2daa886df 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -101,6 +101,7 @@ struct iwl_device_cmd;
101 * @kick_nic: remove the RESET from the embedded CPU and let it run 101 * @kick_nic: remove the RESET from the embedded CPU and let it run
102 * @free: release all the ressource for the transport layer itself such as 102 * @free: release all the ressource for the transport layer itself such as
103 * irq, tasklet etc... 103 * irq, tasklet etc...
104 * @stop_queue: stop a specific queue
104 * @check_stuck_queue: check if a specific queue is stuck 105 * @check_stuck_queue: check if a specific queue is stuck
105 * @wait_tx_queue_empty: wait until all tx queues are empty 106 * @wait_tx_queue_empty: wait until all tx queues are empty
106 * @dbgfs_register: add the dbgfs files under this directory. Files will be 107 * @dbgfs_register: add the dbgfs files under this directory. Files will be
@@ -143,6 +144,8 @@ struct iwl_trans_ops {
143 144
144 void (*free)(struct iwl_trans *trans); 145 void (*free)(struct iwl_trans *trans);
145 146
147 void (*stop_queue)(struct iwl_trans *trans, int q);
148
146 int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); 149 int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
147 int (*check_stuck_queue)(struct iwl_trans *trans, int q); 150 int (*check_stuck_queue)(struct iwl_trans *trans, int q);
148 int (*wait_tx_queue_empty)(struct iwl_trans *trans); 151 int (*wait_tx_queue_empty)(struct iwl_trans *trans);
@@ -256,6 +259,11 @@ static inline void iwl_trans_free(struct iwl_trans *trans)
256 trans->ops->free(trans); 259 trans->ops->free(trans);
257} 260}
258 261
262static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q)
263{
264 trans->ops->stop_queue(trans, q);
265}
266
259static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) 267static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
260{ 268{
261 return trans->ops->wait_tx_queue_empty(trans); 269 return trans->ops->wait_tx_queue_empty(trans);