]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.fixes/iwl3945-fix-rfkill.patch
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / iwl3945-fix-rfkill.patch
CommitLineData
00e5a55c
BS
1From: Helmut Schaa <helmut.schaa@googlemail.com>
2Subject: iwl3945: report killswitch changes even if the interface is down
3Patch-mainline: wireless-testing (2.6.30?)
4References: bnc#446013
5
6Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
7Acked-by: Samuel Ortiz <samuel.ortiz@intel.com>
8Signed-off-by: John W. Linville <linville@tuxdriver.com>
9Acked-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);