From cdb2256f795e8e78cc43f32d091695b127dfb4df Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 25 Oct 2019 09:28:17 +0200 Subject: mwifiex: Re-work support for SDIO HW reset The SDIO HW reset procedure in mwifiex_sdio_card_reset_work() is broken, when the SDIO card is shared with another SDIO func driver. This is the case when the Bluetooth btmrvl driver is being used in combination with mwifiex. More precisely, when mwifiex_sdio_card_reset_work() runs to resets the SDIO card, the btmrvl driver doesn't get notified about it. Beyond that point, the btmrvl driver will fail to communicate with the SDIO card. This is a generic problem for SDIO func drivers sharing an SDIO card, which are about to be addressed in subsequent changes to the mmc core and the mmc_hw_reset() interface. In principle, these changes means the mmc_hw_reset() interface starts to return 1 if the are multiple drivers for the SDIO card, as to indicate to the caller that the reset needed to be scheduled asynchronously through a hotplug mechanism of the SDIO card. Let's prepare the mwifiex driver to support the upcoming new behaviour of mmc_hw_reset(), which means extending the mwifiex_sdio_card_reset_work() to support the asynchronous SDIO HW reset path. This also means, we need to allow the ->remove() callback to run, without waiting for the FW to be loaded. Additionally, during system suspend, mwifiex_sdio_suspend() may be called when a reset has been scheduled, but waiting to be executed. In this scenario let's simply return -EBUSY to abort the suspend process, as to allow the reset to be completed first. Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson Cc: stable@vger.kernel.org # v5.4+ Acked-by: Kalle Valo Signed-off-by: Ulf Hansson --- drivers/net/wireless/marvell/mwifiex/main.c | 5 ++++- drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/sdio.c | 33 +++++++++++++++++++---------- 3 files changed, 27 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index a9657ae6d782..d14e55e3c9da 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -631,6 +631,7 @@ static int _mwifiex_fw_dpc(const struct firmware *firmware, void *context) mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); mwifiex_dbg(adapter, MSG, "driver_version = %s\n", fmt); + adapter->is_up = true; goto done; err_add_intf: @@ -1469,6 +1470,7 @@ int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter) mwifiex_deauthenticate(priv, NULL); mwifiex_uninit_sw(adapter); + adapter->is_up = false; if (adapter->if_ops.down_dev) adapter->if_ops.down_dev(adapter); @@ -1730,7 +1732,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter) if (!adapter) return 0; - mwifiex_uninit_sw(adapter); + if (adapter->is_up) + mwifiex_uninit_sw(adapter); if (adapter->irq_wakeup >= 0) device_init_wakeup(adapter->dev, false); diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 095837fba300..547ff3c578ee 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1017,6 +1017,7 @@ struct mwifiex_adapter { /* For synchronizing FW initialization with device lifecycle. */ struct completion *fw_done; + bool is_up; bool ext_scan; u8 fw_api_ver; diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index 24c041dad9f6..fec38b6e86ff 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -444,6 +444,9 @@ static int mwifiex_sdio_suspend(struct device *dev) return 0; } + if (!adapter->is_up) + return -EBUSY; + mwifiex_enable_wake(adapter); /* Enable the Host Sleep */ @@ -2220,22 +2223,30 @@ static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) struct sdio_func *func = card->func; int ret; + /* Prepare the adapter for the reset. */ mwifiex_shutdown_sw(adapter); + clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); + clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags); - /* power cycle the adapter */ + /* Run a HW reset of the SDIO interface. */ sdio_claim_host(func); - mmc_hw_reset(func->card->host); + ret = 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); + switch (ret) { + case 1: + dev_dbg(&func->dev, "SDIO HW reset asynchronous\n"); + complete_all(adapter->fw_done); + break; + case 0: + ret = mwifiex_reinit_sw(adapter); + if (ret) + dev_err(&func->dev, "reinit failed: %d\n", ret); + break; + default: + dev_err(&func->dev, "SDIO HW reset failed: %d\n", ret); + break; + } } /* This function read/write firmware */ -- cgit v1.2.3-59-g8ed1b From 9b8d7072d6552ee5c57e5765f211f267041f9557 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Thu, 7 Nov 2019 11:30:35 +0100 Subject: net: wireless: ti: wl1251 add device tree support We will have the wl1251 defined as a child node of the mmc interface and can read setup for gpios, interrupts and the ti,use-eeprom property from there instead of pdata to be provided by pdata-quirks. Fixes: 81eef6ca9201 ("mmc: omap_hsmmc: Use dma_request_chan() for requesting DMA channel") Signed-off-by: H. Nikolaus Schaller Acked-by: Kalle Valo Cc: # v4.7+ [Ulf: Fixed up some complaints from checkpatch] Signed-off-by: Ulf Hansson --- drivers/net/wireless/ti/wl1251/sdio.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index 677f1146ccf0..f1224b948f83 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include #include "wl1251.h" @@ -217,6 +220,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, struct ieee80211_hw *hw; struct wl1251_sdio *wl_sdio; const struct wl1251_platform_data *wl1251_board_data; + struct device_node *np = func->dev.of_node; hw = wl1251_alloc_hw(); if (IS_ERR(hw)) @@ -248,6 +252,17 @@ static int wl1251_sdio_probe(struct sdio_func *func, wl->power_gpio = wl1251_board_data->power_gpio; wl->irq = wl1251_board_data->irq; wl->use_eeprom = wl1251_board_data->use_eeprom; + } else if (np) { + wl->use_eeprom = of_property_read_bool(np, + "ti,wl1251-has-eeprom"); + wl->power_gpio = of_get_named_gpio(np, "ti,power-gpio", 0); + wl->irq = of_irq_get(np, 0); + + if (wl->power_gpio == -EPROBE_DEFER || + wl->irq == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto disable; + } } if (gpio_is_valid(wl->power_gpio)) { -- cgit v1.2.3-59-g8ed1b From d8620bbc32541a30f84154007defad917f5179f0 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Thu, 7 Nov 2019 11:30:44 +0100 Subject: net: wireless: ti: wl1251 use new SDIO_VENDOR_ID_TI_WL1251 definition SDIO_VENDOR_ID_TI_WL1251 is now defined in mmc/sdio_ids.h separately from SDIO_VENDOR_ID_TI for wl1271. Fixes: 884f38607897 ("mmc: core: move some sdio IDs out of quirks file") Signed-off-by: H. Nikolaus Schaller Acked-by: Kalle Valo Cc: # v4.11+ Signed-off-by: Ulf Hansson --- drivers/net/wireless/ti/wl1251/sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index f1224b948f83..ac677309dab6 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c @@ -52,7 +52,7 @@ static void wl1251_sdio_interrupt(struct sdio_func *func) } static const struct sdio_device_id wl1251_devices[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) }, + { SDIO_DEVICE(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251) }, {} }; MODULE_DEVICE_TABLE(sdio, wl1251_devices); -- cgit v1.2.3-59-g8ed1b From b2bf5015dae3a427166768bc6ca4f300247f9554 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Thu, 7 Nov 2019 11:30:45 +0100 Subject: net: wireless: ti: remove local VENDOR_ID and DEVICE_ID definitions They are already included from mmc/sdio_ids.h and do not need a local definition. Fixes: 884f38607897 ("mmc: core: move some sdio IDs out of quirks file") Signed-off-by: H. Nikolaus Schaller Acked-by: Kalle Valo Cc: # v4.11+ Signed-off-by: Ulf Hansson --- drivers/net/wireless/ti/wl1251/sdio.c | 8 -------- drivers/net/wireless/ti/wlcore/sdio.c | 8 -------- 2 files changed, 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index ac677309dab6..94569cd695c8 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c @@ -22,14 +22,6 @@ #include "wl1251.h" -#ifndef SDIO_VENDOR_ID_TI -#define SDIO_VENDOR_ID_TI 0x104c -#endif - -#ifndef SDIO_DEVICE_ID_TI_WL1251 -#define SDIO_DEVICE_ID_TI_WL1251 0x9066 -#endif - struct wl1251_sdio { struct sdio_func *func; u32 elp_val; diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 7afaf35f2453..9fd8cf2d270c 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -26,14 +26,6 @@ #include "wl12xx_80211.h" #include "io.h" -#ifndef SDIO_VENDOR_ID_TI -#define SDIO_VENDOR_ID_TI 0x0097 -#endif - -#ifndef SDIO_DEVICE_ID_TI_WL1271 -#define SDIO_DEVICE_ID_TI_WL1271 0x4076 -#endif - static bool dump = false; struct wl12xx_sdio_glue { -- cgit v1.2.3-59-g8ed1b