mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-21 23:16:50 +08:00
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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user