From 153212bcc87ee0f4868f7d07e33b6b22b8928f72 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Sun, 12 Sep 2021 11:30:51 -0700 Subject: [PATCH 1/2] rpmsg: glink: Add mutual exclusion to irq The change to defer excessive glink processing to threaded irq context uses the IRQF_ONESHOT flags and assumes the hardirq handler will never run when the threaded irq is running. There are a couple instances where this does not hold true. One known instance is during irq_resend() where an interrupt is resent in tasklet context. In this case, it has been observed that the hard irq handler will run even if the threaded portion of the interrupt is running. Add a lock and state to check if the irq is running. If it is already running, then bail out of the irq. If threaded handler is already in execution when suspend happens and next glink interrupt is received in suspend, interrupt handler returns without waking up system. Move wakeup logic in the beginning of interrupt handler. Change-Id: Ied7808962e525ff0b7430d3fac666f7fee032722 Signed-off-by: Chris Lew --- drivers/rpmsg/qcom_glink_native.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index fd2708b9bc32..899382d7f32a 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -114,6 +114,8 @@ struct qcom_glink { int irq; char irqname[GLINK_NAME_SIZE]; + spinlock_t irq_lock; + bool irq_running; struct work_struct rx_work; spinlock_t rx_lock; @@ -1115,6 +1117,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid) static int qcom_glink_native_rx(struct qcom_glink *glink, int iterations) { struct glink_msg msg; + unsigned long flags; unsigned int param1; unsigned int param2; unsigned int avail; @@ -1128,6 +1131,15 @@ static int qcom_glink_native_rx(struct qcom_glink *glink, int iterations) should_wake = false; pm_system_wakeup(); } + + spin_lock_irqsave(&glink->irq_lock, flags); + if (glink->irq_running) { + spin_unlock_irqrestore(&glink->irq_lock, flags); + return 0; + } + glink->irq_running = true; + spin_unlock_irqrestore(&glink->irq_lock, flags); + /* To wakeup any blocking writers */ wake_up_all(&glink->tx_avail_notify); @@ -1192,6 +1204,10 @@ static int qcom_glink_native_rx(struct qcom_glink *glink, int iterations) break; } + spin_lock_irqsave(&glink->irq_lock, flags); + glink->irq_running = false; + spin_unlock_irqrestore(&glink->irq_lock, flags); + return qcom_glink_rx_avail(glink); } @@ -1984,6 +2000,9 @@ int qcom_glink_native_start(struct qcom_glink *glink) int irq; int ret; + spin_lock_init(&glink->irq_lock); + glink->irq_running = false; + irq = of_irq_get(dev->of_node, 0); ret = devm_request_threaded_irq(dev, irq, qcom_glink_native_intr, From 1cb52ea9b9ce97042d48061c11c574f693ba7d86 Mon Sep 17 00:00:00 2001 From: Maria Yu Date: Tue, 7 Dec 2021 10:07:54 +0800 Subject: [PATCH 2/2] rpmsg: glink: multi enter for unregister path Support multi enter for unregister path. Change-Id: I3dd37604e740582ee851c208a4c67fe08f20d83f Signed-off-by: Maria Yu [quic_clew@quicinc.com: This is a work around until remoteproc resolves a race where unregister is called from multiple contexts] Signed-off-by: Chris Lew --- drivers/rpmsg/qcom_glink_smem.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 0df41abc5233..e7a982f7c3e8 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -317,6 +317,9 @@ EXPORT_SYMBOL(qcom_glink_smem_start); void qcom_glink_smem_unregister(struct qcom_glink *glink) { + if (!glink) + return; + qcom_glink_native_remove(glink); qcom_glink_native_unregister(glink); }