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: 157865 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp2239813jaa; Fri, 8 Feb 2019 09:55:24 -0800 (PST) X-Google-Smtp-Source: AHgI3IYXfNOYEOGXzCt4S08hYBZP7vNwu4aMSM3K7bQ7akEWQMmU60YDaBdAbdX5HAESNuKfNf8J X-Received: by 2002:a62:4882:: with SMTP id q2mr15092441pfi.167.1549648524516; Fri, 08 Feb 2019 09:55:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549648524; cv=none; d=google.com; s=arc-20160816; b=Q+wt7jxrrMErGlXrBSPDVhde3wE1jxdbDYLGcSM8ojdcAvajngSFNmqJ2XVHzkuYzh m/jncamZjok8hRGGb3WTddz4XMMtCRzQ6W5kdzj//wqUaJXwox+sJJUsHzDByfyP0xSy HX9I3ZR4H6PyLgtfyy92cG56p4ilYZH171X0AbneHAo7ZzzlJPuiCIH9aiLDmXJcHsNC vI5FITz4JZ2lnGIVbb//4qmaq4e5JL6yOwVkxN+Tif2anOvdb2dBH7lrXSs4SA2w9U0t LNzLLVIl/pMbYhA4lPyo52TpmqsGnsnEpKTGTK03rMnk8C1xLjSmVqIvBKdX8cTls7Ri 9OFA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=beAq55IerBLB4oPI+Hv3Vh7cxwg89eky+TIgBx+dpU4=; b=m2QXXyAMXsBDEJMzGNCgxPunQkQdhedrA36dSS134WOWkFgcBgPycBOc1LLHqUlEto nq9nQ6sTBbojaP1JyL4xz+b99KM4LvJq71w3Mt6anvVb1Mj8MzAlmY1dEGWV/Skxm39Y VEYCZKDSnlYnuFC+WIUyNKJN/iUcG17nywfUxUMnIEHqO2lTF2c4JaSo8XQaSzl6xyg1 e5FvyD1qUuGtqLlv1GHyZmHu07RMZKCtAA7ULqtb+oLSBuSneMhaKvB0GIUZrFoS6OVu HFz+l6tevlxXEB/6WmvObDWLkhqVcE1b5Vy6dpm9nfvFOcjFOlEtcz/YIOoy6NWZhgyi kDVA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Sk/TVzQn"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z20si2816530pfd.204.2019.02.08.09.55.24; Fri, 08 Feb 2019 09:55:24 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Sk/TVzQn"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727903AbfBHRzW (ORCPT + 31 others); Fri, 8 Feb 2019 12:55:22 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:50856 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727291AbfBHRzW (ORCPT ); Fri, 8 Feb 2019 12:55:22 -0500 Received: by mail-wm1-f65.google.com with SMTP id z5so4497905wmf.0 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=ZlRHT6MurWsNGqQDM+GB/ovQfvYSyXYxJQRYe+l6q5DEULSlvUkXiPpUCsaR4wCK3f 3nYkBDshchTxbz1Pkc7cLsWjKDz/iECllz8J+KZXDkz+swWn8GxvFDTuqgFpwljRDnag XCdSZx+uymJLUlU72CelIgAqelQjkPQzRwi8Fr9CJJq5yTcOsrQFU9zg1a22pbWkzMaB QZp/Oaz50QvuvtcVALzpSuJlZvlIeG1aK8f0mC3ubYRUe0eFbajZfDZZT5XVdfPqOCQg /JiXChpFQwc0l2oy2khbT5q9ghrv8Iq2lF7A2A1vwM3NFadUZ/OJ0WFbupgd2Jwpy5DP ifmA== X-Gm-Message-State: AHQUAubNV5fEWQz43KHBd/2Nriu38I9xXa8B53aeicjgPDY9C58E4BnI zL5mTtgzFaf/xzLUCR4ripNz5Q== 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-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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(-) -- 2.20.1 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); } /*