mmc: core: Fix error paths for UHS-II card init and re-init

The error path didn't manage the removal of the allocated mmc_card
correctly. Let's fix this to avoid potential memory leaks.

While at it, move the assignment of host->card to slightly later in the
init process and drop also a somewhat silly dev_warn() when CMD8 fails.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Message-ID: <20241029131752.226764-4-ulf.hansson@linaro.org>
This commit is contained in:
Ulf Hansson 2024-10-29 14:17:49 +01:00
parent 7acbd2da48
commit 88df25ad0c

View File

@ -827,24 +827,28 @@ static int sd_uhs2_init_card(struct mmc_host *host, struct mmc_card *oldcard)
err = sd_uhs2_config_read(host, card);
if (err)
return err;
goto err;
err = sd_uhs2_config_write(host, card);
if (err)
return err;
goto err;
host->card = card;
/* If change speed to Range B, need to GO_DORMANT_STATE */
if (host->ios.timing == MMC_TIMING_UHS2_SPEED_B ||
host->ios.timing == MMC_TIMING_UHS2_SPEED_B_HD) {
err = sd_uhs2_go_dormant_state(host, node_id);
if (err)
return err;
goto err;
}
host->uhs2_sd_tran = true;
host->card = card;
return 0;
err:
if (!oldcard)
mmc_remove_card(card);
return err;
}
/*
@ -855,7 +859,7 @@ static int sd_uhs2_init_card(struct mmc_host *host, struct mmc_card *oldcard)
* survives a soft reset through the GO_DORMANT_STATE command.
*/
static int sd_uhs2_legacy_init(struct mmc_host *host, struct mmc_card *card,
struct mmc_card *oldcard)
bool reinit)
{
int err;
u32 cid[4];
@ -873,17 +877,15 @@ static int sd_uhs2_legacy_init(struct mmc_host *host, struct mmc_card *card,
/* Send CMD8 to communicate SD interface operation condition */
err = mmc_send_if_cond(host, host->ocr_avail);
if (err) {
dev_warn(mmc_dev(host), "CMD8 error\n");
goto err;
}
if (err)
return err;
/*
* Probe SD card working voltage.
*/
err = mmc_send_app_op_cond(host, 0, &ocr);
if (err)
goto err;
return err;
card->ocr = ocr;
@ -907,20 +909,18 @@ static int sd_uhs2_legacy_init(struct mmc_host *host, struct mmc_card *card,
err = mmc_send_app_op_cond(host, ocr, &rocr);
if (err)
goto err;
return err;
err = mmc_send_cid(host, cid);
if (err)
goto err;
return err;
if (oldcard) {
if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
if (reinit) {
if (memcmp(cid, card->raw_cid, sizeof(cid)) != 0) {
pr_debug("%s: Perhaps the card was replaced\n",
mmc_hostname(host));
return -ENOENT;
}
card = oldcard;
} else {
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
mmc_decode_cid(card);
@ -931,29 +931,29 @@ static int sd_uhs2_legacy_init(struct mmc_host *host, struct mmc_card *card,
*/
err = mmc_send_relative_addr(host, &card->rca);
if (err)
goto err;
return err;
err = mmc_sd_get_csd(card, false);
if (err)
goto err;
return err;
/*
* Select card, as all following commands rely on that.
*/
err = mmc_select_card(card);
if (err)
goto err;
return err;
/*
* Fetch SCR from card.
*/
err = mmc_app_send_scr(card);
if (err)
goto err;
return err;
err = mmc_decode_scr(card);
if (err)
goto err;
return err;
/*
* Switch to high power consumption mode.
@ -989,9 +989,6 @@ static int sd_uhs2_legacy_init(struct mmc_host *host, struct mmc_card *card,
kfree(status);
return 0;
err:
return err;
}
static int sd_uhs2_reinit(struct mmc_host *host)
@ -1011,7 +1008,7 @@ static int sd_uhs2_reinit(struct mmc_host *host)
if (err)
return err;
return sd_uhs2_legacy_init(host, card, card);
return sd_uhs2_legacy_init(host, card, true);
}
static void sd_uhs2_remove(struct mmc_host *host)
@ -1172,9 +1169,9 @@ static int sd_uhs2_attach(struct mmc_host *host)
if (err)
goto err;
err = sd_uhs2_legacy_init(host, host->card, NULL);
err = sd_uhs2_legacy_init(host, host->card, false);
if (err)
goto err;
goto remove_card;
mmc_attach_bus(host, &sd_uhs2_ops);
@ -1185,13 +1182,11 @@ static int sd_uhs2_attach(struct mmc_host *host)
goto remove_card;
mmc_claim_host(host);
return 0;
remove_card:
sd_uhs2_remove(host);
mmc_claim_host(host);
err:
mmc_detach_bus(host);
sd_uhs2_power_off(host);