aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/spi.c
diff options
context:
space:
mode:
authorIdo Yariv <ido@wizery.com>2011-03-31 04:07:01 -0400
committerLuciano Coelho <coelho@ti.com>2011-04-19 09:49:20 -0400
commit341b7cde6ccc60672fcd7fc84dd24a1b7c0b8d94 (patch)
tree25b284f436f24a0c21e4a656531831619002757c /drivers/net/wireless/wl12xx/spi.c
parentd2f4d47d84f8c665ab9babb2cc84d2e7872a96e1 (diff)
wl12xx: Handle platforms without level trigger interrupts
Some platforms are incapable of triggering on level interrupts. Add a platform quirks member in the platform data structure, as well as an edge interrupt quirk which can be set on such platforms. When the interrupt is requested with IRQF_TRIGGER_RISING, IRQF_ONESHOT cannot be used, as we might miss interrupts that occur after the FW status is cleared and before the threaded interrupt handler exits. Moreover, when IRQF_ONESHOT is not set, iterating more than once in the threaded interrupt handler introduces a few race conditions between this handler and the hardirq handler. Currently this is worked around by limiting the loop to one iteration only. This workaround has an impact on performance. To remove to this restriction, the race conditions will need to be addressed. Signed-off-by: Ido Yariv <ido@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/spi.c')
-rw-r--r--drivers/net/wireless/wl12xx/spi.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 7b82b5f0e490..51662bb68019 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -364,6 +364,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
364 struct wl12xx_platform_data *pdata; 364 struct wl12xx_platform_data *pdata;
365 struct ieee80211_hw *hw; 365 struct ieee80211_hw *hw;
366 struct wl1271 *wl; 366 struct wl1271 *wl;
367 unsigned long irqflags;
367 int ret; 368 int ret;
368 369
369 pdata = spi->dev.platform_data; 370 pdata = spi->dev.platform_data;
@@ -402,6 +403,12 @@ static int __devinit wl1271_probe(struct spi_device *spi)
402 403
403 wl->ref_clock = pdata->board_ref_clock; 404 wl->ref_clock = pdata->board_ref_clock;
404 wl->tcxo_clock = pdata->board_tcxo_clock; 405 wl->tcxo_clock = pdata->board_tcxo_clock;
406 wl->platform_quirks = pdata->platform_quirks;
407
408 if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
409 irqflags = IRQF_TRIGGER_RISING;
410 else
411 irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
405 412
406 wl->irq = spi->irq; 413 wl->irq = spi->irq;
407 if (wl->irq < 0) { 414 if (wl->irq < 0) {
@@ -411,7 +418,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
411 } 418 }
412 419
413 ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, 420 ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
414 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 421 irqflags,
415 DRIVER_NAME, wl); 422 DRIVER_NAME, wl);
416 if (ret < 0) { 423 if (ret < 0) {
417 wl1271_error("request_irq() failed: %d", ret); 424 wl1271_error("request_irq() failed: %d", ret);