]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
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?) | |
4 | References: bnc#446013 | |
5 | ||
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> | |
10 | --- | |
11 | ||
12 | --- | |
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(-) | |
16 | ||
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 " | |
32 | "device\n"); | |
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); | |
37 | } else { | |
38 | ||
39 | @@ -6040,6 +6041,25 @@ static void iwl3945_bg_rf_kill(struct wo | |
40 | iwl3945_rfkill_set_hw_state(priv); | |
41 | } | |
42 | ||
43 | +static void iwl3945_rfkill_poll(struct work_struct *data) | |
44 | +{ | |
45 | + struct iwl3945_priv *priv = | |
46 | + container_of(data, struct iwl3945_priv, rfkill_poll.work); | |
47 | + unsigned long status = priv->status; | |
48 | + | |
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); | |
51 | + else | |
52 | + set_bit(STATUS_RF_KILL_HW, &priv->status); | |
53 | + | |
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); | |
56 | + | |
57 | + queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | |
58 | + round_jiffies_relative(2 * HZ)); | |
59 | + | |
60 | +} | |
61 | + | |
62 | static void iwl3945_bg_set_monitor(struct work_struct *work) | |
63 | { | |
64 | struct iwl3945_priv *priv = container_of(work, | |
65 | @@ -6481,20 +6501,6 @@ static int iwl3945_mac_start(struct ieee | |
66 | ||
67 | IWL_DEBUG_MAC80211("enter\n"); | |
68 | ||
69 | - if (pci_enable_device(priv->pci_dev)) { | |
70 | - IWL_ERROR("Fail to pci_enable_device\n"); | |
71 | - return -ENODEV; | |
72 | - } | |
73 | - pci_restore_state(priv->pci_dev); | |
74 | - pci_enable_msi(priv->pci_dev); | |
75 | - | |
76 | - ret = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED, | |
77 | - DRV_NAME, priv); | |
78 | - if (ret) { | |
79 | - IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq); | |
80 | - goto out_disable_msi; | |
81 | - } | |
82 | - | |
83 | /* we should be verifying the device is ready to be opened */ | |
84 | mutex_lock(&priv->mutex); | |
85 | ||
86 | @@ -6539,15 +6545,15 @@ static int iwl3945_mac_start(struct ieee | |
87 | } | |
88 | } | |
89 | ||
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); | |
93 | + | |
94 | priv->is_open = 1; | |
95 | IWL_DEBUG_MAC80211("leave\n"); | |
96 | return 0; | |
97 | ||
98 | out_release_irq: | |
99 | - free_irq(priv->pci_dev->irq, priv); | |
100 | -out_disable_msi: | |
101 | - pci_disable_msi(priv->pci_dev); | |
102 | - pci_disable_device(priv->pci_dev); | |
103 | priv->is_open = 0; | |
104 | IWL_DEBUG_MAC80211("leave - failed\n"); | |
105 | return ret; | |
106 | @@ -6579,10 +6585,10 @@ static void iwl3945_mac_stop(struct ieee | |
107 | iwl3945_down(priv); | |
108 | ||
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); | |
114 | + | |
115 | + /* start polling the killswitch state again */ | |
116 | + queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | |
117 | + round_jiffies_relative(2 * HZ)); | |
118 | ||
119 | IWL_DEBUG_MAC80211("leave\n"); | |
120 | } | |
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); | |
126 | ||
127 | iwl3945_hw_setup_deferred_work(priv); | |
128 | ||
129 | @@ -7988,6 +7995,15 @@ static int iwl3945_pci_probe(struct pci_ | |
130 | iwl3945_disable_interrupts(priv); | |
131 | spin_unlock_irqrestore(&priv->lock, flags); | |
132 | ||
133 | + pci_enable_msi(priv->pci_dev); | |
134 | + | |
135 | + err = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED, | |
136 | + DRV_NAME, priv); | |
137 | + if (err) { | |
138 | + IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq); | |
139 | + goto out_disable_msi; | |
140 | + } | |
141 | + | |
142 | err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); | |
143 | if (err) { | |
144 | IWL_ERROR("failed to create sysfs device attributes\n"); | |
145 | @@ -8037,14 +8053,16 @@ static int iwl3945_pci_probe(struct pci_ | |
146 | ||
147 | priv->hw->conf.beacon_int = 100; | |
148 | priv->mac80211_registered = 1; | |
149 | - pci_save_state(pdev); | |
150 | - pci_disable_device(pdev); | |
151 | ||
152 | err = iwl3945_rfkill_init(priv); | |
153 | if (err) | |
154 | IWL_ERROR("Unable to initialize RFKILL system. " | |
155 | "Ignoring error: %d\n", err); | |
156 | ||
157 | + /* Start monitoring the killswitch */ | |
158 | + queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | |
159 | + 2 * HZ); | |
160 | + | |
161 | return 0; | |
162 | ||
163 | out_free_geos: | |
164 | @@ -8055,10 +8073,13 @@ static int iwl3945_pci_probe(struct pci_ | |
165 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | |
166 | ||
167 | out_release_irq: | |
168 | + free_irq(priv->pci_dev->irq, priv); | |
169 | destroy_workqueue(priv->workqueue); | |
170 | priv->workqueue = NULL; | |
171 | iwl3945_unset_hw_setting(priv); | |
172 | - | |
173 | + out_disable_msi: | |
174 | + pci_disable_msi(priv->pci_dev); | |
175 | + | |
176 | out_iounmap: | |
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); | |
181 | ||
182 | iwl3945_rfkill_unregister(priv); | |
183 | + cancel_delayed_work(&priv->rfkill_poll); | |
184 | + | |
185 | iwl3945_dealloc_ucode_pci(priv); | |
186 | ||
187 | if (priv->rxq.bd) | |
188 | @@ -8119,6 +8142,9 @@ static void __devexit iwl3945_pci_remove | |
189 | destroy_workqueue(priv->workqueue); | |
190 | priv->workqueue = NULL; | |
191 | ||
192 | + free_irq(pdev->irq, priv); | |
193 | + pci_disable_msi(pdev); | |
194 | + | |
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); | |
200 | priv->is_open = 1; | |
201 | } | |
202 | - | |
203 | + pci_save_state(pdev); | |
204 | + pci_disable_device(pdev); | |
205 | pci_set_power_state(pdev, PCI_D3hot); | |
206 | ||
207 | return 0; | |
208 | @@ -8155,6 +8182,8 @@ static int iwl3945_pci_resume(struct pci | |
209 | struct iwl3945_priv *priv = pci_get_drvdata(pdev); | |
210 | ||
211 | pci_set_power_state(pdev, PCI_D0); | |
212 | + pci_enable_device(pdev); | |
213 | + pci_restore_state(pdev); | |
214 | ||
215 | if (priv->is_open) | |
216 | iwl3945_mac_start(priv->hw); |