From 7daf95ce98b623ad569d87a35e68544263e18b2f Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Fri, 13 Aug 2021 12:19:16 -0700 Subject: [PATCH] rpmsg: glink: Use threaded interrupts On newer chipsets there is an increase in traffic generated from the remote for new usecases, this is resulting in the glink interrupt handler running for an extended amount of time. In combination with the IPCC architecture, this can starve out other users of IPCC including other GLINKs. Change the interrupt to a threaded interrupt to prevent the glink ISR from starving the CPU with interrupts disabled. In order to make sure performance for latency sensitive clients is preserved, handle up to 10 packets in hard irq context. Defer the remaining work to the threaded interrupt if required. Change-Id: I2f1b085c38c02d231f9a3da2fcce32b129be2012 Signed-off-by: Chris Lew --- drivers/rpmsg/qcom_glink_native.c | 34 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 7a0fb37a4750..fd2708b9bc32 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1112,15 +1112,15 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid) return 0; } -static irqreturn_t qcom_glink_native_intr(int irq, void *data) +static int qcom_glink_native_rx(struct qcom_glink *glink, int iterations) { - struct qcom_glink *glink = data; struct glink_msg msg; unsigned int param1; unsigned int param2; unsigned int avail; unsigned int cmd; int ret = 0; + int i; if (should_wake) { pr_info("%s: wakeup %s\n", __func__, glink->irqname); @@ -1131,7 +1131,7 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) /* To wakeup any blocking writers */ wake_up_all(&glink->tx_avail_notify); - for (;;) { + for (i = 0; i < iterations || !iterations; i++) { avail = qcom_glink_rx_avail(glink); if (avail < sizeof(msg)) break; @@ -1192,6 +1192,25 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) break; } + return qcom_glink_rx_avail(glink); +} + +static irqreturn_t qcom_glink_native_intr(int irq, void *data) +{ + struct qcom_glink *glink = data; + int ret; + + ret = qcom_glink_native_rx(glink, 10); + + return (ret) ? IRQ_WAKE_THREAD : IRQ_HANDLED; +} + +static irqreturn_t qcom_glink_native_thread_intr(int irq, void *data) +{ + struct qcom_glink *glink = data; + + qcom_glink_native_rx(glink, 0); + return IRQ_HANDLED; } @@ -1966,10 +1985,11 @@ int qcom_glink_native_start(struct qcom_glink *glink) int ret; irq = of_irq_get(dev->of_node, 0); - ret = devm_request_irq(dev, irq, - qcom_glink_native_intr, - IRQF_NO_SUSPEND | IRQF_SHARED, - glink->irqname, glink); + ret = devm_request_threaded_irq(dev, irq, + qcom_glink_native_intr, + qcom_glink_native_thread_intr, + IRQF_NO_SUSPEND | IRQF_ONESHOT, + glink->irqname, glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); return ret;