[PATCH v2 2/2] mmc: rtsx_usb_sdmmc: suppress false CD after init timeout
Sean Rhodes <[email protected]> Mon, 6 Jul 2026 16:40:44 +0100
| Newsgroups | org.kernel.vger.linux-mmc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <1d6f22a3777e78d6232cbe7dc3aa17ded8fc32e2.1783352430.git.sean@starlabs.systems> |
Some Realtek USB SD readers with a tray keep raw SD_CD asserted when an empty tray is inserted. The MMC core then repeatedly tries to initialize non-existent media, sees command timeouts, calls ->get_cd() again, and starts the same detect cycle over. Do not qualify media by open-coding MMC commands in ->get_cd(). Instead, let the normal MMC rescan path probe the card. If an initialization command times out before a card has been attached, suppress the raw SD_CD signal so the host can settle and the USB parent can autosuspend. Clear the suppression only when raw SD_CD drops. On the affected tray reader, changing media requires removing and reinserting the tray, so a low CD transition is the signal that a new insertion attempt can be trusted again. Signed-off-by: Sean Rhodes <[email protected]> --- drivers/mmc/host/rtsx_usb_sdmmc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 84674659a84d..bf37fab233cf 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c @@ -44,6 +44,7 @@ struct rtsx_usb_sdmmc { bool double_clk; bool host_removal; bool card_exist; + bool suppress_cd; bool initial_mode; bool ddr_mode; @@ -774,6 +775,7 @@ static int sdmmc_get_cd(struct mmc_host *mmc) struct rtsx_ucr *ucr = host->ucr; int err; u16 val; + bool cd; if (host->host_removal) return -ENOMEDIUM; @@ -791,8 +793,14 @@ static int sdmmc_get_cd(struct mmc_host *mmc) /* get OCP status */ host->ocp_stat = (val >> 4) & 0x03; + cd = val & SD_CD; - if (val & SD_CD) { + if (!cd) { + WRITE_ONCE(host->suppress_cd, false); + goto no_card; + } + + if (!READ_ONCE(host->suppress_cd)) { host->card_exist = true; return 1; } @@ -874,6 +882,8 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) * detect card when fail to update card existence state and * speed up card removal when retry */ + if (!mmc->card && cmd->error == -ETIMEDOUT) + WRITE_ONCE(host->suppress_cd, true); sdmmc_get_cd(mmc); dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); } @@ -1359,6 +1369,7 @@ static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host) host->power_mode = MMC_POWER_OFF; host->ocp_stat = 0; + host->suppress_cd = false; } static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev)