diff options
-rw-r--r-- | drivers/staging/wfx/bh.c | 1 | ||||
-rw-r--r-- | drivers/staging/wfx/bus.h | 2 | ||||
-rw-r--r-- | drivers/staging/wfx/bus_sdio.c | 17 | ||||
-rw-r--r-- | drivers/staging/wfx/bus_spi.c | 16 | ||||
-rw-r--r-- | drivers/staging/wfx/hif_tx.c | 3 | ||||
-rw-r--r-- | drivers/staging/wfx/main.c | 28 | ||||
-rw-r--r-- | drivers/staging/wfx/wfx.h | 1 |
7 files changed, 47 insertions, 21 deletions
diff --git a/drivers/staging/wfx/bh.c b/drivers/staging/wfx/bh.c index d3e7eed89c38..2572fbcf1a33 100644 --- a/drivers/staging/wfx/bh.c +++ b/drivers/staging/wfx/bh.c @@ -320,6 +320,7 @@ void wfx_bh_poll_irq(struct wfx_dev *wdev) ktime_t now, start; u32 reg; + WARN(!wdev->poll_irq, "unexpected IRQ polling can mask IRQ"); start = ktime_get(); for (;;) { control_reg_read(wdev, ®); diff --git a/drivers/staging/wfx/bus.h b/drivers/staging/wfx/bus.h index 62d6ecabe4cb..0370b6c59863 100644 --- a/drivers/staging/wfx/bus.h +++ b/drivers/staging/wfx/bus.h @@ -25,6 +25,8 @@ struct hwbus_ops { void *dst, size_t count); int (*copy_to_io)(void *bus_priv, unsigned int addr, const void *src, size_t count); + int (*irq_subscribe)(void *bus_priv); + int (*irq_unsubscribe)(void *bus_priv); void (*lock)(void *bus_priv); void (*unlock)(void *bus_priv); size_t (*align_size)(void *bus_priv, size_t size); diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c index 43a6b10c772a..6464b2c508e4 100644 --- a/drivers/staging/wfx/bus_sdio.c +++ b/drivers/staging/wfx/bus_sdio.c @@ -106,8 +106,9 @@ static irqreturn_t wfx_sdio_irq_handler_ext(int irq, void *priv) return IRQ_HANDLED; } -static int wfx_sdio_irq_subscribe(struct wfx_sdio_priv *bus) +static int wfx_sdio_irq_subscribe(void *priv) { + struct wfx_sdio_priv *bus = priv; u32 flags; int ret; u8 cccr; @@ -134,8 +135,9 @@ static int wfx_sdio_irq_subscribe(struct wfx_sdio_priv *bus) "wfx", bus); } -static int wfx_sdio_irq_unsubscribe(struct wfx_sdio_priv *bus) +static int wfx_sdio_irq_unsubscribe(void *priv) { + struct wfx_sdio_priv *bus = priv; int ret; if (bus->of_irq) @@ -156,6 +158,8 @@ static size_t wfx_sdio_align_size(void *priv, size_t size) static const struct hwbus_ops wfx_sdio_hwbus_ops = { .copy_from_io = wfx_sdio_copy_from_io, .copy_to_io = wfx_sdio_copy_to_io, + .irq_subscribe = wfx_sdio_irq_subscribe, + .irq_unsubscribe = wfx_sdio_irq_unsubscribe, .lock = wfx_sdio_lock, .unlock = wfx_sdio_unlock, .align_size = wfx_sdio_align_size, @@ -218,18 +222,12 @@ static int wfx_sdio_probe(struct sdio_func *func, goto err1; } - ret = wfx_sdio_irq_subscribe(bus); - if (ret) - goto err1; - ret = wfx_probe(bus->core); if (ret) - goto err2; + goto err1; return 0; -err2: - wfx_sdio_irq_unsubscribe(bus); err1: sdio_claim_host(func); sdio_disable_func(func); @@ -243,7 +241,6 @@ static void wfx_sdio_remove(struct sdio_func *func) struct wfx_sdio_priv *bus = sdio_get_drvdata(func); wfx_release(bus->core); - wfx_sdio_irq_unsubscribe(bus); 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 00613d046c3f..e8da61fb096b 100644 --- a/drivers/staging/wfx/bus_spi.c +++ b/drivers/staging/wfx/bus_spi.c @@ -12,6 +12,7 @@ #include <linux/gpio/consumer.h> #include <linux/spi/spi.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/of.h> #include "bus.h" @@ -143,8 +144,9 @@ static irqreturn_t wfx_spi_irq_handler(int irq, void *priv) return IRQ_HANDLED; } -static int wfx_spi_irq_subscribe(struct wfx_spi_priv *bus) +static int wfx_spi_irq_subscribe(void *priv) { + struct wfx_spi_priv *bus = priv; u32 flags; flags = irq_get_trigger_type(bus->func->irq); @@ -156,6 +158,14 @@ static int wfx_spi_irq_subscribe(struct wfx_spi_priv *bus) "wfx", bus); } +static int wfx_spi_irq_unsubscribe(void *priv) +{ + struct wfx_spi_priv *bus = priv; + + devm_free_irq(&bus->func->dev, bus->func->irq, bus); + return 0; +} + static size_t wfx_spi_align_size(void *priv, size_t size) { // Most of SPI controllers avoid DMA if buffer size is not 32bit aligned @@ -165,6 +175,8 @@ static size_t wfx_spi_align_size(void *priv, size_t size) static const struct hwbus_ops wfx_spi_hwbus_ops = { .copy_from_io = wfx_spi_copy_from_io, .copy_to_io = wfx_spi_copy_to_io, + .irq_subscribe = wfx_spi_irq_subscribe, + .irq_unsubscribe = wfx_spi_irq_unsubscribe, .lock = wfx_spi_lock, .unlock = wfx_spi_unlock, .align_size = wfx_spi_align_size, @@ -216,8 +228,6 @@ static int wfx_spi_probe(struct spi_device *func) if (!bus->core) return -EIO; - wfx_spi_irq_subscribe(bus); - return wfx_probe(bus->core); } diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index e8f3c5f9ce7b..511ef874a6d9 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -82,6 +82,9 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, void *reply, if (async) return 0; + if (wdev->poll_irq) + wfx_bh_poll_irq(wdev); + ret = wait_for_completion_timeout(&wdev->hif_cmd.done, 1 * HZ); if (!ret) { dev_err(wdev->dev, "chip is abnormally long to answer\n"); diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c index 5d0754b55429..623a9fc31153 100644 --- a/drivers/staging/wfx/main.c +++ b/drivers/staging/wfx/main.c @@ -363,22 +363,24 @@ int wfx_probe(struct wfx_dev *wdev) // prevent bh() to touch it. gpio_saved = wdev->pdata.gpio_wakeup; wdev->pdata.gpio_wakeup = NULL; + wdev->poll_irq = true; wfx_bh_register(wdev); err = wfx_init_device(wdev); if (err) - goto err1; + goto err0; + wfx_bh_poll_irq(wdev); err = wait_for_completion_timeout(&wdev->firmware_ready, 1 * HZ); if (err <= 0) { if (err == 0) { - dev_err(wdev->dev, "timeout while waiting for startup indication. IRQ configuration error?\n"); + dev_err(wdev->dev, "timeout while waiting for startup indication\n"); err = -ETIMEDOUT; } else if (err == -ERESTARTSYS) { dev_info(wdev->dev, "probe interrupted by user\n"); } - goto err1; + goto err0; } // FIXME: fill wiphy::hw_version @@ -400,14 +402,14 @@ int wfx_probe(struct wfx_dev *wdev) "unsupported firmware API version (expect 1 while firmware returns %d)\n", wdev->hw_caps.api_version_major); err = -ENOTSUPP; - goto err1; + goto err0; } err = wfx_sl_init(wdev); if (err && wdev->hw_caps.capabilities.link_mode == SEC_LINK_ENFORCED) { dev_err(wdev->dev, "chip require secure_link, but can't negociate it\n"); - goto err1; + goto err0; } if (wdev->hw_caps.regul_sel_mode_info.region_sel_mode) { @@ -420,7 +422,16 @@ int wfx_probe(struct wfx_dev *wdev) wdev->pdata.file_pds); err = wfx_send_pdata_pds(wdev); if (err < 0) - goto err1; + goto err0; + + wdev->poll_irq = false; + err = wdev->hwbus_ops->irq_subscribe(wdev->hwbus_priv); + if (err) + goto err0; + + err = hif_use_multi_tx_conf(wdev, true); + if (err) + dev_err(wdev->dev, "misconfigured IRQ?\n"); wdev->pdata.gpio_wakeup = gpio_saved; if (wdev->pdata.gpio_wakeup) { @@ -435,8 +446,6 @@ int wfx_probe(struct wfx_dev *wdev) hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_DOZE); } - hif_use_multi_tx_conf(wdev, true); - for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) { eth_zero_addr(wdev->addresses[i].addr); macaddr = of_get_mac_address(wdev->dev->of_node); @@ -470,6 +479,8 @@ int wfx_probe(struct wfx_dev *wdev) err2: ieee80211_unregister_hw(wdev->hw); err1: + wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); +err0: wfx_bh_unregister(wdev); return err; } @@ -478,6 +489,7 @@ void wfx_release(struct wfx_dev *wdev) { ieee80211_unregister_hw(wdev->hw); hif_shutdown(wdev); + wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); wfx_bh_unregister(wdev); wfx_sl_deinit(wdev); } diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 09bbb5da4f06..4eb7762142fc 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -46,6 +46,7 @@ struct wfx_dev { struct wfx_hif hif; struct sl_context sl; struct delayed_work cooling_timeout_work; + bool poll_irq; bool chip_frozen; struct mutex conf_mutex; |