From patchwork Thu Nov 15 18:49:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 151238 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp7364530ljp; Thu, 15 Nov 2018 10:51:22 -0800 (PST) X-Google-Smtp-Source: AJdET5fY7fwwhdnz5P2jwptIPagruzNlRLBK5VzzKeLhtVmrqsosxkD/Ku4iddsnhcQW0+FtLZCl X-Received: by 2002:a63:9809:: with SMTP id q9mr6917405pgd.109.1542307882602; Thu, 15 Nov 2018 10:51:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542307882; cv=none; d=google.com; s=arc-20160816; b=qeU4ySmYd+UUxnfyZauke0I1h9uLCI/eLPtFY8QyGW2YZbVoCihy9BuUvtKuvkZ6MI E7dRfCAhExDfzHUs5lLlnGRbe7yIIjLtDKp29ECQ4+gfTTcdiKSw+2V5EeQauMYK8gMs 0Di2sbOK966YUCQLHTxtT+sZhU1N+ILov6QLSTMTTzeyjUD0mEvrkP5G4qBdTlv/sqmU +htefGh2whcNrSbPFTpfqV0C3587AtZUeqa/bRYO0UZ5uyp8yLmQQtdEJGjLKcabbMWQ yUqhmNTWAiuxplDT3+oFe242QJ96V7YZVudC10W5s6VBwpr6bFFQcMfu7bsPl3mo7pw8 nzfw== 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=sVVVJRDtxWCbkosUADu0QKnN/SDpjii7tg+i5cBf3Lk=; b=ms6V6SNZ3Bj/+ttGzxBXurtLGXMuPwIqWGGlT2XmsapkJRyA0NxFu3CKmBpTmYPxnf NkZCIepaH4izz0xRjRV97xWn40M/BuRcFOZXXarN2VMfqcw2+gVtvncxxkN10Gh/wal0 Ycw3LxV5aSPR/N4e1bBXM08KaUP4sihVbjiG00RfWPhApGoZWwd75s7mkkZX0Vdt/4GC ARzdZjQCS+Xo3okNXRvTNRFYuoC0D17uBLMc9XrNJszfm5sqD7bMsl2iTq0azaneXkJV fAWpoMPi3K+gkWKW9qZepAm4G7gMZFpagHH5unDBkx0gUm5RxX+HNEvNYU4vgXBLQj+s SBwA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=WVyirmtl; spf=pass (google.com: best guess record for domain of linux-arm-msm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-arm-msm-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 4-v6si29589636pla.176.2018.11.15.10.51.21; Thu, 15 Nov 2018 10:51:22 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-arm-msm-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=WVyirmtl; spf=pass (google.com: best guess record for domain of linux-arm-msm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-arm-msm-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 S1725809AbeKPFAR (ORCPT + 14 others); Fri, 16 Nov 2018 00:00:17 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:37675 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725781AbeKPFAR (ORCPT ); Fri, 16 Nov 2018 00:00:17 -0500 Received: by mail-wr1-f67.google.com with SMTP id j10so8120114wru.4 for ; Thu, 15 Nov 2018 10:51:19 -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=sVVVJRDtxWCbkosUADu0QKnN/SDpjii7tg+i5cBf3Lk=; b=WVyirmtlchID+UnXV5f+lxKXJnx3fxBoyq5vdwsOpDucEkBZwZKk9mUAR8G+TbEHVy nFAClMmedwSfhn0rNvwCCFiWIWgPYZSVl27NAzehwoK8/+Npu+IXHPTNUIMd6tW6ZH62 i8XpBJJyTnN+gfsiGKEfx+Kc5Lb/TYnCibN38= 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=sVVVJRDtxWCbkosUADu0QKnN/SDpjii7tg+i5cBf3Lk=; b=m+Am11aAspUb826ewX4tw7mqkAJrV9si9WsH76cbxjXwxi3731BGEtVE4HZM9ccMuH BtW82+qq2p04PeFYtKYAXs5OVUaevX1Q7c3m+qLaGnmVx1fqwBSpdrz4IZAHoowEAMoy 8aNyqqAHF5F+wYfmWYqtPI6qxD0ilDlks+CxXvyw7YGjNQvyOj3AuYckYx6IAsao3Gfc iHQCJAdegt4ZuZPeJWqYRlqLqCXSGaQ9Oh7Rwyqn/BhqF0McpY6HMQ/B/udDislYRPV7 jJzOMzvERRHh9gm/r6EjGM7f0WF5dqAXuQcIlv3OYK1lTCaGzvrZ9uXnIUVIKirHgAEP o+0w== X-Gm-Message-State: AA+aEWaZ7s94NU2Wvek42XQc65PY5cr+yd/dEP/olQXBwjExWm59KXL3 uk0XVzRkFaBCPy8n3iHTC5Sghg== X-Received: by 2002:adf:ff09:: with SMTP id k9mr268596wrr.97.1542307878468; Thu, 15 Nov 2018 10:51:18 -0800 (PST) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id y138sm16529481wmc.16.2018.11.15.10.51.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 15 Nov 2018 10:51:17 -0800 (PST) From: Srinivas Kandagatla To: andy.gross@linaro.org Cc: david.brown@linaro.org, linux-arm-msm@vger.kernel.org, linux-soc@vger.kernel.org, linux-kernel@vger.kernel.org, bgoswami@codeaurora.org, rohitkr@codeaurora.org, bjorn.andersson@linaro.org, Srinivas Kandagatla Subject: [PATCH] qcom: apr: Make apr callbacks in non-atomic context Date: Thu, 15 Nov 2018 18:49:04 +0000 Message-Id: <20181115184904.27223-1-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.19.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 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 --- drivers/soc/qcom/apr.c | 74 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 5 deletions(-) -- 2.19.1 Reviewed-by: Bjorn Andersson diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index 74f8b9607daa..8cfa825fce81 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,6 +363,10 @@ 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); + + flush_workqueue(apr->rxwq); + destroy_workqueue(apr->rxwq); device_for_each_child(&rpdev->dev, NULL, apr_remove_device); }