aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlegacy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlegacy')
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-lib.c3
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-core.c20
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-core.h1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-dev.h4
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-hcmd.c4
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-helpers.h6
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-tx.c52
-rw-r--r--drivers/net/wireless/iwlegacy/iwl3945-base.c22
-rw-r--r--drivers/net/wireless/iwlegacy/iwl4965-base.c45
9 files changed, 82 insertions, 75 deletions
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
index 5a8a3cce27bc..7e5e85a017b5 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
@@ -955,9 +955,6 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
955 if (priv->cfg->scan_rx_antennas[band]) 955 if (priv->cfg->scan_rx_antennas[band])
956 rx_ant = priv->cfg->scan_rx_antennas[band]; 956 rx_ant = priv->cfg->scan_rx_antennas[band];
957 957
958 if (priv->cfg->scan_tx_antennas[band])
959 scan_tx_antennas = priv->cfg->scan_tx_antennas[band];
960
961 priv->scan_tx_ant[band] = iwl4965_toggle_tx_ant(priv, 958 priv->scan_tx_ant[band] = iwl4965_toggle_tx_ant(priv,
962 priv->scan_tx_ant[band], 959 priv->scan_tx_ant[band],
963 scan_tx_antennas); 960 scan_tx_antennas);
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
index c1511b14b239..d743373a9424 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.c
+++ b/drivers/net/wireless/iwlegacy/iwl-core.c
@@ -211,10 +211,7 @@ int iwl_legacy_init_geos(struct iwl_priv *priv)
211 if (!iwl_legacy_is_channel_valid(ch)) 211 if (!iwl_legacy_is_channel_valid(ch))
212 continue; 212 continue;
213 213
214 if (iwl_legacy_is_channel_a_band(ch)) 214 sband = &priv->bands[ch->band];
215 sband = &priv->bands[IEEE80211_BAND_5GHZ];
216 else
217 sband = &priv->bands[IEEE80211_BAND_2GHZ];
218 215
219 geo_ch = &sband->channels[sband->n_channels++]; 216 geo_ch = &sband->channels[sband->n_channels++];
220 217
@@ -2117,10 +2114,9 @@ int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
2117 IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", 2114 IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
2118 channel->hw_value, changed); 2115 channel->hw_value, changed);
2119 2116
2120 if (unlikely(!priv->cfg->mod_params->disable_hw_scan && 2117 if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
2121 test_bit(STATUS_SCANNING, &priv->status))) {
2122 scan_active = 1; 2118 scan_active = 1;
2123 IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); 2119 IWL_DEBUG_MAC80211(priv, "scan active\n");
2124 } 2120 }
2125 2121
2126 if (changed & (IEEE80211_CONF_CHANGE_SMPS | 2122 if (changed & (IEEE80211_CONF_CHANGE_SMPS |
@@ -2433,11 +2429,13 @@ void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
2433 2429
2434 IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); 2430 IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
2435 2431
2436 if (!iwl_legacy_is_alive(priv))
2437 return;
2438
2439 mutex_lock(&priv->mutex); 2432 mutex_lock(&priv->mutex);
2440 2433
2434 if (!iwl_legacy_is_alive(priv)) {
2435 mutex_unlock(&priv->mutex);
2436 return;
2437 }
2438
2441 if (changes & BSS_CHANGED_QOS) { 2439 if (changes & BSS_CHANGED_QOS) {
2442 unsigned long flags; 2440 unsigned long flags;
2443 2441
@@ -2646,7 +2644,7 @@ unplugged:
2646 2644
2647none: 2645none:
2648 /* re-enable interrupts here since we don't have anything to service. */ 2646 /* re-enable interrupts here since we don't have anything to service. */
2649 /* only Re-enable if diabled by irq */ 2647 /* only Re-enable if disabled by irq */
2650 if (test_bit(STATUS_INT_ENABLED, &priv->status)) 2648 if (test_bit(STATUS_INT_ENABLED, &priv->status))
2651 iwl_legacy_enable_interrupts(priv); 2649 iwl_legacy_enable_interrupts(priv);
2652 spin_unlock_irqrestore(&priv->lock, flags); 2650 spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h
index f03b463e4378..bc66c604106c 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.h
+++ b/drivers/net/wireless/iwlegacy/iwl-core.h
@@ -287,7 +287,6 @@ struct iwl_cfg {
287 struct iwl_base_params *base_params; 287 struct iwl_base_params *base_params;
288 /* params likely to change within a device family */ 288 /* params likely to change within a device family */
289 u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; 289 u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
290 u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
291 enum iwl_led_mode led_mode; 290 enum iwl_led_mode led_mode;
292}; 291};
293 292
diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h
index 9ee849d669f3..2d87dba2cfa3 100644
--- a/drivers/net/wireless/iwlegacy/iwl-dev.h
+++ b/drivers/net/wireless/iwlegacy/iwl-dev.h
@@ -134,7 +134,7 @@ struct iwl_queue {
134 * space more than this */ 134 * space more than this */
135 int high_mark; /* high watermark, stop queue if free 135 int high_mark; /* high watermark, stop queue if free
136 * space less than this */ 136 * space less than this */
137} __packed; 137};
138 138
139/* One for each TFD */ 139/* One for each TFD */
140struct iwl_tx_info { 140struct iwl_tx_info {
@@ -290,6 +290,7 @@ enum {
290 CMD_SIZE_HUGE = (1 << 0), 290 CMD_SIZE_HUGE = (1 << 0),
291 CMD_ASYNC = (1 << 1), 291 CMD_ASYNC = (1 << 1),
292 CMD_WANT_SKB = (1 << 2), 292 CMD_WANT_SKB = (1 << 2),
293 CMD_MAPPED = (1 << 3),
293}; 294};
294 295
295#define DEF_CMD_PAYLOAD_SIZE 320 296#define DEF_CMD_PAYLOAD_SIZE 320
@@ -1076,7 +1077,6 @@ struct iwl_priv {
1076 spinlock_t hcmd_lock; /* protect hcmd */ 1077 spinlock_t hcmd_lock; /* protect hcmd */
1077 spinlock_t reg_lock; /* protect hw register access */ 1078 spinlock_t reg_lock; /* protect hw register access */
1078 struct mutex mutex; 1079 struct mutex mutex;
1079 struct mutex sync_cmd_mutex; /* enable serialization of sync commands */
1080 1080
1081 /* basic pci-network driver stuff */ 1081 /* basic pci-network driver stuff */
1082 struct pci_dev *pci_dev; 1082 struct pci_dev *pci_dev;
diff --git a/drivers/net/wireless/iwlegacy/iwl-hcmd.c b/drivers/net/wireless/iwlegacy/iwl-hcmd.c
index 9d721cbda5bb..62b4b09122cb 100644
--- a/drivers/net/wireless/iwlegacy/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlegacy/iwl-hcmd.c
@@ -145,6 +145,8 @@ int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
145 int cmd_idx; 145 int cmd_idx;
146 int ret; 146 int ret;
147 147
148 lockdep_assert_held(&priv->mutex);
149
148 BUG_ON(cmd->flags & CMD_ASYNC); 150 BUG_ON(cmd->flags & CMD_ASYNC);
149 151
150 /* A synchronous command can not have a callback set. */ 152 /* A synchronous command can not have a callback set. */
@@ -152,7 +154,6 @@ int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
152 154
153 IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", 155 IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
154 iwl_legacy_get_cmd_string(cmd->id)); 156 iwl_legacy_get_cmd_string(cmd->id));
155 mutex_lock(&priv->sync_cmd_mutex);
156 157
157 set_bit(STATUS_HCMD_ACTIVE, &priv->status); 158 set_bit(STATUS_HCMD_ACTIVE, &priv->status);
158 IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", 159 IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
@@ -224,7 +225,6 @@ fail:
224 cmd->reply_page = 0; 225 cmd->reply_page = 0;
225 } 226 }
226out: 227out:
227 mutex_unlock(&priv->sync_cmd_mutex);
228 return ret; 228 return ret;
229} 229}
230EXPORT_SYMBOL(iwl_legacy_send_cmd_sync); 230EXPORT_SYMBOL(iwl_legacy_send_cmd_sync);
diff --git a/drivers/net/wireless/iwlegacy/iwl-helpers.h b/drivers/net/wireless/iwlegacy/iwl-helpers.h
index 02132e755831..a6effdae63f9 100644
--- a/drivers/net/wireless/iwlegacy/iwl-helpers.h
+++ b/drivers/net/wireless/iwlegacy/iwl-helpers.h
@@ -149,6 +149,12 @@ static inline void iwl_legacy_disable_interrupts(struct iwl_priv *priv)
149 IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); 149 IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
150} 150}
151 151
152static inline void iwl_legacy_enable_rfkill_int(struct iwl_priv *priv)
153{
154 IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
155 iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
156}
157
152static inline void iwl_legacy_enable_interrupts(struct iwl_priv *priv) 158static inline void iwl_legacy_enable_interrupts(struct iwl_priv *priv)
153{ 159{
154 IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); 160 IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
diff --git a/drivers/net/wireless/iwlegacy/iwl-tx.c b/drivers/net/wireless/iwlegacy/iwl-tx.c
index a227773cb384..4fff995c6f3e 100644
--- a/drivers/net/wireless/iwlegacy/iwl-tx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-tx.c
@@ -146,33 +146,32 @@ void iwl_legacy_cmd_queue_unmap(struct iwl_priv *priv)
146{ 146{
147 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; 147 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
148 struct iwl_queue *q = &txq->q; 148 struct iwl_queue *q = &txq->q;
149 bool huge = false;
150 int i; 149 int i;
151 150
152 if (q->n_bd == 0) 151 if (q->n_bd == 0)
153 return; 152 return;
154 153
155 while (q->read_ptr != q->write_ptr) { 154 while (q->read_ptr != q->write_ptr) {
156 /* we have no way to tell if it is a huge cmd ATM */
157 i = iwl_legacy_get_cmd_index(q, q->read_ptr, 0); 155 i = iwl_legacy_get_cmd_index(q, q->read_ptr, 0);
158 156
159 if (txq->meta[i].flags & CMD_SIZE_HUGE) 157 if (txq->meta[i].flags & CMD_MAPPED) {
160 huge = true;
161 else
162 pci_unmap_single(priv->pci_dev, 158 pci_unmap_single(priv->pci_dev,
163 dma_unmap_addr(&txq->meta[i], mapping), 159 dma_unmap_addr(&txq->meta[i], mapping),
164 dma_unmap_len(&txq->meta[i], len), 160 dma_unmap_len(&txq->meta[i], len),
165 PCI_DMA_BIDIRECTIONAL); 161 PCI_DMA_BIDIRECTIONAL);
162 txq->meta[i].flags = 0;
163 }
166 164
167 q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd); 165 q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd);
168 } 166 }
169 167
170 if (huge) { 168 i = q->n_window;
171 i = q->n_window; 169 if (txq->meta[i].flags & CMD_MAPPED) {
172 pci_unmap_single(priv->pci_dev, 170 pci_unmap_single(priv->pci_dev,
173 dma_unmap_addr(&txq->meta[i], mapping), 171 dma_unmap_addr(&txq->meta[i], mapping),
174 dma_unmap_len(&txq->meta[i], len), 172 dma_unmap_len(&txq->meta[i], len),
175 PCI_DMA_BIDIRECTIONAL); 173 PCI_DMA_BIDIRECTIONAL);
174 txq->meta[i].flags = 0;
176 } 175 }
177} 176}
178EXPORT_SYMBOL(iwl_legacy_cmd_queue_unmap); 177EXPORT_SYMBOL(iwl_legacy_cmd_queue_unmap);
@@ -467,29 +466,27 @@ int iwl_legacy_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
467 return -EIO; 466 return -EIO;
468 } 467 }
469 468
469 spin_lock_irqsave(&priv->hcmd_lock, flags);
470
470 if (iwl_legacy_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { 471 if (iwl_legacy_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
471 IWL_ERR(priv, "No space in command queue\n"); 472 spin_unlock_irqrestore(&priv->hcmd_lock, flags);
472 IWL_ERR(priv, "Restarting adapter due to queue full\n"); 473
474 IWL_ERR(priv, "Restarting adapter due to command queue full\n");
473 queue_work(priv->workqueue, &priv->restart); 475 queue_work(priv->workqueue, &priv->restart);
474 return -ENOSPC; 476 return -ENOSPC;
475 } 477 }
476 478
477 spin_lock_irqsave(&priv->hcmd_lock, flags);
478
479 /* If this is a huge cmd, mark the huge flag also on the meta.flags
480 * of the _original_ cmd. This is used for DMA mapping clean up.
481 */
482 if (cmd->flags & CMD_SIZE_HUGE) {
483 idx = iwl_legacy_get_cmd_index(q, q->write_ptr, 0);
484 txq->meta[idx].flags = CMD_SIZE_HUGE;
485 }
486
487 idx = iwl_legacy_get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); 479 idx = iwl_legacy_get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
488 out_cmd = txq->cmd[idx]; 480 out_cmd = txq->cmd[idx];
489 out_meta = &txq->meta[idx]; 481 out_meta = &txq->meta[idx];
490 482
483 if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
484 spin_unlock_irqrestore(&priv->hcmd_lock, flags);
485 return -ENOSPC;
486 }
487
491 memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ 488 memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
492 out_meta->flags = cmd->flags; 489 out_meta->flags = cmd->flags | CMD_MAPPED;
493 if (cmd->flags & CMD_WANT_SKB) 490 if (cmd->flags & CMD_WANT_SKB)
494 out_meta->source = cmd; 491 out_meta->source = cmd;
495 if (cmd->flags & CMD_ASYNC) 492 if (cmd->flags & CMD_ASYNC)
@@ -610,6 +607,7 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
610 struct iwl_device_cmd *cmd; 607 struct iwl_device_cmd *cmd;
611 struct iwl_cmd_meta *meta; 608 struct iwl_cmd_meta *meta;
612 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; 609 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
610 unsigned long flags;
613 611
614 /* If a Tx command is being handled and it isn't in the actual 612 /* If a Tx command is being handled and it isn't in the actual
615 * command queue then there a command routing bug has been introduced 613 * command queue then there a command routing bug has been introduced
@@ -623,14 +621,6 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
623 return; 621 return;
624 } 622 }
625 623
626 /* If this is a huge cmd, clear the huge flag on the meta.flags
627 * of the _original_ cmd. So that iwl_legacy_cmd_queue_free won't unmap
628 * the DMA buffer for the scan (huge) command.
629 */
630 if (huge) {
631 cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, 0);
632 txq->meta[cmd_index].flags = 0;
633 }
634 cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, huge); 624 cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, huge);
635 cmd = txq->cmd[cmd_index]; 625 cmd = txq->cmd[cmd_index];
636 meta = &txq->meta[cmd_index]; 626 meta = &txq->meta[cmd_index];
@@ -647,6 +637,8 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
647 } else if (meta->callback) 637 } else if (meta->callback)
648 meta->callback(priv, cmd, pkt); 638 meta->callback(priv, cmd, pkt);
649 639
640 spin_lock_irqsave(&priv->hcmd_lock, flags);
641
650 iwl_legacy_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); 642 iwl_legacy_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
651 643
652 if (!(meta->flags & CMD_ASYNC)) { 644 if (!(meta->flags & CMD_ASYNC)) {
@@ -655,6 +647,10 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
655 iwl_legacy_get_cmd_string(cmd->hdr.cmd)); 647 iwl_legacy_get_cmd_string(cmd->hdr.cmd));
656 wake_up_interruptible(&priv->wait_command_queue); 648 wake_up_interruptible(&priv->wait_command_queue);
657 } 649 }
650
651 /* Mark as unmapped */
658 meta->flags = 0; 652 meta->flags = 0;
653
654 spin_unlock_irqrestore(&priv->hcmd_lock, flags);
659} 655}
660EXPORT_SYMBOL(iwl_legacy_tx_cmd_complete); 656EXPORT_SYMBOL(iwl_legacy_tx_cmd_complete);
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
index cc7ebcee60e5..0ee6be6a9c5d 100644
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -2748,11 +2748,12 @@ static void iwl3945_bg_init_alive_start(struct work_struct *data)
2748 struct iwl_priv *priv = 2748 struct iwl_priv *priv =
2749 container_of(data, struct iwl_priv, init_alive_start.work); 2749 container_of(data, struct iwl_priv, init_alive_start.work);
2750 2750
2751 mutex_lock(&priv->mutex);
2751 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 2752 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
2752 return; 2753 goto out;
2753 2754
2754 mutex_lock(&priv->mutex);
2755 iwl3945_init_alive_start(priv); 2755 iwl3945_init_alive_start(priv);
2756out:
2756 mutex_unlock(&priv->mutex); 2757 mutex_unlock(&priv->mutex);
2757} 2758}
2758 2759
@@ -2761,11 +2762,12 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
2761 struct iwl_priv *priv = 2762 struct iwl_priv *priv =
2762 container_of(data, struct iwl_priv, alive_start.work); 2763 container_of(data, struct iwl_priv, alive_start.work);
2763 2764
2765 mutex_lock(&priv->mutex);
2764 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 2766 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
2765 return; 2767 goto out;
2766 2768
2767 mutex_lock(&priv->mutex);
2768 iwl3945_alive_start(priv); 2769 iwl3945_alive_start(priv);
2770out:
2769 mutex_unlock(&priv->mutex); 2771 mutex_unlock(&priv->mutex);
2770} 2772}
2771 2773
@@ -2995,10 +2997,12 @@ static void iwl3945_bg_restart(struct work_struct *data)
2995 } else { 2997 } else {
2996 iwl3945_down(priv); 2998 iwl3945_down(priv);
2997 2999
2998 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3000 mutex_lock(&priv->mutex);
3001 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
3002 mutex_unlock(&priv->mutex);
2999 return; 3003 return;
3004 }
3000 3005
3001 mutex_lock(&priv->mutex);
3002 __iwl3945_up(priv); 3006 __iwl3945_up(priv);
3003 mutex_unlock(&priv->mutex); 3007 mutex_unlock(&priv->mutex);
3004 } 3008 }
@@ -3009,11 +3013,12 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
3009 struct iwl_priv *priv = 3013 struct iwl_priv *priv =
3010 container_of(data, struct iwl_priv, rx_replenish); 3014 container_of(data, struct iwl_priv, rx_replenish);
3011 3015
3016 mutex_lock(&priv->mutex);
3012 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3017 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3013 return; 3018 goto out;
3014 3019
3015 mutex_lock(&priv->mutex);
3016 iwl3945_rx_replenish(priv); 3020 iwl3945_rx_replenish(priv);
3021out:
3017 mutex_unlock(&priv->mutex); 3022 mutex_unlock(&priv->mutex);
3018} 3023}
3019 3024
@@ -3810,7 +3815,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
3810 INIT_LIST_HEAD(&priv->free_frames); 3815 INIT_LIST_HEAD(&priv->free_frames);
3811 3816
3812 mutex_init(&priv->mutex); 3817 mutex_init(&priv->mutex);
3813 mutex_init(&priv->sync_cmd_mutex);
3814 3818
3815 priv->ieee_channels = NULL; 3819 priv->ieee_channels = NULL;
3816 priv->ieee_rates = NULL; 3820 priv->ieee_rates = NULL;
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
index f8870543d68f..f781b7e225b4 100644
--- a/drivers/net/wireless/iwlegacy/iwl4965-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
@@ -1069,9 +1069,12 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
1069 } 1069 }
1070 1070
1071 /* Re-enable all interrupts */ 1071 /* Re-enable all interrupts */
1072 /* only Re-enable if diabled by irq */ 1072 /* only Re-enable if disabled by irq */
1073 if (test_bit(STATUS_INT_ENABLED, &priv->status)) 1073 if (test_bit(STATUS_INT_ENABLED, &priv->status))
1074 iwl_legacy_enable_interrupts(priv); 1074 iwl_legacy_enable_interrupts(priv);
1075 /* Re-enable RF_KILL if it occurred */
1076 else if (handled & CSR_INT_BIT_RF_KILL)
1077 iwl_legacy_enable_rfkill_int(priv);
1075 1078
1076#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG 1079#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
1077 if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) { 1080 if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) {
@@ -2139,7 +2142,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv);
2139static void __iwl4965_down(struct iwl_priv *priv) 2142static void __iwl4965_down(struct iwl_priv *priv)
2140{ 2143{
2141 unsigned long flags; 2144 unsigned long flags;
2142 int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); 2145 int exit_pending;
2143 2146
2144 IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); 2147 IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
2145 2148
@@ -2401,11 +2404,12 @@ static void iwl4965_bg_init_alive_start(struct work_struct *data)
2401 struct iwl_priv *priv = 2404 struct iwl_priv *priv =
2402 container_of(data, struct iwl_priv, init_alive_start.work); 2405 container_of(data, struct iwl_priv, init_alive_start.work);
2403 2406
2407 mutex_lock(&priv->mutex);
2404 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 2408 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
2405 return; 2409 goto out;
2406 2410
2407 mutex_lock(&priv->mutex);
2408 priv->cfg->ops->lib->init_alive_start(priv); 2411 priv->cfg->ops->lib->init_alive_start(priv);
2412out:
2409 mutex_unlock(&priv->mutex); 2413 mutex_unlock(&priv->mutex);
2410} 2414}
2411 2415
@@ -2414,11 +2418,12 @@ static void iwl4965_bg_alive_start(struct work_struct *data)
2414 struct iwl_priv *priv = 2418 struct iwl_priv *priv =
2415 container_of(data, struct iwl_priv, alive_start.work); 2419 container_of(data, struct iwl_priv, alive_start.work);
2416 2420
2421 mutex_lock(&priv->mutex);
2417 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 2422 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
2418 return; 2423 goto out;
2419 2424
2420 mutex_lock(&priv->mutex);
2421 iwl4965_alive_start(priv); 2425 iwl4965_alive_start(priv);
2426out:
2422 mutex_unlock(&priv->mutex); 2427 mutex_unlock(&priv->mutex);
2423} 2428}
2424 2429
@@ -2468,10 +2473,12 @@ static void iwl4965_bg_restart(struct work_struct *data)
2468 } else { 2473 } else {
2469 iwl4965_down(priv); 2474 iwl4965_down(priv);
2470 2475
2471 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 2476 mutex_lock(&priv->mutex);
2477 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
2478 mutex_unlock(&priv->mutex);
2472 return; 2479 return;
2480 }
2473 2481
2474 mutex_lock(&priv->mutex);
2475 __iwl4965_up(priv); 2482 __iwl4965_up(priv);
2476 mutex_unlock(&priv->mutex); 2483 mutex_unlock(&priv->mutex);
2477 } 2484 }
@@ -2624,9 +2631,10 @@ void iwl4965_mac_stop(struct ieee80211_hw *hw)
2624 2631
2625 flush_workqueue(priv->workqueue); 2632 flush_workqueue(priv->workqueue);
2626 2633
2627 /* enable interrupts again in order to receive rfkill changes */ 2634 /* User space software may expect getting rfkill changes
2635 * even if interface is down */
2628 iwl_write32(priv, CSR_INT, 0xFFFFFFFF); 2636 iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
2629 iwl_legacy_enable_interrupts(priv); 2637 iwl_legacy_enable_rfkill_int(priv);
2630 2638
2631 IWL_DEBUG_MAC80211(priv, "leave\n"); 2639 IWL_DEBUG_MAC80211(priv, "leave\n");
2632} 2640}
@@ -2847,21 +2855,22 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
2847 2855
2848 IWL_DEBUG_MAC80211(priv, "enter\n"); 2856 IWL_DEBUG_MAC80211(priv, "enter\n");
2849 2857
2858 mutex_lock(&priv->mutex);
2859
2850 if (iwl_legacy_is_rfkill(priv)) 2860 if (iwl_legacy_is_rfkill(priv))
2851 goto out_exit; 2861 goto out;
2852 2862
2853 if (test_bit(STATUS_EXIT_PENDING, &priv->status) || 2863 if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
2854 test_bit(STATUS_SCANNING, &priv->status)) 2864 test_bit(STATUS_SCANNING, &priv->status))
2855 goto out_exit; 2865 goto out;
2856 2866
2857 if (!iwl_legacy_is_associated_ctx(ctx)) 2867 if (!iwl_legacy_is_associated_ctx(ctx))
2858 goto out_exit; 2868 goto out;
2859 2869
2860 /* channel switch in progress */ 2870 /* channel switch in progress */
2861 if (priv->switch_rxon.switch_in_progress == true) 2871 if (priv->switch_rxon.switch_in_progress == true)
2862 goto out_exit; 2872 goto out;
2863 2873
2864 mutex_lock(&priv->mutex);
2865 if (priv->cfg->ops->lib->set_channel_switch) { 2874 if (priv->cfg->ops->lib->set_channel_switch) {
2866 2875
2867 ch = channel->hw_value; 2876 ch = channel->hw_value;
@@ -2917,7 +2926,6 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
2917 } 2926 }
2918out: 2927out:
2919 mutex_unlock(&priv->mutex); 2928 mutex_unlock(&priv->mutex);
2920out_exit:
2921 if (!priv->switch_rxon.switch_in_progress) 2929 if (!priv->switch_rxon.switch_in_progress)
2922 ieee80211_chswitch_done(ctx->vif, false); 2930 ieee80211_chswitch_done(ctx->vif, false);
2923 IWL_DEBUG_MAC80211(priv, "leave\n"); 2931 IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3116,7 +3124,6 @@ static int iwl4965_init_drv(struct iwl_priv *priv)
3116 INIT_LIST_HEAD(&priv->free_frames); 3124 INIT_LIST_HEAD(&priv->free_frames);
3117 3125
3118 mutex_init(&priv->mutex); 3126 mutex_init(&priv->mutex);
3119 mutex_init(&priv->sync_cmd_mutex);
3120 3127
3121 priv->ieee_channels = NULL; 3128 priv->ieee_channels = NULL;
3122 priv->ieee_rates = NULL; 3129 priv->ieee_rates = NULL;
@@ -3406,14 +3413,14 @@ iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3406 * 8. Enable interrupts and read RFKILL state 3413 * 8. Enable interrupts and read RFKILL state
3407 *********************************************/ 3414 *********************************************/
3408 3415
3409 /* enable interrupts if needed: hw bug w/a */ 3416 /* enable rfkill interrupt: hw bug w/a */
3410 pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); 3417 pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
3411 if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { 3418 if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
3412 pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; 3419 pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
3413 pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); 3420 pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
3414 } 3421 }
3415 3422
3416 iwl_legacy_enable_interrupts(priv); 3423 iwl_legacy_enable_rfkill_int(priv);
3417 3424
3418 /* If platform's RF_KILL switch is NOT set to KILL */ 3425 /* If platform's RF_KILL switch is NOT set to KILL */
3419 if (iwl_read32(priv, CSR_GP_CNTRL) & 3426 if (iwl_read32(priv, CSR_GP_CNTRL) &