1 From: Helmut Schaa <helmut.schaa@googlemail.com>
2 Subject: iwl3945: report killswitch changes even if the interface is down
3 Patch-mainline: wireless-testing (2.6.30?)
6 Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
7 Acked-by: Samuel Ortiz <samuel.ortiz@intel.com>
8 Signed-off-by: John W. Linville <linville@tuxdriver.com>
9 Acked-by: Helmut Schaa <hschaa@suse.de>
13 drivers/net/wireless/iwlwifi/iwl-3945.h | 1
14 drivers/net/wireless/iwlwifi/iwl3945-base.c | 83 ++++++++++++++++++----------
15 2 files changed, 57 insertions(+), 27 deletions(-)
17 --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-3945.h
18 +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-3945.h
19 @@ -893,6 +893,7 @@ struct iwl3945_priv {
20 struct delayed_work alive_start;
21 struct delayed_work activity_timer;
22 struct delayed_work thermal_periodic;
23 + struct delayed_work rfkill_poll;
24 struct delayed_work gather_stats;
25 struct delayed_work scan_check;
26 struct delayed_work post_associate;
27 --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl3945-base.c
28 +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl3945-base.c
29 @@ -6023,7 +6023,8 @@ static void iwl3945_bg_rf_kill(struct wo
30 IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
31 "HW and/or SW RF Kill no longer active, restarting "
33 - if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
34 + if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
35 + test_bit(STATUS_ALIVE, &priv->status))
36 queue_work(priv->workqueue, &priv->restart);
39 @@ -6040,6 +6041,25 @@ static void iwl3945_bg_rf_kill(struct wo
40 iwl3945_rfkill_set_hw_state(priv);
43 +static void iwl3945_rfkill_poll(struct work_struct *data)
45 + struct iwl3945_priv *priv =
46 + container_of(data, struct iwl3945_priv, rfkill_poll.work);
47 + unsigned long status = priv->status;
49 + if (iwl3945_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
50 + clear_bit(STATUS_RF_KILL_HW, &priv->status);
52 + set_bit(STATUS_RF_KILL_HW, &priv->status);
54 + if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status))
55 + queue_work(priv->workqueue, &priv->rf_kill);
57 + queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
58 + round_jiffies_relative(2 * HZ));
62 static void iwl3945_bg_set_monitor(struct work_struct *work)
64 struct iwl3945_priv *priv = container_of(work,
65 @@ -6481,20 +6501,6 @@ static int iwl3945_mac_start(struct ieee
67 IWL_DEBUG_MAC80211("enter\n");
69 - if (pci_enable_device(priv->pci_dev)) {
70 - IWL_ERROR("Fail to pci_enable_device\n");
73 - pci_restore_state(priv->pci_dev);
74 - pci_enable_msi(priv->pci_dev);
76 - ret = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
79 - IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
80 - goto out_disable_msi;
83 /* we should be verifying the device is ready to be opened */
84 mutex_lock(&priv->mutex);
86 @@ -6539,15 +6545,15 @@ static int iwl3945_mac_start(struct ieee
90 + /* ucode is running and will send rfkill notifications,
91 + * no need to poll the killswitch state anymore */
92 + cancel_delayed_work(&priv->rfkill_poll);
95 IWL_DEBUG_MAC80211("leave\n");
99 - free_irq(priv->pci_dev->irq, priv);
101 - pci_disable_msi(priv->pci_dev);
102 - pci_disable_device(priv->pci_dev);
104 IWL_DEBUG_MAC80211("leave - failed\n");
106 @@ -6579,10 +6585,10 @@ static void iwl3945_mac_stop(struct ieee
109 flush_workqueue(priv->workqueue);
110 - free_irq(priv->pci_dev->irq, priv);
111 - pci_disable_msi(priv->pci_dev);
112 - pci_save_state(priv->pci_dev);
113 - pci_disable_device(priv->pci_dev);
115 + /* start polling the killswitch state again */
116 + queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
117 + round_jiffies_relative(2 * HZ));
119 IWL_DEBUG_MAC80211("leave\n");
121 @@ -7776,6 +7782,7 @@ static void iwl3945_setup_deferred_work(
122 INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
123 INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
124 INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check);
125 + INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll);
127 iwl3945_hw_setup_deferred_work(priv);
129 @@ -7988,6 +7995,15 @@ static int iwl3945_pci_probe(struct pci_
130 iwl3945_disable_interrupts(priv);
131 spin_unlock_irqrestore(&priv->lock, flags);
133 + pci_enable_msi(priv->pci_dev);
135 + err = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
138 + IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
139 + goto out_disable_msi;
142 err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
144 IWL_ERROR("failed to create sysfs device attributes\n");
145 @@ -8037,14 +8053,16 @@ static int iwl3945_pci_probe(struct pci_
147 priv->hw->conf.beacon_int = 100;
148 priv->mac80211_registered = 1;
149 - pci_save_state(pdev);
150 - pci_disable_device(pdev);
152 err = iwl3945_rfkill_init(priv);
154 IWL_ERROR("Unable to initialize RFKILL system. "
155 "Ignoring error: %d\n", err);
157 + /* Start monitoring the killswitch */
158 + queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
164 @@ -8055,10 +8073,13 @@ static int iwl3945_pci_probe(struct pci_
165 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
168 + free_irq(priv->pci_dev->irq, priv);
169 destroy_workqueue(priv->workqueue);
170 priv->workqueue = NULL;
171 iwl3945_unset_hw_setting(priv);
174 + pci_disable_msi(priv->pci_dev);
177 pci_iounmap(pdev, priv->hw_base);
178 out_pci_release_regions:
179 @@ -8098,6 +8119,8 @@ static void __devexit iwl3945_pci_remove
180 sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
182 iwl3945_rfkill_unregister(priv);
183 + cancel_delayed_work(&priv->rfkill_poll);
185 iwl3945_dealloc_ucode_pci(priv);
188 @@ -8119,6 +8142,9 @@ static void __devexit iwl3945_pci_remove
189 destroy_workqueue(priv->workqueue);
190 priv->workqueue = NULL;
192 + free_irq(pdev->irq, priv);
193 + pci_disable_msi(pdev);
195 pci_iounmap(pdev, priv->hw_base);
196 pci_release_regions(pdev);
197 pci_disable_device(pdev);
198 @@ -8144,7 +8170,8 @@ static int iwl3945_pci_suspend(struct pc
199 iwl3945_mac_stop(priv->hw);
203 + pci_save_state(pdev);
204 + pci_disable_device(pdev);
205 pci_set_power_state(pdev, PCI_D3hot);
208 @@ -8155,6 +8182,8 @@ static int iwl3945_pci_resume(struct pci
209 struct iwl3945_priv *priv = pci_get_drvdata(pdev);
211 pci_set_power_state(pdev, PCI_D0);
212 + pci_enable_device(pdev);
213 + pci_restore_state(pdev);
216 iwl3945_mac_start(priv->hw);