Commit f380f2c4 authored by Grazvydas Ignotas's avatar Grazvydas Ignotas Committed by John W. Linville

wl1251: fix oops on early interrupt

This driver disables interrupt just after requesting it and enables it
later, after interface is up. However currently there is a time window
between request_irq() and disable_irq() where if interrupt arrives, the
driver oopses because it's not yet ready to process it. This can be
reproduced by inserting the module, associating and removing the module
multiple times.

Eliminate this race by setting IRQF_NOAUTOEN flag before request_irq().

Cc: stable@vger.kernel.org # v2.6.37+
Signed-off-by: default avatarGrazvydas Ignotas <notasas@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 75813bde
...@@ -260,6 +260,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, ...@@ -260,6 +260,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
} }
if (wl->irq) { if (wl->irq) {
irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
if (ret < 0) { if (ret < 0) {
wl1251_error("request_irq() failed: %d", ret); wl1251_error("request_irq() failed: %d", ret);
...@@ -267,7 +268,6 @@ static int wl1251_sdio_probe(struct sdio_func *func, ...@@ -267,7 +268,6 @@ static int wl1251_sdio_probe(struct sdio_func *func,
} }
irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
disable_irq(wl->irq);
wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
......
...@@ -281,6 +281,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi) ...@@ -281,6 +281,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
wl->use_eeprom = pdata->use_eeprom; wl->use_eeprom = pdata->use_eeprom;
irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl); ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
if (ret < 0) { if (ret < 0) {
wl1251_error("request_irq() failed: %d", ret); wl1251_error("request_irq() failed: %d", ret);
...@@ -289,8 +290,6 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi) ...@@ -289,8 +290,6 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
disable_irq(wl->irq);
ret = wl1251_init_ieee80211(wl); ret = wl1251_init_ieee80211(wl);
if (ret) if (ret)
goto out_irq; goto out_irq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment