Commit 18937b04 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/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
parents 2eb824f6 8d280b1d
...@@ -134,6 +134,7 @@ struct mmc_blk_data { ...@@ -134,6 +134,7 @@ struct mmc_blk_data {
* track of the current selected device partition. * track of the current selected device partition.
*/ */
unsigned int part_curr; unsigned int part_curr;
#define MMC_BLK_PART_INVALID UINT_MAX /* Unknown partition active */
int area_type; int area_type;
/* debugfs files (only in main mmc_blk_data) */ /* debugfs files (only in main mmc_blk_data) */
...@@ -987,33 +988,39 @@ static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host, ...@@ -987,33 +988,39 @@ static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host,
return ms; 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, static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
int type) int type)
{ {
int err; int err;
struct mmc_blk_data *main_md = dev_get_drvdata(&host->card->dev);
if (md->reset_done & type) if (md->reset_done & type)
return -EEXIST; return -EEXIST;
md->reset_done |= type; md->reset_done |= type;
err = mmc_hw_reset(host->card); 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 */ /* Ensure we switch back to the correct partition */
if (err) { if (mmc_blk_part_switch(host->card, md->part_type))
struct mmc_blk_data *main_md = /*
dev_get_drvdata(&host->card->dev); * We have failed to get back into the correct
int part_err; * partition, so we need to abort the whole request.
*/
main_md->part_curr = main_md->part_type; return -ENODEV;
part_err = mmc_blk_part_switch(host->card, md->part_type); return 0;
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;
} }
static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
...@@ -1871,8 +1878,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) ...@@ -1871,8 +1878,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req)
return; return;
/* Reset before last retry */ /* Reset before last retry */
if (mqrq->retries + 1 == MMC_MAX_RETRIES) if (mqrq->retries + 1 == MMC_MAX_RETRIES &&
mmc_blk_reset(md, card->host, type); mmc_blk_reset(md, card->host, type))
return;
/* Command errors fail fast, so use all MMC_MAX_RETRIES */ /* Command errors fail fast, so use all MMC_MAX_RETRIES */
if (brq->sbc.error || brq->cmd.error) if (brq->sbc.error || brq->cmd.error)
......
...@@ -48,6 +48,7 @@ static enum mmc_issue_type mmc_cqe_issue_type(struct mmc_host *host, ...@@ -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_DRV_OUT:
case REQ_OP_DISCARD: case REQ_OP_DISCARD:
case REQ_OP_SECURE_ERASE: case REQ_OP_SECURE_ERASE:
case REQ_OP_WRITE_ZEROES:
return MMC_ISSUE_SYNC; return MMC_ISSUE_SYNC;
case REQ_OP_FLUSH: case REQ_OP_FLUSH:
return mmc_cqe_can_dcmd(host) ? MMC_ISSUE_DCMD : MMC_ISSUE_SYNC; return mmc_cqe_can_dcmd(host) ? MMC_ISSUE_DCMD : MMC_ISSUE_SYNC;
...@@ -493,6 +494,13 @@ void mmc_cleanup_queue(struct mmc_queue *mq) ...@@ -493,6 +494,13 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
if (blk_queue_quiesced(q)) if (blk_queue_quiesced(q))
blk_mq_unquiesce_queue(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); blk_mq_free_tag_set(&mq->tag_set);
/* /*
......
...@@ -291,7 +291,8 @@ static void sdio_release_func(struct device *dev) ...@@ -291,7 +291,8 @@ static void sdio_release_func(struct device *dev)
{ {
struct sdio_func *func = dev_to_sdio_func(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->info);
kfree(func->tmpbuf); kfree(func->tmpbuf);
......
...@@ -1075,9 +1075,10 @@ config MMC_SDHCI_OMAP ...@@ -1075,9 +1075,10 @@ config MMC_SDHCI_OMAP
config MMC_SDHCI_AM654 config MMC_SDHCI_AM654
tristate "Support for the SDHCI Controller in TI's AM654 SOCs" 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_SDHCI_IO_ACCESSORS
select MMC_CQHCI select MMC_CQHCI
select REGMAP_MMIO
help help
This selects the Secure Digital Host Controller Interface (SDHCI) This selects the Secure Digital Host Controller Interface (SDHCI)
support present in TI's AM654 SOCs. The controller supports support present in TI's AM654 SOCs. The controller supports
......
...@@ -1660,6 +1660,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) ...@@ -1660,6 +1660,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
host->mmc_host_ops.execute_tuning = usdhc_execute_tuning; 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) if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
sdhci_esdhc_ops.platform_execute_tuning = sdhci_esdhc_ops.platform_execute_tuning =
esdhc_executing_tuning; esdhc_executing_tuning;
...@@ -1667,13 +1671,15 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) ...@@ -1667,13 +1671,15 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; 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; host->mmc->caps2 |= MMC_CAP2_HS400;
if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23)
host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN; 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->caps2 |= MMC_CAP2_HS400_ES;
host->mmc_host_ops.hs400_enhanced_strobe = host->mmc_host_ops.hs400_enhanced_strobe =
esdhc_hs400_enhanced_strobe; esdhc_hs400_enhanced_strobe;
...@@ -1695,10 +1701,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) ...@@ -1695,10 +1701,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
goto disable_ahb_clk; 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); sdhci_esdhc_imx_hwinit(host);
err = sdhci_add_host(host); err = sdhci_add_host(host);
......
...@@ -914,6 +914,12 @@ static bool glk_broken_cqhci(struct sdhci_pci_slot *slot) ...@@ -914,6 +914,12 @@ static bool glk_broken_cqhci(struct sdhci_pci_slot *slot)
dmi_match(DMI_SYS_VENDOR, "IRBIS")); 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) static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
{ {
int ret = byt_emmc_probe_slot(slot); int ret = byt_emmc_probe_slot(slot);
...@@ -922,9 +928,11 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot) ...@@ -922,9 +928,11 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
slot->host->mmc->caps2 |= MMC_CAP2_CQE; slot->host->mmc->caps2 |= MMC_CAP2_CQE;
if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) { if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) {
slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES; if (!jsl_broken_hs400es(slot)) {
slot->host->mmc_host_ops.hs400_enhanced_strobe = slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES;
intel_hs400_enhanced_strobe; slot->host->mmc_host_ops.hs400_enhanced_strobe =
intel_hs400_enhanced_strobe;
}
slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD; slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment