diff options
author | Ulf Hansson <ulf.hansson@linaro.org> | 2019-10-25 09:28:17 +0200 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2019-11-06 09:41:27 +0100 |
commit | c9f4996df9c950561f9caa6cca1158cb28111fb2 (patch) | |
tree | 6f872d3530ab14d492ad94d3624782cfa633d8f2 | |
parent | b103fe822cb1df7dcbbfcd5b84ad78ab1ddeb6bc (diff) |
mwifiex: Re-work support for SDIO HW resetref_sdio_hw_reset_notify
To fix the HW reset behaviour when multiple SDIO funcs shares the same SDIO
card, the SDIO core have added support for SDIO func reset notifiers.
These are used to inform clients about the reset process, which allows them
to take relevant actions.
As a mwifiex SDIO func can shared the SDIO interface with a bluetooth SDIO
func, this is needed to properly support SDIO HW reset. Therefore, register
the corresponding notifier with the SDIO core and implement support for
this.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/sdio.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index 24c041dad9f6..ebce0b3e1913 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -32,6 +32,8 @@ #define SDIO_VERSION "1.0" static void mwifiex_sdio_work(struct work_struct *work); +static int mwifiex_sdio_nb(struct notifier_block *nb, unsigned long val, + void *data); static struct mwifiex_if_ops sdio_ops; @@ -147,6 +149,8 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) goto err_disable; } + func->nb.notifier_call = mwifiex_sdio_nb; + sdio_add_notifier(func); return 0; err_disable: @@ -377,6 +381,8 @@ mwifiex_sdio_remove(struct sdio_func *func) int ret = 0; u16 firmware_stat; + sdio_remove_notifier(func); + card = sdio_get_drvdata(func); if (!card) return; @@ -2214,28 +2220,43 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) port, card->mp_data_port_mask); } -static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) +static int mwifiex_sdio_nb(struct notifier_block *nb, unsigned long val, + void *data) { - struct sdio_mmc_card *card = adapter->card; - struct sdio_func *func = card->func; + struct sdio_func *func = nb_to_sdio_func(nb); + struct sdio_mmc_card *card; int ret; - mwifiex_shutdown_sw(adapter); + card = sdio_get_drvdata(func); + if (!card || !card->adapter) + return 0; + + switch (val) { + case SDIO_HW_RESET_PREP: + mwifiex_shutdown_sw(adapter); + clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); + clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags); + break; + case SDIO_HW_RESET_POST: + ret = mwifiex_reinit_sw(adapter); + if (ret) + dev_err(&func->dev, "reinit failed: %d\n", ret); + break; + default: + break; + } + + return 0; +} + +static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) +{ + struct sdio_func *func = adapter->card->func; /* power cycle the adapter */ sdio_claim_host(func); mmc_hw_reset(func->card->host); sdio_release_host(func); - - /* Previous save_adapter won't be valid after this. We will cancel - * pending work requests. - */ - clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); - clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags); - - ret = mwifiex_reinit_sw(adapter); - if (ret) - dev_err(&func->dev, "reinit failed: %d\n", ret); } /* This function read/write firmware */ |