Commit fee3c824 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull spi fixes from Mark Brown:
 "This is a relatively large set of fixes, the bulk of it being a series
  from Lukas Wunner which fixes confusion with the lifetime of driver
  data allocated along with the SPI controller structure that's been
  created as part of the conversion to devm APIs.

  The simplest fix, explained in detail in Lukas' commit message, is to
  move to a devm_ function for allocation of the controller and hence
  driver data in order to push the free of that after anything tries to
  reference the driver data in the remove path. This results in a
  relatively large diff due to the addition of a new function but isn't
  particularly complex.

  There's also a fix from Sven van Asbroeck which fixes yet more fallout
  from the conflicts between the various different places one can
  configure the polarity of GPIOs in modern systems.

  Otherwise everything is fairly small and driver specific"

* tag 'spi-fix-v5.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: npcm-fiu: Don't leak SPI master in probe error path
  spi: dw: Set transfer handler before unmasking the IRQs
  spi: cadence-quadspi: Fix error return code in cqspi_probe
  spi: bcm2835aux: Restore err assignment in bcm2835aux_spi_probe
  spi: lpspi: Fix use-after-free on unbind
  spi: bcm-qspi: Fix use-after-free on unbind
  spi: bcm2835aux: Fix use-after-free on unbind
  spi: bcm2835: Fix use-after-free on unbind
  spi: Introduce device-managed SPI controller allocation
  spi: fsi: Fix transfer returning without finalizing message
  spi: fix client driver breakages when using GPIO descriptors
parents d748287a 04a9cd51
Loading
Loading
Loading
Loading
+12 −22
Original line number Diff line number Diff line
@@ -1327,7 +1327,7 @@ int bcm_qspi_probe(struct platform_device *pdev,

	data = of_id->data;

	master = spi_alloc_master(dev, sizeof(struct bcm_qspi));
	master = devm_spi_alloc_master(dev, sizeof(struct bcm_qspi));
	if (!master) {
		dev_err(dev, "error allocating spi_master\n");
		return -ENOMEM;
@@ -1367,21 +1367,17 @@ int bcm_qspi_probe(struct platform_device *pdev,

	if (res) {
		qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
		if (IS_ERR(qspi->base[MSPI])) {
			ret = PTR_ERR(qspi->base[MSPI]);
			goto qspi_resource_err;
		}
		if (IS_ERR(qspi->base[MSPI]))
			return PTR_ERR(qspi->base[MSPI]);
	} else {
		goto qspi_resource_err;
		return 0;
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
	if (res) {
		qspi->base[BSPI]  = devm_ioremap_resource(dev, res);
		if (IS_ERR(qspi->base[BSPI])) {
			ret = PTR_ERR(qspi->base[BSPI]);
			goto qspi_resource_err;
		}
		if (IS_ERR(qspi->base[BSPI]))
			return PTR_ERR(qspi->base[BSPI]);
		qspi->bspi_mode = true;
	} else {
		qspi->bspi_mode = false;
@@ -1392,18 +1388,14 @@ int bcm_qspi_probe(struct platform_device *pdev,
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs_reg");
	if (res) {
		qspi->base[CHIP_SELECT]  = devm_ioremap_resource(dev, res);
		if (IS_ERR(qspi->base[CHIP_SELECT])) {
			ret = PTR_ERR(qspi->base[CHIP_SELECT]);
			goto qspi_resource_err;
		}
		if (IS_ERR(qspi->base[CHIP_SELECT]))
			return PTR_ERR(qspi->base[CHIP_SELECT]);
	}

	qspi->dev_ids = kcalloc(num_irqs, sizeof(struct bcm_qspi_dev_id),
				GFP_KERNEL);
	if (!qspi->dev_ids) {
		ret = -ENOMEM;
		goto qspi_resource_err;
	}
	if (!qspi->dev_ids)
		return -ENOMEM;

	for (val = 0; val < num_irqs; val++) {
		irq = -1;
@@ -1484,7 +1476,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
	qspi->xfer_mode.addrlen = -1;
	qspi->xfer_mode.hp = -1;

	ret = devm_spi_register_master(&pdev->dev, master);
	ret = spi_register_master(master);
	if (ret < 0) {
		dev_err(dev, "can't register master\n");
		goto qspi_reg_err;
@@ -1497,8 +1489,6 @@ qspi_reg_err:
	clk_disable_unprepare(qspi->clk);
qspi_probe_err:
	kfree(qspi->dev_ids);
qspi_resource_err:
	spi_master_put(master);
	return ret;
}
/* probe function to be called by SoC specific platform driver probe */
@@ -1508,10 +1498,10 @@ int bcm_qspi_remove(struct platform_device *pdev)
{
	struct bcm_qspi *qspi = platform_get_drvdata(pdev);

	spi_unregister_master(qspi->master);
	bcm_qspi_hw_uninit(qspi);
	clk_disable_unprepare(qspi->clk);
	kfree(qspi->dev_ids);
	spi_unregister_master(qspi->master);

	return 0;
}
+8 −16
Original line number Diff line number Diff line
@@ -1278,7 +1278,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
	struct bcm2835_spi *bs;
	int err;

	ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
	ctlr = devm_spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
						  dma_get_cache_alignment()));
	if (!ctlr)
		return -ENOMEM;
@@ -1299,23 +1299,17 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
	bs->ctlr = ctlr;

	bs->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(bs->regs)) {
		err = PTR_ERR(bs->regs);
		goto out_controller_put;
	}
	if (IS_ERR(bs->regs))
		return PTR_ERR(bs->regs);

	bs->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(bs->clk)) {
		err = dev_err_probe(&pdev->dev, PTR_ERR(bs->clk),
	if (IS_ERR(bs->clk))
		return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk),
				     "could not get clk\n");
		goto out_controller_put;
	}

	bs->irq = platform_get_irq(pdev, 0);
	if (bs->irq <= 0) {
		err = bs->irq ? bs->irq : -ENODEV;
		goto out_controller_put;
	}
	if (bs->irq <= 0)
		return bs->irq ? bs->irq : -ENODEV;

	clk_prepare_enable(bs->clk);

@@ -1349,8 +1343,6 @@ out_dma_release:
	bcm2835_dma_release(ctlr, bs);
out_clk_disable:
	clk_disable_unprepare(bs->clk);
out_controller_put:
	spi_controller_put(ctlr);
	return err;
}

+7 −13
Original line number Diff line number Diff line
@@ -494,7 +494,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
	unsigned long clk_hz;
	int err;

	master = spi_alloc_master(&pdev->dev, sizeof(*bs));
	master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs));
	if (!master)
		return -ENOMEM;

@@ -524,29 +524,25 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)

	/* the main area */
	bs->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(bs->regs)) {
		err = PTR_ERR(bs->regs);
		goto out_master_put;
	}
	if (IS_ERR(bs->regs))
		return PTR_ERR(bs->regs);

	bs->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(bs->clk)) {
		err = PTR_ERR(bs->clk);
		dev_err(&pdev->dev, "could not get clk: %d\n", err);
		goto out_master_put;
		return err;
	}

	bs->irq = platform_get_irq(pdev, 0);
	if (bs->irq <= 0) {
		err = bs->irq ? bs->irq : -ENODEV;
		goto out_master_put;
	}
	if (bs->irq <= 0)
		return bs->irq ? bs->irq : -ENODEV;

	/* this also enables the HW block */
	err = clk_prepare_enable(bs->clk);
	if (err) {
		dev_err(&pdev->dev, "could not prepare clock: %d\n", err);
		goto out_master_put;
		return err;
	}

	/* just checking if the clock returns a sane value */
@@ -581,8 +577,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)

out_clk_disable:
	clk_disable_unprepare(bs->clk);
out_master_put:
	spi_master_put(master);
	return err;
}

+2 −0
Original line number Diff line number Diff line
@@ -1260,12 +1260,14 @@ static int cqspi_probe(struct platform_device *pdev)
	/* Obtain QSPI reset control */
	rstc = devm_reset_control_get_optional_exclusive(dev, "qspi");
	if (IS_ERR(rstc)) {
		ret = PTR_ERR(rstc);
		dev_err(dev, "Cannot get QSPI reset.\n");
		goto probe_reset_failed;
	}

	rstc_ocp = devm_reset_control_get_optional_exclusive(dev, "qspi-ocp");
	if (IS_ERR(rstc_ocp)) {
		ret = PTR_ERR(rstc_ocp);
		dev_err(dev, "Cannot get QSPI OCP reset.\n");
		goto probe_reset_failed;
	}
+2 −2
Original line number Diff line number Diff line
@@ -357,11 +357,11 @@ static void dw_spi_irq_setup(struct dw_spi *dws)
	dw_writel(dws, DW_SPI_TXFTLR, level);
	dw_writel(dws, DW_SPI_RXFTLR, level - 1);

	dws->transfer_handler = dw_spi_transfer_handler;

	imask = SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI |
		SPI_INT_RXFI;
	spi_umask_intr(dws, imask);

	dws->transfer_handler = dw_spi_transfer_handler;
}

/*
Loading