Skip to content

Commit

Permalink
Merge tag 'mmc-v6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/ulfh/mmc

Pull MMC fixes from Ulf Hansson:
 "MMC core:
   - Cancel recovery work on cleanup to avoid NULL pointer dereference
   - Fix error path in the read/write error recovery path
   - Fix kernel panic when remove non-standard SDIO card
   - Fix WRITE_ZEROES handling for CQE

  MMC host:
   - sdhci_am654: Fixup Kconfig dependency for REGMAP_MMIO
   - sdhci-esdhc-imx: Avoid warning of misconfigured bus-width
   - sdhci-pci: Disable broken HS400 ES mode for ASUS BIOS on Jasper
     Lake"

* tag 'mmc-v6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: sdhci_am654: 'select', not 'depends' REGMAP_MMIO
  mmc: core: Fix WRITE_ZEROES CQE handling
  mmc: core: Fix kernel panic when remove non-standard SDIO card
  mmc: sdhci-pci-core: Disable ES for ASUS BIOS on Jasper Lake
  mmc: sdhci-esdhc-imx: Propagate ESDHC_FLAG_HS400* only on 8bit bus
  mmc: queue: Cancel recovery work on cleanup
  mmc: block: Remove error check of hw_reset on reset
  • Loading branch information
torvalds committed Oct 28, 2022
2 parents 2eb824f + 8d280b1 commit 18937b0
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 29 deletions.
44 changes: 26 additions & 18 deletions drivers/mmc/core/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct mmc_blk_data {
* track of the current selected device partition.
*/
unsigned int part_curr;
#define MMC_BLK_PART_INVALID UINT_MAX /* Unknown partition active */
int area_type;

/* debugfs files (only in main mmc_blk_data) */
Expand Down Expand Up @@ -987,33 +988,39 @@ static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host,
return ms;
}

/*
* Attempts to reset the card and get back to the requested partition.
* Therefore any error here must result in cancelling the block layer
* request, it must not be reattempted without going through the mmc_blk
* partition sanity checks.
*/
static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
int type)
{
int err;
struct mmc_blk_data *main_md = dev_get_drvdata(&host->card->dev);

if (md->reset_done & type)
return -EEXIST;

md->reset_done |= type;
err = mmc_hw_reset(host->card);
/*
* A successful reset will leave the card in the main partition, but
* upon failure it might not be, so set it to MMC_BLK_PART_INVALID
* in that case.
*/
main_md->part_curr = err ? MMC_BLK_PART_INVALID : main_md->part_type;
if (err)
return err;
/* Ensure we switch back to the correct partition */
if (err) {
struct mmc_blk_data *main_md =
dev_get_drvdata(&host->card->dev);
int part_err;

main_md->part_curr = main_md->part_type;
part_err = mmc_blk_part_switch(host->card, md->part_type);
if (part_err) {
/*
* We have failed to get back into the correct
* partition, so we need to abort the whole request.
*/
return -ENODEV;
}
}
return err;
if (mmc_blk_part_switch(host->card, md->part_type))
/*
* We have failed to get back into the correct
* partition, so we need to abort the whole request.
*/
return -ENODEV;
return 0;
}

static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
Expand Down Expand Up @@ -1871,8 +1878,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req)
return;

/* Reset before last retry */
if (mqrq->retries + 1 == MMC_MAX_RETRIES)
mmc_blk_reset(md, card->host, type);
if (mqrq->retries + 1 == MMC_MAX_RETRIES &&
mmc_blk_reset(md, card->host, type))
return;

/* Command errors fail fast, so use all MMC_MAX_RETRIES */
if (brq->sbc.error || brq->cmd.error)
Expand Down
8 changes: 8 additions & 0 deletions drivers/mmc/core/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static enum mmc_issue_type mmc_cqe_issue_type(struct mmc_host *host,
case REQ_OP_DRV_OUT:
case REQ_OP_DISCARD:
case REQ_OP_SECURE_ERASE:
case REQ_OP_WRITE_ZEROES:
return MMC_ISSUE_SYNC;
case REQ_OP_FLUSH:
return mmc_cqe_can_dcmd(host) ? MMC_ISSUE_DCMD : MMC_ISSUE_SYNC;
Expand Down Expand Up @@ -493,6 +494,13 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
if (blk_queue_quiesced(q))
blk_mq_unquiesce_queue(q);

/*
* If the recovery completes the last (and only remaining) request in
* the queue, and the card has been removed, we could end up here with
* the recovery not quite finished yet, so cancel it.
*/
cancel_work_sync(&mq->recovery_work);

blk_mq_free_tag_set(&mq->tag_set);

/*
Expand Down
3 changes: 2 additions & 1 deletion drivers/mmc/core/sdio_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ static void sdio_release_func(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);

sdio_free_func_cis(func);
if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO))
sdio_free_func_cis(func);

kfree(func->info);
kfree(func->tmpbuf);
Expand Down
3 changes: 2 additions & 1 deletion drivers/mmc/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1075,9 +1075,10 @@ config MMC_SDHCI_OMAP

config MMC_SDHCI_AM654
tristate "Support for the SDHCI Controller in TI's AM654 SOCs"
depends on MMC_SDHCI_PLTFM && OF && REGMAP_MMIO
depends on MMC_SDHCI_PLTFM && OF
select MMC_SDHCI_IO_ACCESSORS
select MMC_CQHCI
select REGMAP_MMIO
help
This selects the Secure Digital Host Controller Interface (SDHCI)
support present in TI's AM654 SOCs. The controller supports
Expand Down
14 changes: 8 additions & 6 deletions drivers/mmc/host/sdhci-esdhc-imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1660,20 +1660,26 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
host->mmc_host_ops.execute_tuning = usdhc_execute_tuning;
}

err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
if (err)
goto disable_ahb_clk;

if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
sdhci_esdhc_ops.platform_execute_tuning =
esdhc_executing_tuning;

if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;

if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
if (host->caps & MMC_CAP_8_BIT_DATA &&
imx_data->socdata->flags & ESDHC_FLAG_HS400)
host->mmc->caps2 |= MMC_CAP2_HS400;

if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23)
host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN;

if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
if (host->caps & MMC_CAP_8_BIT_DATA &&
imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
host->mmc->caps2 |= MMC_CAP2_HS400_ES;
host->mmc_host_ops.hs400_enhanced_strobe =
esdhc_hs400_enhanced_strobe;
Expand All @@ -1695,10 +1701,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
goto disable_ahb_clk;
}

err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
if (err)
goto disable_ahb_clk;

sdhci_esdhc_imx_hwinit(host);

err = sdhci_add_host(host);
Expand Down
14 changes: 11 additions & 3 deletions drivers/mmc/host/sdhci-pci-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,12 @@ static bool glk_broken_cqhci(struct sdhci_pci_slot *slot)
dmi_match(DMI_SYS_VENDOR, "IRBIS"));
}

static bool jsl_broken_hs400es(struct sdhci_pci_slot *slot)
{
return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_JSL_EMMC &&
dmi_match(DMI_BIOS_VENDOR, "ASUSTeK COMPUTER INC.");
}

static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
{
int ret = byt_emmc_probe_slot(slot);
Expand All @@ -922,9 +928,11 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
slot->host->mmc->caps2 |= MMC_CAP2_CQE;

if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) {
slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES;
slot->host->mmc_host_ops.hs400_enhanced_strobe =
intel_hs400_enhanced_strobe;
if (!jsl_broken_hs400es(slot)) {
slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES;
slot->host->mmc_host_ops.hs400_enhanced_strobe =
intel_hs400_enhanced_strobe;
}
slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD;
}

Expand Down

0 comments on commit 18937b0

Please sign in to comment.