Hi Mukesh,It's an improvement to serve transfer during early resume time. Doesn't fix any crash issue.
On Thu, Mar 28, 2024 at 06:07:43PM +0530, Mukesh Kumar Savaliya wrote:
pm_runtime_get_sync() function fails during PM early resume and returning
-EACCES because runtime PM for the device is disabled at the early stage
causing i2c transfer to fail. Make changes to serve transfer with force
resume.
1. Register interrupt with IRQF_EARLY_RESUME and IRQF_NO_SUSPEND flags
to avoid timeout of transfer when IRQ is not enabled during early stage.
2. Do force resume if pm_runtime_get_sync() is failing after system
suspend when runtime PM is not enabled.
3. Increment power usage count after forced resume to balance
it against regular runtime suspend.
Co-developed-by: Viken Dadhaniya <quic_vdadhani@xxxxxxxxxxx>
Signed-off-by: Viken Dadhaniya <quic_vdadhani@xxxxxxxxxxx>
Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy@xxxxxxxxxxx>
Is this a fix? O mostly an improvement?
Sure, Done.
...
gi2c->err = 0;
reinit_completion(&gi2c->done);
- ret = pm_runtime_get_sync(gi2c->se.dev);
- if (ret < 0) {
- dev_err(gi2c->se.dev, "error turning SE resources:%d\n", ret);
- pm_runtime_put_noidle(gi2c->se.dev);
- /* Set device in suspended since resume failed */
- pm_runtime_set_suspended(gi2c->se.dev);
- return ret;
+
+ if (!pm_runtime_enabled(dev) && gi2c->suspended) {
+ dev_dbg(gi2c->se.dev, "RT_PM disabled, Do force resume, usage_count:%d\n",
dev
nit: you could leave a space after the ':'.Sure, Done.
Done.+ atomic_read(&dev->power.usage_count));
+ ret = geni_i2c_force_resume(gi2c);
+ if (ret)
+ return ret;
+ } else {
+ ret = pm_runtime_get_sync(dev);
+ if (ret == -EACCES && gi2c->suspended) {
+ dev_dbg(gi2c->se.dev, "PM get_sync() failed-%d, force resume\n", ret);
dev
No More else cases required.+ ret = geni_i2c_force_resume(gi2c);
+ if (ret)
+ return ret;
+ }
Are we missing some cases here? Do we need a few more else's?
Andi
Checked it, but seems we need additional flag too to be added at one place where as common part is 2 lines of code. If this code continues to be repeated, i can think of keeping under a wrapper function. Please let me know if still needed to make a separate function.}
qcom_geni_i2c_conf(gi2c);
@@ -702,8 +730,15 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
else
ret = geni_i2c_fifo_xfer(gi2c, msgs, num);
- pm_runtime_mark_last_busy(gi2c->se.dev);
- pm_runtime_put_autosuspend(gi2c->se.dev);
+ if (!pm_runtime_enabled(dev) && !gi2c->suspended) {
+ pm_runtime_put_noidle(dev);
+ pm_runtime_set_suspended(dev);
this looks like repeated code, how about making it a function?
Sure, Let me go little descriptive here.+ gi2c->suspended = 0;
+ } else {
+ pm_runtime_mark_last_busy(gi2c->se.dev);
+ pm_runtime_put_autosuspend(gi2c->se.dev);
+ }
+
gi2c->cur = NULL;
gi2c->err = 0;
return ret;
@@ -820,7 +855,7 @@ static int geni_i2c_probe(struct platform_device *pdev)
init_completion(&gi2c->done);
spin_lock_init(&gi2c->lock);
platform_set_drvdata(pdev, gi2c);
- ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, 0,
+ ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_EARLY_RESUME | IRQF_NO_SUSPEND,
Can you provide a bit more information on how an early interrupt
would be handled once the device is resumed?
Thanks,
Andi
dev_name(dev), gi2c);
if (ret) {
dev_err(dev, "Request_irq failed:%d: err:%d\n",
--
2.25.1