Unverified Commit 40369bfe authored by Han Xu's avatar Han Xu Committed by Mark Brown
Browse files

spi: fsl-qspi: use devm function instead of driver remove



Driver use devm APIs to manage clk/irq/resources and register the spi
controller, but the legacy remove function will be called first during
device detach and trigger kernel panic. Drop the remove function and use
devm_add_action_or_reset() for driver cleanup to ensure the release
sequence.

Trigger kernel panic on i.MX8MQ by
echo 30bb0000.spi >/sys/bus/platform/drivers/fsl-quadspi/unbind

Cc: stable@vger.kernel.org
Fixes: 8fcb830a ("spi: spi-fsl-qspi: use devm_spi_register_controller")
Reported-by: default avatarKevin Hao <haokexin@gmail.com>
Signed-off-by: default avatarHan Xu <han.xu@nxp.com>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20250326224152.2147099-1-han.xu@nxp.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent d32c4e58
Loading
Loading
Loading
Loading
+17 −14
Original line number Diff line number Diff line
@@ -844,6 +844,19 @@ static const struct spi_controller_mem_caps fsl_qspi_mem_caps = {
	.per_op_freq = true,
};

static void fsl_qspi_cleanup(void *data)
{
	struct fsl_qspi *q = data;

	/* disable the hardware */
	qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
	qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);

	fsl_qspi_clk_disable_unprep(q);

	mutex_destroy(&q->lock);
}

static int fsl_qspi_probe(struct platform_device *pdev)
{
	struct spi_controller *ctlr;
@@ -934,6 +947,10 @@ static int fsl_qspi_probe(struct platform_device *pdev)

	ctlr->dev.of_node = np;

	ret = devm_add_action_or_reset(dev, fsl_qspi_cleanup, q);
	if (ret)
		goto err_destroy_mutex;

	ret = devm_spi_register_controller(dev, ctlr);
	if (ret)
		goto err_destroy_mutex;
@@ -953,19 +970,6 @@ static int fsl_qspi_probe(struct platform_device *pdev)
	return ret;
}

static void fsl_qspi_remove(struct platform_device *pdev)
{
	struct fsl_qspi *q = platform_get_drvdata(pdev);

	/* disable the hardware */
	qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
	qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);

	fsl_qspi_clk_disable_unprep(q);

	mutex_destroy(&q->lock);
}

static int fsl_qspi_suspend(struct device *dev)
{
	return 0;
@@ -1003,7 +1007,6 @@ static struct platform_driver fsl_qspi_driver = {
		.pm =   &fsl_qspi_pm_ops,
	},
	.probe          = fsl_qspi_probe,
	.remove		= fsl_qspi_remove,
};
module_platform_driver(fsl_qspi_driver);