]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.fixes/iwl3945-fix-rfkill.patch
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / iwl3945-fix-rfkill.patch
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);