mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
i2c: at91: release DMA channels on remove and probe error
at91_twi_configure_dma() requests exclusive tx/rx DMA channels, but
nothing ever releases them on driver detach, and the probe error path
after the channels are acquired (i2c_add_numbered_adapter() failure)
returns without releasing them either, because the remove callback is
not invoked after a failed probe.
Move the release into a helper, call it from the existing
configure-failure path, the adapter-registration failure path, and
at91_twi_remove().
Fixes: 60937b2cdb ("i2c: at91: add dma support")
Assisted-by: GLM:5.3
Signed-off-by: Shengzhuo Wei <me@cherr.cc>
Cc: <stable@vger.kernel.org> # v3.8+
Acked-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://patch.msgid.link/20260827-i2c-dma-channel-leak-v1-1-271d4adc03a0@cherr.cc
This commit is contained in:
parent
ad34235808
commit
f7eeb1af85
|
|
@ -255,6 +255,7 @@ static int at91_twi_probe(struct platform_device *pdev)
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pm_runtime_disable(dev->dev);
|
pm_runtime_disable(dev->dev);
|
||||||
pm_runtime_set_suspended(dev->dev);
|
pm_runtime_set_suspended(dev->dev);
|
||||||
|
at91_twi_dma_release(dev);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
@ -270,6 +271,8 @@ static void at91_twi_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
i2c_del_adapter(&dev->adapter);
|
i2c_del_adapter(&dev->adapter);
|
||||||
|
|
||||||
|
at91_twi_dma_release(dev);
|
||||||
|
|
||||||
pm_runtime_disable(dev->dev);
|
pm_runtime_disable(dev->dev);
|
||||||
pm_runtime_set_suspended(dev->dev);
|
pm_runtime_set_suspended(dev->dev);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -817,11 +817,21 @@ static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
|
||||||
error:
|
error:
|
||||||
if (ret != -EPROBE_DEFER)
|
if (ret != -EPROBE_DEFER)
|
||||||
dev_info(dev->dev, "can't get DMA channel, continue without DMA support\n");
|
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)
|
if (dma->chan_rx)
|
||||||
dma_release_channel(dma->chan_rx);
|
dma_release_channel(dma->chan_rx);
|
||||||
if (dma->chan_tx)
|
if (dma->chan_tx)
|
||||||
dma_release_channel(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,
|
static int at91_init_twi_recovery_gpio(struct platform_device *pdev,
|
||||||
|
|
|
||||||
|
|
@ -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(struct at91_twi_dev *dev);
|
||||||
|
|
||||||
void at91_init_twi_bus_master(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,
|
int at91_twi_probe_master(struct platform_device *pdev, u32 phy_addr,
|
||||||
struct at91_twi_dev *dev);
|
struct at91_twi_dev *dev);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user