From patchwork Fri Feb 8 17:55:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 10803593 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9016B13BF for ; Fri, 8 Feb 2019 17:55:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 80BDC2E8DB for ; Fri, 8 Feb 2019 17:55:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 72A392EA2D; Fri, 8 Feb 2019 17:55:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EDDA02E8DB for ; Fri, 8 Feb 2019 17:55:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727736AbfBHRzW (ORCPT ); Fri, 8 Feb 2019 12:55:22 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:54949 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727379AbfBHRzW (ORCPT ); Fri, 8 Feb 2019 12:55:22 -0500 Received: by mail-wm1-f66.google.com with SMTP id a62so4485242wmh.4 for ; Fri, 08 Feb 2019 09:55:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=beAq55IerBLB4oPI+Hv3Vh7cxwg89eky+TIgBx+dpU4=; b=Sk/TVzQnzcOlskkXJ9RKFRzk/+JZ2CIxueOOAOmDDOGEMfEL9S99Kce2uqWQIlcCVY tVMMTw5gmTtXfdjaGEufLZDId8k1lGp5W3ub3p8dvFaRUO3i7XJJ/YKiZKMwTpyuhGCb nHP/WCzPpR9h7VR/yHvfLR9SYquDChEFE3Q2XXRBw6EgqrBtZmWmD9OJ1d7/gQ5sJ67I rXxV7GMEIsVzRazt7R8yRAtjwbNfBp9K1MzBrGpPb1In/ZFBBc6GjdXwECN/yKvypp4B +6c9r+xSl+42KEe8Gh1/QlKxQE73H6dc5n80seBkkeH3kriKRyeVH+rerux5m8Nt2VMY oLWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=beAq55IerBLB4oPI+Hv3Vh7cxwg89eky+TIgBx+dpU4=; b=jAb8EyXgOFhWKHg7OKQnW6LsC7llYdxfRzdRC4gYAq/zI41+8gafwtqrx98UE3v7kr NQOcWF8y0d3IqKg5HpeAc6NKQy5wgHqx/Z1QZF9GkwWKFigLOB/+eYw3+rRV3bmjr3XO AMyUGNsNBb5brg9dtQ4uE9/ONu1zQ3AKrTk5Wnt2RIpSPfvdZ8YhqJ0DocezGMCczaOj OWq5H9E1E+/DxW14ToWiCOsDNpPNahRIz4c6bZFUyCb2593VT+lxL9jFSSlOeEGnicAK 0po9ka6agBe9uLNhH8nAPwYRqUEzU50/Qd/SLp54M5UzMorvtyh1jkcHBw8T1XHudSNf Qdsg== X-Gm-Message-State: AHQUAuZSrN0nvJFbw31hiHeNFed88TYl3Gv5jTCHQsK9fb2/LriYoo0W e1hs6DyQIkIgbVBRkynjc/6Wnw== X-Google-Smtp-Source: AHgI3IaYE2gbqCdMFXzZST+PSoQGc01l5ZmiJZ475LI/3TLGZg0z9yQZYqWEzy5LI2C4ddYU388IkQ== X-Received: by 2002:a1c:ab87:: with SMTP id u129mr12607012wme.104.1549648519604; Fri, 08 Feb 2019 09:55:19 -0800 (PST) Received: from srini-hackbox.lan (cpc89974-aztw32-2-0-cust43.18-1.cable.virginm.net. [86.30.250.44]) by smtp.gmail.com with ESMTPSA id f134sm3455765wme.31.2019.02.08.09.55.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 08 Feb 2019 09:55:18 -0800 (PST) From: Srinivas Kandagatla To: andy.gross@linaro.org Cc: linux-arm-msm@vger.kernel.org, linux-soc@vger.kernel.org, linux-kernel@vger.kernel.org, rohitkr@codeaurora.org, bgoswami@codeaurora.org, Srinivas Kandagatla , Bjorn Andersson Subject: [PATCH v2] qcom: apr: Make apr callbacks in non-atomic context Date: Fri, 8 Feb 2019 17:55:10 +0000 Message-Id: <20190208175510.26837-1-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP APR communication with DSP is not atomic in nature. Its request-response type. Trying to pretend that these are atomic and invoking apr client callbacks directly under atomic/irq context has endless issues with soundcard. It makes more sense to convert these to nonatomic calls. This also coverts all the dais to be nonatomic. All the callbacks are now invoked as part of rx work queue. Signed-off-by: Srinivas Kandagatla Reviewed-by: Bjorn Andersson --- Changes since v1: - flush and destroy work queue after removing the device to avoid active communication from device. suggested by Bjorn. drivers/soc/qcom/apr.c | 74 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index 74f8b9607daa..039e3aa6f5e0 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -17,8 +18,18 @@ struct apr { struct rpmsg_endpoint *ch; struct device *dev; spinlock_t svcs_lock; + spinlock_t rx_lock; struct idr svcs_idr; int dest_domain_id; + struct workqueue_struct *rxwq; + struct work_struct rx_work; + struct list_head rx_list; +}; + +struct apr_rx_buf { + struct list_head node; + int len; + uint8_t buf[]; }; /** @@ -62,11 +73,7 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf, int len, void *priv, u32 addr) { struct apr *apr = dev_get_drvdata(&rpdev->dev); - uint16_t hdr_size, msg_type, ver, svc_id; - struct apr_device *svc = NULL; - struct apr_driver *adrv = NULL; - struct apr_resp_pkt resp; - struct apr_hdr *hdr; + struct apr_rx_buf *abuf; unsigned long flags; if (len <= APR_HDR_SIZE) { @@ -75,6 +82,34 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf, return -EINVAL; } + abuf = kzalloc(sizeof(*abuf) + len, GFP_ATOMIC); + if (!abuf) + return -ENOMEM; + + abuf->len = len; + memcpy(abuf->buf, buf, len); + + spin_lock_irqsave(&apr->rx_lock, flags); + list_add_tail(&abuf->node, &apr->rx_list); + spin_unlock_irqrestore(&apr->rx_lock, flags); + + queue_work(apr->rxwq, &apr->rx_work); + + return 0; +} + + +static int apr_do_rx_callback(struct apr *apr, struct apr_rx_buf *abuf) +{ + uint16_t hdr_size, msg_type, ver, svc_id; + struct apr_device *svc = NULL; + struct apr_driver *adrv = NULL; + struct apr_resp_pkt resp; + struct apr_hdr *hdr; + unsigned long flags; + void *buf = abuf->buf; + int len = abuf->len; + hdr = buf; ver = APR_HDR_FIELD_VER(hdr->hdr_field); if (ver > APR_PKT_VER + 1) @@ -132,6 +167,23 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf, return 0; } +static void apr_rxwq(struct work_struct *work) +{ + struct apr *apr = container_of(work, struct apr, rx_work); + struct apr_rx_buf *abuf, *b; + unsigned long flags; + + if (!list_empty(&apr->rx_list)) { + list_for_each_entry_safe(abuf, b, &apr->rx_list, node) { + apr_do_rx_callback(apr, abuf); + spin_lock_irqsave(&apr->rx_lock, flags); + list_del(&abuf->node); + spin_unlock_irqrestore(&apr->rx_lock, flags); + kfree(abuf); + } + } +} + static int apr_device_match(struct device *dev, struct device_driver *drv) { struct apr_device *adev = to_apr_device(dev); @@ -285,6 +337,14 @@ static int apr_probe(struct rpmsg_device *rpdev) dev_set_drvdata(dev, apr); apr->ch = rpdev->ept; apr->dev = dev; + apr->rxwq = create_singlethread_workqueue("qcom_apr_rx"); + if (!apr->rxwq) { + dev_err(apr->dev, "Failed to start Rx WQ\n"); + return -ENOMEM; + } + INIT_WORK(&apr->rx_work, apr_rxwq); + INIT_LIST_HEAD(&apr->rx_list); + spin_lock_init(&apr->rx_lock); spin_lock_init(&apr->svcs_lock); idr_init(&apr->svcs_idr); of_register_apr_devices(dev); @@ -303,7 +363,11 @@ static int apr_remove_device(struct device *dev, void *null) static void apr_remove(struct rpmsg_device *rpdev) { + struct apr *apr = dev_get_drvdata(&rpdev->dev); + device_for_each_child(&rpdev->dev, NULL, apr_remove_device); + flush_workqueue(apr->rxwq); + destroy_workqueue(apr->rxwq); } /*