Commit 1ae7efb3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull MMC fixes from Ulf Hansson:
 "MMC core:
   - Fix a couple of quite severe issues for the CQE request path

  MMC host:
   - alcor: Fix a resource leak in the error path for ->probe()
   - sdhci-acpi: Fix the DMA support for the AMD eMMC v5.0 variant
   - sdhci-pci-gli: Fix system resume support for GL975x
   - sdhci-pci-gli: Fix reboot error for GL9750"

* tag 'mmc-v5.7-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: sdhci-acpi: Add SDHCI_QUIRK2_BROKEN_64_BIT_DMA for AMDI0040
  mmc: block: Fix request completion in the CQE timeout path
  mmc: core: Fix recursive locking issue in CQE recovery path
  mmc: core: Check request type before completing the request
  mmc: sdhci-pci-gli: Fix can not access GL9750 after reboot from Windows 10
  mmc: alcor: Fix a resource leak in the error path for ->probe()
  mmc: sdhci-pci-gli: Fix no irq handler from suspend
parents decd6167 45a3fe3b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1370,6 +1370,7 @@ static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req)
	struct mmc_request *mrq = &mqrq->brq.mrq;
	struct request_queue *q = req->q;
	struct mmc_host *host = mq->card->host;
	enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
	unsigned long flags;
	bool put_card;
	int err;
@@ -1399,7 +1400,7 @@ static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req)

	spin_lock_irqsave(&mq->lock, flags);

	mq->in_flight[mmc_issue_type(mq, req)] -= 1;
	mq->in_flight[issue_type] -= 1;

	put_card = (mmc_tot_in_flight(mq) == 0);

+5 −11
Original line number Diff line number Diff line
@@ -107,11 +107,10 @@ static enum blk_eh_timer_return mmc_cqe_timed_out(struct request *req)
	case MMC_ISSUE_DCMD:
		if (host->cqe_ops->cqe_timeout(host, mrq, &recovery_needed)) {
			if (recovery_needed)
				__mmc_cqe_recovery_notifier(mq);
				mmc_cqe_recovery_notifier(mrq);
			return BLK_EH_RESET_TIMER;
		}
		/* No timeout (XXX: huh? comment doesn't make much sense) */
		blk_mq_complete_request(req);
		/* The request has gone already */
		return BLK_EH_DONE;
	default:
		/* Timeout is handled by mmc core */
@@ -127,18 +126,13 @@ static enum blk_eh_timer_return mmc_mq_timed_out(struct request *req,
	struct mmc_card *card = mq->card;
	struct mmc_host *host = card->host;
	unsigned long flags;
	int ret;
	bool ignore_tout;

	spin_lock_irqsave(&mq->lock, flags);

	if (mq->recovery_needed || !mq->use_cqe || host->hsq_enabled)
		ret = BLK_EH_RESET_TIMER;
	else
		ret = mmc_cqe_timed_out(req);

	ignore_tout = mq->recovery_needed || !mq->use_cqe || host->hsq_enabled;
	spin_unlock_irqrestore(&mq->lock, flags);

	return ret;
	return ignore_tout ? BLK_EH_RESET_TIMER : mmc_cqe_timed_out(req);
}

static void mmc_mq_recovery_handler(struct work_struct *work)
+5 −1
Original line number Diff line number Diff line
@@ -1104,7 +1104,7 @@ static int alcor_pci_sdmmc_drv_probe(struct platform_device *pdev)

	if (ret) {
		dev_err(&pdev->dev, "Failed to get irq for data line\n");
		return ret;
		goto free_host;
	}

	mutex_init(&host->cmd_mutex);
@@ -1116,6 +1116,10 @@ static int alcor_pci_sdmmc_drv_probe(struct platform_device *pdev)
	dev_set_drvdata(&pdev->dev, host);
	mmc_add_host(mmc);
	return 0;

free_host:
	mmc_free_host(mmc);
	return ret;
}

static int alcor_pci_sdmmc_drv_remove(struct platform_device *pdev)
+6 −4
Original line number Diff line number Diff line
@@ -607,8 +607,10 @@ static int sdhci_acpi_emmc_amd_probe_slot(struct platform_device *pdev,
static const struct sdhci_acpi_slot sdhci_acpi_slot_amd_emmc = {
	.chip		= &sdhci_acpi_chip_amd,
	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
	.quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE |
	.quirks		= SDHCI_QUIRK_32BIT_DMA_ADDR |
			  SDHCI_QUIRK_32BIT_DMA_SIZE |
			  SDHCI_QUIRK_32BIT_ADMA_SIZE,
	.quirks2	= SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
	.probe_slot     = sdhci_acpi_emmc_amd_probe_slot,
};

+23 −0
Original line number Diff line number Diff line
@@ -26,6 +26,9 @@
#define   SDHCI_GLI_9750_DRIVING_2    GENMASK(27, 26)
#define   GLI_9750_DRIVING_1_VALUE    0xFFF
#define   GLI_9750_DRIVING_2_VALUE    0x3
#define   SDHCI_GLI_9750_SEL_1        BIT(29)
#define   SDHCI_GLI_9750_SEL_2        BIT(31)
#define   SDHCI_GLI_9750_ALL_RST      (BIT(24)|BIT(25)|BIT(28)|BIT(30))

#define SDHCI_GLI_9750_PLL	      0x864
#define   SDHCI_GLI_9750_PLL_TX2_INV    BIT(23)
@@ -122,6 +125,8 @@ static void gli_set_9750(struct sdhci_host *host)
				    GLI_9750_DRIVING_1_VALUE);
	driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_2,
				    GLI_9750_DRIVING_2_VALUE);
	driving_value &= ~(SDHCI_GLI_9750_SEL_1|SDHCI_GLI_9750_SEL_2|SDHCI_GLI_9750_ALL_RST);
	driving_value |= SDHCI_GLI_9750_SEL_2;
	sdhci_writel(host, driving_value, SDHCI_GLI_9750_DRIVING);

	sw_ctrl_value &= ~SDHCI_GLI_9750_SW_CTRL_4;
@@ -334,6 +339,18 @@ static u32 sdhci_gl9750_readl(struct sdhci_host *host, int reg)
	return value;
}

#ifdef CONFIG_PM_SLEEP
static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip)
{
	struct sdhci_pci_slot *slot = chip->slots[0];

	pci_free_irq_vectors(slot->chip->pdev);
	gli_pcie_enable_msi(slot);

	return sdhci_pci_resume_host(chip);
}
#endif

static const struct sdhci_ops sdhci_gl9755_ops = {
	.set_clock		= sdhci_set_clock,
	.enable_dma		= sdhci_pci_enable_dma,
@@ -348,6 +365,9 @@ const struct sdhci_pci_fixes sdhci_gl9755 = {
	.quirks2	= SDHCI_QUIRK2_BROKEN_DDR50,
	.probe_slot	= gli_probe_slot_gl9755,
	.ops            = &sdhci_gl9755_ops,
#ifdef CONFIG_PM_SLEEP
	.resume         = sdhci_pci_gli_resume,
#endif
};

static const struct sdhci_ops sdhci_gl9750_ops = {
@@ -366,4 +386,7 @@ const struct sdhci_pci_fixes sdhci_gl9750 = {
	.quirks2	= SDHCI_QUIRK2_BROKEN_DDR50,
	.probe_slot	= gli_probe_slot_gl9750,
	.ops            = &sdhci_gl9750_ops,
#ifdef CONFIG_PM_SLEEP
	.resume         = sdhci_pci_gli_resume,
#endif
};