From: Yige Jiang <yigejiang86@gmail.com>
To: linux-i2c@vger.kernel.org
Cc: Yige Jiang <yigejiang86@gmail.com>,
Andi Shyti <andi.shyti@kernel.org>,
linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org,
Stephan Gerhold <stephan@gerhold.net>,
Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Subject: [PATCH v2] i2c: qup: Release DMA channels if interconnect lookup fails
Date: Fri, 6 Nov 2026 15:03:02 +0800 [thread overview]
Message-ID: <rc-review-20261106-v2-vc48-group-8e29ee9ee1f6@gmail.com> (raw)
qup_i2c_probe() acquires both BAM DMA channels before getting its
interconnect path. If devm_of_icc_get() fails, the direct return skips
the DMA cleanup and leaks both channels, including when probe is
deferred. A later probe can no longer acquire those channels.
Use devm_dma_request_chan() so probe failure automatically releases the
channels. Group the two requests so a failed RX request also releases
TX immediately before probe falls back to PIO. Keep reusing the acquired
pair when the transfer path calls qup_i2c_req_dma() again.
Close the successful group so it can be released explicitly at the
existing probe unwind and remove sites without releasing later device
resources. Release the group directly in remove, preserving the channel
pointer state there. The direct interconnect error return is covered by
the automatic devres cleanup.
Fixes: d4f35233a634 ("i2c: qup: Vote for interconnect bandwidth to DRAM")
Signed-off-by: Yige Jiang <yigejiang86@gmail.com>
---
Changes in v2:
- Use devm_dma_request_chan(), as suggested by Konrad.
- Group TX/RX requests to preserve immediate rollback before PIO fallback.
- Reuse an existing pair in the transfer path and release the closed group
at the existing probe unwind and remove sites.
v1: https://lore.kernel.org/r/rc-review-20261105-vc-48-dbf6a486c74f@gmail.com
Based on linux-next next-20261102 (2637bdec0535).
Validated this package on arm64: the W=1 i2c-qup module build and
a DMA_ENGINE-disabled driver build passed without warnings.
QEMU KUnit/KASAN passed 11 expected observations using real
DMAengine/devres code and a synthetic DMA provider. These checks
do not execute QUP hardware transfers or prove concurrent unbind
safety. No QUP/BAM hardware test was available.
AI assistance was used for analysis and patch preparation.
drivers/i2c/busses/i2c-qup.c | 54 +++++++++++++++++++++-----------------------
1 file changed, 26 insertions(+), 28 deletions(-)
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index ce30634e1f402ddbc092d9b220532d76455fc047..865c03d9aa891b9fc38538ae184541f74c0a2819 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -637,10 +637,7 @@ static int qup_sg_set_buf(struct scatterlist *sg, void *buf,
static void qup_i2c_rel_dma(struct qup_i2c_dev *qup)
{
- if (qup->btx.dma)
- dma_release_channel(qup->btx.dma);
- if (qup->brx.dma)
- dma_release_channel(qup->brx.dma);
+ devres_release_group(qup->dev, qup);
qup->btx.dma = NULL;
qup->brx.dma = NULL;
}
@@ -649,27 +646,32 @@ static int qup_i2c_req_dma(struct qup_i2c_dev *qup)
{
int err;
- if (!qup->btx.dma) {
- qup->btx.dma = dma_request_chan(qup->dev, "tx");
- if (IS_ERR(qup->btx.dma)) {
- err = PTR_ERR(qup->btx.dma);
- qup->btx.dma = NULL;
- dev_err(qup->dev, "\n tx channel not available");
- return err;
- }
+ if (qup->btx.dma && qup->brx.dma)
+ return 0;
+
+ if (!devres_open_group(qup->dev, qup, GFP_KERNEL))
+ return -ENOMEM;
+
+ qup->btx.dma = devm_dma_request_chan(qup->dev, "tx");
+ if (IS_ERR(qup->btx.dma)) {
+ err = PTR_ERR(qup->btx.dma);
+ dev_err(qup->dev, "\n tx channel not available");
+ goto err_release_group;
}
- if (!qup->brx.dma) {
- qup->brx.dma = dma_request_chan(qup->dev, "rx");
- if (IS_ERR(qup->brx.dma)) {
- dev_err(qup->dev, "\n rx channel not available");
- err = PTR_ERR(qup->brx.dma);
- qup->brx.dma = NULL;
- qup_i2c_rel_dma(qup);
- return err;
- }
+ qup->brx.dma = devm_dma_request_chan(qup->dev, "rx");
+ if (IS_ERR(qup->brx.dma)) {
+ err = PTR_ERR(qup->brx.dma);
+ dev_err(qup->dev, "\n rx channel not available");
+ goto err_release_group;
}
+
+ devres_close_group(qup->dev, qup);
return 0;
+
+err_release_group:
+ qup_i2c_rel_dma(qup);
+ return err;
}
static int qup_i2c_bam_make_desc(struct qup_i2c_dev *qup, struct i2c_msg *msg)
@@ -1952,9 +1954,7 @@ fail:
qup_i2c_disable_clocks(qup);
fail_dma:
if (qup->btx.dma)
- dma_release_channel(qup->btx.dma);
- if (qup->brx.dma)
- dma_release_channel(qup->brx.dma);
+ qup_i2c_rel_dma(qup);
return ret;
}
@@ -1962,10 +1962,8 @@ static void qup_i2c_remove(struct platform_device *pdev)
{
struct qup_i2c_dev *qup = platform_get_drvdata(pdev);
- if (qup->is_dma) {
- dma_release_channel(qup->btx.dma);
- dma_release_channel(qup->brx.dma);
- }
+ if (qup->is_dma)
+ devres_release_group(qup->dev, qup);
disable_irq(qup->irq);
qup_i2c_disable_clocks(qup);
base-commit: 2637bdec0535a2044cd830eba9a79363651d9043
reply other threads:[~2026-11-06 7:03 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=rc-review-20261106-v2-vc48-group-8e29ee9ee1f6@gmail.com \
--to=yigejiang86@gmail.com \
--cc=andi.shyti@kernel.org \
--cc=konrad.dybcio@oss.qualcomm.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stephan@gerhold.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®