From 341b7cde6ccc60672fcd7fc84dd24a1b7c0b8d94 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 31 Mar 2011 10:07:01 +0200 Subject: 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 Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/wl12xx/sdio.c') diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 8246e9de4306..bcd4ad7ba90d 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -220,6 +220,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, struct ieee80211_hw *hw; const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; + unsigned long irqflags; int ret; /* We are only able to handle the wlan function */ @@ -251,9 +252,15 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; wl->tcxo_clock = wlan_data->board_tcxo_clock; + wl->platform_quirks = wlan_data->platform_quirks; + + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + irqflags = IRQF_TRIGGER_RISING; + else + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + irqflags, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); -- cgit v1.2.3