From dad847b72581039bc01b159651de10922f67d26b Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Fri, 5 Feb 2021 10:54:19 +0530 Subject: [PATCH 1/2] rpmsg: glink: Use IRQF_NO_SUSPEND and pm_system_wakeup() for glink irq Glink irq should be wakeup capable, to achieve this irq is marked with enable_irq_wake(). There are some use cases where glink communication is required in system suspend path and glink interrupt handler needs to be run immediately. But wakeup cpabale interrupts even if received during suspend will not run immediately, this will be marked pending and run when system resumes from suspend. In such scenario there can be a potential deadock in suspend path due to any irq thread which is waiting for glink interrupt completion while glink interrupt cannot be handled immediately. One such use case is usb plugin interrupt received during suspend, which calls regulator api to communicate with rpm over glink and waits for rpm ack. RPM ack cannot be processed because glink interrupt received from rpm goes in pending state. Suspend path is blocked because regulator irq thread is still waiting. So there is requirement to run glink interrupt handler in suspend path at the same time making it wakeup capable. IRQ frameworks forbids usage of both IRQF_NO_SUSPEND and enable_irq_wake() together. This patch adds IRQF_NO_SUSPEND and pm_system_wakeup() for glink irq to implement this requirement. Change-Id: I1da199c9e10c640bb84d00e569c4fafc5c104d24 Signed-off-by: Deepak Kumar Singh --- drivers/rpmsg/qcom_glink_native.c | 30 +++++++++++++++++++++++++++--- drivers/rpmsg/qcom_glink_native.h | 1 + 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 8051c7ad2d13..2117a9dd0435 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2016-2017, Linaro Ltd - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "rpmsg_internal.h" @@ -54,6 +55,8 @@ do { \ #define RPM_GLINK_CID_MIN 1 #define RPM_GLINK_CID_MAX 65536 +static int should_wake; + struct glink_msg { __le16 cmd; __le16 param1; @@ -1240,6 +1243,8 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) unsigned int cmd; int ret = 0; + if (should_wake) + pm_system_wakeup(); /* To wakeup any blocking writers */ wake_up_all(&glink->tx_avail_notify); @@ -2114,14 +2119,13 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, irq = of_irq_get(dev->of_node, 0); ret = devm_request_irq(dev, irq, qcom_glink_native_intr, - IRQF_SHARED, + IRQF_NO_SUSPEND | IRQF_SHARED, glink->irqname, glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); goto unregister; } - enable_irq_wake(irq); glink->irq = irq; size = of_property_count_u32_elems(dev->of_node, "cpu-affinity"); @@ -2212,5 +2216,25 @@ void qcom_glink_native_unregister(struct qcom_glink *glink) } EXPORT_SYMBOL_GPL(qcom_glink_native_unregister); +static int qcom_glink_suspend_no_irq(struct device *dev) +{ + should_wake = true; + + return 0; +} + +static int qcom_glink_resume_no_irq(struct device *dev) +{ + should_wake = false; + + return 0; +} + +const struct dev_pm_ops glink_native_pm_ops = { + .suspend_noirq = qcom_glink_suspend_no_irq, + .resume_noirq = qcom_glink_resume_no_irq, +}; +EXPORT_SYMBOL(glink_native_pm_ops); + MODULE_DESCRIPTION("Qualcomm GLINK driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h index 51c8e0d2c3f6..7a83d7bfe153 100644 --- a/drivers/rpmsg/qcom_glink_native.h +++ b/drivers/rpmsg/qcom_glink_native.h @@ -27,6 +27,7 @@ struct qcom_glink_pipe { }; struct qcom_glink; +extern const struct dev_pm_ops glink_native_pm_ops; struct qcom_glink *qcom_glink_native_probe(struct device *dev, unsigned long features, From ac790b1d1b0f0a9e50f4b56daf6d18c3243a943d Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Fri, 19 Feb 2021 16:25:16 +0530 Subject: [PATCH 2/2] rpmsg: glink: add dev_pm_ops for tracking no irq phase Glink native interrupt handler need to wakeup local host only in post noirq phase of suspend. Adding dev_pm_ops to track suspend/resume noirq phase. Change-Id: I46ff9108e28cd2355562ff95e54b955d3d90c07c Signed-off-by: Deepak Kumar Singh --- drivers/rpmsg/qcom_glink_rpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index f64f45d1a735..7a7600f34342 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -331,6 +331,7 @@ static struct platform_driver glink_rpm_driver = { .driver = { .name = "qcom_glink_rpm", .of_match_table = glink_rpm_of_match, + .pm = &glink_native_pm_ops, }, };