From 6da6d4b80e1449a0fe174e235d365fe06cb19d35 Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Tue, 31 Mar 2026 17:47:12 +0530 Subject: [PATCH] PENDING: i2c: qcom-geni: Fix -EACCES error during system resume When other drivers attempt I2C transfers during early resume phase, the I2C controller is still runtime suspended, causing pm_runtime_get_sync() to fail with -EACCES (-13): [ 101.914202] geni_i2c 980000.i2c: error turning SE resources:-13 The PM runtime core returns -EACCES when runtime PM is disabled (dev->power.disable_depth > 0). This occurs because: 1. During suspend_noirq, I2C driver calls geni_i2c_runtime_suspend() and then pm_runtime_disable() 2. I2C driver's noirq_resume only marks adapter as resumed but doesn't re-enable runtime PM or power up the hardware 3. Other drivers resuming later attempt I2C transfers 4. pm_runtime_get_sync() returns -EACCES because runtime PM is still disabled Fix this by calling pm_runtime_force_resume() in geni_i2c_resume_noirq() to properly resume the hardware and re-enable runtime PM during the noirq phase. This ensures the I2C controller is powered and ready for use when other drivers need it during resume. Upstream-Status: Pending Signed-off-by: Viken Dadhaniya --- drivers/i2c/busses/i2c-qcom-geni.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index bfb352b04902c..d2021520bded8 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -831,8 +831,14 @@ static int geni_i2c_probe(struct platform_device *pdev) spin_lock_init(&gi2c->lock); platform_set_drvdata(pdev, gi2c); - /* Keep interrupts disabled initially to allow for low-power modes */ - ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN, + /* + * Keep interrupts disabled initially to allow for low-power modes. + * IRQF_NO_SUSPEND: Keep IRQ enabled during suspend to handle I2C transfers + * in noirq phase (e.g., from PCIe driver's noirq_resume). + * IRQF_EARLY_RESUME: Enable IRQ early during resume sequence. + */ + ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, + IRQF_NO_AUTOEN | IRQF_NO_SUSPEND | IRQF_EARLY_RESUME, dev_name(dev), gi2c); if (ret) return dev_err_probe(dev, ret, @@ -1044,6 +1050,20 @@ static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev) static int __maybe_unused geni_i2c_resume_noirq(struct device *dev) { struct geni_i2c_dev *gi2c = dev_get_drvdata(dev); + int ret = 0; + + /* + * Resume hardware to handle I2C transfers from other drivers' + * noirq_resume callbacks (e.g., PCIe driver). + * pm_runtime_force_resume() properly handles PM state and usage_count. + */ + if (gi2c->suspended) { + ret = pm_runtime_force_resume(dev); + if (ret) { + dev_err(dev, "Failed to resume I2C during noirq: %d\n", ret); + return ret; + } + } i2c_mark_adapter_resumed(&gi2c->adap); return 0;