Move interrupt request and free so to avoid following WARN on probe
and possible use-after-free on remove.

WARNING: CPU: 0 PID: 827 at drivers/staging/wfx/bus_spi.c:142 
wfx_spi_irq_handler+0x5c/0x64 [wfx]
race condition in driver init/deinit

Cc: sta...@vger.kernel.org
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/staging/wfx/bus_sdio.c | 16 ++++++++--------
 drivers/staging/wfx/bus_spi.c  | 16 +++++++++-------
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c
index 29688b324b33..2bfaf61e8f62 100644
--- a/drivers/staging/wfx/bus_sdio.c
+++ b/drivers/staging/wfx/bus_sdio.c
@@ -200,16 +200,16 @@ static int wfx_sdio_probe(struct sdio_func *func,
        if (ret)
                goto err0;
 
-       ret = wfx_sdio_irq_subscribe(bus);
-       if (ret)
-               goto err1;
-
        bus->core = wfx_init_common(&func->dev, &wfx_sdio_pdata,
                                    &wfx_sdio_hwbus_ops, bus);
        if (!bus->core) {
                ret = -EIO;
+               goto err1;
+       }
+
+       ret = wfx_sdio_irq_subscribe(bus);
+       if (ret)
                goto err2;
-       }
 
        ret = wfx_probe(bus->core);
        if (ret)
@@ -218,9 +218,9 @@ static int wfx_sdio_probe(struct sdio_func *func,
        return 0;
 
 err3:
-       wfx_free_common(bus->core);
+       wfx_sdio_irq_unsubscribe(bus);
 err2:
-       wfx_sdio_irq_unsubscribe(bus);
+       wfx_free_common(bus->core);
 err1:
        sdio_claim_host(func);
        sdio_disable_func(func);
@@ -234,8 +234,8 @@ static void wfx_sdio_remove(struct sdio_func *func)
        struct wfx_sdio_priv *bus = sdio_get_drvdata(func);
 
        wfx_release(bus->core);
-       wfx_free_common(bus->core);
        wfx_sdio_irq_unsubscribe(bus);
+       wfx_free_common(bus->core);
        sdio_claim_host(func);
        sdio_disable_func(func);
        sdio_release_host(func);
diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c
index 3ba705477ca8..2b108a9fa5ae 100644
--- a/drivers/staging/wfx/bus_spi.c
+++ b/drivers/staging/wfx/bus_spi.c
@@ -211,20 +211,22 @@ static int wfx_spi_probe(struct spi_device *func)
                udelay(2000);
        }
 
-       ret = devm_request_irq(&func->dev, func->irq, wfx_spi_irq_handler,
-                              IRQF_TRIGGER_RISING, "wfx", bus);
-       if (ret)
-               return ret;
-
        INIT_WORK(&bus->request_rx, wfx_spi_request_rx);
        bus->core = wfx_init_common(&func->dev, &wfx_spi_pdata,
                                    &wfx_spi_hwbus_ops, bus);
        if (!bus->core)
                return -EIO;
 
+       ret = devm_request_irq(&func->dev, func->irq, wfx_spi_irq_handler,
+                              IRQF_TRIGGER_RISING, "wfx", bus);
+       if (ret)
+               return ret;
+
        ret = wfx_probe(bus->core);
-       if (ret)
+       if (ret) {
+               devm_free_irq(&func->dev, func->irq, bus);
                wfx_free_common(bus->core);
+       }
 
        return ret;
 }
@@ -234,11 +236,11 @@ static int wfx_spi_remove(struct spi_device *func)
        struct wfx_spi_priv *bus = spi_get_drvdata(func);
 
        wfx_release(bus->core);
-       wfx_free_common(bus->core);
        // A few IRQ will be sent during device release. Hopefully, no IRQ
        // should happen after wdev/wvif are released.
        devm_free_irq(&func->dev, func->irq, bus);
        flush_work(&bus->request_rx);
+       wfx_free_common(bus->core);
        return 0;
 }
 
-- 
2.20.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to