summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-03-20 09:54:40 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-03-20 09:54:40 -0700
commit9f582e39712f950f13dfa1ad49748a90937e48be (patch)
treef3fdf5ba65511f3ece31c8459d7e0e2ee569095f
parent007fe2321509a8287050413655f460d4c5ad8e8c (diff)
parent8c89a077ca796a2fe248c584e9d7e66cff0388c8 (diff)
Merge tag 'spi-fix-v7.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "There's a couple of core fixes here from Johan, fixing a race condition and an error handling path, plus a bunch of driver specific fixups. The Qualcomm issues could be nasty if you ran into them, especially the DMA ordering one" * tag 'spi-fix-v7.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: geni-qcom: Check DMA interrupts early in ISR spi: fix statistics allocation spi: fix use-after-free on controller registration failure spi: geni-qcom: Fix CPHA and CPOL mode change detection spi: axiado: Fix double-free in ax_spi_probe() spi: amlogic-spisg: Fix memory leak in aml_spisg_probe() spi: amlogic: spifc-a4: Remove redundant clock cleanup
-rw-r--r--drivers/spi/spi-amlogic-spifc-a4.c46
-rw-r--r--drivers/spi/spi-amlogic-spisg.c12
-rw-r--r--drivers/spi/spi-axiado.c31
-rw-r--r--drivers/spi/spi-geni-qcom.c13
-rw-r--r--drivers/spi/spi.c25
5 files changed, 41 insertions, 86 deletions
diff --git a/drivers/spi/spi-amlogic-spifc-a4.c b/drivers/spi/spi-amlogic-spifc-a4.c
index 3956869cfec1..1aabafa36e48 100644
--- a/drivers/spi/spi-amlogic-spifc-a4.c
+++ b/drivers/spi/spi-amlogic-spifc-a4.c
@@ -1083,14 +1083,6 @@ static int aml_sfc_clk_init(struct aml_sfc *sfc)
return clk_set_rate(sfc->core_clk, SFC_BUS_DEFAULT_CLK);
}
-static int aml_sfc_disable_clk(struct aml_sfc *sfc)
-{
- clk_disable_unprepare(sfc->core_clk);
- clk_disable_unprepare(sfc->gate_clk);
-
- return 0;
-}
-
static int aml_sfc_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1141,16 +1133,12 @@ static int aml_sfc_probe(struct platform_device *pdev)
/* Enable Amlogic flash controller spi mode */
ret = regmap_write(sfc->regmap_base, SFC_SPI_CFG, SPI_MODE_EN);
- if (ret) {
- dev_err(dev, "failed to enable SPI mode\n");
- goto err_out;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable SPI mode\n");
ret = dma_set_mask(sfc->dev, DMA_BIT_MASK(32));
- if (ret) {
- dev_err(sfc->dev, "failed to set dma mask\n");
- goto err_out;
- }
+ if (ret)
+ return dev_err_probe(sfc->dev, ret, "failed to set dma mask\n");
sfc->ecc_eng.dev = &pdev->dev;
sfc->ecc_eng.integration = NAND_ECC_ENGINE_INTEGRATION_PIPELINED;
@@ -1158,10 +1146,8 @@ static int aml_sfc_probe(struct platform_device *pdev)
sfc->ecc_eng.priv = sfc;
ret = nand_ecc_register_on_host_hw_engine(&sfc->ecc_eng);
- if (ret) {
- dev_err(&pdev->dev, "failed to register Aml host ecc engine.\n");
- goto err_out;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to register Aml host ecc engine.\n");
ret = of_property_read_u32(np, "amlogic,rx-adj", &val);
if (!ret)
@@ -1177,24 +1163,7 @@ static int aml_sfc_probe(struct platform_device *pdev)
ctrl->min_speed_hz = SFC_MIN_FREQUENCY;
ctrl->num_chipselect = SFC_MAX_CS_NUM;
- ret = devm_spi_register_controller(dev, ctrl);
- if (ret)
- goto err_out;
-
- return 0;
-
-err_out:
- aml_sfc_disable_clk(sfc);
-
- return ret;
-}
-
-static void aml_sfc_remove(struct platform_device *pdev)
-{
- struct spi_controller *ctlr = platform_get_drvdata(pdev);
- struct aml_sfc *sfc = spi_controller_get_devdata(ctlr);
-
- aml_sfc_disable_clk(sfc);
+ return devm_spi_register_controller(dev, ctrl);
}
static const struct of_device_id aml_sfc_of_match[] = {
@@ -1212,7 +1181,6 @@ static struct platform_driver aml_sfc_driver = {
.of_match_table = aml_sfc_of_match,
},
.probe = aml_sfc_probe,
- .remove = aml_sfc_remove,
};
module_platform_driver(aml_sfc_driver);
diff --git a/drivers/spi/spi-amlogic-spisg.c b/drivers/spi/spi-amlogic-spisg.c
index 1509df2b17ae..9d568e385f05 100644
--- a/drivers/spi/spi-amlogic-spisg.c
+++ b/drivers/spi/spi-amlogic-spisg.c
@@ -729,9 +729,9 @@ static int aml_spisg_probe(struct platform_device *pdev)
};
if (of_property_read_bool(dev->of_node, "spi-slave"))
- ctlr = spi_alloc_target(dev, sizeof(*spisg));
+ ctlr = devm_spi_alloc_target(dev, sizeof(*spisg));
else
- ctlr = spi_alloc_host(dev, sizeof(*spisg));
+ ctlr = devm_spi_alloc_host(dev, sizeof(*spisg));
if (!ctlr)
return -ENOMEM;
@@ -750,10 +750,8 @@ static int aml_spisg_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(spisg->map), "regmap init failed\n");
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- ret = irq;
- goto out_controller;
- }
+ if (irq < 0)
+ return irq;
ret = device_reset_optional(dev);
if (ret)
@@ -817,8 +815,6 @@ out_clk:
if (spisg->core)
clk_disable_unprepare(spisg->core);
clk_disable_unprepare(spisg->pclk);
-out_controller:
- spi_controller_put(ctlr);
return ret;
}
diff --git a/drivers/spi/spi-axiado.c b/drivers/spi/spi-axiado.c
index 8cea81432c5b..8ddcd27def22 100644
--- a/drivers/spi/spi-axiado.c
+++ b/drivers/spi/spi-axiado.c
@@ -765,30 +765,22 @@ static int ax_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ctlr);
xspi->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(xspi->regs)) {
- ret = PTR_ERR(xspi->regs);
- goto remove_ctlr;
- }
+ if (IS_ERR(xspi->regs))
+ return PTR_ERR(xspi->regs);
xspi->pclk = devm_clk_get(&pdev->dev, "pclk");
- if (IS_ERR(xspi->pclk)) {
- dev_err(&pdev->dev, "pclk clock not found.\n");
- ret = PTR_ERR(xspi->pclk);
- goto remove_ctlr;
- }
+ if (IS_ERR(xspi->pclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(xspi->pclk),
+ "pclk clock not found.\n");
xspi->ref_clk = devm_clk_get(&pdev->dev, "ref");
- if (IS_ERR(xspi->ref_clk)) {
- dev_err(&pdev->dev, "ref clock not found.\n");
- ret = PTR_ERR(xspi->ref_clk);
- goto remove_ctlr;
- }
+ if (IS_ERR(xspi->ref_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(xspi->ref_clk),
+ "ref clock not found.\n");
ret = clk_prepare_enable(xspi->pclk);
- if (ret) {
- dev_err(&pdev->dev, "Unable to enable APB clock.\n");
- goto remove_ctlr;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Unable to enable APB clock.\n");
ret = clk_prepare_enable(xspi->ref_clk);
if (ret) {
@@ -869,8 +861,7 @@ clk_dis_all:
clk_disable_unprepare(xspi->ref_clk);
clk_dis_apb:
clk_disable_unprepare(xspi->pclk);
-remove_ctlr:
- spi_controller_put(ctlr);
+
return ret;
}
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 43ce47f2454c..d5fb0edc8e0c 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -359,9 +359,9 @@ static int setup_fifo_params(struct spi_device *spi_slv,
writel((spi_slv->mode & SPI_LOOP) ? LOOPBACK_ENABLE : 0, se->base + SE_SPI_LOOPBACK);
if (cs_changed)
writel(chipselect, se->base + SE_SPI_DEMUX_SEL);
- if (mode_changed & SE_SPI_CPHA)
+ if (mode_changed & SPI_CPHA)
writel((spi_slv->mode & SPI_CPHA) ? CPHA : 0, se->base + SE_SPI_CPHA);
- if (mode_changed & SE_SPI_CPOL)
+ if (mode_changed & SPI_CPOL)
writel((spi_slv->mode & SPI_CPOL) ? CPOL : 0, se->base + SE_SPI_CPOL);
if ((mode_changed & SPI_CS_HIGH) || (cs_changed && (spi_slv->mode & SPI_CS_HIGH)))
writel((spi_slv->mode & SPI_CS_HIGH) ? BIT(chipselect) : 0, se->base + SE_SPI_DEMUX_OUTPUT_INV);
@@ -906,10 +906,13 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
struct spi_controller *spi = data;
struct spi_geni_master *mas = spi_controller_get_devdata(spi);
struct geni_se *se = &mas->se;
- u32 m_irq;
+ u32 m_irq, dma_tx_status, dma_rx_status;
m_irq = readl(se->base + SE_GENI_M_IRQ_STATUS);
- if (!m_irq)
+ dma_tx_status = readl_relaxed(se->base + SE_DMA_TX_IRQ_STAT);
+ dma_rx_status = readl_relaxed(se->base + SE_DMA_RX_IRQ_STAT);
+
+ if (!m_irq && !dma_tx_status && !dma_rx_status)
return IRQ_NONE;
if (m_irq & (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |
@@ -957,8 +960,6 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
}
} else if (mas->cur_xfer_mode == GENI_SE_DMA) {
const struct spi_transfer *xfer = mas->cur_xfer;
- u32 dma_tx_status = readl_relaxed(se->base + SE_DMA_TX_IRQ_STAT);
- u32 dma_rx_status = readl_relaxed(se->base + SE_DMA_RX_IRQ_STAT);
if (dma_tx_status)
writel(dma_tx_status, se->base + SE_DMA_TX_IRQ_CLR);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 61f7bde8c7fb..53dee314d76a 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -3049,6 +3049,8 @@ static void spi_controller_release(struct device *dev)
struct spi_controller *ctlr;
ctlr = container_of(dev, struct spi_controller, dev);
+
+ free_percpu(ctlr->pcpu_statistics);
kfree(ctlr);
}
@@ -3192,6 +3194,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
if (!ctlr)
return NULL;
+ ctlr->pcpu_statistics = spi_alloc_pcpu_stats(NULL);
+ if (!ctlr->pcpu_statistics) {
+ kfree(ctlr);
+ return NULL;
+ }
+
device_initialize(&ctlr->dev);
INIT_LIST_HEAD(&ctlr->queue);
spin_lock_init(&ctlr->queue_lock);
@@ -3480,17 +3488,8 @@ int spi_register_controller(struct spi_controller *ctlr)
dev_info(dev, "controller is unqueued, this is deprecated\n");
} else if (ctlr->transfer_one || ctlr->transfer_one_message) {
status = spi_controller_initialize_queue(ctlr);
- if (status) {
- device_del(&ctlr->dev);
- goto free_bus_id;
- }
- }
- /* Add statistics */
- ctlr->pcpu_statistics = spi_alloc_pcpu_stats(dev);
- if (!ctlr->pcpu_statistics) {
- dev_err(dev, "Error allocating per-cpu statistics\n");
- status = -ENOMEM;
- goto destroy_queue;
+ if (status)
+ goto del_ctrl;
}
mutex_lock(&board_lock);
@@ -3504,8 +3503,8 @@ int spi_register_controller(struct spi_controller *ctlr)
acpi_register_spi_devices(ctlr);
return status;
-destroy_queue:
- spi_destroy_queue(ctlr);
+del_ctrl:
+ device_del(&ctlr->dev);
free_bus_id:
mutex_lock(&board_lock);
idr_remove(&spi_controller_idr, ctlr->bus_num);