aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2009-08-07 06:33:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:13:38 -0400
commitb5ed9c1b6f8fcb2d2315f12599fd5808f7933f16 (patch)
tree33f56a3d843dc59b7643a28ea3e5916a7ac7d362 /drivers/net/wireless/wl12xx
parent3ec410d747fa1da035183c43775a64c0e285e399 (diff)
wl1251: make irq handling interface specific
In SDIO, the host driver requests the IRQ and invokes a callback to the card driver. This differs from SPI, so the relevant code needs to be interface-specific. This patch pushes the irq code down into _spi.c and _sdio.c, and adds enable/disable callbacks. This fixes the following warning: [ 566.343887] ------------[ cut here ]------------ [ 566.349105] WARNING: at kernel/irq/manage.c:222 __enable_irq+0x3c/0x6c() [ 566.356735] Unbalanced enable for IRQ 0 [ 566.361099] Modules linked in: msm_wifi wl12xx_sdio wl12xx mac80211 cfg80211 rfkill_backport lib80211_crypt_ccmp lib80211_crypt_wep lib80211_crypt_tkip lib80211 [ 566.381240] [<c025acec>] (dump_stack+0x0/0x14) from [<c004b610>] (warn_slowpath+0x70/0x8c) [ 566.391860] [<c004b5a0>] (warn_slowpath+0x0/0x8c) from [<c0077c10>] (__enable_irq+0x3c/0x6c) [ 566.402572] r3:00000000 r2:c02cad13 [ 566.407516] r7:00001002 r6:00000000 r5:c0310be4 r4:c0310be4 [ 566.415786] [<c0077bd4>] (__enable_irq+0x0/0x6c) from [<c0077fd0>] (enable_irq+0x38/0x64) [ 566.425826] r5:c0310be4 r4:a0000013 [ 566.430709] [<c0077f98>] (enable_irq+0x0/0x64) from [<bf0dfa78>] (wl12xx_boot_run_firmware+0xfc/0x170 [wl12xx]) [ 566.442947] r7:00001002 r6:c440a9fc r5:00000072 r4:c440a9e0 [ 566.450851] [<bf0df97c>] (wl12xx_boot_run_firmware+0x0/0x170 [wl12xx]) from [<bf0e05f0>] (wl1251_boot+0xd4/0x108 [wl12xx]) [ 566.464492] r5:00000000 r4:c440a9e0 [ 566.469466] [<bf0e051c>] (wl1251_boot+0x0/0x108 [wl12xx]) from [<bf0dd27c>] (wl12xx_op_start+0x54/0xb8 [wl12xx]) [ 566.482162] r5:00000000 r4:c440a9e0 [ 566.487472] [<bf0dd228>] (wl12xx_op_start+0x0/0xb8 [wl12xx]) from [<bf0b96dc>] (ieee80211_open+0x2dc/0x720 [mac80211]) [ 566.500594] r7:00001002 r6:c4950800 r5:c440a220 r4:00000000 [ 566.508865] [<bf0b9400>] (ieee80211_open+0x0/0x720 [mac80211]) from [<c01f1edc>] (dev_open+0x9c/0xfc) [ 566.520705] [<c01f1e40>] (dev_open+0x0/0xfc) from [<c01f17dc>] (dev_change_flags+0x98/0x170) [ 566.531417] r5:00000041 r4:c4950800 [ 566.536330] [<c01f1744>] (dev_change_flags+0x0/0x170) from [<c023041c>] (devinet_ioctl+0x3a8/0x784) [ 566.547683] r7:c128e380 r6:00000001 r5:00008914 r4:00000000 [ 566.555587] [<c0230074>] (devinet_ioctl+0x0/0x784) from [<c02318cc>] (inet_ioctl+0xdc/0x114) [ 566.566299] [<c02317f0>] (inet_ioctl+0x0/0x114) from [<c01e1a60>] (sock_ioctl+0x1f0/0x248) [ 566.576827] r5:00008914 r4:c572c1a0 [ 566.581771] [<c01e1870>] (sock_ioctl+0x0/0x248) from [<c00b23a0>] (vfs_ioctl+0x34/0x94) [ 566.592086] r7:c572c1a0 r6:bee497e8 r5:00008914 r4:c572c1a0 [ 566.599990] [<c00b236c>] (vfs_ioctl+0x0/0x94) from [<c00b2a28>] (do_vfs_ioctl+0x52c/0x584) [ 566.610549] r7:c572c1a0 r6:00008914 r5:c572c1a0 r4:c3201228 [ 566.618453] [<c00b24fc>] (do_vfs_ioctl+0x0/0x584) from [<c00b2ac0>] (sys_ioctl+0x40/0x64) [ 566.628890] [<c00b2a80>] (sys_ioctl+0x0/0x64) from [<c0021da0>] (ret_fast_syscall+0x0/0x2c) [ 566.639541] r7:00000036 r6:00000000 r5:00000004 r4:001a11f3 [ 566.647445] ---[ end trace 15c26ef7dd5e7b03 ]--- Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: Kalle Valo <kalle.valo@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r--drivers/net/wireless/wl12xx/wl1251.h5
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_boot.c7
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c24
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_sdio.c36
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_spi.c26
5 files changed, 65 insertions, 33 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index ebe2c70559cd..13f0589beec9 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -285,6 +285,8 @@ struct wl1251_if_operations {
285 void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len); 285 void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
286 void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); 286 void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
287 void (*reset)(struct wl1251 *wl); 287 void (*reset)(struct wl1251 *wl);
288 void (*enable_irq)(struct wl1251 *wl);
289 void (*disable_irq)(struct wl1251 *wl);
288}; 290};
289 291
290struct wl1251 { 292struct wl1251 {
@@ -404,10 +406,11 @@ struct wl1251 {
404int wl1251_plt_start(struct wl1251 *wl); 406int wl1251_plt_start(struct wl1251 *wl);
405int wl1251_plt_stop(struct wl1251 *wl); 407int wl1251_plt_stop(struct wl1251 *wl);
406 408
407irqreturn_t wl1251_irq(int irq, void *cookie);
408struct ieee80211_hw *wl1251_alloc_hw(void); 409struct ieee80211_hw *wl1251_alloc_hw(void);
409int wl1251_free_hw(struct wl1251 *wl); 410int wl1251_free_hw(struct wl1251 *wl);
410int wl1251_init_ieee80211(struct wl1251 *wl); 411int wl1251_init_ieee80211(struct wl1251 *wl);
412void wl1251_enable_interrupts(struct wl1251 *wl);
413void wl1251_disable_interrupts(struct wl1251 *wl);
411 414
412#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */ 415#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */
413#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS 416#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index 5c6f32757ac4..8b50d44d8243 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -29,11 +29,6 @@
29#include "wl1251_spi.h" 29#include "wl1251_spi.h"
30#include "wl1251_event.h" 30#include "wl1251_event.h"
31 31
32static void wl1251_boot_enable_interrupts(struct wl1251 *wl)
33{
34 enable_irq(wl->irq);
35}
36
37void wl1251_boot_target_enable_interrupts(struct wl1251 *wl) 32void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
38{ 33{
39 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); 34 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
@@ -278,7 +273,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
278 */ 273 */
279 274
280 /* enable gpio interrupts */ 275 /* enable gpio interrupts */
281 wl1251_boot_enable_interrupts(wl); 276 wl1251_enable_interrupts(wl);
282 277
283 wl->chip.op_target_enable_interrupts(wl); 278 wl->chip.op_target_enable_interrupts(wl);
284 279
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index abe157a174c7..4c1aad33fb51 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -42,9 +42,14 @@
42#include "wl1251_init.h" 42#include "wl1251_init.h"
43#include "wl1251_debugfs.h" 43#include "wl1251_debugfs.h"
44 44
45static void wl1251_disable_interrupts(struct wl1251 *wl) 45void wl1251_enable_interrupts(struct wl1251 *wl)
46{ 46{
47 disable_irq(wl->irq); 47 wl->if_ops->enable_irq(wl);
48}
49
50void wl1251_disable_interrupts(struct wl1251 *wl)
51{
52 wl->if_ops->disable_irq(wl);
48} 53}
49 54
50static void wl1251_power_off(struct wl1251 *wl) 55static void wl1251_power_off(struct wl1251 *wl)
@@ -57,20 +62,6 @@ static void wl1251_power_on(struct wl1251 *wl)
57 wl->set_power(true); 62 wl->set_power(true);
58} 63}
59 64
60irqreturn_t wl1251_irq(int irq, void *cookie)
61{
62 struct wl1251 *wl;
63
64 wl1251_debug(DEBUG_IRQ, "IRQ");
65
66 wl = cookie;
67
68 schedule_work(&wl->irq_work);
69
70 return IRQ_HANDLED;
71}
72EXPORT_SYMBOL_GPL(wl1251_irq);
73
74static int wl1251_fetch_firmware(struct wl1251 *wl) 65static int wl1251_fetch_firmware(struct wl1251 *wl)
75{ 66{
76 const struct firmware *fw; 67 const struct firmware *fw;
@@ -1280,7 +1271,6 @@ int wl1251_free_hw(struct wl1251 *wl)
1280 1271
1281 wl1251_debugfs_exit(wl); 1272 wl1251_debugfs_exit(wl);
1282 1273
1283 free_irq(wl->irq, wl);
1284 kfree(wl->target_mem_map); 1274 kfree(wl->target_mem_map);
1285 kfree(wl->data_path); 1275 kfree(wl->data_path);
1286 kfree(wl->fw); 1276 kfree(wl->fw);
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index f1d9e76e0484..f7e451fed8b5 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -50,7 +50,12 @@ static struct sdio_func *wl_to_func(struct wl1251 *wl)
50 50
51static void wl1251_sdio_interrupt(struct sdio_func *func) 51static void wl1251_sdio_interrupt(struct sdio_func *func)
52{ 52{
53 wl1251_irq(0, sdio_get_drvdata(func)); 53 struct wl1251 *wl = sdio_get_drvdata(func);
54
55 wl1251_debug(DEBUG_IRQ, "IRQ");
56
57 /* FIXME should be synchronous for sdio */
58 schedule_work(&wl->irq_work);
54} 59}
55 60
56static const struct sdio_device_id wl1251_devices[] = { 61static const struct sdio_device_id wl1251_devices[] = {
@@ -88,6 +93,24 @@ void wl1251_sdio_reset(struct wl1251 *wl)
88{ 93{
89} 94}
90 95
96static void wl1251_sdio_enable_irq(struct wl1251 *wl)
97{
98 struct sdio_func *func = wl_to_func(wl);
99
100 sdio_claim_host(func);
101 sdio_claim_irq(func, wl1251_sdio_interrupt);
102 sdio_release_host(func);
103}
104
105static void wl1251_sdio_disable_irq(struct wl1251 *wl)
106{
107 struct sdio_func *func = wl_to_func(wl);
108
109 sdio_claim_host(func);
110 sdio_release_irq(func);
111 sdio_release_host(func);
112}
113
91void wl1251_sdio_set_power(bool enable) 114void wl1251_sdio_set_power(bool enable)
92{ 115{
93} 116}
@@ -96,6 +119,8 @@ struct wl1251_if_operations wl1251_sdio_ops = {
96 .read = wl1251_sdio_read, 119 .read = wl1251_sdio_read,
97 .write = wl1251_sdio_write, 120 .write = wl1251_sdio_write,
98 .reset = wl1251_sdio_reset, 121 .reset = wl1251_sdio_reset,
122 .enable_irq = wl1251_sdio_enable_irq,
123 .disable_irq = wl1251_sdio_disable_irq,
99}; 124};
100 125
101int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) 126int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
@@ -124,21 +149,14 @@ int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
124 149
125 sdio_release_host(func); 150 sdio_release_host(func);
126 ret = wl1251_init_ieee80211(wl); 151 ret = wl1251_init_ieee80211(wl);
127 sdio_claim_host(func);
128 if (ret) 152 if (ret)
129 goto disable; 153 goto disable;
130 154
131 ret = sdio_claim_irq(func, wl1251_sdio_interrupt);
132 if (ret)
133 goto no_irq;
134
135 sdio_release_host(func);
136 sdio_set_drvdata(func, wl); 155 sdio_set_drvdata(func, wl);
137 return ret; 156 return ret;
138 157
139no_irq:
140 wl1251_free_hw(wl);
141disable: 158disable:
159 sdio_claim_host(func);
142 sdio_disable_func(func); 160 sdio_disable_func(func);
143release: 161release:
144 sdio_release_host(func); 162 sdio_release_host(func);
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index 5967317ef025..7d1031b7a088 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -31,6 +31,19 @@
31#include "reg.h" 31#include "reg.h"
32#include "wl1251_spi.h" 32#include "wl1251_spi.h"
33 33
34static irqreturn_t wl1251_irq(int irq, void *cookie)
35{
36 struct wl1251 *wl;
37
38 wl1251_debug(DEBUG_IRQ, "IRQ");
39
40 wl = cookie;
41
42 schedule_work(&wl->irq_work);
43
44 return IRQ_HANDLED;
45}
46
34static struct spi_device *wl_to_spi(struct wl1251 *wl) 47static struct spi_device *wl_to_spi(struct wl1251 *wl)
35{ 48{
36 return wl->if_priv; 49 return wl->if_priv;
@@ -193,10 +206,22 @@ static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
193 wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); 206 wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
194} 207}
195 208
209static void wl1251_spi_enable_irq(struct wl1251 *wl)
210{
211 return enable_irq(wl->irq);
212}
213
214static void wl1251_spi_disable_irq(struct wl1251 *wl)
215{
216 return disable_irq(wl->irq);
217}
218
196static const struct wl1251_if_operations wl1251_spi_ops = { 219static const struct wl1251_if_operations wl1251_spi_ops = {
197 .read = wl1251_spi_read, 220 .read = wl1251_spi_read,
198 .write = wl1251_spi_write, 221 .write = wl1251_spi_write,
199 .reset = wl1251_spi_reset_wake, 222 .reset = wl1251_spi_reset_wake,
223 .enable_irq = wl1251_spi_enable_irq,
224 .disable_irq = wl1251_spi_disable_irq,
200}; 225};
201 226
202static int __devinit wl1251_spi_probe(struct spi_device *spi) 227static int __devinit wl1251_spi_probe(struct spi_device *spi)
@@ -274,6 +299,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi)
274{ 299{
275 struct wl1251 *wl = dev_get_drvdata(&spi->dev); 300 struct wl1251 *wl = dev_get_drvdata(&spi->dev);
276 301
302 free_irq(wl->irq, wl);
277 wl1251_free_hw(wl); 303 wl1251_free_hw(wl);
278 304
279 return 0; 305 return 0;