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
This commit is contained in:
Linus Torvalds
2026-03-20 09:54:40 -07:00
5 changed files with 41 additions and 86 deletions

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);