i2c-fixes for v7.3-rc4

Fixes mainly for cleanup and error handling, a good part of them
 around DMA resource management.
 
 - at91: ensure DMA channels are released on all exit paths
 
 - imx: fix autosuspend cleanup on remove
 
 - qcom-cci: fix device node reference leak
 
 - atr, imx, qcom-geni: set adapter slot to NULL on registration
   failure
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQScDfrjQa34uOld1VLaeAVmJtMtbgUCaq+VLAAKCRDaeAVmJtMt
 bqmsAP9umA0ew1WQkQGTlTJLfbQdhwy8IDS7tMRAlgL7vsUxOQEApvFqr6Xtq2j7
 HiSP35cHybZlA7P2T70A+MVniCJDRQ4=
 =Sn1c
 -----END PGP SIGNATURE-----

Merge tag 'i2c-fixes-7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux

Pull i2c fixes from Andi Shyti:
 "Fixes mainly for cleanup and error handling, a good part of them
  around DMA resource management:

   - at91: ensure DMA channels are released on all exit paths

   - imx: fix autosuspend cleanup on remove

   - qcom-cci: fix device node reference leak

   - atr, imx, qcom-geni: set adapter slot to NULL on registration
     failure"

* tag 'i2c-fixes-7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux:
  i2c: qcom-cci: fix device_node refcount leak in cci_probe()/cci_remove()
  i2c: qcom-geni: release DMA channels on probe error
  i2c: imx: release DMA channels on probe error
  i2c: at91: release DMA channels on remove and probe error
  i2c: atr: fix dangling adapter pointer on add failure
  i2c: imx: disable autosuspend on remove
This commit is contained in:
Linus Torvalds 2026-09-20 07:57:47 -07:00
commit aa211c7a58
7 changed files with 33 additions and 11 deletions

View File

@ -255,6 +255,7 @@ static int at91_twi_probe(struct platform_device *pdev)
if (rc) {
pm_runtime_disable(dev->dev);
pm_runtime_set_suspended(dev->dev);
at91_twi_dma_release(dev);
return rc;
}
@ -270,6 +271,8 @@ static void at91_twi_remove(struct platform_device *pdev)
i2c_del_adapter(&dev->adapter);
at91_twi_dma_release(dev);
pm_runtime_disable(dev->dev);
pm_runtime_set_suspended(dev->dev);
}

View File

@ -817,11 +817,21 @@ static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
error:
if (ret != -EPROBE_DEFER)
dev_info(dev->dev, "can't get DMA channel, continue without DMA support\n");
at91_twi_dma_release(dev);
return ret;
}
void at91_twi_dma_release(struct at91_twi_dev *dev)
{
struct at91_twi_dma *dma = &dev->dma;
if (dma->chan_rx)
dma_release_channel(dma->chan_rx);
if (dma->chan_tx)
dma_release_channel(dma->chan_tx);
return ret;
dma->chan_rx = NULL;
dma->chan_tx = NULL;
dev->use_dma = false;
}
static int at91_init_twi_recovery_gpio(struct platform_device *pdev,

View File

@ -172,6 +172,7 @@ void at91_twi_irq_restore(struct at91_twi_dev *dev);
void at91_init_twi_bus(struct at91_twi_dev *dev);
void at91_init_twi_bus_master(struct at91_twi_dev *dev);
void at91_twi_dma_release(struct at91_twi_dev *dev);
int at91_twi_probe_master(struct platform_device *pdev, u32 phy_addr,
struct at91_twi_dev *dev);

View File

@ -1880,6 +1880,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
clk_notifier_unregister:
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
if (i2c_imx->dma)
i2c_imx_dma_free(i2c_imx);
free_irq(irq, i2c_imx);
rpm_disable:
pm_runtime_put_noidle(&pdev->dev);
@ -1920,6 +1922,7 @@ static void i2c_imx_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
}
static int i2c_imx_runtime_suspend(struct device *dev)

View File

@ -497,10 +497,14 @@ static const struct dev_pm_ops qcom_cci_pm = {
SET_RUNTIME_PM_OPS(cci_suspend_runtime, cci_resume_runtime, NULL)
};
static void cci_put_of_node(void *data)
{
of_node_put(data);
}
static int cci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *child;
struct resource *r;
struct cci *cci;
int ret, i;
@ -516,7 +520,7 @@ static int cci_probe(struct platform_device *pdev)
if (!cci->data)
return -ENOENT;
for_each_available_child_of_node(dev->of_node, child) {
for_each_available_child_of_node_scoped(dev->of_node, child) {
struct cci_master *master;
u32 idx;
@ -537,6 +541,9 @@ static int cci_probe(struct platform_device *pdev)
master->adap.algo = &cci_algo;
master->adap.dev.parent = dev;
master->adap.dev.of_node = of_node_get(child);
ret = devm_add_action_or_reset(dev, cci_put_of_node, child);
if (ret)
return ret;
master->master = idx;
master->cci = cci;
@ -606,10 +613,8 @@ static int cci_probe(struct platform_device *pdev)
continue;
ret = i2c_add_adapter(&cci->master[i].adap);
if (ret < 0) {
of_node_put(cci->master[i].adap.dev.of_node);
if (ret < 0)
goto error_i2c;
}
}
return 0;
@ -617,10 +622,8 @@ static int cci_probe(struct platform_device *pdev)
error_i2c:
for (--i ; i >= 0; i--) {
if (cci->master[i].cci) {
if (cci->master[i].cci)
i2c_del_adapter(&cci->master[i].adap);
of_node_put(cci->master[i].adap.dev.of_node);
}
}
disable_clocks:
cci_disable_clocks(cci);
@ -636,7 +639,6 @@ static void cci_remove(struct platform_device *pdev)
for (i = 0; i < cci->data->num_masters; i++) {
if (cci->master[i].cci) {
i2c_del_adapter(&cci->master[i].adap);
of_node_put(cci->master[i].adap.dev.of_node);
cci_halt(cci, i);
}
}

View File

@ -1189,8 +1189,10 @@ static int geni_i2c_probe(struct platform_device *pdev)
return ret;
ret = i2c_add_adapter(&gi2c->adap);
if (ret)
if (ret) {
release_gpi_dma(gi2c);
return dev_err_probe(dev, ret, "Error adding i2c adapter\n");
}
dev_dbg(dev, "Geni-I2C adaptor successfully added\n");

View File

@ -855,6 +855,7 @@ int i2c_atr_add_adapter(struct i2c_atr *atr, struct i2c_atr_adap_desc *desc)
ret = i2c_add_adapter(&chan->adap);
if (ret) {
atr->adapter[chan_id] = NULL;
dev_err(dev, "failed to add atr-adapter %u (error=%d)\n",
chan_id, ret);
goto err_free_alias_pool;