aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2019-10-25 09:28:17 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2019-11-06 09:41:27 +0100
commitc9f4996df9c950561f9caa6cca1158cb28111fb2 (patch)
tree6f872d3530ab14d492ad94d3624782cfa633d8f2
parentb103fe822cb1df7dcbbfcd5b84ad78ab1ddeb6bc (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.c49
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 */