At least HiKey board can fail to bring up wireless interface again
if the interface is brought down and up with no delay inbetween.

This can be done tested with:

# while true; do ifconfig wlan0 down; ifconfig wlan0 up; done

According to Ricardo Salveti <[email protected]>, we need to
wait between 30 - 40 ms on HiKey. This seems to happen when we
get -EBUSY returned by pm_runtime_put() basedon the check in
rpm_check_suspend_allowed(). But as it still unclear if part of
the delay needed is because of capacitance, let's always do a
at least 50 ms msleep even if no -EBUSY is returned.

Cc: Anders Roxell <[email protected]>
Cc: Eyal Reizer <[email protected]>
Cc: John Stultz <[email protected]>
Cc: Ricardo Salveti <[email protected]>
Cc: Ulf Hansson <[email protected]>
Reported-by: Ricardo Salveti <[email protected]>
Fixes: 60f36637bbbd ("wlcore: sdio: allow pm to handle sdio power")
Signed-off-by: Tony Lindgren <[email protected]>
---

Uffe, do you have some better ideas on how to fix this issue?

---
 drivers/net/wireless/ti/wlcore/sdio.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wlcore/sdio.c 
b/drivers/net/wireless/ti/wlcore/sdio.c
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -174,7 +174,7 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue 
*glue)
 {
        struct sdio_func *func = dev_to_sdio_func(glue->dev);
        struct mmc_card *card = func->card;
-       int error;
+       int error, retries = 5;
 
        sdio_claim_host(func);
        sdio_disable_func(func);
@@ -188,6 +188,17 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue 
*glue)
                return error;
        }
 
+       /* Wait a bit to ensure the card gets power off. Otherwise
+        * bringing interface down and up again may not power off the
+        * card inbetween. And then firmware load will fail on trying
+        * to bring the card up again. We need to wait between 30 - 40
+        * ms for this based on measurements on HiKey board.
+        */
+       do {
+               msleep(50);
+       } while (error == -EBUSY && !pm_runtime_suspended(&card->dev) &&
+                retries--);
+
        return 0;
 }
 
-- 
2.19.2

Reply via email to