diff --git a/bes2600/bes2600_sdio.c b/bes2600/bes2600_sdio.c index deefba9..c0b67b0 100644 --- a/bes2600/bes2600_sdio.c +++ b/bes2600/bes2600_sdio.c @@ -1789,10 +1789,32 @@ static void bes2600_sdio_halt_device(struct sbus_priv *self) */ static int bes2600_sdio_bus_reset(struct sbus_priv *self) { + struct mmc_host *host; + int ret; + if (!self || !self->func || !self->func->card) return -EINVAL; - return mmc_hw_reset(self->func->card); + host = self->func->card->host; + ret = mmc_hw_reset(self->func->card); + + /* + * On multi-function SDIO cards (BES2600 has WLAN func 1 + BT + * companion func 2), mmc_sdio_hw_reset() removes the card and + * returns 1 to signal "remove happened, caller must trigger + * rescan". The kernel does NOT auto-rescan in this case; + * single-function cards take the rescan path inline and return 0. + * Treat any non-negative return as success and force a rescan if + * mmc_hw_reset signalled the multi-function path - otherwise the + * card stays removed indefinitely after a wedge recovery, + * leaving wifi (and the BT companion) silent until reboot. + */ + if (ret > 0) { + bes_info("multi-func mmc_hw_reset removed card; scheduling rescan\n"); + mmc_detect_change(host, 0); + ret = 0; + } + return ret; } static bool bes2600_sdio_wakeup_source(struct sbus_priv *self)