From patchwork Fri Feb 8 17:11:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 10803423 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 2E5661390 for ; Fri, 8 Feb 2019 17:14:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F8742844C for ; Fri, 8 Feb 2019 17:14:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 12AA82D8F6; Fri, 8 Feb 2019 17:14:04 +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 A29382844C for ; Fri, 8 Feb 2019 17:14:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726522AbfBHRNb (ORCPT ); Fri, 8 Feb 2019 12:13:31 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:39447 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727353AbfBHRNa (ORCPT ); Fri, 8 Feb 2019 12:13:30 -0500 Received: by mail-wm1-f66.google.com with SMTP id f16so4152363wmh.4 for ; Fri, 08 Feb 2019 09:13:28 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=bIjMZWBApTZOoaJL6tl091AuE0dnp0afLV6yVMOATA4=; b=jUQv4oTcJp+WfiWAnh4utQ406+UUmL1iwAJM7bwXkcK+9jADsoctShsdBVRWXvNsuv EHIwvMR0ES7RkV4+E7LmmYOAUyz1zPq1kOA5PWpTWhDaK9tb92veZZ1FBLjAHNe4MsX6 2lbyw7WLBqfc3viVnulEM1mUWjSAp+OHoGJbQqd89ULgWuZeJvLrMyulvO1Py/R1bGjC jsP7r8CUECZYyQvI6kQzgyuKqzsf6hrGr1ocgnbf5DkFt0pByXWjte4mQqoafbk0qRRX MZUJux/8iZw/9w+usOK7u02YmyfocFKTYe/VZ+ojaP/v6JQMpKW3INukrOpxFVYwbMjK 5ppg== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=bIjMZWBApTZOoaJL6tl091AuE0dnp0afLV6yVMOATA4=; b=EZ8LUpZ8yjUOkych2JsE6wutEtBahOwzyeaez7qRnbx4q7m8mnloeIbNTkLV3mW/KX F0trRebJSKhC8H+/2Rj+TOUZbh8peSBT4gZYUpjHBu8tlSiKOwL11P/vjlJltoVtZDaz Y7a6uUo1/7HD/RABMpBBbuii2p/qMifUbAFbfvsrFSR8Bkiw3Mhvpoopr3lWOdwSECVj CY2/6W7kTOsafuQ2qNseN6C5RXq3qj0kdfen+xjWcKOcY+pkoAstk8kt9XIKSZis+Dtp A85TPqO1DaaGw2QktbnC5+dco6Npxhgr/B/xr5IhDJExEE4lFd3q4Lz1VhVXZu11zUSp b80g== X-Gm-Message-State: AHQUAuZs+xMIhFrqMGkF0XgT25VDLLyOYIHLhTLV/FVQHJaBN4s8c0nQ lylLBeQAfCeuymVjnpf4j00qsw== X-Google-Smtp-Source: AHgI3Ibnpp6U9aAms4ZLkCxm/BL6VhML23jO6FJL2tltqsvH/HSItrFoN8B5GYR9tRTVy6PNUFd86w== X-Received: by 2002:a5d:414c:: with SMTP id c12mr16971086wrq.204.1549646008130; Fri, 08 Feb 2019 09:13:28 -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 f139sm4521634wmd.19.2019.02.08.09.13.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 08 Feb 2019 09:13:27 -0800 (PST) From: Srinivas Kandagatla To: gregkh@linuxfoundation.org, arnd@arndb.de Cc: robh+dt@kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, bkumar@qti.qualcomm.com, linux-arm-msm@vger.kernel.org, Srinivas Kandagatla , Thierry Escande , Rob Herring Subject: [PATCH v7 1/5] misc: dt-bindings: Add Qualcomm Fastrpc bindings Date: Fri, 8 Feb 2019 17:11:23 +0000 Message-Id: <20190208171127.24168-2-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> References: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> 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 The FastRPC driver implements an IPC (Inter-Processor Communication) mechanism that allows for clients to transparently make remote method invocations across DSP and APPS boundaries. This enables developers to offload tasks to the DSP and free up the application processor for other tasks. Co-developed-by: Thierry Escande Signed-off-by: Thierry Escande Signed-off-by: Srinivas Kandagatla Reviewed-by: Rob Herring --- .../devicetree/bindings/misc/qcom,fastrpc.txt | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/qcom,fastrpc.txt diff --git a/Documentation/devicetree/bindings/misc/qcom,fastrpc.txt b/Documentation/devicetree/bindings/misc/qcom,fastrpc.txt new file mode 100644 index 000000000000..2a1827ab50d2 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/qcom,fastrpc.txt @@ -0,0 +1,78 @@ +Qualcomm Technologies, Inc. FastRPC Driver + +The FastRPC implements an IPC (Inter-Processor Communication) +mechanism that allows for clients to transparently make remote method +invocations across DSP and APPS boundaries. This enables developers +to offload tasks to the DSP and free up the application processor for +other tasks. + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,fastrpc" + +- label + Usage: required + Value type: + Definition: should specify the dsp domain name this fastrpc + corresponds to. must be one of this: "adsp", "mdsp", "sdsp", "cdsp" + +- #address-cells + Usage: required + Value type: + Definition: Must be 1 + +- #size-cells + Usage: required + Value type: + Definition: Must be 0 + += COMPUTE BANKS +Each subnode of the Fastrpc represents compute context banks available +on the dsp. +- All Compute context banks MUST contain the following properties: + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,fastrpc-compute-cb" + +- reg + Usage: required + Value type: + Definition: Context Bank ID. + +- qcom,nsessions: + Usage: Optional + Value type: + Defination: A value indicating how many sessions can share this + context bank. Defaults to 1 when this property + is not specified. + +Example: + +adsp-pil { + compatible = "qcom,msm8996-adsp-pil"; + ... + smd-edge { + label = "lpass"; + fastrpc { + compatible = "qcom,fastrpc"; + qcom,smd-channels = "fastrpcsmd-apps-dsp"; + label = "adsp"; + #address-cells = <1>; + #size-cells = <0>; + + cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + }; + + cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + }; + ... + }; + }; +}; From patchwork Fri Feb 8 17:11:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 10803421 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 A67D61575 for ; Fri, 8 Feb 2019 17:14:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 923FC2844C for ; Fri, 8 Feb 2019 17:14:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 824C92D8F6; Fri, 8 Feb 2019 17:14:02 +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 A70BC2844C for ; Fri, 8 Feb 2019 17:14:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727782AbfBHROA (ORCPT ); Fri, 8 Feb 2019 12:14:00 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:40000 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727780AbfBHRNc (ORCPT ); Fri, 8 Feb 2019 12:13:32 -0500 Received: by mail-wm1-f65.google.com with SMTP id q21so4143226wmc.5 for ; Fri, 08 Feb 2019 09:13:30 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=5TP06mW8YPclspiLkxOAsy9BVnZLcLJJ6Okf+8NjKBM=; b=HKub6qINo9t3eEotpypmzo4Z9sSufTTBDKdUJFAjAoFN6yKVZawGXeGs0cffdxVZP+ /lQqkep4wHOLmS/fkLKUJfZU/fZW1vehiO4w5LaNL43tZGvqJhKW9UUHNnYQ8s/3AnxG wT1+NWwKm19JAMUM/WxCUE1Lna2V2ybnsf8yj9rZQDW4DIpJ7gcU3h58uuF1AHungqDv KDHOwKD4WKkX1ejhoN/2Ge8e1kYME5ltWIQVgWdyjjnMOjvOASf61cIC2on9z7nsDDId nfYEe8ErAVhRVCEFV/kd5K3d2OvG7VvEmfhQV0JiwYZEsptEm9yDtRRm26cQepXmqjod SUfA== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=5TP06mW8YPclspiLkxOAsy9BVnZLcLJJ6Okf+8NjKBM=; b=H9wa5txbD/KIjqZwV6O/G8igt9MAtfTh95xcJW2CoH7sjPI4eIrfrJIk4WHpSTyDPG q9aCNbGweIYTj/26u6FX04ynwInmrlYRE2tD5iDnkXvpE9iTruXZh9frgkxxKF/d73RU DzqnDEPkm0a0nVEsbeJrnQ0gBtUwyRC1ekOfzr+baGxDt0pZe0hbHTR/MT/BOj72S6U5 qdYaWhn/AIKy9fCNr+Ff87QmUZND3e0a/Osf/8iOw4s5FJMvxLNA5B0HD8jz5iG1TnpQ vlaxmZ+hIVOs3aTjJKxhqEAwhoIXsMYRiIUTwaksjrTApsdhWTrn1xAUM/bXfgzTrlZt hSUg== X-Gm-Message-State: AHQUAuaxXyAZRl2K2deyzI50efyPJ9k9uZbc2sUOotIDfCLopJPigP0z 6vizkTrHxJI2SaQTk3tlhJKMcQ== X-Google-Smtp-Source: AHgI3Iaan5RbyrytOmy4neXCJwCBCU5rYR7f+vSfH8mgUuvxl9xH+9Gl9atN9uU+Xw8wKyCEc9v55A== X-Received: by 2002:a1c:ed0b:: with SMTP id l11mr11596265wmh.43.1549646009667; Fri, 08 Feb 2019 09:13:29 -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 f139sm4521634wmd.19.2019.02.08.09.13.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 08 Feb 2019 09:13:28 -0800 (PST) From: Srinivas Kandagatla To: gregkh@linuxfoundation.org, arnd@arndb.de Cc: robh+dt@kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, bkumar@qti.qualcomm.com, linux-arm-msm@vger.kernel.org, Srinivas Kandagatla , Thierry Escande Subject: [PATCH v7 2/5] misc: fastrpc: Add Qualcomm fastrpc basic driver model Date: Fri, 8 Feb 2019 17:11:24 +0000 Message-Id: <20190208171127.24168-3-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> References: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> 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 This patch adds basic driver model for Qualcomm FastRPC driver which implements an IPC (Inter-Processor Communication) mechanism that allows for clients to transparently make remote method invocations across processor boundaries. Each DSP rpmsg channel is represented as fastrpc channel context and is exposed as a character device for userspace interface. Each compute context bank is represented as fastrpc-session-context, which are dynamically managed by the channel context char device. Co-developed-by: Thierry Escande Signed-off-by: Thierry Escande Signed-off-by: Srinivas Kandagatla --- drivers/misc/Kconfig | 10 ++ drivers/misc/Makefile | 1 + drivers/misc/fastrpc.c | 322 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 333 insertions(+) create mode 100644 drivers/misc/fastrpc.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index f417b06e11c5..7e0726253755 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -295,6 +295,16 @@ config QCOM_COINCELL to maintain PMIC register and RTC state in the absence of external power. +config QCOM_FASTRPC + tristate "Qualcomm FastRPC" + depends on ARCH_QCOM || COMPILE_TEST + depends on RPMSG + help + Provides a communication mechanism that allows for clients to + make remote method invocations across processor boundary to + applications DSP processor. Say M if you want to enable this + module. + config SGI_GRU tristate "SGI GRU driver" depends on X86_UV && SMP diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index e39ccbbc1b3a..623d002c59ce 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o obj-$(CONFIG_PHANTOM) += phantom.o obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o +obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o obj-$(CONFIG_SGI_IOC4) += ioc4.o diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c new file mode 100644 index 000000000000..10b93fd5659a --- /dev/null +++ b/drivers/misc/fastrpc.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. +// Copyright (c) 2018, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADSP_DOMAIN_ID (0) +#define MDSP_DOMAIN_ID (1) +#define SDSP_DOMAIN_ID (2) +#define CDSP_DOMAIN_ID (3) +#define FASTRPC_DEV_MAX 4 /* adsp, mdsp, slpi, cdsp*/ +#define FASTRPC_MAX_SESSIONS 9 /*8 compute, 1 cpz*/ +#define FASTRPC_CTX_MAX (256) +#define FASTRPC_CTXID_MASK (0xFF0) +#define FASTRPC_DEVICE_NAME "fastrpc" + +#define miscdev_to_cctx(d) container_of(d, struct fastrpc_channel_ctx, miscdev) + +static const char *domains[FASTRPC_DEV_MAX] = { "adsp", "mdsp", + "sdsp", "cdsp"}; + +struct fastrpc_session_ctx { + struct device *dev; + int sid; + bool used; + bool valid; +}; + +struct fastrpc_channel_ctx { + int domain_id; + int sesscount; + struct rpmsg_device *rpdev; + struct fastrpc_session_ctx session[FASTRPC_MAX_SESSIONS]; + spinlock_t lock; + struct idr ctx_idr; + struct list_head users; + struct miscdevice miscdev; +}; + +struct fastrpc_user { + struct list_head user; + struct list_head maps; + struct list_head pending; + + struct fastrpc_channel_ctx *cctx; + struct fastrpc_session_ctx *sctx; + + int tgid; + int pd; + /* Lock for lists */ + spinlock_t lock; + /* lock for allocations */ + struct mutex mutex; +}; + +static struct fastrpc_session_ctx *fastrpc_session_alloc( + struct fastrpc_channel_ctx *cctx) +{ + struct fastrpc_session_ctx *session = NULL; + int i; + + spin_lock(&cctx->lock); + for (i = 0; i < cctx->sesscount; i++) { + if (!cctx->session[i].used && cctx->session[i].valid) { + cctx->session[i].used = true; + session = &cctx->session[i]; + break; + } + } + spin_unlock(&cctx->lock); + + return session; +} + +static void fastrpc_session_free(struct fastrpc_channel_ctx *cctx, + struct fastrpc_session_ctx *session) +{ + spin_lock(&cctx->lock); + session->used = false; + spin_unlock(&cctx->lock); +} + +static int fastrpc_device_release(struct inode *inode, struct file *file) +{ + struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data; + struct fastrpc_channel_ctx *cctx = fl->cctx; + + spin_lock(&cctx->lock); + list_del(&fl->user); + spin_unlock(&cctx->lock); + + fastrpc_session_free(cctx, fl->sctx); + + mutex_destroy(&fl->mutex); + kfree(fl); + file->private_data = NULL; + + return 0; +} + +static int fastrpc_device_open(struct inode *inode, struct file *filp) +{ + struct fastrpc_channel_ctx *cctx = miscdev_to_cctx(filp->private_data); + struct fastrpc_user *fl = NULL; + + fl = kzalloc(sizeof(*fl), GFP_KERNEL); + if (!fl) + return -ENOMEM; + + filp->private_data = fl; + spin_lock_init(&fl->lock); + mutex_init(&fl->mutex); + INIT_LIST_HEAD(&fl->pending); + INIT_LIST_HEAD(&fl->maps); + INIT_LIST_HEAD(&fl->user); + fl->tgid = current->tgid; + fl->cctx = cctx; + spin_lock(&cctx->lock); + list_add_tail(&fl->user, &cctx->users); + spin_unlock(&cctx->lock); + fl->sctx = fastrpc_session_alloc(cctx); + + return 0; +} + +static const struct file_operations fastrpc_fops = { + .open = fastrpc_device_open, + .release = fastrpc_device_release, +}; + +static int fastrpc_cb_probe(struct platform_device *pdev) +{ + struct fastrpc_channel_ctx *cctx; + struct fastrpc_session_ctx *sess; + struct device *dev = &pdev->dev; + int i, sessions = 0; + + cctx = dev_get_drvdata(dev->parent); + if (!cctx) + return -EINVAL; + + of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions); + + spin_lock(&cctx->lock); + sess = &cctx->session[cctx->sesscount]; + sess->used = false; + sess->valid = true; + sess->dev = dev; + dev_set_drvdata(dev, sess); + + if (of_property_read_u32(dev->of_node, "reg", &sess->sid)) + dev_info(dev, "FastRPC Session ID not specified in DT\n"); + + if (sessions > 0) { + struct fastrpc_session_ctx *dup_sess; + + for (i = 1; i < sessions; i++) { + if (cctx->sesscount++ >= FASTRPC_MAX_SESSIONS) + break; + dup_sess = &cctx->session[cctx->sesscount]; + memcpy(dup_sess, sess, sizeof(*dup_sess)); + } + } + cctx->sesscount++; + spin_unlock(&cctx->lock); + dma_set_mask(dev, DMA_BIT_MASK(32)); + + return 0; +} + +static int fastrpc_cb_remove(struct platform_device *pdev) +{ + struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent); + struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev); + int i; + + spin_lock(&cctx->lock); + for (i = 1; i < FASTRPC_MAX_SESSIONS; i++) { + if (cctx->session[i].sid == sess->sid) { + cctx->session[i].valid = false; + cctx->sesscount--; + } + } + spin_unlock(&cctx->lock); + + return 0; +} + +static const struct of_device_id fastrpc_match_table[] = { + { .compatible = "qcom,fastrpc-compute-cb", }, + {} +}; + +static struct platform_driver fastrpc_cb_driver = { + .probe = fastrpc_cb_probe, + .remove = fastrpc_cb_remove, + .driver = { + .name = "qcom,fastrpc-cb", + .of_match_table = fastrpc_match_table, + .suppress_bind_attrs = true, + }, +}; + +static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) +{ + struct device *rdev = &rpdev->dev; + struct fastrpc_channel_ctx *data; + int i, err, domain_id = -1; + const char *domain; + + data = devm_kzalloc(rdev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + err = of_property_read_string(rdev->of_node, "label", &domain); + if (err) { + dev_info(rdev, "FastRPC Domain not specified in DT\n"); + return err; + } + + for (i = 0; i <= CDSP_DOMAIN_ID; i++) { + if (!strcmp(domains[i], domain)) { + domain_id = i; + break; + } + } + + if (domain_id < 0) { + dev_info(rdev, "FastRPC Invalid Domain ID %d\n", domain_id); + return -EINVAL; + } + + data->miscdev.minor = MISC_DYNAMIC_MINOR; + data->miscdev.name = kasprintf(GFP_KERNEL, "fastrpc-%s", + domains[domain_id]); + data->miscdev.fops = &fastrpc_fops; + err = misc_register(&data->miscdev); + if (err) + return err; + + dev_set_drvdata(&rpdev->dev, data); + dma_set_mask_and_coherent(rdev, DMA_BIT_MASK(32)); + INIT_LIST_HEAD(&data->users); + spin_lock_init(&data->lock); + idr_init(&data->ctx_idr); + data->domain_id = domain_id; + data->rpdev = rpdev; + + return of_platform_populate(rdev->of_node, NULL, NULL, rdev); +} + +static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) +{ + struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev); + + misc_deregister(&cctx->miscdev); + of_platform_depopulate(&rpdev->dev); + kfree(cctx); +} + +static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, + int len, void *priv, u32 addr) +{ + return 0; +} + +static const struct of_device_id fastrpc_rpmsg_of_match[] = { + { .compatible = "qcom,fastrpc" }, + { }, +}; +MODULE_DEVICE_TABLE(of, fastrpc_rpmsg_of_match); + +static struct rpmsg_driver fastrpc_driver = { + .probe = fastrpc_rpmsg_probe, + .remove = fastrpc_rpmsg_remove, + .callback = fastrpc_rpmsg_callback, + .drv = { + .name = "qcom,fastrpc", + .of_match_table = fastrpc_rpmsg_of_match, + }, +}; + +static int fastrpc_init(void) +{ + int ret; + + ret = platform_driver_register(&fastrpc_cb_driver); + if (ret < 0) { + pr_err("fastrpc: failed to register cb driver\n"); + return ret; + } + + ret = register_rpmsg_driver(&fastrpc_driver); + if (ret < 0) { + pr_err("fastrpc: failed to register rpmsg driver\n"); + platform_driver_unregister(&fastrpc_cb_driver); + return ret; + } + + return 0; +} +module_init(fastrpc_init); + +static void fastrpc_exit(void) +{ + platform_driver_unregister(&fastrpc_cb_driver); + unregister_rpmsg_driver(&fastrpc_driver); +} +module_exit(fastrpc_exit); + +MODULE_LICENSE("GPL v2"); From patchwork Fri Feb 8 17:11:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 10803419 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 9C2F91575 for ; Fri, 8 Feb 2019 17:13:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8AFD62844C for ; Fri, 8 Feb 2019 17:13:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7E6942D8F6; Fri, 8 Feb 2019 17:13:58 +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 14C502844C for ; Fri, 8 Feb 2019 17:13:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727604AbfBHRN4 (ORCPT ); Fri, 8 Feb 2019 12:13:56 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:35624 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727844AbfBHRNg (ORCPT ); Fri, 8 Feb 2019 12:13:36 -0500 Received: by mail-wm1-f66.google.com with SMTP id t200so4184802wmt.0 for ; Fri, 08 Feb 2019 09:13:32 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=5nb3/DcZ/KAj72cqZ3a64b2GmFVKMBqHe3LVsfGYl2o=; b=eQDXkY/S1+ui6jOmZSm9h5RjCgL8NHewo3AUEKpPyjHcSV9nju1ANdJfeiLbbOBC8E tY/XkSfHurbKsdUPLW5jsisNJDKfcIABmoAShPPGAYGXFQJwg0NIE9fiVkxhjZKbyUDh mIxEH0vPHRx+J9YFr+5nhcUTga+QQ9Fgba98XBdzvW0TYX7vWit4OEPXyN/dapFYApQ+ MUIjQtCk6GMbldMkBjSFSn31RIAto2nduNaClA2TiL59yAD9SG6rkmmvC791ph715dMw l0b8L11jNhk3cc7MWFfEnX2he5F3xWdgP9wulIqtmu79IFdSwbOWdTuM5FusOS0Ou0PQ So4Q== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=5nb3/DcZ/KAj72cqZ3a64b2GmFVKMBqHe3LVsfGYl2o=; b=Tbl/4zvL4hIPLzN7sthKMav0CS43LBhjzN0JkizrTuDaCf3CrxX88959ioHBJj+biB F0IFbZ6U8n0QKoMHiO6Nu/ErgVsxDubYf8HJSAX6VkQ9xXf7T96S89ypx+TQqkR+Tom1 cT2qIg5AEA9Hu/TEomYwkgsqwbcKyZMJhZEB7iwYumv7CP+bxuYRrCW+XPRpPoFNdd+b b+GhIB4c+LhMGFFMT/lsbSg1ZpxhGDUxYlb8ciAm30PWcKiUI1ALSUIur64fe8jk2MYc QOq9e99EQzxNf7dgBMSk04RdDRNIW/Up/LrKpQ/x5kiIkIQ1eRExgA4kDrSTKaEnvUM6 Zgog== X-Gm-Message-State: AHQUAuZs/bgnmVJbMgCwOnIUCA6zxrioaN/qNTfNRA6DAiWLvP7Rgxjw oUQnVzbM9GjOn+73GKwUZ6cwAabPJ3k= X-Google-Smtp-Source: AHgI3IZN45qHFq07zZr7lkl0m6f/GDPtj5O7tLqPfh+cwrdqVH9tQYQmJi8ZF1zl9CqbS/8AZuciGA== X-Received: by 2002:a7b:cb0a:: with SMTP id u10mr12996749wmj.0.1549646011538; Fri, 08 Feb 2019 09:13:31 -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 f139sm4521634wmd.19.2019.02.08.09.13.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 08 Feb 2019 09:13:30 -0800 (PST) From: Srinivas Kandagatla To: gregkh@linuxfoundation.org, arnd@arndb.de Cc: robh+dt@kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, bkumar@qti.qualcomm.com, linux-arm-msm@vger.kernel.org, Srinivas Kandagatla , Thierry Escande Subject: [PATCH v7 3/5] misc: fastrpc: Add support for context Invoke method Date: Fri, 8 Feb 2019 17:11:25 +0000 Message-Id: <20190208171127.24168-4-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> References: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> 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 This patch adds support to compute context invoke method on the remote processor (DSP). This involves setting up the functions input and output arguments, input and output handles and mapping the dmabuf fd for the argument/handle buffers. The below diagram depicts invocation of a single method where the client and objects reside on different processors. An object could expose multiple methods which can be grouped together and referred to as an interface. ,--------, ,------, ,-----------, ,------, ,--------, | | method | | | | | | method | | | Client |------->| Stub |->| Transport |->| Skel |------->| Object | | | | | | | | | | | `--------` `------` `-----------` `------` `--------` Client: Linux user mode process that initiates the remote invocation Stub: Auto generated code linked in with the user mode process that takes care of marshaling parameters Transport: Involved in carrying an invocation from a client to an object. This involves two portions: 1) FastRPC Linux kernel driver that receives the remote invocation, queues them up and then waits for the response after signaling the remote side. 2) Service running on the remote side that dequeues the messages from the queue and dispatches them for processing. Skel: Auto generated code that takes care of un-marshaling parameters Object: Method implementation Most of the work is derived from various downstream Qualcomm kernels. Credits to various Qualcomm authors who have contributed to this code. Specially Tharun Kumar Merugu Co-developed-by: Thierry Escande Signed-off-by: Thierry Escande Signed-off-by: Srinivas Kandagatla --- drivers/misc/fastrpc.c | 730 ++++++++++++++++++++++++++++++++++++ include/uapi/misc/fastrpc.h | 23 ++ 2 files changed, 753 insertions(+) create mode 100644 include/uapi/misc/fastrpc.h diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 10b93fd5659a..cd69f8b308f6 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -2,7 +2,9 @@ // Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. // Copyright (c) 2018, Linaro Limited +#include #include +#include #include #include #include @@ -14,6 +16,7 @@ #include #include #include +#include #define ADSP_DOMAIN_ID (0) #define MDSP_DOMAIN_ID (1) @@ -21,14 +24,118 @@ #define CDSP_DOMAIN_ID (3) #define FASTRPC_DEV_MAX 4 /* adsp, mdsp, slpi, cdsp*/ #define FASTRPC_MAX_SESSIONS 9 /*8 compute, 1 cpz*/ +#define FASTRPC_ALIGN 128 +#define FASTRPC_MAX_FDLIST 16 +#define FASTRPC_MAX_CRCLIST 64 +#define FASTRPC_PHYS(p) ((p) & 0xffffffff) #define FASTRPC_CTX_MAX (256) #define FASTRPC_CTXID_MASK (0xFF0) #define FASTRPC_DEVICE_NAME "fastrpc" +/* Retrives number of input buffers from the scalars parameter */ +#define REMOTE_SCALARS_INBUFS(sc) (((sc) >> 16) & 0x0ff) + +/* Retrives number of output buffers from the scalars parameter */ +#define REMOTE_SCALARS_OUTBUFS(sc) (((sc) >> 8) & 0x0ff) + +/* Retrives number of input handles from the scalars parameter */ +#define REMOTE_SCALARS_INHANDLES(sc) (((sc) >> 4) & 0x0f) + +/* Retrives number of output handles from the scalars parameter */ +#define REMOTE_SCALARS_OUTHANDLES(sc) ((sc) & 0x0f) + +#define REMOTE_SCALARS_LENGTH(sc) (REMOTE_SCALARS_INBUFS(sc) + \ + REMOTE_SCALARS_OUTBUFS(sc) + \ + REMOTE_SCALARS_INHANDLES(sc)+ \ + REMOTE_SCALARS_OUTHANDLES(sc)) +#define FASTRPC_BUILD_SCALARS(attr, method, in, out, oin, oout) \ + (((attr & 0x07) << 29) | \ + ((method & 0x1f) << 24) | \ + ((in & 0xff) << 16) | \ + ((out & 0xff) << 8) | \ + ((oin & 0x0f) << 4) | \ + (oout & 0x0f)) + +#define FASTRPC_SCALARS(method, in, out) \ + FASTRPC_BUILD_SCALARS(0, method, in, out, 0, 0) + #define miscdev_to_cctx(d) container_of(d, struct fastrpc_channel_ctx, miscdev) static const char *domains[FASTRPC_DEV_MAX] = { "adsp", "mdsp", "sdsp", "cdsp"}; +struct fastrpc_phy_page { + u64 addr; /* physical address */ + u64 size; /* size of contiguous region */ +}; + +struct fastrpc_invoke_buf { + u32 num; /* number of contiguous regions */ + u32 pgidx; /* index to start of contiguous region */ +}; + +struct fastrpc_remote_arg { + u64 pv; + u64 len; +}; + +struct fastrpc_msg { + int pid; /* process group id */ + int tid; /* thread id */ + u64 ctx; /* invoke caller context */ + u32 handle; /* handle to invoke */ + u32 sc; /* scalars structure describing the data */ + u64 addr; /* physical address */ + u64 size; /* size of contiguous region */ +}; + +struct fastrpc_invoke_rsp { + u64 ctx; /* invoke caller context */ + int retval; /* invoke return value */ +}; + +struct fastrpc_buf { + struct fastrpc_user *fl; + struct device *dev; + void *virt; + u64 phys; + u64 size; +}; + +struct fastrpc_map { + struct list_head node; + struct fastrpc_user *fl; + int fd; + struct dma_buf *buf; + struct sg_table *table; + struct dma_buf_attachment *attach; + u64 phys; + u64 size; + void *va; + u64 len; + struct kref refcount; +}; + +struct fastrpc_invoke_ctx { + int nscalars; + int nbufs; + int retval; + int pid; + int tgid; + u32 sc; + u32 *crc; + u64 ctxid; + u64 msg_sz; + struct kref refcount; + struct list_head node; /* list of ctxs */ + struct completion work; + struct fastrpc_msg msg; + struct fastrpc_user *fl; + struct fastrpc_remote_arg *rpra; + struct fastrpc_map **maps; + struct fastrpc_buf *buf; + struct fastrpc_invoke_args *args; + struct fastrpc_channel_ctx *cctx; +}; struct fastrpc_session_ctx { struct device *dev; @@ -55,6 +162,7 @@ struct fastrpc_user { struct fastrpc_channel_ctx *cctx; struct fastrpc_session_ctx *sctx; + struct fastrpc_buf *init_mem; int tgid; int pd; @@ -64,6 +172,522 @@ struct fastrpc_user { struct mutex mutex; }; +static void fastrpc_free_map(struct kref *ref) +{ + struct fastrpc_map *map; + + map = container_of(ref, struct fastrpc_map, refcount); + + if (map->table) { + dma_buf_unmap_attachment(map->attach, map->table, + DMA_BIDIRECTIONAL); + dma_buf_detach(map->buf, map->attach); + dma_buf_put(map->buf); + } + + kfree(map); +} + +static void fastrpc_map_put(struct fastrpc_map *map) +{ + if (map) + kref_put(&map->refcount, fastrpc_free_map); +} + +static void fastrpc_map_get(struct fastrpc_map *map) +{ + if (map) + kref_get(&map->refcount); +} + +static int fastrpc_map_find(struct fastrpc_user *fl, int fd, + struct fastrpc_map **ppmap) +{ + struct fastrpc_map *map = NULL; + + mutex_lock(&fl->mutex); + list_for_each_entry(map, &fl->maps, node) { + if (map->fd == fd) { + fastrpc_map_get(map); + *ppmap = map; + mutex_unlock(&fl->mutex); + return 0; + } + } + mutex_unlock(&fl->mutex); + + return -ENOENT; +} + +static void fastrpc_buf_free(struct fastrpc_buf *buf) +{ + dma_free_coherent(buf->dev, buf->size, buf->virt, + FASTRPC_PHYS(buf->phys)); + kfree(buf); +} + +static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev, + u64 size, struct fastrpc_buf **obuf) +{ + struct fastrpc_buf *buf; + + buf = kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf->fl = fl; + buf->virt = NULL; + buf->phys = 0; + buf->size = size; + buf->dev = dev; + + buf->virt = dma_alloc_coherent(dev, buf->size, (dma_addr_t *)&buf->phys, + GFP_KERNEL); + if (!buf->virt) + return -ENOMEM; + + if (fl->sctx && fl->sctx->sid) + buf->phys += ((u64)fl->sctx->sid << 32); + + *obuf = buf; + + return 0; +} + +static void fastrpc_context_free(struct kref *ref) +{ + struct fastrpc_invoke_ctx *ctx; + struct fastrpc_channel_ctx *cctx; + int i; + + ctx = container_of(ref, struct fastrpc_invoke_ctx, refcount); + cctx = ctx->cctx; + + for (i = 0; i < ctx->nscalars; i++) + fastrpc_map_put(ctx->maps[i]); + + if (ctx->buf) + fastrpc_buf_free(ctx->buf); + + spin_lock(&cctx->lock); + idr_remove(&cctx->ctx_idr, ctx->ctxid >> 4); + spin_unlock(&cctx->lock); + + kfree(ctx->maps); + kfree(ctx); +} + +static void fastrpc_context_get(struct fastrpc_invoke_ctx *ctx) +{ + kref_get(&ctx->refcount); +} + +static void fastrpc_context_put(struct fastrpc_invoke_ctx *ctx) +{ + kref_put(&ctx->refcount, fastrpc_context_free); +} + +static struct fastrpc_invoke_ctx *fastrpc_context_alloc( + struct fastrpc_user *user, u32 kernel, u32 sc, + struct fastrpc_invoke_args *args) +{ + struct fastrpc_channel_ctx *cctx = user->cctx; + struct fastrpc_invoke_ctx *ctx = NULL; + int ret; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&ctx->node); + ctx->fl = user; + ctx->nscalars = REMOTE_SCALARS_LENGTH(sc); + ctx->nbufs = REMOTE_SCALARS_INBUFS(sc) + + REMOTE_SCALARS_OUTBUFS(sc); + + if (ctx->nscalars) { + ctx->maps = kcalloc(ctx->nscalars, + sizeof(*ctx->maps), GFP_KERNEL); + if (!ctx->maps) { + kfree(ctx); + return ERR_PTR(-ENOMEM); + } + ctx->args = args; + } + + ctx->sc = sc; + ctx->retval = -1; + ctx->pid = current->pid; + ctx->tgid = user->tgid; + ctx->cctx = cctx; + init_completion(&ctx->work); + + spin_lock(&user->lock); + list_add_tail(&ctx->node, &user->pending); + spin_unlock(&user->lock); + + spin_lock(&cctx->lock); + ret = idr_alloc_cyclic(&cctx->ctx_idr, ctx, 1, + FASTRPC_CTX_MAX, GFP_ATOMIC); + if (ret < 0) { + spin_unlock(&cctx->lock); + goto err_idr; + } + ctx->ctxid = ret << 4; + spin_unlock(&cctx->lock); + + kref_init(&ctx->refcount); + + return ctx; +err_idr: + spin_lock(&user->lock); + list_del(&ctx->node); + spin_unlock(&user->lock); + kfree(ctx->maps); + kfree(ctx); + + return ERR_PTR(ret); +} + +static int fastrpc_map_create(struct fastrpc_user *fl, int fd, + u64 len, struct fastrpc_map **ppmap) +{ + struct fastrpc_session_ctx *sess = fl->sctx; + struct fastrpc_map *map = NULL; + int err = 0; + + if (!fastrpc_map_find(fl, fd, ppmap)) + return 0; + + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (!map) + return -ENOMEM; + + INIT_LIST_HEAD(&map->node); + map->fl = fl; + map->fd = fd; + map->buf = dma_buf_get(fd); + if (!map->buf) { + err = -EINVAL; + goto get_err; + } + + map->attach = dma_buf_attach(map->buf, sess->dev); + if (IS_ERR(map->attach)) { + dev_err(sess->dev, "Failed to attach dmabuf\n"); + err = PTR_ERR(map->attach); + goto attach_err; + } + + map->table = dma_buf_map_attachment(map->attach, DMA_BIDIRECTIONAL); + if (IS_ERR(map->table)) { + err = PTR_ERR(map->table); + goto map_err; + } + + map->phys = sg_dma_address(map->table->sgl); + map->phys += ((u64)fl->sctx->sid << 32); + map->size = len; + map->va = sg_virt(map->table->sgl); + map->len = len; + kref_init(&map->refcount); + + spin_lock(&fl->lock); + list_add_tail(&map->node, &fl->maps); + spin_unlock(&fl->lock); + *ppmap = map; + + return 0; + +map_err: + dma_buf_detach(map->buf, map->attach); +attach_err: + dma_buf_put(map->buf); +get_err: + kfree(map); + + return err; +} + +/* + * Fastrpc payload buffer with metadata looks like: + * + * >>>>>> START of METADATA <<<<<<<<< + * +---------------------------------+ + * | Arguments | + * | type:(struct fastrpc_remote_arg)| + * | (0 - N) | + * +---------------------------------+ + * | Invoke Buffer list | + * | type:(struct fastrpc_invoke_buf)| + * | (0 - N) | + * +---------------------------------+ + * | Page info list | + * | type:(struct fastrpc_phy_page) | + * | (0 - N) | + * +---------------------------------+ + * | Optional info | + * |(can be specific to SoC/Firmware)| + * +---------------------------------+ + * >>>>>>>> END of METADATA <<<<<<<<< + * +---------------------------------+ + * | Inline ARGS | + * | (0-N) | + * +---------------------------------+ + */ + +static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx) +{ + int size = 0; + + size = (sizeof(struct fastrpc_remote_arg) + + sizeof(struct fastrpc_invoke_buf) + + sizeof(struct fastrpc_phy_page)) * ctx->nscalars + + sizeof(u64) * FASTRPC_MAX_FDLIST + + sizeof(u32) * FASTRPC_MAX_CRCLIST; + + return size; +} + +static u64 fastrpc_get_payload_size(struct fastrpc_invoke_ctx *ctx, int metalen) +{ + u64 size = 0; + int i; + + size = ALIGN(metalen, FASTRPC_ALIGN); + for (i = 0; i < ctx->nscalars; i++) { + if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1) { + size = ALIGN(size, FASTRPC_ALIGN); + size += ctx->args[i].length; + } + } + + return size; +} + +static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx) +{ + struct device *dev = ctx->fl->sctx->dev; + int i, err; + + for (i = 0; i < ctx->nscalars; ++i) { + /* Make sure reserved field is set to 0 */ + if (ctx->args[i].reserved) + return -EINVAL; + + if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1 || + ctx->args[i].length == 0) + continue; + + err = fastrpc_map_create(ctx->fl, ctx->args[i].fd, + ctx->args[i].length, &ctx->maps[i]); + if (err) { + dev_err(dev, "Error Creating map %d\n", err); + return -EINVAL; + } + + } + return 0; +} + +static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) +{ + struct device *dev = ctx->fl->sctx->dev; + struct fastrpc_remote_arg *rpra; + struct fastrpc_invoke_buf *list; + struct fastrpc_phy_page *pages; + int inbufs, i, err = 0; + u64 rlen, pkt_size; + uintptr_t args; + int metalen; + + + inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); + metalen = fastrpc_get_meta_size(ctx); + pkt_size = fastrpc_get_payload_size(ctx, metalen); + + err = fastrpc_create_maps(ctx); + if (err) + return err; + + ctx->msg_sz = pkt_size; + + err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, &ctx->buf); + if (err) + return err; + + rpra = ctx->buf->virt; + list = ctx->buf->virt + ctx->nscalars * sizeof(*rpra); + pages = ctx->buf->virt + ctx->nscalars * (sizeof(*list) + + sizeof(*rpra)); + args = (uintptr_t)ctx->buf->virt + metalen; + rlen = pkt_size - metalen; + ctx->rpra = rpra; + + for (i = 0; i < ctx->nbufs; ++i) { + u64 len = ctx->args[i].length; + + rpra[i].pv = 0; + rpra[i].len = len; + list[i].num = len ? 1 : 0; + list[i].pgidx = i; + + if (!len) + continue; + + pages[i].size = roundup(len, PAGE_SIZE); + + if (ctx->maps[i]) { + rpra[i].pv = (u64) ctx->args[i].ptr; + pages[i].addr = ctx->maps[i]->phys; + } else { + rlen -= ALIGN(args, FASTRPC_ALIGN) - args; + args = ALIGN(args, FASTRPC_ALIGN); + if (rlen < len) + goto bail; + + rpra[i].pv = args; + pages[i].addr = ctx->buf->phys + (pkt_size - rlen); + pages[i].addr = pages[i].addr & PAGE_MASK; + args = args + len; + rlen -= len; + } + + if (i < inbufs && !ctx->maps[i]) { + void *dst = (void *)(uintptr_t)rpra[i].pv; + void *src = (void *)(uintptr_t)ctx->args[i].ptr; + + if (!kernel) { + if (copy_from_user(dst, (void __user *)src, + len)) { + err = -EFAULT; + goto bail; + } + } else { + memcpy(dst, src, len); + } + } + } + + for (i = ctx->nbufs; i < ctx->nscalars; ++i) { + rpra[i].pv = (u64) ctx->args[i].ptr; + rpra[i].len = ctx->args[i].length; + list[i].num = ctx->args[i].length ? 1 : 0; + list[i].pgidx = i; + pages[i].addr = ctx->maps[i]->phys; + pages[i].size = ctx->maps[i]->size; + } + +bail: + if (err) + dev_err(dev, "Error: get invoke args failed:%d\n", err); + + return err; +} + +static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx, + u32 kernel) +{ + struct fastrpc_remote_arg *rpra = ctx->rpra; + int i, inbufs; + + inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); + + for (i = inbufs; i < ctx->nbufs; ++i) { + void *src = (void *)(uintptr_t)rpra[i].pv; + void *dst = (void *)(uintptr_t)ctx->args[i].ptr; + u64 len = rpra[i].len; + + if (!kernel) { + if (copy_to_user((void __user *)dst, src, len)) + return -EFAULT; + } else { + memcpy(dst, src, len); + } + } + + return 0; +} + +static int fastrpc_invoke_send(struct fastrpc_session_ctx *sctx, + struct fastrpc_invoke_ctx *ctx, + u32 kernel, uint32_t handle) +{ + struct fastrpc_channel_ctx *cctx; + struct fastrpc_user *fl = ctx->fl; + struct fastrpc_msg *msg = &ctx->msg; + + cctx = fl->cctx; + msg->pid = fl->tgid; + msg->tid = current->pid; + + if (kernel) + msg->pid = 0; + + msg->ctx = ctx->ctxid | fl->pd; + msg->handle = handle; + msg->sc = ctx->sc; + msg->addr = ctx->buf ? ctx->buf->phys : 0; + msg->size = roundup(ctx->msg_sz, PAGE_SIZE); + fastrpc_context_get(ctx); + + return rpmsg_send(cctx->rpdev->ept, (void *)msg, sizeof(*msg)); +} + +static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, + u32 handle, u32 sc, + struct fastrpc_invoke_args *args) +{ + struct fastrpc_invoke_ctx *ctx = NULL; + int err = 0; + + if (!fl->sctx) + return -EINVAL; + + ctx = fastrpc_context_alloc(fl, kernel, sc, args); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + if (ctx->nscalars) { + err = fastrpc_get_args(kernel, ctx); + if (err) + goto bail; + } + /* Send invoke buffer to remote dsp */ + err = fastrpc_invoke_send(fl->sctx, ctx, kernel, handle); + if (err) + goto bail; + + /* Wait for remote dsp to respond or time out */ + err = wait_for_completion_interruptible(&ctx->work); + if (err) + goto bail; + + /* Check the response from remote dsp */ + err = ctx->retval; + if (err) + goto bail; + + if (ctx->nscalars) { + /* populate all the output buffers with results */ + err = fastrpc_put_args(ctx, kernel); + if (err) + goto bail; + } + +bail: + /* We are done with this compute context, remove it from pending list */ + spin_lock(&fl->lock); + list_del(&ctx->node); + spin_unlock(&fl->lock); + fastrpc_context_put(ctx); + + if (err) + dev_dbg(fl->sctx->dev, "Error: Invoke Failed %d\n", err); + + return err; +} + static struct fastrpc_session_ctx *fastrpc_session_alloc( struct fastrpc_channel_ctx *cctx) { @@ -95,11 +719,26 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) { struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data; struct fastrpc_channel_ctx *cctx = fl->cctx; + struct fastrpc_invoke_ctx *ctx, *n; + struct fastrpc_map *map, *m; spin_lock(&cctx->lock); list_del(&fl->user); spin_unlock(&cctx->lock); + if (fl->init_mem) + fastrpc_buf_free(fl->init_mem); + + list_for_each_entry_safe(ctx, n, &fl->pending, node) { + list_del(&ctx->node); + fastrpc_context_put(ctx); + } + + list_for_each_entry_safe(map, m, &fl->maps, node) { + list_del(&map->node); + fastrpc_map_put(map); + } + fastrpc_session_free(cctx, fl->sctx); mutex_destroy(&fl->mutex); @@ -134,9 +773,60 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) return 0; } +static int fastrpc_invoke(struct fastrpc_user *fl, char __user *argp) +{ + struct fastrpc_invoke_args *args = NULL; + struct fastrpc_invoke inv; + u32 nscalars; + int err; + + if (copy_from_user(&inv, argp, sizeof(inv))) + return -EFAULT; + + /* nscalars is truncated here to max supported value */ + nscalars = REMOTE_SCALARS_LENGTH(inv.sc); + if (nscalars) { + args = kcalloc(nscalars, sizeof(*args), GFP_KERNEL); + if (!args) + return -ENOMEM; + + if (copy_from_user(args, (void __user *)(uintptr_t)inv.args, + nscalars * sizeof(*args))) { + kfree(args); + return -EFAULT; + } + } + + err = fastrpc_internal_invoke(fl, false, inv.handle, inv.sc, args); + kfree(args); + + return err; +} + +static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data; + char __user *argp = (char __user *)arg; + int err; + + switch (cmd) { + case FASTRPC_IOCTL_INVOKE: + err = fastrpc_invoke(fl, argp); + break; + default: + err = -ENOTTY; + break; + } + + return err; +} + static const struct file_operations fastrpc_fops = { .open = fastrpc_device_open, .release = fastrpc_device_release, + .unlocked_ioctl = fastrpc_device_ioctl, + .compat_ioctl = fastrpc_device_ioctl, }; static int fastrpc_cb_probe(struct platform_device *pdev) @@ -260,9 +950,25 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) return of_platform_populate(rdev->of_node, NULL, NULL, rdev); } +static void fastrpc_notify_users(struct fastrpc_user *user) +{ + struct fastrpc_invoke_ctx *ctx; + + spin_lock(&user->lock); + list_for_each_entry(ctx, &user->pending, node) + complete(&ctx->work); + spin_unlock(&user->lock); +} + static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) { struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev); + struct fastrpc_user *user; + + spin_lock(&cctx->lock); + list_for_each_entry(user, &cctx->users, user) + fastrpc_notify_users(user); + spin_unlock(&cctx->lock); misc_deregister(&cctx->miscdev); of_platform_depopulate(&rpdev->dev); @@ -272,6 +978,30 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 addr) { + struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev); + struct fastrpc_invoke_rsp *rsp = data; + struct fastrpc_invoke_ctx *ctx; + unsigned long flags; + unsigned long ctxid; + + if (len < sizeof(*rsp)) + return -EINVAL; + + ctxid = ((rsp->ctx & FASTRPC_CTXID_MASK) >> 4); + + spin_lock_irqsave(&cctx->lock, flags); + ctx = idr_find(&cctx->ctx_idr, ctxid); + spin_unlock_irqrestore(&cctx->lock, flags); + + if (!ctx) { + dev_err(&rpdev->dev, "No context ID matches response\n"); + return -ENOENT; + } + + ctx->retval = rsp->retval; + complete(&ctx->work); + fastrpc_context_put(ctx); + return 0; } diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h new file mode 100644 index 000000000000..a69ef33dc37e --- /dev/null +++ b/include/uapi/misc/fastrpc.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __QCOM_FASTRPC_H__ +#define __QCOM_FASTRPC_H__ + +#include + +#define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke) + +struct fastrpc_invoke_args { + __u64 ptr; + __u64 length; + __s32 fd; + __u32 reserved; +}; + +struct fastrpc_invoke { + __u32 handle; + __u32 sc; + __u64 args; +}; + +#endif /* __QCOM_FASTRPC_H__ */ From patchwork Fri Feb 8 17:11:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 10803417 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 682E21823 for ; Fri, 8 Feb 2019 17:13:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 557602D8CF for ; Fri, 8 Feb 2019 17:13:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 489162D972; Fri, 8 Feb 2019 17:13:57 +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 95F712D8CF for ; Fri, 8 Feb 2019 17:13:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727911AbfBHRNf (ORCPT ); Fri, 8 Feb 2019 12:13:35 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:52307 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727887AbfBHRNf (ORCPT ); Fri, 8 Feb 2019 12:13:35 -0500 Received: by mail-wm1-f65.google.com with SMTP id m1so4212495wml.2 for ; Fri, 08 Feb 2019 09:13:33 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=Pw02RysD3yARf0G9aEsHcDFW4VSiASPNF5YAbP0ZM24=; b=aMyRio0wQzWbiR+AyTuJpioEIXdfpo8+3i/n5R4zaIsRYWbm9O1uCvgYDr75XR39mC 1lTxFNDNmxtJzegSwfZfTMVXlevgyoBjW6+up3aICJrGhvWnELH/lPUbcyNKKhgvRSry I66BXAQgL0Sgcc9qADz/pCpCJJ+aCpzlpVpFGeiqLMvTpfrQJfRasLmE1EEl6Tz1GJyP iOhqICndPt7Sn4+Ehy6/ceLc7ht6Dl1E5WCuXJc3ZHwMHpsOdJiwFbxti/BXT3Wkl0Fg Dt/1HyPEYAX9y6h7wvozc+IlhV9a8PqODRjZubMmzeIPRRbVio95AE7yu+I8VMIQmB5c 43aw== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=Pw02RysD3yARf0G9aEsHcDFW4VSiASPNF5YAbP0ZM24=; b=QijbsNtXsS2Ocamegqqh1Z4pyVz/M68Rm4x6aOLcLFimy2h+71o9JrjFpXO/GYMufb OUjLTxESCF/Ql0rFXzOywyIzgtOP3QQX0OSUvtN0u/ugUXvaVw7T+CnPv2sWcAyXZOpk 4iU0a5xXdDYoNx7nGL2KZyAE0tzfzELMd/D72TJVw/bFHjcSEO+h5c9fvH8b89H/wQm4 LanjPJYDfrBokrVemt3HL6ecNGOGB4bkrhXNMiZlYiG3SG2gPBXbC6en1R/UkRuhftEu iT/XmZ/Ip1NShn7mTPAf1RSI9s0eBJpXFTfAlYkWlfWDh0liQ6Y5iof4ObQR/rvcJWLY lP8A== X-Gm-Message-State: AHQUAuaVPaLES3nLSRraT0tHZclEOl3aHfQr0Hd6EozGcxOi/HTGB1YT yvjQYRumOJfg7p5uxWYe9RfKEQ== X-Google-Smtp-Source: AHgI3IYKKOtaUJd+12ivq3E5K5E08REHHUIvApa6n3EpFT9UFduuBiKILErf1YhhLECnSOPyyDvLpA== X-Received: by 2002:a1c:f00a:: with SMTP id a10mr2730227wmb.148.1549646012897; Fri, 08 Feb 2019 09:13:32 -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 f139sm4521634wmd.19.2019.02.08.09.13.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 08 Feb 2019 09:13:32 -0800 (PST) From: Srinivas Kandagatla To: gregkh@linuxfoundation.org, arnd@arndb.de Cc: robh+dt@kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, bkumar@qti.qualcomm.com, linux-arm-msm@vger.kernel.org, Srinivas Kandagatla , Thierry Escande Subject: [PATCH v7 4/5] misc: fastrpc: Add support for create remote init process Date: Fri, 8 Feb 2019 17:11:26 +0000 Message-Id: <20190208171127.24168-5-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> References: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> 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 This patch adds support to create or attach remote shell process. The shell process called fastrpc_shell_0 is usually loaded on the DSP when a user process is spawned. Most of the work is derived from various downstream Qualcomm kernels. Credits to various Qualcomm authors who have contributed to this code. Specially Tharun Kumar Merugu Co-developed-by: Thierry Escande Signed-off-by: Thierry Escande Signed-off-by: Srinivas Kandagatla --- drivers/misc/fastrpc.c | 156 ++++++++++++++++++++++++++++++++++++ include/uapi/misc/fastrpc.h | 10 +++ 2 files changed, 166 insertions(+) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index cd69f8b308f6..ceb498487569 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -29,7 +29,10 @@ #define FASTRPC_MAX_CRCLIST 64 #define FASTRPC_PHYS(p) ((p) & 0xffffffff) #define FASTRPC_CTX_MAX (256) +#define FASTRPC_INIT_HANDLE 1 #define FASTRPC_CTXID_MASK (0xFF0) +#define INIT_FILELEN_MAX (2 * 1024 * 1024) +#define INIT_MEMLEN_MAX (8 * 1024 * 1024) #define FASTRPC_DEVICE_NAME "fastrpc" /* Retrives number of input buffers from the scalars parameter */ @@ -59,6 +62,14 @@ #define FASTRPC_SCALARS(method, in, out) \ FASTRPC_BUILD_SCALARS(0, method, in, out, 0, 0) +#define FASTRPC_CREATE_PROCESS_NARGS 6 +/* Remote Method id table */ +#define FASTRPC_RMID_INIT_ATTACH 0 +#define FASTRPC_RMID_INIT_RELEASE 1 +#define FASTRPC_RMID_INIT_CREATE 6 +#define FASTRPC_RMID_INIT_CREATE_ATTR 7 +#define FASTRPC_RMID_INIT_CREATE_STATIC 8 + #define miscdev_to_cctx(d) container_of(d, struct fastrpc_channel_ctx, miscdev) static const char *domains[FASTRPC_DEV_MAX] = { "adsp", "mdsp", @@ -688,6 +699,109 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, return err; } +static int fastrpc_init_create_process(struct fastrpc_user *fl, + char __user *argp) +{ + struct fastrpc_init_create init; + struct fastrpc_invoke_args *args; + struct fastrpc_phy_page pages[1]; + struct fastrpc_map *map = NULL; + struct fastrpc_buf *imem = NULL; + int memlen; + int err; + struct { + int pgid; + u32 namelen; + u32 filelen; + u32 pageslen; + u32 attrs; + u32 siglen; + } inbuf; + u32 sc; + + args = kcalloc(FASTRPC_CREATE_PROCESS_NARGS, sizeof(*args), GFP_KERNEL); + if (!args) + return -ENOMEM; + + if (copy_from_user(&init, argp, sizeof(init))) { + err = -EFAULT; + goto bail; + } + + if (init.filelen > INIT_FILELEN_MAX) { + err = -EINVAL; + goto bail; + } + + inbuf.pgid = fl->tgid; + inbuf.namelen = strlen(current->comm) + 1; + inbuf.filelen = init.filelen; + inbuf.pageslen = 1; + inbuf.attrs = init.attrs; + inbuf.siglen = init.siglen; + fl->pd = 1; + + if (init.filelen && init.filefd) { + err = fastrpc_map_create(fl, init.filefd, init.filelen, &map); + if (err) + goto bail; + } + + memlen = ALIGN(max(INIT_FILELEN_MAX, (int)init.filelen * 4), + 1024 * 1024); + err = fastrpc_buf_alloc(fl, fl->sctx->dev, memlen, + &imem); + if (err) { + fastrpc_map_put(map); + goto bail; + } + + fl->init_mem = imem; + args[0].ptr = (u64)(uintptr_t)&inbuf; + args[0].length = sizeof(inbuf); + args[0].fd = -1; + + args[1].ptr = (u64)(uintptr_t)current->comm; + args[1].length = inbuf.namelen; + args[1].fd = -1; + + args[2].ptr = (u64) init.file; + args[2].length = inbuf.filelen; + args[2].fd = init.filefd; + + pages[0].addr = imem->phys; + pages[0].size = imem->size; + + args[3].ptr = (u64)(uintptr_t) pages; + args[3].length = 1 * sizeof(*pages); + args[3].fd = -1; + + args[4].ptr = (u64)(uintptr_t)&inbuf.attrs; + args[4].length = sizeof(inbuf.attrs); + args[4].fd = -1; + + args[5].ptr = (u64)(uintptr_t) &inbuf.siglen; + args[5].length = sizeof(inbuf.siglen); + args[5].fd = -1; + + sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0); + if (init.attrs) + sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 6, 0); + + err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, + sc, args); + + if (err) { + fastrpc_map_put(map); + fastrpc_buf_free(imem); + } + +bail: + kfree(args); + + return err; +} + static struct fastrpc_session_ctx *fastrpc_session_alloc( struct fastrpc_channel_ctx *cctx) { @@ -715,6 +829,23 @@ static void fastrpc_session_free(struct fastrpc_channel_ctx *cctx, spin_unlock(&cctx->lock); } +static int fastrpc_release_current_dsp_process(struct fastrpc_user *fl) +{ + struct fastrpc_invoke_args args[1]; + int tgid = 0; + u32 sc; + + tgid = fl->tgid; + args[0].ptr = (u64)(uintptr_t) &tgid; + args[0].length = sizeof(tgid); + args[0].fd = -1; + args[0].reserved = 0; + sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_RELEASE, 1, 0); + + return fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, + sc, &args[0]); +} + static int fastrpc_device_release(struct inode *inode, struct file *file) { struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data; @@ -722,6 +853,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) struct fastrpc_invoke_ctx *ctx, *n; struct fastrpc_map *map, *m; + fastrpc_release_current_dsp_process(fl); + spin_lock(&cctx->lock); list_del(&fl->user); spin_unlock(&cctx->lock); @@ -773,6 +906,23 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) return 0; } +static int fastrpc_init_attach(struct fastrpc_user *fl) +{ + struct fastrpc_invoke_args args[1]; + int tgid = fl->tgid; + u32 sc; + + args[0].ptr = (u64)(uintptr_t) &tgid; + args[0].length = sizeof(tgid); + args[0].fd = -1; + args[0].reserved = 0; + sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_ATTACH, 1, 0); + fl->pd = 0; + + return fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, + sc, &args[0]); +} + static int fastrpc_invoke(struct fastrpc_user *fl, char __user *argp) { struct fastrpc_invoke_args *args = NULL; @@ -814,6 +964,12 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, case FASTRPC_IOCTL_INVOKE: err = fastrpc_invoke(fl, argp); break; + case FASTRPC_IOCTL_INIT_ATTACH: + err = fastrpc_init_attach(fl); + break; + case FASTRPC_IOCTL_INIT_CREATE: + err = fastrpc_init_create_process(fl, argp); + break; default: err = -ENOTTY; break; diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h index a69ef33dc37e..32d191c3b7bc 100644 --- a/include/uapi/misc/fastrpc.h +++ b/include/uapi/misc/fastrpc.h @@ -6,6 +6,8 @@ #include #define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke) +#define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4) +#define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create) struct fastrpc_invoke_args { __u64 ptr; @@ -20,4 +22,12 @@ struct fastrpc_invoke { __u64 args; }; +struct fastrpc_init_create { + __u32 filelen; /* elf file length */ + __s32 filefd; /* fd for the file */ + __u32 attrs; + __u32 siglen; + __u64 file; /* pointer to elf file */ +}; + #endif /* __QCOM_FASTRPC_H__ */ From patchwork Fri Feb 8 17:11:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 10803415 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 EF8111390 for ; Fri, 8 Feb 2019 17:13:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D99912844C for ; Fri, 8 Feb 2019 17:13:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CA2812D972; Fri, 8 Feb 2019 17:13:56 +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 27BB62844C for ; Fri, 8 Feb 2019 17:13:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727497AbfBHRNz (ORCPT ); Fri, 8 Feb 2019 12:13:55 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:38768 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727908AbfBHRNh (ORCPT ); Fri, 8 Feb 2019 12:13:37 -0500 Received: by mail-wm1-f68.google.com with SMTP id v26so4148733wmh.3 for ; Fri, 08 Feb 2019 09:13:35 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=jLAFz+SLcfOn5L8KoIvA61cF20ujkNrtIV9nbAA85VI=; b=j9ItVn2MqVk81W+x1MB5123Xi4cEDE3G2MYyX7Ihu2r3eLN6bHJBniJpE2YDQAHQbV cvuV1VYYNs/LPlRHk4GmFleiApxLL8Y52wxVNtPHiVy3XXZXZKBswlScV1npceFk5SKg f6KUlcb5MCAHDi9fIBsflwfLBiF9sxunVdyOdrSwQ127PyUHgBdK6Slj9sGlfMgHsR4u nWjCcV62GyWWHHN0HYkT5QweSVGNAZvMZtaa0goV6tDpMlGLW8YCR7f34l/eCMbCyYx9 wkevaivOYtjePxbdNIoyKzzfahzIrW7FuvQpBdDdgXo7EvhOnzD5otc34/PlsxlyIufk zaAg== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=jLAFz+SLcfOn5L8KoIvA61cF20ujkNrtIV9nbAA85VI=; b=DSz3Eov+VygzeqH/kJrrHg3e9JIOTEBbqi3Op36pQwrQFZOps473JaIEp3v56xQ9dQ ue5w1RP/Lut91moEGXlKspsqiDdRS2Ace1JXo47L6Z2E3SCtdaUTWg5gPw16yqLcCALG yNs4XUeVeNocdph+DKvlz/WRn2YDRadqFcMNsa8yHWeTeGFsT+k4fX8i19WXp/i9IpZ/ +1q/xkz4+qVORkagSh0nCs0cGasaxtp1pKFzjIo6nK1YVmO4joqkbhhakOkqctPEuLNC hG0yl44ZMVvBcqMbDEbvH57emzobNS/X+TLj0vkOYsircTLRCB65eveaJ0MEsYKUePS9 04ag== X-Gm-Message-State: AHQUAua4BvbQp5jnIxbLbirmVHzdoCgYhV06gY1AhD2Of0MFPop1HSvf Bmo+w2foaYwtbiXkhe3oyX9eNw== X-Google-Smtp-Source: AHgI3IY1kvVVb0wOfZBFbURe6aoBKne6BDXaEOjd2xU4odQ3G4Hazd/55tGJMkdqw9yNMiw74S2vqQ== X-Received: by 2002:a7b:cd14:: with SMTP id f20mr11577525wmj.93.1549646014819; Fri, 08 Feb 2019 09:13:34 -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 f139sm4521634wmd.19.2019.02.08.09.13.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 08 Feb 2019 09:13:33 -0800 (PST) From: Srinivas Kandagatla To: gregkh@linuxfoundation.org, arnd@arndb.de Cc: robh+dt@kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, bkumar@qti.qualcomm.com, linux-arm-msm@vger.kernel.org, Srinivas Kandagatla , Thierry Escande Subject: [PATCH v7 5/5] misc: fastrpc: Add support for dmabuf exporter Date: Fri, 8 Feb 2019 17:11:27 +0000 Message-Id: <20190208171127.24168-6-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> References: <20190208171127.24168-1-srinivas.kandagatla@linaro.org> 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 User process can involve dealing with big buffer sizes, and also passing buffers from one compute context bank to other compute context bank for complex dsp algorithms. This patch adds support to fastrpc to make it a proper dmabuf exporter to avoid making copies of buffers. Co-developed-by: Thierry Escande Signed-off-by: Thierry Escande Signed-off-by: Srinivas Kandagatla --- drivers/misc/fastrpc.c | 184 ++++++++++++++++++++++++++++++++++++ include/uapi/misc/fastrpc.h | 8 ++ 2 files changed, 192 insertions(+) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index ceb498487569..4b0db33896df 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -106,10 +106,20 @@ struct fastrpc_invoke_rsp { struct fastrpc_buf { struct fastrpc_user *fl; + struct dma_buf *dmabuf; struct device *dev; void *virt; u64 phys; u64 size; + /* Lock for dma buf attachments */ + struct mutex lock; + struct list_head attachments; +}; + +struct fastrpc_dma_buf_attachment { + struct device *dev; + struct sg_table sgt; + struct list_head node; }; struct fastrpc_map { @@ -246,6 +256,9 @@ static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev, if (!buf) return -ENOMEM; + INIT_LIST_HEAD(&buf->attachments); + mutex_init(&buf->lock); + buf->fl = fl; buf->virt = NULL; buf->phys = 0; @@ -360,6 +373,111 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( return ERR_PTR(ret); } +static struct sg_table * +fastrpc_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction dir) +{ + struct fastrpc_dma_buf_attachment *a = attachment->priv; + struct sg_table *table; + + table = &a->sgt; + + if (!dma_map_sg(attachment->dev, table->sgl, table->nents, dir)) + return ERR_PTR(-ENOMEM); + + return table; +} + +static void fastrpc_unmap_dma_buf(struct dma_buf_attachment *attach, + struct sg_table *table, + enum dma_data_direction dir) +{ + dma_unmap_sg(attach->dev, table->sgl, table->nents, dir); +} + +static void fastrpc_release(struct dma_buf *dmabuf) +{ + struct fastrpc_buf *buffer = dmabuf->priv; + + fastrpc_buf_free(buffer); +} + +static int fastrpc_dma_buf_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct fastrpc_dma_buf_attachment *a; + struct fastrpc_buf *buffer = dmabuf->priv; + int ret; + + a = kzalloc(sizeof(*a), GFP_KERNEL); + if (!a) + return -ENOMEM; + + ret = dma_get_sgtable(buffer->dev, &a->sgt, buffer->virt, + FASTRPC_PHYS(buffer->phys), buffer->size); + if (ret < 0) { + dev_err(buffer->dev, "failed to get scatterlist from DMA API\n"); + return -EINVAL; + } + + a->dev = attachment->dev; + INIT_LIST_HEAD(&a->node); + attachment->priv = a; + + mutex_lock(&buffer->lock); + list_add(&a->node, &buffer->attachments); + mutex_unlock(&buffer->lock); + + return 0; +} + +static void fastrpc_dma_buf_detatch(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct fastrpc_dma_buf_attachment *a = attachment->priv; + struct fastrpc_buf *buffer = dmabuf->priv; + + mutex_lock(&buffer->lock); + list_del(&a->node); + mutex_unlock(&buffer->lock); + kfree(a); +} + +static void *fastrpc_kmap(struct dma_buf *dmabuf, unsigned long pgnum) +{ + struct fastrpc_buf *buf = dmabuf->priv; + + return buf->virt ? buf->virt + pgnum * PAGE_SIZE : NULL; +} + +static void *fastrpc_vmap(struct dma_buf *dmabuf) +{ + struct fastrpc_buf *buf = dmabuf->priv; + + return buf->virt; +} + +static int fastrpc_mmap(struct dma_buf *dmabuf, + struct vm_area_struct *vma) +{ + struct fastrpc_buf *buf = dmabuf->priv; + size_t size = vma->vm_end - vma->vm_start; + + return dma_mmap_coherent(buf->dev, vma, buf->virt, + FASTRPC_PHYS(buf->phys), size); +} + +static const struct dma_buf_ops fastrpc_dma_buf_ops = { + .attach = fastrpc_dma_buf_attach, + .detach = fastrpc_dma_buf_detatch, + .map_dma_buf = fastrpc_map_dma_buf, + .unmap_dma_buf = fastrpc_unmap_dma_buf, + .mmap = fastrpc_mmap, + .map = fastrpc_kmap, + .vmap = fastrpc_vmap, + .release = fastrpc_release, +}; + static int fastrpc_map_create(struct fastrpc_user *fl, int fd, u64 len, struct fastrpc_map **ppmap) { @@ -906,6 +1024,66 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) return 0; } +static int fastrpc_dmabuf_free(struct fastrpc_user *fl, char __user *argp) +{ + struct dma_buf *buf; + int info; + + if (copy_from_user(&info, argp, sizeof(info))) + return -EFAULT; + + buf = dma_buf_get(info); + if (IS_ERR_OR_NULL(buf)) + return -EINVAL; + /* + * one for the last get and other for the ALLOC_DMA_BUFF ioctl + */ + dma_buf_put(buf); + dma_buf_put(buf); + + return 0; +} + +static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp) +{ + struct fastrpc_alloc_dma_buf bp; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct fastrpc_buf *buf = NULL; + int err; + + if (copy_from_user(&bp, argp, sizeof(bp))) + return -EFAULT; + + err = fastrpc_buf_alloc(fl, fl->sctx->dev, bp.size, &buf); + if (err) + return err; + exp_info.ops = &fastrpc_dma_buf_ops; + exp_info.size = bp.size; + exp_info.flags = O_RDWR; + exp_info.priv = buf; + buf->dmabuf = dma_buf_export(&exp_info); + if (IS_ERR(buf->dmabuf)) { + err = PTR_ERR(buf->dmabuf); + fastrpc_buf_free(buf); + return err; + } + + bp.fd = dma_buf_fd(buf->dmabuf, O_ACCMODE); + if (bp.fd < 0) { + dma_buf_put(buf->dmabuf); + return -EINVAL; + } + + if (copy_to_user(argp, &bp, sizeof(bp))) { + dma_buf_put(buf->dmabuf); + return -EFAULT; + } + + get_dma_buf(buf->dmabuf); + + return 0; +} + static int fastrpc_init_attach(struct fastrpc_user *fl) { struct fastrpc_invoke_args args[1]; @@ -970,6 +1148,12 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, case FASTRPC_IOCTL_INIT_CREATE: err = fastrpc_init_create_process(fl, argp); break; + case FASTRPC_IOCTL_FREE_DMA_BUFF: + err = fastrpc_dmabuf_free(fl, argp); + break; + case FASTRPC_IOCTL_ALLOC_DMA_BUFF: + err = fastrpc_dmabuf_alloc(fl, argp); + break; default: err = -ENOTTY; break; diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h index 32d191c3b7bc..6d701af9fc42 100644 --- a/include/uapi/misc/fastrpc.h +++ b/include/uapi/misc/fastrpc.h @@ -5,6 +5,8 @@ #include +#define FASTRPC_IOCTL_ALLOC_DMA_BUFF _IOWR('R', 1, struct fastrpc_alloc_dma_buf) +#define FASTRPC_IOCTL_FREE_DMA_BUFF _IOWR('R', 2, __u32) #define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke) #define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4) #define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create) @@ -30,4 +32,10 @@ struct fastrpc_init_create { __u64 file; /* pointer to elf file */ }; +struct fastrpc_alloc_dma_buf { + __s32 fd; /* fd */ + __u32 flags; /* flags to map with */ + __u64 size; /* size */ +}; + #endif /* __QCOM_FASTRPC_H__ */