aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-12-27 15:43:48 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-05 08:39:12 -0500
commit2bfb50924c7e92362ac937aef2ab56bc7bd3ca52 (patch)
tree26518070c19eb9cfb38ab48cda31fe16c1235433
parentc9f7a8ab7792b48259af6e94706a5d02dd74caef (diff)
iwlwifi: use threaded interrupt handler
With new transports coming up, move to threaded interrupt handling now. This has the advantage that we can use the same locking scheme with all different transports we may need to implement. Note that the TX path obviously still runs in a tasklet, so some spin_lock() calls need to change to spin_lock_bh() calls to properly lock out the TX path. In my test on a Calpella platform this has no impact on throughput or latency. Also add lockdep annotations to avoid lockups due to catch sending synchronous commands or using locks that connect with them from the irq thread. Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/sta.c4
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-op-mode.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h29
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c12
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h3
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c40
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c11
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c8
11 files changed, 85 insertions, 52 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c
index e8d5b90abf5c..a4eed2055fdb 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rx.c
@@ -790,7 +790,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
790 790
791 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); 791 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
792 792
793 ieee80211_rx(priv->hw, skb); 793 ieee80211_rx_ni(priv->hw, skb);
794} 794}
795 795
796static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) 796static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c
index ab768045696b..2d33760a9dc2 100644
--- a/drivers/net/wireless/iwlwifi/dvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/dvm/sta.c
@@ -77,7 +77,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
77 IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", 77 IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
78 sta_id); 78 sta_id);
79 79
80 spin_lock(&priv->sta_lock); 80 spin_lock_bh(&priv->sta_lock);
81 81
82 switch (add_sta_resp->status) { 82 switch (add_sta_resp->status) {
83 case ADD_STA_SUCCESS_MSK: 83 case ADD_STA_SUCCESS_MSK:
@@ -119,7 +119,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
119 priv->stations[sta_id].sta.mode == 119 priv->stations[sta_id].sta.mode ==
120 STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", 120 STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
121 addsta->sta.addr); 121 addsta->sta.addr);
122 spin_unlock(&priv->sta_lock); 122 spin_unlock_bh(&priv->sta_lock);
123 123
124 return ret; 124 return ret;
125} 125}
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 7b0550d35a91..4ece5ea81b86 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -1117,7 +1117,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
1117 sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> 1117 sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
1118 IWLAGN_TX_RES_RA_POS; 1118 IWLAGN_TX_RES_RA_POS;
1119 1119
1120 spin_lock(&priv->sta_lock); 1120 spin_lock_bh(&priv->sta_lock);
1121 1121
1122 if (is_agg) 1122 if (is_agg)
1123 iwl_rx_reply_tx_agg(priv, tx_resp); 1123 iwl_rx_reply_tx_agg(priv, tx_resp);
@@ -1239,11 +1239,11 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
1239 le16_to_cpu(tx_resp->seq_ctl)); 1239 le16_to_cpu(tx_resp->seq_ctl));
1240 1240
1241 iwl_check_abort_status(priv, tx_resp->frame_count, status); 1241 iwl_check_abort_status(priv, tx_resp->frame_count, status);
1242 spin_unlock(&priv->sta_lock); 1242 spin_unlock_bh(&priv->sta_lock);
1243 1243
1244 while (!skb_queue_empty(&skbs)) { 1244 while (!skb_queue_empty(&skbs)) {
1245 skb = __skb_dequeue(&skbs); 1245 skb = __skb_dequeue(&skbs);
1246 ieee80211_tx_status(priv->hw, skb); 1246 ieee80211_tx_status_ni(priv->hw, skb);
1247 } 1247 }
1248 1248
1249 if (is_offchannel_skb) 1249 if (is_offchannel_skb)
@@ -1290,12 +1290,12 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1290 tid = ba_resp->tid; 1290 tid = ba_resp->tid;
1291 agg = &priv->tid_data[sta_id][tid].agg; 1291 agg = &priv->tid_data[sta_id][tid].agg;
1292 1292
1293 spin_lock(&priv->sta_lock); 1293 spin_lock_bh(&priv->sta_lock);
1294 1294
1295 if (unlikely(!agg->wait_for_ba)) { 1295 if (unlikely(!agg->wait_for_ba)) {
1296 if (unlikely(ba_resp->bitmap)) 1296 if (unlikely(ba_resp->bitmap))
1297 IWL_ERR(priv, "Received BA when not expected\n"); 1297 IWL_ERR(priv, "Received BA when not expected\n");
1298 spin_unlock(&priv->sta_lock); 1298 spin_unlock_bh(&priv->sta_lock);
1299 return 0; 1299 return 0;
1300 } 1300 }
1301 1301
@@ -1309,7 +1309,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1309 IWL_DEBUG_TX_QUEUES(priv, 1309 IWL_DEBUG_TX_QUEUES(priv,
1310 "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n", 1310 "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n",
1311 scd_flow, sta_id, tid, agg->txq_id); 1311 scd_flow, sta_id, tid, agg->txq_id);
1312 spin_unlock(&priv->sta_lock); 1312 spin_unlock_bh(&priv->sta_lock);
1313 return 0; 1313 return 0;
1314 } 1314 }
1315 1315
@@ -1378,11 +1378,11 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1378 } 1378 }
1379 } 1379 }
1380 1380
1381 spin_unlock(&priv->sta_lock); 1381 spin_unlock_bh(&priv->sta_lock);
1382 1382
1383 while (!skb_queue_empty(&reclaimed_skbs)) { 1383 while (!skb_queue_empty(&reclaimed_skbs)) {
1384 skb = __skb_dequeue(&reclaimed_skbs); 1384 skb = __skb_dequeue(&reclaimed_skbs);
1385 ieee80211_tx_status(priv->hw, skb); 1385 ieee80211_tx_status_ni(priv->hw, skb);
1386 } 1386 }
1387 1387
1388 return 0; 1388 return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index dc792584f401..4a680019e117 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -113,13 +113,13 @@ struct iwl_cfg;
113 * May sleep 113 * May sleep
114 * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the 114 * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
115 * HCMD the this Rx responds to. 115 * HCMD the this Rx responds to.
116 * Must be atomic and called with BH disabled. 116 * This callback may sleep, it is called from a threaded IRQ handler.
117 * @queue_full: notifies that a HW queue is full. 117 * @queue_full: notifies that a HW queue is full.
118 * Must be atomic and called with BH disabled. 118 * Must be atomic and called with BH disabled.
119 * @queue_not_full: notifies that a HW queue is not full any more. 119 * @queue_not_full: notifies that a HW queue is not full any more.
120 * Must be atomic and called with BH disabled. 120 * Must be atomic and called with BH disabled.
121 * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that 121 * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that
122 * the radio is killed. Must be atomic. 122 * the radio is killed. May sleep.
123 * @free_skb: allows the transport layer to free skbs that haven't been 123 * @free_skb: allows the transport layer to free skbs that haven't been
124 * reclaimed by the op_mode. This can happen when the driver is freed and 124 * reclaimed by the op_mode. This can happen when the driver is freed and
125 * there are Tx packets pending in the transport layer. 125 * there are Tx packets pending in the transport layer.
@@ -130,8 +130,7 @@ struct iwl_cfg;
130 * called with BH disabled. 130 * called with BH disabled.
131 * @nic_config: configure NIC, called before firmware is started. 131 * @nic_config: configure NIC, called before firmware is started.
132 * May sleep 132 * May sleep
133 * @wimax_active: invoked when WiMax becomes active. Must be atomic and called 133 * @wimax_active: invoked when WiMax becomes active. May sleep
134 * with BH disabled.
135 */ 134 */
136struct iwl_op_mode_ops { 135struct iwl_op_mode_ops {
137 struct iwl_op_mode *(*start)(struct iwl_trans *trans, 136 struct iwl_op_mode *(*start)(struct iwl_trans *trans,
@@ -178,6 +177,7 @@ static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode,
178 struct iwl_rx_cmd_buffer *rxb, 177 struct iwl_rx_cmd_buffer *rxb,
179 struct iwl_device_cmd *cmd) 178 struct iwl_device_cmd *cmd)
180{ 179{
180 might_sleep();
181 return op_mode->ops->rx(op_mode, rxb, cmd); 181 return op_mode->ops->rx(op_mode, rxb, cmd);
182} 182}
183 183
@@ -196,6 +196,7 @@ static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode,
196static inline void iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, 196static inline void iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode,
197 bool state) 197 bool state)
198{ 198{
199 might_sleep();
199 op_mode->ops->hw_rf_kill(op_mode, state); 200 op_mode->ops->hw_rf_kill(op_mode, state);
200} 201}
201 202
@@ -223,6 +224,7 @@ static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)
223 224
224static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode) 225static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode)
225{ 226{
227 might_sleep();
226 op_mode->ops->wimax_active(op_mode); 228 op_mode->ops->wimax_active(op_mode);
227} 229}
228 230
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 0a3d4df5f434..8c7bec6b9a0b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -65,6 +65,7 @@
65 65
66#include <linux/ieee80211.h> 66#include <linux/ieee80211.h>
67#include <linux/mm.h> /* for page_address */ 67#include <linux/mm.h> /* for page_address */
68#include <linux/lockdep.h>
68 69
69#include "iwl-debug.h" 70#include "iwl-debug.h"
70#include "iwl-config.h" 71#include "iwl-config.h"
@@ -526,6 +527,10 @@ struct iwl_trans {
526 527
527 struct dentry *dbgfs_dir; 528 struct dentry *dbgfs_dir;
528 529
530#ifdef CONFIG_LOCKDEP
531 struct lockdep_map sync_cmd_lockdep_map;
532#endif
533
529 /* pointer to trans specific struct */ 534 /* pointer to trans specific struct */
530 /*Ensure that this pointer will always be aligned to sizeof pointer */ 535 /*Ensure that this pointer will always be aligned to sizeof pointer */
531 char trans_specific[0] __aligned(sizeof(void *)); 536 char trans_specific[0] __aligned(sizeof(void *));
@@ -602,12 +607,22 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
602} 607}
603 608
604static inline int iwl_trans_send_cmd(struct iwl_trans *trans, 609static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
605 struct iwl_host_cmd *cmd) 610 struct iwl_host_cmd *cmd)
606{ 611{
612 int ret;
613
607 WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, 614 WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
608 "%s bad state = %d", __func__, trans->state); 615 "%s bad state = %d", __func__, trans->state);
609 616
610 return trans->ops->send_cmd(trans, cmd); 617 if (!(cmd->flags & CMD_ASYNC))
618 lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
619
620 ret = trans->ops->send_cmd(trans, cmd);
621
622 if (!(cmd->flags & CMD_ASYNC))
623 lock_map_release(&trans->sync_cmd_lockdep_map);
624
625 return ret;
611} 626}
612 627
613static inline struct iwl_device_cmd * 628static inline struct iwl_device_cmd *
@@ -791,4 +806,14 @@ iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags)
791int __must_check iwl_pci_register_driver(void); 806int __must_check iwl_pci_register_driver(void);
792void iwl_pci_unregister_driver(void); 807void iwl_pci_unregister_driver(void);
793 808
809static inline void trans_lockdep_init(struct iwl_trans *trans)
810{
811#ifdef CONFIG_LOCKDEP
812 static struct lock_class_key __key;
813
814 lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map",
815 &__key, 0);
816#endif
817}
818
794#endif /* __iwl_trans_h__ */ 819#endif /* __iwl_trans_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index 52da375e5740..3f3ce91ad5c2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -121,7 +121,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
121 121
122 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); 122 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
123 123
124 ieee80211_rx(mvm->hw, skb); 124 ieee80211_rx_ni(mvm->hw, skb);
125} 125}
126 126
127/* 127/*
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index cada8efe0cca..6b67ce3f679c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -620,7 +620,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
620 seq_ctl = le16_to_cpu(hdr->seq_ctrl); 620 seq_ctl = le16_to_cpu(hdr->seq_ctrl);
621 } 621 }
622 622
623 ieee80211_tx_status(mvm->hw, skb); 623 ieee80211_tx_status_ni(mvm->hw, skb);
624 } 624 }
625 625
626 if (txq_id >= IWL_FIRST_AMPDU_QUEUE) { 626 if (txq_id >= IWL_FIRST_AMPDU_QUEUE) {
@@ -663,12 +663,12 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
663 struct iwl_mvm_tid_data *tid_data = 663 struct iwl_mvm_tid_data *tid_data =
664 &mvmsta->tid_data[tid]; 664 &mvmsta->tid_data[tid];
665 665
666 spin_lock(&mvmsta->lock); 666 spin_lock_bh(&mvmsta->lock);
667 tid_data->next_reclaimed = next_reclaimed; 667 tid_data->next_reclaimed = next_reclaimed;
668 IWL_DEBUG_TX_REPLY(mvm, "Next reclaimed packet:%d\n", 668 IWL_DEBUG_TX_REPLY(mvm, "Next reclaimed packet:%d\n",
669 next_reclaimed); 669 next_reclaimed);
670 iwl_mvm_check_ratid_empty(mvm, sta, tid); 670 iwl_mvm_check_ratid_empty(mvm, sta, tid);
671 spin_unlock(&mvmsta->lock); 671 spin_unlock_bh(&mvmsta->lock);
672 } 672 }
673 673
674#ifdef CONFIG_PM_SLEEP 674#ifdef CONFIG_PM_SLEEP
@@ -832,7 +832,7 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
832 return 0; 832 return 0;
833 } 833 }
834 834
835 spin_lock(&mvmsta->lock); 835 spin_lock_bh(&mvmsta->lock);
836 836
837 __skb_queue_head_init(&reclaimed_skbs); 837 __skb_queue_head_init(&reclaimed_skbs);
838 838
@@ -886,13 +886,13 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
886 } 886 }
887 } 887 }
888 888
889 spin_unlock(&mvmsta->lock); 889 spin_unlock_bh(&mvmsta->lock);
890 890
891 rcu_read_unlock(); 891 rcu_read_unlock();
892 892
893 while (!skb_queue_empty(&reclaimed_skbs)) { 893 while (!skb_queue_empty(&reclaimed_skbs)) {
894 skb = __skb_dequeue(&reclaimed_skbs); 894 skb = __skb_dequeue(&reclaimed_skbs);
895 ieee80211_tx_status(mvm->hw, skb); 895 ieee80211_tx_status_ni(mvm->hw, skb);
896 } 896 }
897 897
898 return 0; 898 return 0;
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 5f6bb4e09d42..aa2a39a637dd 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -249,7 +249,6 @@ struct iwl_trans_pcie {
249 int ict_index; 249 int ict_index;
250 u32 inta; 250 u32 inta;
251 bool use_ict; 251 bool use_ict;
252 struct tasklet_struct irq_tasklet;
253 struct isr_statistics isr_stats; 252 struct isr_statistics isr_stats;
254 253
255 spinlock_t irq_lock; 254 spinlock_t irq_lock;
@@ -330,7 +329,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans);
330* RX 329* RX
331******************************************************/ 330******************************************************/
332int iwl_pcie_rx_init(struct iwl_trans *trans); 331int iwl_pcie_rx_init(struct iwl_trans *trans);
333void iwl_pcie_tasklet(struct iwl_trans *trans); 332irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id);
334int iwl_pcie_rx_stop(struct iwl_trans *trans); 333int iwl_pcie_rx_stop(struct iwl_trans *trans);
335void iwl_pcie_rx_free(struct iwl_trans *trans); 334void iwl_pcie_rx_free(struct iwl_trans *trans);
336 335
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index a9ca1d35fa93..b0ae06d2456f 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -81,10 +81,10 @@
81 * 'processed' and 'read' driver indexes as well) 81 * 'processed' and 'read' driver indexes as well)
82 * + A received packet is processed and handed to the kernel network stack, 82 * + A received packet is processed and handed to the kernel network stack,
83 * detached from the iwl->rxq. The driver 'processed' index is updated. 83 * detached from the iwl->rxq. The driver 'processed' index is updated.
84 * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free 84 * + The Host/Firmware iwl->rxq is replenished at irq thread time from the
85 * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ 85 * rx_free list. If there are no allocated buffers in iwl->rxq->rx_free,
86 * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there 86 * the READ INDEX is not incremented and iwl->status(RX_STALLED) is set.
87 * were enough free buffers and RX_STALLED is set it is cleared. 87 * If there were enough free buffers and RX_STALLED is set it is cleared.
88 * 88 *
89 * 89 *
90 * Driver sequence: 90 * Driver sequence:
@@ -214,9 +214,9 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
214 /* 214 /*
215 * If the device isn't enabled - not need to try to add buffers... 215 * If the device isn't enabled - not need to try to add buffers...
216 * This can happen when we stop the device and still have an interrupt 216 * This can happen when we stop the device and still have an interrupt
217 * pending. We stop the APM before we sync the interrupts / tasklets 217 * pending. We stop the APM before we sync the interrupts because we
218 * because we have to (see comment there). On the other hand, since 218 * have to (see comment there). On the other hand, since the APM is
219 * the APM is stopped, we cannot access the HW (in particular not prph). 219 * stopped, we cannot access the HW (in particular not prph).
220 * So don't try to restock if the APM has been already stopped. 220 * So don't try to restock if the APM has been already stopped.
221 */ 221 */
222 if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) 222 if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status))
@@ -796,11 +796,14 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
796 clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); 796 clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
797 wake_up(&trans_pcie->wait_command_queue); 797 wake_up(&trans_pcie->wait_command_queue);
798 798
799 local_bh_disable();
799 iwl_op_mode_nic_error(trans->op_mode); 800 iwl_op_mode_nic_error(trans->op_mode);
801 local_bh_enable();
800} 802}
801 803
802void iwl_pcie_tasklet(struct iwl_trans *trans) 804irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
803{ 805{
806 struct iwl_trans *trans = dev_id;
804 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 807 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
805 struct isr_statistics *isr_stats = &trans_pcie->isr_stats; 808 struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
806 u32 inta = 0; 809 u32 inta = 0;
@@ -811,6 +814,8 @@ void iwl_pcie_tasklet(struct iwl_trans *trans)
811 u32 inta_mask; 814 u32 inta_mask;
812#endif 815#endif
813 816
817 lock_map_acquire(&trans->sync_cmd_lockdep_map);
818
814 spin_lock_irqsave(&trans_pcie->irq_lock, flags); 819 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
815 820
816 /* Ack/clear/reset pending uCode interrupts. 821 /* Ack/clear/reset pending uCode interrupts.
@@ -855,7 +860,7 @@ void iwl_pcie_tasklet(struct iwl_trans *trans)
855 860
856 handled |= CSR_INT_BIT_HW_ERR; 861 handled |= CSR_INT_BIT_HW_ERR;
857 862
858 return; 863 goto out;
859 } 864 }
860 865
861#ifdef CONFIG_IWLWIFI_DEBUG 866#ifdef CONFIG_IWLWIFI_DEBUG
@@ -1005,6 +1010,10 @@ void iwl_pcie_tasklet(struct iwl_trans *trans)
1005 /* Re-enable RF_KILL if it occurred */ 1010 /* Re-enable RF_KILL if it occurred */
1006 else if (handled & CSR_INT_BIT_RF_KILL) 1011 else if (handled & CSR_INT_BIT_RF_KILL)
1007 iwl_enable_rfkill_int(trans); 1012 iwl_enable_rfkill_int(trans);
1013
1014out:
1015 lock_map_release(&trans->sync_cmd_lockdep_map);
1016 return IRQ_HANDLED;
1008} 1017}
1009 1018
1010/****************************************************************************** 1019/******************************************************************************
@@ -1127,7 +1136,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
1127 1136
1128 /* Disable (but don't clear!) interrupts here to avoid 1137 /* Disable (but don't clear!) interrupts here to avoid
1129 * back-to-back ISRs and sporadic interrupts from our NIC. 1138 * back-to-back ISRs and sporadic interrupts from our NIC.
1130 * If we have something to service, the tasklet will re-enable ints. 1139 * If we have something to service, the irq thread will re-enable ints.
1131 * If we *don't* have something, we'll re-enable before leaving here. */ 1140 * If we *don't* have something, we'll re-enable before leaving here. */
1132 inta_mask = iwl_read32(trans, CSR_INT_MASK); 1141 inta_mask = iwl_read32(trans, CSR_INT_MASK);
1133 iwl_write32(trans, CSR_INT_MASK, 0x00000000); 1142 iwl_write32(trans, CSR_INT_MASK, 0x00000000);
@@ -1167,9 +1176,9 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
1167#endif 1176#endif
1168 1177
1169 trans_pcie->inta |= inta; 1178 trans_pcie->inta |= inta;
1170 /* iwl_pcie_tasklet() will service interrupts and re-enable them */ 1179 /* the thread will service interrupts and re-enable them */
1171 if (likely(inta)) 1180 if (likely(inta))
1172 tasklet_schedule(&trans_pcie->irq_tasklet); 1181 return IRQ_WAKE_THREAD;
1173 else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && 1182 else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
1174 !trans_pcie->inta) 1183 !trans_pcie->inta)
1175 iwl_enable_interrupts(trans); 1184 iwl_enable_interrupts(trans);
@@ -1277,9 +1286,10 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
1277 trans_pcie->inta |= inta; 1286 trans_pcie->inta |= inta;
1278 1287
1279 /* iwl_pcie_tasklet() will service interrupts and re-enable them */ 1288 /* iwl_pcie_tasklet() will service interrupts and re-enable them */
1280 if (likely(inta)) 1289 if (likely(inta)) {
1281 tasklet_schedule(&trans_pcie->irq_tasklet); 1290 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1282 else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && 1291 return IRQ_WAKE_THREAD;
1292 } else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
1283 !trans_pcie->inta) { 1293 !trans_pcie->inta) {
1284 /* Allow interrupt if was disabled by this handler and 1294 /* Allow interrupt if was disabled by this handler and
1285 * no tasklet was schedules, We should not enable interrupt, 1295 * no tasklet was schedules, We should not enable interrupt,
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 56d4f72500bc..17bedc50e753 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -760,7 +760,6 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
760 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 760 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
761 761
762 synchronize_irq(trans_pcie->pci_dev->irq); 762 synchronize_irq(trans_pcie->pci_dev->irq);
763 tasklet_kill(&trans_pcie->irq_tasklet);
764 763
765 iwl_pcie_tx_free(trans); 764 iwl_pcie_tx_free(trans);
766 iwl_pcie_rx_free(trans); 765 iwl_pcie_rx_free(trans);
@@ -1480,6 +1479,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
1480 1479
1481 trans->ops = &trans_ops_pcie; 1480 trans->ops = &trans_ops_pcie;
1482 trans->cfg = cfg; 1481 trans->cfg = cfg;
1482 trans_lockdep_init(trans);
1483 trans_pcie->trans = trans; 1483 trans_pcie->trans = trans;
1484 spin_lock_init(&trans_pcie->irq_lock); 1484 spin_lock_init(&trans_pcie->irq_lock);
1485 spin_lock_init(&trans_pcie->reg_lock); 1485 spin_lock_init(&trans_pcie->reg_lock);
@@ -1567,15 +1567,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
1567 1567
1568 trans_pcie->inta_mask = CSR_INI_SET_MASK; 1568 trans_pcie->inta_mask = CSR_INI_SET_MASK;
1569 1569
1570 tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long))
1571 iwl_pcie_tasklet, (unsigned long)trans);
1572
1573 if (iwl_pcie_alloc_ict(trans)) 1570 if (iwl_pcie_alloc_ict(trans))
1574 goto out_free_cmd_pool; 1571 goto out_free_cmd_pool;
1575 1572
1576 err = request_irq(pdev->irq, iwl_pcie_isr_ict, 1573 if (request_threaded_irq(pdev->irq, iwl_pcie_isr_ict,
1577 IRQF_SHARED, DRV_NAME, trans); 1574 iwl_pcie_irq_handler,
1578 if (err) { 1575 IRQF_SHARED, DRV_NAME, trans)) {
1579 IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq); 1576 IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq);
1580 goto out_free_ict; 1577 goto out_free_ict;
1581 } 1578 }
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 041127ad372a..8e9e3212fe78 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -926,7 +926,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
926 if (WARN_ON(txq_id == trans_pcie->cmd_queue)) 926 if (WARN_ON(txq_id == trans_pcie->cmd_queue))
927 return; 927 return;
928 928
929 spin_lock(&txq->lock); 929 spin_lock_bh(&txq->lock);
930 930
931 if (txq->q.read_ptr == tfd_num) 931 if (txq->q.read_ptr == tfd_num)
932 goto out; 932 goto out;
@@ -970,7 +970,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
970 if (iwl_queue_space(&txq->q) > txq->q.low_mark) 970 if (iwl_queue_space(&txq->q) > txq->q.low_mark)
971 iwl_wake_queue(trans, txq); 971 iwl_wake_queue(trans, txq);
972out: 972out:
973 spin_unlock(&txq->lock); 973 spin_unlock_bh(&txq->lock);
974} 974}
975 975
976/* 976/*
@@ -1371,7 +1371,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
1371 return; 1371 return;
1372 } 1372 }
1373 1373
1374 spin_lock(&txq->lock); 1374 spin_lock_bh(&txq->lock);
1375 1375
1376 cmd_index = get_cmd_index(&txq->q, index); 1376 cmd_index = get_cmd_index(&txq->q, index);
1377 cmd = txq->entries[cmd_index].cmd; 1377 cmd = txq->entries[cmd_index].cmd;
@@ -1405,7 +1405,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
1405 1405
1406 meta->flags = 0; 1406 meta->flags = 0;
1407 1407
1408 spin_unlock(&txq->lock); 1408 spin_unlock_bh(&txq->lock);
1409} 1409}
1410 1410
1411#define HOST_COMPLETE_TIMEOUT (2 * HZ) 1411#define HOST_COMPLETE_TIMEOUT (2 * HZ)