Commit bda6cfae authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull MMC fixes from Ulf Hansson:
 "MMC core:
   - Fix potential resource leaks in SDIO card detection error path

  MMC host:
   - jz4740: Decrease maximum clock rate to workaround bug on JZ4760(B)
   - meson-gx: Fix SDIO support to get some WiFi modules to work again
   - mmc_spi: Fix error handling in ->probe()"

* tag 'mmc-v6.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: jz4740: Work around bug on JZ4760(B)
  mmc: mmc_spi: fix error handling in mmc_spi_probe()
  mmc: sdio: fix possible resource leaks in some error paths
  mmc: meson-gx: fix SDIO mode if cap_sdio_irq isn't set
parents 64e0253d 3f18c504
Loading
Loading
Loading
Loading
+14 −3
Original line number Original line Diff line number Diff line
@@ -294,6 +294,12 @@ static void sdio_release_func(struct device *dev)
	if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO))
	if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO))
		sdio_free_func_cis(func);
		sdio_free_func_cis(func);


	/*
	 * We have now removed the link to the tuples in the
	 * card structure, so remove the reference.
	 */
	put_device(&func->card->dev);

	kfree(func->info);
	kfree(func->info);
	kfree(func->tmpbuf);
	kfree(func->tmpbuf);
	kfree(func);
	kfree(func);
@@ -324,6 +330,12 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)


	device_initialize(&func->dev);
	device_initialize(&func->dev);


	/*
	 * We may link to tuples in the card structure,
	 * we need make sure we have a reference to it.
	 */
	get_device(&func->card->dev);

	func->dev.parent = &card->dev;
	func->dev.parent = &card->dev;
	func->dev.bus = &sdio_bus_type;
	func->dev.bus = &sdio_bus_type;
	func->dev.release = sdio_release_func;
	func->dev.release = sdio_release_func;
@@ -377,10 +389,9 @@ int sdio_add_func(struct sdio_func *func)
 */
 */
void sdio_remove_func(struct sdio_func *func)
void sdio_remove_func(struct sdio_func *func)
{
{
	if (!sdio_func_present(func))
	if (sdio_func_present(func))
		return;

		device_del(&func->dev);
		device_del(&func->dev);

	of_node_put(func->dev.of_node);
	of_node_put(func->dev.of_node);
	put_device(&func->dev);
	put_device(&func->dev);
}
}
+0 −12
Original line number Original line Diff line number Diff line
@@ -403,12 +403,6 @@ int sdio_read_func_cis(struct sdio_func *func)
	if (ret)
	if (ret)
		return ret;
		return ret;


	/*
	 * Since we've linked to tuples in the card structure,
	 * we must make sure we have a reference to it.
	 */
	get_device(&func->card->dev);

	/*
	/*
	 * Vendor/device id is optional for function CIS, so
	 * Vendor/device id is optional for function CIS, so
	 * copy it from the card structure as needed.
	 * copy it from the card structure as needed.
@@ -434,11 +428,5 @@ void sdio_free_func_cis(struct sdio_func *func)
	}
	}


	func->tuples = NULL;
	func->tuples = NULL;

	/*
	 * We have now removed the link to the tuples in the
	 * card structure, so remove the reference.
	 */
	put_device(&func->card->dev);
}
}
+10 −0
Original line number Original line Diff line number Diff line
@@ -1053,6 +1053,16 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
	mmc->ops = &jz4740_mmc_ops;
	mmc->ops = &jz4740_mmc_ops;
	if (!mmc->f_max)
	if (!mmc->f_max)
		mmc->f_max = JZ_MMC_CLK_RATE;
		mmc->f_max = JZ_MMC_CLK_RATE;

	/*
	 * There seems to be a problem with this driver on the JZ4760 and
	 * JZ4760B SoCs. There, when using the maximum rate supported (50 MHz),
	 * the communication fails with many SD cards.
	 * Until this bug is sorted out, limit the maximum rate to 24 MHz.
	 */
	if (host->version == JZ_MMC_JZ4760 && mmc->f_max > JZ_MMC_CLK_RATE)
		mmc->f_max = JZ_MMC_CLK_RATE;

	mmc->f_min = mmc->f_max / 128;
	mmc->f_min = mmc->f_max / 128;
	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;


+13 −10
Original line number Original line Diff line number Diff line
@@ -435,6 +435,7 @@ static int meson_mmc_clk_init(struct meson_host *host)
	clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, CLK_PHASE_180);
	clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, CLK_PHASE_180);
	clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, CLK_PHASE_0);
	clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, CLK_PHASE_0);
	clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, CLK_PHASE_0);
	clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, CLK_PHASE_0);
	if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
		clk_reg |= CLK_IRQ_SDIO_SLEEP(host);
		clk_reg |= CLK_IRQ_SDIO_SLEEP(host);
	writel(clk_reg, host->regs + SD_EMMC_CLOCK);
	writel(clk_reg, host->regs + SD_EMMC_CLOCK);


@@ -948,16 +949,18 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
{
{
	struct meson_host *host = dev_id;
	struct meson_host *host = dev_id;
	struct mmc_command *cmd;
	struct mmc_command *cmd;
	u32 status, raw_status;
	u32 status, raw_status, irq_mask = IRQ_EN_MASK;
	irqreturn_t ret = IRQ_NONE;
	irqreturn_t ret = IRQ_NONE;


	if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
		irq_mask |= IRQ_SDIO;
	raw_status = readl(host->regs + SD_EMMC_STATUS);
	raw_status = readl(host->regs + SD_EMMC_STATUS);
	status = raw_status & (IRQ_EN_MASK | IRQ_SDIO);
	status = raw_status & irq_mask;


	if (!status) {
	if (!status) {
		dev_dbg(host->dev,
		dev_dbg(host->dev,
			"Unexpected IRQ! irq_en 0x%08lx - status 0x%08x\n",
			"Unexpected IRQ! irq_en 0x%08x - status 0x%08x\n",
			 IRQ_EN_MASK | IRQ_SDIO, raw_status);
			 irq_mask, raw_status);
		return IRQ_NONE;
		return IRQ_NONE;
	}
	}


@@ -1204,6 +1207,11 @@ static int meson_mmc_probe(struct platform_device *pdev)
		goto free_host;
		goto free_host;
	}
	}


	mmc->caps |= MMC_CAP_CMD23;

	if (mmc->caps & MMC_CAP_SDIO_IRQ)
		mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;

	host->data = (struct meson_mmc_data *)
	host->data = (struct meson_mmc_data *)
		of_device_get_match_data(&pdev->dev);
		of_device_get_match_data(&pdev->dev);
	if (!host->data) {
	if (!host->data) {
@@ -1277,11 +1285,6 @@ static int meson_mmc_probe(struct platform_device *pdev)


	spin_lock_init(&host->lock);
	spin_lock_init(&host->lock);


	mmc->caps |= MMC_CAP_CMD23;

	if (mmc->caps & MMC_CAP_SDIO_IRQ)
		mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;

	if (host->dram_access_quirk) {
	if (host->dram_access_quirk) {
		/* Limit segments to 1 due to low available sram memory */
		/* Limit segments to 1 due to low available sram memory */
		mmc->max_segs = 1;
		mmc->max_segs = 1;
+4 −4
Original line number Original line Diff line number Diff line
@@ -1437,7 +1437,7 @@ static int mmc_spi_probe(struct spi_device *spi)


	status = mmc_add_host(mmc);
	status = mmc_add_host(mmc);
	if (status != 0)
	if (status != 0)
		goto fail_add_host;
		goto fail_glue_init;


	/*
	/*
	 * Index 0 is card detect
	 * Index 0 is card detect
@@ -1445,7 +1445,7 @@ static int mmc_spi_probe(struct spi_device *spi)
	 */
	 */
	status = mmc_gpiod_request_cd(mmc, NULL, 0, false, 1000);
	status = mmc_gpiod_request_cd(mmc, NULL, 0, false, 1000);
	if (status == -EPROBE_DEFER)
	if (status == -EPROBE_DEFER)
		goto fail_add_host;
		goto fail_gpiod_request;
	if (!status) {
	if (!status) {
		/*
		/*
		 * The platform has a CD GPIO signal that may support
		 * The platform has a CD GPIO signal that may support
@@ -1460,7 +1460,7 @@ static int mmc_spi_probe(struct spi_device *spi)
	/* Index 1 is write protect/read only */
	/* Index 1 is write protect/read only */
	status = mmc_gpiod_request_ro(mmc, NULL, 1, 0);
	status = mmc_gpiod_request_ro(mmc, NULL, 1, 0);
	if (status == -EPROBE_DEFER)
	if (status == -EPROBE_DEFER)
		goto fail_add_host;
		goto fail_gpiod_request;
	if (!status)
	if (!status)
		has_ro = true;
		has_ro = true;


@@ -1474,7 +1474,7 @@ static int mmc_spi_probe(struct spi_device *spi)
				? ", cd polling" : "");
				? ", cd polling" : "");
	return 0;
	return 0;


fail_add_host:
fail_gpiod_request:
	mmc_remove_host(mmc);
	mmc_remove_host(mmc);
fail_glue_init:
fail_glue_init:
	mmc_spi_dma_free(host);
	mmc_spi_dma_free(host);