From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54D3DECAAD3 for ; Sat, 17 Sep 2022 07:25:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229821AbiIQHZR (ORCPT ); Sat, 17 Sep 2022 03:25:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51934 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229615AbiIQHYM (ORCPT ); Sat, 17 Sep 2022 03:24:12 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8E28C44564 for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p1.samsung.com (unknown [182.195.41.45]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220917072359epoutp0308919e70e68337a07a87a6a5024077fc~VlPocIDWb1145111451epoutp03C for ; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220917072359epoutp0308919e70e68337a07a87a6a5024077fc~VlPocIDWb1145111451epoutp03C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399439; bh=WT8eilAWkTa8t5HFry4jFn1w86JhqlxqX0PBHLU1jNE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sIUHtDV53RbJw+w9boMVNOXpsGGH1kkmVdP2noOIDmypIyvj563dGHKyGgQnVr/T4 rMXP+Vl3Xx4Q57fKeoaP79dUPMe9yCS2WLloaP51zxW2LC6SrOEeZqpNhpYd88Y4KB N11OMMK4FGw8A/lfkNKiCfqqZ5xuhTCsqmLs0aXw= Received: from epsnrtp1.localdomain (unknown [182.195.42.162]) by epcas1p4.samsung.com (KnoxPortal) with ESMTP id 20220917072358epcas1p4b275a1decc0c6ca70d4312c6b931014c~VlPn0Eb7d2970529705epcas1p4M; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epsmges1p5.samsung.com (unknown [182.195.36.136]) by epsnrtp1.localdomain (Postfix) with ESMTP id 4MV2Vj5SNDz4x9Pp; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epcas1p4.samsung.com ( [182.195.41.48]) by epsmges1p5.samsung.com (Symantec Messaging Gateway) with SMTP id 3A.6D.64988.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas1p1.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epcas1p17b277154f0d020435417450fa0337906~VlPmlEvQD0249402494epcas1p1Q; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220917072357epsmtrp15ca8750a23a350e31ca9ddba0aec4934~VlPmhcLng0556805568epsmtrp1a; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) X-AuditID: b6c32a39-8d3fa7000001fddc-75-6325760dd1f0 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 11.45.14392.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072356epsmtip22d49e7b22f2e4a27d30a62f82cd2bff9~VlPmNbiKB2857628576epsmtip24; Sat, 17 Sep 2022 07:23:56 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 01/13] trinity: Add base driver Date: Sat, 17 Sep 2022 16:23:44 +0900 Message-Id: <20220917072356.2255620-2-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprAJsWRmVeSWpSXmKPExsWy7bCmgS5vmWqywcoFKhZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbVLZNRmpiSmqRQmpecn5KZl66rZJ3cLxzvKmZgaGuoaWFuZJC XmJuqq2Si0+ArltmDtBVSgpliTmlQKGAxOJiJX07m6L80pJUhYz84hJbpdSClJwC0wK94sTc 4tK8dL281BIrQwMDI1OgwoTsjHdnVrMU7D7OXNExewZbA+PUn0xdjJwcEgImEl939rF1MXJx CAnsYJT4vmQyE4TziVFi1edbUJlvjBInn91khmlp7NzNCJHYyyix4ttXVgjnM6PEz5lTGUGq 2ARUJWbOWMMOYosIlEs0bzwBZjML5Eg8udMENklYwEhi25e/LF2MHBwsQPX/GkNAwrwC1hIb l3wEu49TwEbi5qYmFoi4oMTJmU9YIMbISzRvnc0MsldC4Cu7xIYZR9kgrnORaPq7BOo5YYlX x7ewQ9hSEi/726DsbIkpHYtYIOwCiXPPtzKD3CAhYCxxcUUKiMksoCmxfpc+RIWixM7fcxkh 1vJJvPvawwpRzSvR0SYEUaIkseTPYajhEhJTZ3yDOsBDYvnVQyyQ0OlnlGh/eJhpAqP8LCTf zELyzSyEzQsYmVcxiqUWFOempxYbFpjCozU5P3cTIzhpalnuYJz+9oPeIUYmDsZDjBIczEoi vKqeKslCvCmJlVWpRfnxRaU5qcWHGE2BwTuRWUo0OR+YtvNK4g1NLA1MzIyMTSwMzQyVxHn1 tBmThQTSE0tSs1NTC1KLYPqYODilGpi4viW6dsvsP/d1XX5Fuvi+MwJOeicWMPqusZ5izbuJ 8+wvpazPkU75pXzsdz6ds9P56lP3gtuaaYfk0Uftt4TO8G10LHhxc3v6tAfe6U6LTEpXziz9 P+WVlrBp4PE7r4L43ZLPiTquU3nIPeuF3z0NU46E3xrX2xL4fXf+7Ttxzq35xXn/2WcTFjnP i1K88+j6npU9RafEVh2/K7d908NFDtJZnyfe1bbMtuldnJoxo1VFmntF3vLu+s6nPl63RXUb Z9zfxmrfzDdR42ui3z8Tn5frdp4/fPXKpNrHMv0dYUdtVQ/sVv7msu6hbfjm63OEjxxcx8Y1 sz9h2uJVU/6+PaG13Ku56ajii/f69xfLKrEUZyQaajEXFScCAHuFzYkjBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrFLMWRmVeSWpSXmKPExsWy7bCSvC5vmWqywfEv7BZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAlfGuzOrWQp2H2eu6Jg9g62BcepPpi5G Tg4JAROJxs7djF2MXBxCArsZJX7O6maDSEhIbLq3nLmLkQPIFpY4fLgYouYjo0Rj022wGjYB VYmZM9awg9giArUSB4/OZwaxmQUKJGY/nckCYgsLGEls+/KXBWQOC1D9v8YQkDCvgLXExiUf wW7gFLCRuLmpCaxcCCg+e/pcJogaQYmTM5+wQIyUl2jeOpt5AiP/LCSpWUhSCxiZVjFKphYU 56bnFhsWGOallusVJ+YWl+al6yXn525iBAe3luYOxu2rPugdYmTiYDzEKMHBrCTCq+qpkizE m5JYWZValB9fVJqTWnyIUZqDRUmc90LXyXghgfTEktTs1NSC1CKYLBMHp1QDU252auEm9u19 y1Z1W5xdJSZXw++b8OSjakXUtSVvLr7QflXK7rg5bMGDe+HuPOZL5VcULkkPebH00UYfPoNE 0+Kov7N91cVfsdQ8l1Pd+uHxonw7GxPtlYUM/64+e2f/pXEhzz2F42wl6t2bDx7/8dTq2dLt my8Ecp74XC/owrVx7Z+3O67wJT3kePM2TG1vzMNJUrevvfPInyki+k/C4s7F97Nl7bc/1l3A ZvqBP31REmP+90uyFW65NQyurelPs7avOb/xsoPBi3rBNo6MfRY/v5/bfj59282jt09L3/Fs Zl3Gpiioo9eZX5fF5Rb0jfOA/3q/w1LzDPfekf4WmF73/VNH1NZQhqd6pvxPw5RYijMSDbWY i4oTAU2EVbrdAgAA X-CMS-MailID: 20220917072357epcas1p17b277154f0d020435417450fa0337906 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072357epcas1p17b277154f0d020435417450fa0337906 References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org It contains the base codes for trinity driver. Minimal codes to load and probe device is provided. The Trinity Family is controlled by the Memory-Mapped Registers, the register addresses and offsets are described. And user api interfaces are presented to control device under ioctl manner. Signed-off-by: Jiho Chu Signed-off-by: yelini-jeong Signed-off-by: Dongju Chae Signed-off-by: Parichay Kapoor Signed-off-by: Wook Song Signed-off-by: MyungJoo Ham --- drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/trinity/Kconfig | 25 + drivers/misc/trinity/Makefile | 7 + drivers/misc/trinity/trinity.c | 225 +++++++++ drivers/misc/trinity/trinity_common.h | 437 ++++++++++++++++++ drivers/misc/trinity/trinity_vision2_drv.c | 278 ++++++++++++ drivers/misc/trinity/trinity_vision2_regs.h | 210 +++++++++ include/uapi/misc/trinity.h | 476 ++++++++++++++++++++ 9 files changed, 1660 insertions(+) create mode 100644 drivers/misc/trinity/Kconfig create mode 100644 drivers/misc/trinity/Makefile create mode 100644 drivers/misc/trinity/trinity.c create mode 100644 drivers/misc/trinity/trinity_common.h create mode 100644 drivers/misc/trinity/trinity_vision2_drv.c create mode 100644 drivers/misc/trinity/trinity_vision2_regs.h create mode 100644 include/uapi/misc/trinity.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 41d2bb0ae23a..ad0d5f6af291 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -500,4 +500,5 @@ source "drivers/misc/cardreader/Kconfig" source "drivers/misc/habanalabs/Kconfig" source "drivers/misc/uacce/Kconfig" source "drivers/misc/pvpanic/Kconfig" +source "drivers/misc/trinity/Kconfig" endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 70e800e9127f..c63f3fc89780 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_XILINX_SDFEC) +=3D xilinx_sdfec.o obj-$(CONFIG_HISI_HIKEY_USB) +=3D hisi_hikey_usb.o obj-$(CONFIG_HI6421V600_IRQ) +=3D hi6421v600-irq.o obj-$(CONFIG_OPEN_DICE) +=3D open-dice.o +obj-$(CONFIG_TRINITY) +=3D trinity/ diff --git a/drivers/misc/trinity/Kconfig b/drivers/misc/trinity/Kconfig new file mode 100644 index 000000000000..02ad03c2ca0e --- /dev/null +++ b/drivers/misc/trinity/Kconfig @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config TRINITY + bool "Samsung Neural Processing Unit" + depends on HAS_IOMEM + depends on HAS_DMA + help + Select this option to enable driver support for Samsung + Neural Processing Unit (NPU). + + This driver works as a base driver of the other drivers + for Trinity device family. + + This option should be enabled to support Trinity + Vision 2 (TRIV2), and Trinity Audio (TRIA). + +config TRINITY_VISION2 + tristate "Samsung NPU Trinity Vision 2" + depends on TRINITY + help + Select this option to enable driver support for a Samsung + Neural Processing Unit (NPU), Trinity Vision 2. + + This driver enables userspace system library to access the + device via /dev/triv2-N. diff --git a/drivers/misc/trinity/Makefile b/drivers/misc/trinity/Makefile new file mode 100644 index 000000000000..a8e5697d6d85 --- /dev/null +++ b/drivers/misc/trinity/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_TRINITY_VISION2) +=3D trinity_vision2.o + +trinity-y :=3D trinity.o + +trinity_vision2-objs :=3D $(trinity-y) trinity_vision2_drv.o diff --git a/drivers/misc/trinity/trinity.c b/drivers/misc/trinity/trinity.c new file mode 100644 index 000000000000..1704eecfc439 --- /dev/null +++ b/drivers/misc/trinity/trinity.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Base device driver for Samsung NPU Trinity device family + * + * Copyright (C) 2020-2022 Samsung Electronics + * Copyright (C) 2020 Dongju Chae + * Copyright (C) 2020 Wook Song + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#include + +#include "trinity_common.h" + +#define TRINITY_PADDR_BASE (0x0) + +static DEFINE_IDA(dev_nrs); +static DEFINE_IDA(model_ids); + +/** + * trinity_release() - A common callback for close() in file_operations fo= r a + * Trinity device node. If there are device-specific data to be + * cleaned-up, it is required to clean them up before invoke this + * callback. + * + * @inode: Inode to be closed + * @file: File to be closed + * + * Returns 0 on success. Otherwise, returns negative error. + */ +int trinity_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/** + * trinity_open() - A common callback for open() in file_operations for a = Trinity + * device node. If device-specific open() is required, this + * callback should be invoked by that open(). + * + * @inode: inode to be opened + * @f: file to be opened + * + * Returns 0 on success. Otherwise, returns negative error. + */ +int trinity_open(struct inode *inode, struct file *f) +{ + struct miscdevice *miscdev; + struct trinity_driver *drv; + + miscdev =3D f->private_data; + drv =3D container_of(miscdev, struct trinity_driver, mdev); + f->private_data =3D drv; + + return 0; +} + +/** + * trinity_create_node() - Create trinity node + * + * @drv: an instance of trinity driver + * + * Returns 0 on success. Otherwise, returns negative error. + */ +int trinity_create_node(struct trinity_driver *drv) +{ + struct device *dev =3D drv_to_dev_ptr(drv); + int err; + + /** register as a misc device */ + drv->mdev.minor =3D MISC_DYNAMIC_MINOR; + drv->mdev.parent =3D dev; + drv->mdev.name =3D drv->name; + drv->mdev.fops =3D drv->desc->fops; + + err =3D misc_register(&drv->mdev); + if (err < 0) + dev_err(dev, "failed to register as a misc device"); + + return err; +} + +/** + * trinity_destroy_node() - Destroy trinity node + * + * @drv: an instance of trinity driver + */ +void trinity_destroy_node(struct trinity_driver *drv) +{ + misc_deregister(&drv->mdev); +} + +/** + * trinity_probe() - Probes a new Trinity device. This is a standard inter= face to + * probe a Trinity family device. + * + * @pdev: Platform device structure to probe + * @desc: Device description to probe + * + * Returns 0 on success. Otherwise, returns negative error. + */ +int trinity_probe(struct platform_device *pdev, const struct trinity_desc = *desc) +{ + struct device_node *np; + struct device *dev; + struct trinity_driver *drv; + int i, err; + + dev =3D &pdev->dev; + dev->id =3D ((desc->ver & TRINITY_MASK_DEV) >> TRINITY_SHIFT_DEV); + + /* set private data */ + drv =3D devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); + if (!drv) + return -ENOMEM; + + drv->dev_id =3D ida_alloc(&dev_nrs, GFP_KERNEL); + if (drv->dev_id < 0) { + devm_kfree(dev, drv); + return drv->dev_id; + } + snprintf(drv->name, DEV_NAME_LEN, "%s-%u", desc->type, drv->dev_id); + + platform_set_drvdata(pdev, drv); + dev_set_drvdata(dev, drv); + + drv->dev =3D dev; + drv->desc =3D desc; + + np =3D dev->of_node; + if (of_property_match_string(np, "samsung,trinity-type", desc->type)) { + err =3D -EPROBE_DEFER; + goto err_cleanup; + } + + /* get reg info for MMREG_BASE */ + for (i =3D 0; i < TRINITY_MAX_MMREGS; i++) { + struct resource mmreg; + + err =3D of_address_to_resource(np, i, &mmreg); + if (err < 0) { + dev_err(dev, "failed to get %d-th mmreg info", i); + goto err_cleanup; + } + + drv->mmreg_vaddr[i] =3D devm_ioremap_resource(dev, &mmreg); + if (IS_ERR(drv->mmreg_vaddr[i])) { + dev_err(dev, + "failed to remap %d-th mmreg resource info", i); + err =3D PTR_ERR(drv->mmreg_vaddr[i]); + goto err_cleanup; + } + drv->mmreg_paddr[i] =3D mmreg.start; + } + + /** get a TOPS property */ + err =3D of_property_read_u32(np, "samsung,tops", &drv->tops); + if (err < 0) { + dev_err(dev, "failed to read 'tops' property: %d\n", err); + goto err_cleanup; + } + + /** get a DSPM property */ + err =3D of_property_read_u32(np, "samsung,dspm", &drv->dspm); + if (err < 0) { + dev_warn(dev, "Setting the size of DPSM to 0\n"); + drv->dspm =3D 0; + } + + /* Set IRQ handlers */ + drv->irq =3D platform_get_irq(pdev, 0); + if (drv->irq < 0) { + dev_err(dev, "IRQ is not supported"); + err =3D drv->irq; + goto err_cleanup; + } + + /* get the IRQ number from DT and set handlers for it */ + err =3D devm_request_irq(dev, drv->irq, desc->handle_irq, + IRQF_TRIGGER_HIGH, desc->type, &drv->mdev); + if (err < 0) { + dev_err(dev, "failed to register handlers for IRQ %d", drv->irq); + goto err_cleanup; + } + + /** Initialize device-specific variables */ + init_completion(&drv->complete); + mutex_init(&drv->lock); + INIT_WORK(&drv->work_stop, desc->stop_reqs); + + return 0; + +err_cleanup_common: + devm_free_irq(dev, drv->irq, &drv->mdev); + +err_cleanup: + ida_free(&dev_nrs, drv->dev_id); + devm_kfree(dev, drv); + + return err; +} + +/** + * trinity_remove() - Cleans up the device driver. This is a standard inte= rface to + * remove a Trinity family device. + * + * @pdev: Platform device structure to probe + * @desc: Device description to probe + * + * Always returns 0. + */ +int trinity_remove(struct platform_device *pdev, + const struct trinity_desc *desc) +{ + struct trinity_driver *drv =3D platform_get_drvdata(pdev); + struct device *dev =3D drv_to_dev_ptr(drv); + + ida_free(&dev_nrs, drv->dev_id); + devm_free_irq(dev, drv->irq, &drv->mdev); + devm_kfree(dev, drv); + + return 0; +} diff --git a/drivers/misc/trinity/trinity_common.h b/drivers/misc/trinity/t= rinity_common.h new file mode 100644 index 000000000000..f35d964ab387 --- /dev/null +++ b/drivers/misc/trinity/trinity_common.h @@ -0,0 +1,437 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Common header for trinity devices + * + * Copyright (C) 2020-2022 Samsung Electronics + * Copyright (C) 2020 Wook Song + * Copyright (C) 2020 Parichay Kapoor + * Copyright (C) 2020 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#ifndef __DRIVERS_MISC_TRINITY_COMMON_H__ +#define __DRIVERS_MISC_TRINITY_COMMON_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "trinity_dma.h" +#include "trinity_hwmem.h" + +#define DEV_NAME_LEN (16) + +/** Default timeout to wait for opening device in jiffies */ +#define TRINITY_DEV_TIMEOUT_MSEC (3000) +#define TRINITY_DEV_TIMEOUT (msecs_to_jiffies(TRINITY_DEV_TIMEOUT_MSEC)) + +/** Default timeout to wait for running input in jiffies */ +#define TRINITY_RUN_TIMEOUT_MSEC (4000) +#define TRINITY_RUN_TIMEOUT (msecs_to_jiffies(TRINITY_RUN_TIMEOUT_MSEC)) + +#define TRINITY_DEV_TYPE_LEN (16) +#define TRINITY_DEV_EACH_MAX (2) +#define TRINITY_MAX_MMREGS (3) + +/** A helper function to generate the version code of the device driver */ +#define GENVER(dev, mj, mn, ex) \ + ((dev << TRINITY_SHIFT_DEV) | (mj << TRINITY_SHIFT_MAJOR_VER) | \ + (mn << TRINITY_SHIFT_MINOR_VER) | (ex << TRINITY_SHIFT_EXTRA_VER)) + +#define IDU_LOADED(drv) (drv->idu_set) + +#define trinity_get_iomem_addr(base, offset) (base + offset) +#define drv_to_dev_ptr(d) (d->dev) +#define drv_to_priv(drv) (drv->desc->pdata) + +#define TRINITY_STAT_HASH_BITS (10) +#define TRINITY_STAT_HASH_SIZE (1 << TRINITY_STAT_HASH_BITS) + +#define TRINITY_MODEL_HASH_BITS (10) +#define TRINITY_MODEL_HASH_SIZE (1 << TRINITY_MODEL_HASH_BITS) + +#define TIME_DIFF(t1, t2) ktime_to_ms(ktime_sub(t1, t2)) +#define TIME_DIFF_US(t1, t2) ktime_to_us(ktime_sub(t1, t2)) + +struct trinity_desc; +struct trinity_driver; +struct trinity_req; +struct trinity_stat; +struct trinity_stat_app; +struct trinity_stat_req; +struct trinity_model_htable; +struct trinity_idu; + +/** + * struct trinity_desc - a structure for device description + * + * @type: A string that indicates the type of this device. + * @ver: Coded version information generated via GENVER(). + * @fops: Device-specific file_operations. + * + * @reset: reset trinity function + * @prepare_req: request configuration function before invoking + * trinity_submit_req() (if any). This requires a registered model + * to the driver. + * @handle_timeout: This function is invoked when the request is time-out + * @stop_reqs: stops current working request + * @drain_reqs: waits currently working requests finishes. + * @init_profile: initialize profile configuration + * @check_profile: check current profile data + * @get_profile_meta: get profile metadata for the target request + * @get_profile_buff: get profile data buffer for the target request + * @get_profile: get profile data + * @destroy_profile: destroy profile resources + * + * @idu_set: set IDU binary + * @idu_unset: unset IDU binary + * @idu_version: get IDU version info + * @get_state: get current state of IDU + * @set_state: set IDU state + * @alloc_req: allocate request new trinity request + * @dealloc_req: release request resource + * @invoke_req: prepare to run request and sent it to scheduler + * + * @handle_irq: Device-specific IRQ handler. + */ +struct trinity_desc { + char *type; + uint32_t ver; + + const struct file_operations *fops; + + /* Optional */ + void (*reset)(struct trinity_driver *drv); + int32_t (*prepare_req)(struct trinity_driver *drv, + struct trinity_req *req); + void (*handle_timeout)(struct trinity_driver *drv, + struct trinity_req *req); + void (*stop_reqs)(struct work_struct *work); + void (*drain_reqs)(struct trinity_driver *drv); + void (*init_profile)(struct trinity_driver *drv, + unsigned long profile_size); + int32_t (*check_profile)(struct trinity_driver *drv, + struct trinity_req *req); + int32_t (*get_profile_meta)(const struct trinity_driver *drv, + struct trinity_ioctl_profile_meta *meta); + int32_t (*get_profile_buff)(const struct trinity_driver *drv, + struct trinity_ioctl_profile_buff *buff); + ssize_t (*get_profile)(const struct trinity_driver *drv, char *buf, int r= eq_id); + void (*destroy_profile)(const struct trinity_driver *drv, void *data); + + /* Mandatory */ + int32_t (*idu_set)(struct trinity_driver *drv, struct trinity_ioctl_idu *= idu); + void (*idu_unset)(struct trinity_driver *drv); + int32_t (*idu_version)(struct trinity_driver *drv, uint32_t *major, + uint32_t *minor, uint32_t *extra); + int32_t (*get_state)(const struct trinity_driver *drv); + void (*set_state)(const struct trinity_driver *drv, + enum trinity_state state); + struct trinity_req *(*alloc_req)(struct trinity_driver *drv); + void (*dealloc_req)(struct trinity_driver *drv, + struct trinity_req *req); + int32_t (*invoke_req)(struct trinity_driver *drv, + struct trinity_req *req, void *sched_data); + irq_handler_t handle_irq; +}; + +/** + * struct trinity_stat - A structure for representing a device's statistic= s. + * + * @lock: stat lock + * @hlist_bl_head: stat hash list heads + * @list: list head + * @pdata: private data + */ +struct trinity_stat { + spinlock_t lock; + + struct hlist_bl_head hlist[TRINITY_STAT_HASH_SIZE]; + struct list_head list; + + void *pdata; +}; + +/** + * struct trinity_stat_app - a structure for representing statistics for e= ach app + * @app_id: identifier for each app + * @name: name of stat + * @status: app status + * @parent: parent node + * @total_alloc_mem: total allocated memory size + * @total_free_mem: total freed memory size + * @list_head reqs: list of request + * @num_total_reqs: a number of total requests + * @num_kept_reqs: a number of kept requests + * @num_active_reqs: a number of active requests + * @hnode: hash node + * @lnode: list node + */ +struct trinity_stat_app { + int32_t app_id; /* app identifier */ + char name[TASK_COMM_LEN]; + enum trinity_app_status status; + + struct trinity_stat *parent; + + uint64_t total_alloc_mem; /* total allocated memory */ + uint64_t total_freed_mem; /* total freed memory */ + + struct list_head reqs; + uint32_t num_total_reqs; + uint32_t num_kept_reqs; + uint32_t num_active_reqs; + + struct hlist_bl_node hnode; /* hash node */ + struct list_head lnode; /* list node */ + + unsigned long slot; +}; + +/** + * struct trinity_stat_req - A structure for representing statistics for e= ach request + * @status: request status + * @priority: priority of request + * @parent: parent node + * @req_id: app identifier + * @req_id: request identifier + * @model_id: model identifier + * @is_kernel: requested from other kernel module + * @submitted: submitted time (i.e., when request is submitted to global q= ueue) + * @scheduled: scheduled time (i.e., when request is scheduled to device) + * @completed: completed time (i.e., when output notification arrives) + * @num_runs: total number of runs + * @total_time: total execute time + * @prev_time: previous execute time + * @prev_cycles: previous execute cycles + * @list: list node managed by trinity_stat_app + * @profile: profile data + * @slot: request slot + */ +struct trinity_stat_req { + enum trinity_req_status status; /* status of submit result */ + enum trinity_req_priority priority; + + struct trinity_stat_app *parent; + + int32_t app_id; + int32_t req_id; + uint64_t model_id; + + bool is_kernel; + + ktime_t submitted; + ktime_t scheduled; + ktime_t completed; + + uint32_t num_runs; + uint32_t total_time; + + uint32_t prev_time; + uint32_t prev_cycles; + + struct list_head list; + void *profile; + + unsigned long slot; +}; + +/** + * struct trinity_driver - A private data structure for Trinity device dri= ver + * @desc: A pointer to the device description + * @name: The id-annotated name of the device + * @pdata: private data + * #dev_id: device id + * @mdev: A copy of &struct misc device to which the device is registered. + * @dev: A pointer to &struct device of the device. + * @complete: A &struct completion variable to maintain events from the de= vice. + * @lock: A lock for access control to driver-level static variables + * @irq: acquired IRQ number used for complete event + * @glboal_req_id: a request id to generate id for each request + * @active_reqs: a number of active requests + * @mmreg_vaddr: The iomapped base address of memory-mapped registers + * @mmreg_paddr: The physical base address of memory-mapped registers + * @idu_set: IDU binary is set + * @work_stop: handle stop request + * @tops: Tera Operations Per Second (TOPS) of this device + * @dspm: The size of Data Scratch-Pad Memory (DSPM) in the DSP + * @stat: statistics information + * @debugfs_pdata: debugfs private data + * @sched_pdata: NPU scheduler private data + * @model_htable: model hash table + * @profile_req_id: sysfs requested profile id for show_profile + */ +struct trinity_driver { + const struct trinity_desc *desc; + char name[DEV_NAME_LEN]; + void *pdata; + + uint32_t dev_id; + struct miscdevice mdev; + struct device *dev; + struct completion complete; + struct mutex lock; + int irq; + + atomic_t global_req_id; + atomic_t active_reqs; + + void __iomem *mmreg_vaddr[TRINITY_MAX_MMREGS]; + phys_addr_t mmreg_paddr[TRINITY_MAX_MMREGS]; + + bool idu_set; + + struct work_struct work_stop; + + uint32_t tops; + uint32_t dspm; + + struct trinity_stat stat; + void *debugfs_pdata; + void *sched_pdata; + + struct hlist_bl_head model_htable[TRINITY_MODEL_HASH_SIZE]; + + /* sysfs info */ + int profile_req_id; +}; + +/** + * struct trinity_model - A structure for representing model data + * @config: model configuration + * @import_info: Cached hwmem import info. + * @hnode: hash node for indexing + * @owner_id: Identifier for owner app + * @refcnt: reference count + */ +struct trinity_model { + struct trinity_ioctl_model config; + struct trinity_hwmem_import import_info; + struct hlist_bl_node hnode; + int32_t owner_id; + struct kref refcnt; +} __packed; + +/** + * struct trinity_input - A structure for representing input data + * @config: input configuration + * @import_info: Cached hwmem import info. + */ +struct trinity_input { + struct trinity_ioctl_input config; + struct trinity_hwmem_import import_info; +} __packed; + +/** + * struct trinity_req - A structure for representing a request + * @drv: An instance of the driver. + * @input: Information of the input configuration to be run by this request + * @model: model information to be used for this request + * @status: Status of the submitted request + * @submit_retry: retry count of submit request + * @complete: completion information + * @llist: llist node for request queue + * @time_started: started time + * @is_kernel: requested from kernel module + * @scheduled: scheduled flag + * @priv: A handle of private data + * @note: The allocated 'trinity_req' is shared with ioctl, scheduler + * and interrupt handler routines. After invoking an NPU request, + * the irq handler can make complete the request at anytime, and it + * causes deallocation of the struct. + */ +struct trinity_req { + /** context where the req belongs */ + struct trinity_driver *drv; + + struct trinity_input input; /* the req's input argument */ + struct trinity_model *model; + + struct trinity_stat_req *stat; + + uint64_t submit_retry; + struct completion complete; + struct llist_node llist; + + ktime_t time_started; + bool is_kernel; + + bool scheduled; + bool timeout; + + void *priv; +}; + +static inline void trinity_set_bit(uint32_t bit, void __iomem *addr) +{ + uint32_t reg =3D 0; + + reg |=3D bit; + iowrite32(reg, addr); +} + +/** + * trinity_get_app_id() - Get a app_id for the current opened device + * + * Returns app_id (just returns its tgid for now). + */ +static inline int32_t trinity_get_app_id(void) +{ + return task_tgid_vnr(current); +} + +/* + * Trinity common functions + */ +int trinity_create_node(struct trinity_driver *drv); +void trinity_destroy_node(struct trinity_driver *drv); +int trinity_set_pause(struct trinity_driver *drv); +int trinity_wait_ready(struct trinity_driver *drv); +void trinity_init_model_htable(const struct trinity_driver *drv, + struct trinity_model_htable *ht); +int32_t trinity_get_app_id(void); +phys_addr_t trinity_get_paddr(struct iommu_domain *domain, dma_addr_t dadd= r); + +/* File operations */ +int trinity_open(struct inode *inode, struct file *f); +int trinity_release(struct inode *inode, struct file *f); +long trinity_ioctl(struct file *f, unsigned int cmd, unsigned long arg); + +/* Device probing and removing */ +int trinity_probe(struct platform_device *pdev, + const struct trinity_desc *desc); +int trinity_remove(struct platform_device *pdev, + const struct trinity_desc *desc); + +/* sysfs operations */ +int trinity_sysfs_init(struct trinity_driver *drv); +int trinity_sysfs_cleanup(struct trinity_driver *drv); + +/* debugfs operations */ +int trinity_debug_init(void); +void trinity_debug_exit(void); +int trinity_debug_add(struct trinity_driver *drv); +void trinity_debug_remove(struct trinity_driver *drv); +void trinity_debug_clear(struct trinity_driver *drv, unsigned long msg_max= ); +unsigned long trinity_debug_get_max(struct trinity_driver *drv); +void trinity_debug_dump_msg(struct trinity_driver *drv, const char *fmt, .= ..); +void trinity_debug_dump_model(struct trinity_driver *drv, + const struct trinity_model *model, + const char *fmt, ...); +void trinity_debug_dump_input(struct trinity_driver *drv, + const struct trinity_input *input, + const char *fmt, ...); + +#endif /* __DRIVERS_MISC_TRINITY_COMMON_H__ */ diff --git a/drivers/misc/trinity/trinity_vision2_drv.c b/drivers/misc/trin= ity/trinity_vision2_drv.c new file mode 100644 index 000000000000..bc43cafa39fb --- /dev/null +++ b/drivers/misc/trinity/trinity_vision2_drv.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** + * Samsung NPU Trinity Vision 2 driver + * + * Copyright (C) 2020-2022 Samsung Electronics + * Copyright (C) 2020 Wook Song + * Copyright (C) 2020 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#include +#include +#include +#include + +#include "trinity_common.h" +#include "trinity_vision2_regs.h" + +#define TRIV2_DRV_GET_PDATA(drv) ((struct triv2_pdata *)(drv->pdata)) +#define TRIV2_DRV_GET_CMD_INFO(drv) (&(TRIV2_DRV_GET_PDATA(drv)->cmd_info)) +#define TRIV2_DRV_GET_CMD_BUF(drv) (&(TRIV2_DRV_GET_CMD_INFO(drv)->buf)) +#define TRIV2_DRV_GET_PROF_BUF(drv) (&(TRIV2_DRV_GET_PDATA(drv)->prof_buf)) +#define TRIV2_DRV_GET_BACK_BUF(drv) (&(TRIV2_DRV_GET_PDATA(drv)->back_buf)) + +#define TRIV2_GET_CMD_FROM_SLOT(info, slot) \ + ((struct triv2_cmd *)(info->buf.addr + \ + slot * sizeof(struct triv2_cmd))) + +#define TRIV2_GET_REQ(req) (container_of(req, struct triv2_req, req)) + +#define HALF_PAGE_SIZE (PAGE_SIZE >> 1) + +enum triv2_cmd_status { + STATUS_CMD_NONE =3D 0, + STATUS_CMD_READY =3D 1, + STATUS_CMD_DONE =3D 2, +}; + +/** req command for triv2 */ +struct triv2_cmd { + union { + struct { + uint32_t slot; + uint32_t prog_addr; + uint32_t prog_size; + uint32_t segt_addr; + uint32_t num_visa; + + uint32_t priority; + uint32_t status; + uint32_t input_mode; + uint32_t output_mode; + + /** for profiling */ + uint32_t profile_offset; + + /** for preemptive scheduling */ + uint32_t program_position; + + /** for batch processing */ + uint32_t batch_size; + uint32_t curr_cnt; + uint32_t in_addr[TRIV2_MAX_BATCH_SIZE]; + uint32_t out_addr[TRIV2_MAX_BATCH_SIZE]; + uint32_t poll_addr; + uint32_t poll_magic; + /* deprecated but keep for backward compatibiltiy */ + uint32_t in_seg_idx; + uint32_t out_seg_idx; + + uint32_t total_cycles; + + /* kernel requests */ + uint32_t in_extern_seg_num; + uint32_t out_extern_seg_num; + uint32_t in_extern_seg_idx[TRIV2_MAX_TENSORS]; + uint32_t out_extern_seg_idx[TRIV2_MAX_TENSORS]; + }; + uint8_t reserved[TRIV2_MAX_CMD_SIZE]; + }; +} __packed; + +struct triv2_cmd_info { + DECLARE_BITMAP(bitmap, TRIV2_MAX_CMDSLOTS); + spinlock_t lock; + + struct triv2_req *reqs[TRIV2_MAX_CMDSLOTS]; + struct triv2_cmd cur_cmd; +}; + +struct triv2_hashed_cmd_info { + struct trinity_driver *drv; + struct hlist_bl_node hnode; + struct triv2_req *req; + struct triv2_cmd *cmd; +}; + +struct triv2_kernel_req { + uint32_t in_seg_idx[TRIV2_MAX_TENSORS]; + uint32_t in_seg_size[TRIV2_MAX_TENSORS]; + uint32_t out_seg_idx[TRIV2_MAX_TENSORS]; + uint32_t out_seg_size[TRIV2_MAX_TENSORS]; +}; + +struct triv2_req { + struct trinity_req req; + + int cmd_slot; + + /** kernel requets */ + struct triv2_kernel_req *kernel; + + /** profiling */ + uint32_t profile_offset; + uint32_t total_cycles; + + /** misc */ + uint32_t total_segment_size; +}; + +struct triv2_pdata { + struct trinity_driver *drv; + + /* command info */ + struct triv2_cmd_info cmd_info; +}; + +static void triv2_reset(struct trinity_driver *drv) +{ + struct triv2_pdata *pdata =3D drv->pdata; + + mutex_lock(&pdata->drv->lock); + + triv2_cancel_reqs(pdata->drv); + msleep(100); + + mutex_unlock(&pdata->drv->lock); +} + +static int triv2_open(struct inode *inode, struct file *f) +{ + int ret; + + ret =3D trinity_open(inode, f); + + return ret; +} + +static int triv2_release(struct inode *inode, struct file *f) +{ + int ret; + + ret =3D trinity_release(inode, f); + + return ret; +} + +static const struct file_operations triv2_fops =3D { + .owner =3D THIS_MODULE, + .open =3D triv2_open, + .release =3D triv2_release, + .llseek =3D noop_llseek, +}; + +static int32_t triv2_init_pdata(struct trinity_driver *drv) +{ + struct triv2_pdata *pdata; + struct triv2_cmd_info *cmd_info; + + pdata =3D kzalloc(sizeof(struct triv2_pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + drv->pdata =3D pdata; + pdata->drv =3D drv; + + cmd_info =3D TRIV2_DRV_GET_CMD_INFO(drv); + + spin_lock_init(&cmd_info->lock); + /* init cmd bitmap */ + bitmap_zero(cmd_info->bitmap, TRIV2_MAX_CMDSLOTS); + + return 0; +} + +/** + * triv2_cleanup() - Clean up initialized variables in TRIV2 + */ +static void triv2_cleanup(struct trinity_driver *drv) +{ + if (!drv->pdata) + return; + + kfree(drv->pdata); + drv->pdata =3D NULL; +} + +static struct trinity_desc triv2_desc =3D { + .type =3D "triv2", + .ver =3D GENVER(TRINITY_DEV_VISION2, VER_MAJOR, VER_MINOR, VER_EXTRA), + .fops =3D &triv2_fops, + /* device management */ + .reset =3D triv2_reset, + /* req management */ + .alloc_req =3D triv2_alloc_req, + .dealloc_req =3D triv2_dealloc_req, + .prepare_req =3D triv2_prepare_req, + .invoke_req =3D triv2_invoke_req, +}; + +static const struct of_device_id trinity_match[] =3D { + { + .compatible =3D "samsung,trinity", + }, + { /** sentinel */ }, +}; + +/** + * trinity_triv2_probe() - Probes for Trinity vision devices, inits them i= f found + */ +static int trinity_triv2_probe(struct platform_device *pdev) +{ + struct trinity_driver *drv; + int err; + + err =3D trinity_probe(pdev, &triv2_desc); + if (err < 0) + return err; + + err =3D triv2_init_pdata(drv); + if (err < 0) + goto out_remove; + + err =3D trinity_create_node(drv); + if (err < 0) { + triv2_cleanup(drv); + goto out_remove; + } + + dev_info(drv_to_dev_ptr(drv), "Trinity Vision2 (TRIV2)"); + + return 0; + +out_remove: + trinity_remove(pdev, &triv2_desc); + return err; +} + +/** + * trinity_triv2_remove() - Removes an instance of a Trinity vision device + */ +static int trinity_triv2_remove(struct platform_device *pdev) +{ + struct trinity_driver *drv =3D platform_get_drvdata(pdev); + + trinity_destroy_node(drv); + triv2_cleanup(drv); + return trinity_remove(pdev, &triv2_desc); +} + +static struct platform_driver trinity_triv2 =3D { + .probe =3D trinity_triv2_probe, + .remove =3D trinity_triv2_remove, + .driver =3D { + .name =3D "triv2", + .owner =3D THIS_MODULE, + .of_match_table =3D of_match_ptr(trinity_match), + }, +}; + +module_platform_driver(trinity_triv2); + +MODULE_IMPORT_NS(DMA_BUF); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Samsung Electronics"); +MODULE_DESCRIPTION("Samsung NPU device driver for trinity vision 2"); diff --git a/drivers/misc/trinity/trinity_vision2_regs.h b/drivers/misc/tri= nity/trinity_vision2_regs.h new file mode 100644 index 000000000000..58ef037d320e --- /dev/null +++ b/drivers/misc/trinity/trinity_vision2_regs.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Trinity Vision2 Registers + * + * Copyright (C) 2020-2022 Samsung Electronics + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#ifndef __DRIVERS_MISC_TRINITY_VISION2_REGS_H__ +#define __DRIVERS_MISC_TRINITY_VISION2_REGS_H__ + +/* Register offsets for NPU CP (Config) */ +#define OFFSET_CP_INFO (0x000) /* Processor Information */ +#define OFFSET_CP_PROC_STAT (0x010) /* Processor Status */ +#define OFFSET_CP_PROC_SET (0x014) /* Processor Control (Set) */ +#define OFFSET_CP_PROC_CLR (0x018) /* Processor Control (Clear) */ +#define OFFSET_CP_IMIF_BASE (0x024) /* Instruction Base Address (DRAM) */ +#define OFFSET_CP_CNT_CFG (0x200) /* CP Performance Counter */ + +/* Register offsets for NPU CP (IDU Setup) */ +#define OFFSET_NPU_PROG_BASE (0x100) /* GPR00: Instruction Base Address */ +#define OFFSET_NPU_PROG_SIZE (0x104) /* GPR01: Program Size */ +#define OFFSET_NPU_SEGT_ADDR (0x108) /* GPR02: Segment Table Address */ +#define OFFSET_NPU_PROF_ADDR (0x10C) /* GPR03: NPU Profiling Address */ +#define OFFSET_NPU_PROF_SIZE (0x110) /* GPR04: NPU Profiling Size */ +#define OFFSET_NPU_BACK_ADDR (0x114) /* GPR05: NPU Context Backup Address = */ +#define OFFSET_NPU_BACK_SIZE (0x118) /* GPR06: NPU Context Backup Size */ +#define OFFSET_NPU_PC (0x11C) /* GPR07: NPU Program Counter */ + +/* Register offsets for NPU CP (Commands) */ +#define OFFSET_NPU_CMD_READY (0x124) /* GPR09: Command Ready Status */ +#define OFFSET_NPU_CMD_BASE (0x128) /* GPR10: Command Base Address */ +#define OFFSET_NPU_CMD_REQ (0x12C) /* GPR11: Command Request Slots (not us= ed) */ +#define OFFSET_NPU_CMD_FREE (0x130) /* GPR12: Command Free Slots */ + +/* Register offsets for NPU CP (Cbox Setup) */ +#define OFFSET_NPU_CBOX_BASE (0x134) /* GPR13: NPU CBOX BASE */ + +/* Register offsets for Debugging */ +#define OFFSET_NPU_IDU_VERSION (0x138) /* GPR14: NPU IDU VERSION */ +#define OFFSET_NPU_IDU_STAGE (0x13C) /* GPR15: NPU IDU STAGE */ + +#define OFFSET_NPU_CP_DMAI_EADDR (0x300) /* CP DMA Source Address */ +#define OFFSET_NPU_CP_DMAI_IADDR (0x304) /* CP DMA Dest Address */ +#define OFFSET_NPU_CP_DMAI_TSIZE (0x308) /* CP DMA Transfer Size */ +#define OFFSET_NPU_CP_DMAI_CONTR (0x310) /* CP DMA Status */ +#define OFFSET_NPU_CP_DMAI_CMDID (0x314) /* CP DMA Command ID */ +#define OFFSET_NPU_CP_DMAI_LSTID \ + (0x318) /* CP DMA Command ID of the last transfer */ + +#define OFFSET_NPU_DLA_DMAI_EADDR (0x1000) /* DLA Input External Address */ +#define OFFSET_NPU_DLA_DMAI_EYMOD \ + (0x1004) /* DLA Input External Address Y Modifier */ +#define OFFSET_NPU_DLA_DMAI_EZMOD \ + (0x1008) /* DLA Input External Address Z Modifier */ +#define OFFSET_NPU_DLA_DMAI_IADDR (0x100C) /* DLA Input Internal Address */ +#define OFFSET_NPU_DLA_DMAI_IYMOD \ + (0x1010) /* DLA Input Internal Address Y Modifier */ +#define OFFSET_NPU_DLA_DMAI_IZMOD \ + (0x1014) /* DLA Input Internal Address Z Modifier */ +#define OFFSET_NPU_DLA_DMAI_SIZE0 (0x1018) /* DLA Input Data Size 0 */ +#define OFFSET_NPU_DLA_DMAI_SIZE1 (0x101C) /* DLA Input Data Size 1 */ +#define OFFSET_NPU_DLA_DMAI_CTRL (0x1020) /* DLA Input Channel Status */ + +#define OFFSET_NPU_DLA_DMAO_EADDR (0x1080) /* DLA Output External Address = */ +#define OFFSET_NPU_DLA_DMAO_EYMOD \ + (0x1084) /* DLA Output External Address Y Modifier */ +#define OFFSET_NPU_DLA_DMAO_EZMOD \ + (0x1088) /* DLA Output External Address Z Modifier */ +#define OFFSET_NPU_DLA_DMAO_IADDR (0x108C) /* DLA Output Internal Address = */ +#define OFFSET_NPU_DLA_DMAO_IYMOD \ + (0x1090) /* DLA Output Internal Address Y Modifier */ +#define OFFSET_NPU_DLA_DMAO_IZMOD \ + (0x1094) /* DLA Output Internal Address Z Modifier */ +#define OFFSET_NPU_DLA_DMAO_SIZE0 (0x1098) /* DLA Output Data Size 0 */ +#define OFFSET_NPU_DLA_DMAO_SIZE1 (0x109C) /* DLA Output Data Size 1 */ +#define OFFSET_NPU_DLA_DMAO_CTRL (0x10A0) /* DLA Output Channel Status */ + +#define OFFSET_NPU_DLA_CORE_OPC (0x1100) /* DLA Operation Code */ +#define OFFSET_NPU_DLA_CORE_WIND_CFG (0x1104) +#define OFFSET_NPU_DLA_CORE_SIZE0 (0x1108) +#define OFFSET_NPU_DLA_CORE_SIZE1 (0x110C) +#define OFFSET_NPU_DLA_CORE_ZP (0x1110) +#define OFFSET_NPU_DLA_CORE_OUT_MULT (0x1114) +#define OFFSET_NPU_DLA_CORE_IN0_MULT (0x1118) +#define OFFSET_NPU_DLA_CORE_IN1_MULT (0x111C) +#define OFFSET_NPU_DLA_CORE_OUT_CFG (0x1120) +#define OFFSET_NPU_DLA_CORE_OUT_MOD (0x1124) +#define OFFSET_NPU_DLA_CORE_IN0_CFG (0x1128) +#define OFFSET_NPU_DLA_CORE_IN0_MOD (0x112C) +#define OFFSET_NPU_DLA_CORE_IN1_CFG (0x1130) +#define OFFSET_NPU_DLA_CORE_IN1_MOD (0x1134) +#define OFFSET_NPU_DLA_CORE_PARAM_ADDR (0x1138) +#define OFFSET_NPU_DLA_CORE_PSUM_ADDR (0x113C) +#define OFFSET_NPU_DLA_CORE_CWGT_ADDR (0x1140) +#define OFFSET_NPU_DLA_CORE_CTR (0x1144) /* DLA Core Status */ + +#define OFFSET_NPU_DSP_DMAI_EADDR (0x2000) /* DSP Input External Address */ +#define OFFSET_NPU_DSP_DMAI_EYMOD \ + (0x2004) /* DSP Input External Address Y Modifier */ +#define OFFSET_NPU_DSP_DMAI_EZMOD \ + (0x2008) /* DSP Input External Address Z Modifier */ +#define OFFSET_NPU_DSP_DMAI_IADDR (0x200C) /* DSP Input Internal Address */ +#define OFFSET_NPU_DSP_DMAI_IYMOD \ + (0x2010) /* DSP Input Internal Address Y Modifier */ +#define OFFSET_NPU_DSP_DMAI_IZMOD \ + (0x2014) /* DSP Input Internal Address Z Modifier */ +#define OFFSET_NPU_DSP_DMAI_SIZE0 (0x2018) /* DSP Input Data Size 0 */ +#define OFFSET_NPU_DSP_DMAI_SIZE1 (0x201C) /* DSP Input Data Size 1 */ +#define OFFSET_NPU_DSP_DMAI_CTRL (0x2020) /* DSP Input Channel Status */ + +#define OFFSET_NPU_DSP_DMAO_EADDR (0x2080) /* DSP Output External Address = */ +#define OFFSET_NPU_DSP_DMAO_EYMOD \ + (0x2084) /* DSP Output External Address Y Modifier */ +#define OFFSET_NPU_DSP_DMAO_EZMOD \ + (0x2088) /* DSP Output External Address Z Modifier */ +#define OFFSET_NPU_DSP_DMAO_IADDR (0x208C) /* DSP Output Internal Address = */ +#define OFFSET_NPU_DSP_DMAO_IYMOD \ + (0x2090) /* DSP Output Internal Address Y Modifier */ +#define OFFSET_NPU_DSP_DMAO_IZMOD \ + (0x2094) /* DSP Output Internal Address Z Modifier */ +#define OFFSET_NPU_DSP_DMAO_SIZE0 (0x2098) /* DSP Output Data Size 0 */ +#define OFFSET_NPU_DSP_DMAO_SIZE1 (0x209C) /* DSP Output Data Size 1 */ +#define OFFSET_NPU_DSP_DMAO_CTRL (0x20A0) /* DSP Output Channel Status */ +#define OFFSET_NPU_DSP_CORE_CTRL (0x2140) /* DSP Core Status */ + +/* Register offsets for NPU DSP */ +#define OFFSET_DSP_INFO (0x000) /* Processor Information */ +#define OFFSET_DSP_PROC_STAT (0x010) /* Processor Status */ +#define OFFSET_DSP_PROC_SET (0x014) /* Processor Control (Set) */ +#define OFFSET_DSP_PROC_CLR (0x018) /* Processor Control (Clear) */ +#define OFFSET_DSP_IMIF_BASE (0x024) /* Instruction Base Address (DRAM) */ + +/* Register offsets for NPU ComBox (IRQ) */ +#define OFFSET_CBOX_EXT_IRQ_MSK (0x100) /* External IRQ Output Mask */ +#define OFFSET_CBOX_EXT_IRQ_STA (0x104) /* External IRQ Output Status */ +#define OFFSET_CBOX_CP_SWI_CLR (0x134) /* CP IRQ output Clear */ +#define OFFSET_CBOX_DSP_SWI_CLR (0x154) /* DSP IRQ output Clear */ + +/* Location of bits inside corresponding registers */ +#define BIT_CLR_IRQ_OUT BIT(24) +#define BIT_CLR_PAUSE BIT(0) +#define BIT_SET_SEND_EVT1 BIT(18) +#define BIT_SET_PAUSE BIT(0) +#define BIT_STAT_PAUSED BIT(1) + +/* Performance counter configurations */ +#define BIT_CNT_DST_EN BIT(6) +#define BIT_CNT_IST_EN BIT(5) +#define BIT_CNT_ST_EN BIT(4) +#define BIT_CNT_FR_EN BIT(0) + +/* Bit masks */ +#define MASK_DSP_SWI_STA BIT_MASK(1) +#define MASK_CP_SWI_STA BIT_MASK(0) + +#define MASK_STAT_WFE_PARAM GENMASK(14, 6) +#define MASK_STAT_WFE_PARAM_EVT1 BIT_MASK(8) +#define MASK_STAT_WFE BIT_MASK(5) +#define MASK_STAT_PAUSED BIT_MASK(1) +#define MASK_STAT_PAUSE BIT_MASK(0) + +#define VER_MAJOR (2) +#define VER_MINOR (0) +#define VER_EXTRA (0) + +#define read_idu_file(file, pos, addr, size) kernel_read(filp, addr, size,= &pos) + +/** Macros for Instruction Decode Unit (IDU) */ +#define TRIV2_IDU_DIRPATH_FMT "/lib/modules/%s/kernel/soc/idu" +#define TRIV2_IDU_MAX_SECTORS (3) +#define TRIV2_IDU_ZEROIDX (0) +#define TRIV2_IDU_DATAIDX (1) +#define TRIV2_IDU_CODEIDX (2) +#define TRIV2_IDU_ADDR(addr) ((uint32_t)(addr)) +#define TRIV2_IDU_MAXSIZE (1 << 20) /* 1 MiB */ + +#define TRIV2_IDU_CP_DSPM_SIZE (0x10000) + +#define TRIV2_IDU_MASK_MAJOR (0xFF000000) +#define TRIV2_IDU_MASK_MINOR (0x00FFF000) +#define TRIV2_IDU_MASK_EXTRA (0x00000FFF) + +#define TRIV2_IDU_SHIFT_MAJOR (24) +#define TRIV2_IDU_SHIFT_MINOR (12) + +#define TRIV2_MODEL_HASH_BITS (8) +#define TRIV2_MODEL_HASH_SIZE (1 << TRIV2_MODEL_HASH_BITS) +#define TRIV2_PROFILE_HASH_BITS (6) +#define TRIV2_PROFILE_HASH_SIZE (1 << TRINITY_PROFILE_HASH_BITS) +#define TRIV2_PROFILE_HASH_KEY(id) (hash_long((id), TRIV2_PROFILE_HASH_BIT= S)) + +#define TRIV2_MAX_SEGMENTS (256) +/** Fits in a single 4K Page */ +#define TRIV2_MAX_CMDSLOTS (PAGE_SIZE / sizeof(struct triv2_cmd)) + +#define TRIV2_MAX_TENSORS (16) +#define TRIV2_MAX_CMD_SIZE (512) +#define TRIV2_MAX_BATCH_SIZE (32) + +#define TRIV2_DLA_GBUFFER_SIZE (0x80000) +#define TRIV2_DSP_DSPM_OFFSET (0x10000) + +/* 4MiB (~300ns to flush all caches) */ +#define TRIV2_CACHE_FLUSH_THRESHOLD (0x400000) +#define TRIV2_KERN_TIMEOUT_RESET (1000) + +#endif /* __DRIVERS_MISC_TRINITY_VISION2_REGS_H__ */ diff --git a/include/uapi/misc/trinity.h b/include/uapi/misc/trinity.h new file mode 100644 index 000000000000..9f4808bfdd90 --- /dev/null +++ b/include/uapi/misc/trinity.h @@ -0,0 +1,476 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/** + * User-level header for trinity devices. + * + * Copyright (C) 2020-2022 Samsung Electronics + * Copyright (C) 2020 Wook Song + * Copyright (C) 2020 Dongju Chae + * Copyright (C) 2020 Parichay Kapoor + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#ifndef __TRINITY_H__ +#define __TRINITY_H__ + +#include + +#define TRINITY_API_LEVEL 12 + +/** + * enum trinity_state - Enum that describes a trinity device state + * @TRINITY_STATE_UNKNOWN: A device has unknown state + * @TRINITY_STATE_PAUSE: A device is paused + * @TRINITY_STATE_READY: A device is ready + * @TRINITY_STATE_END: End of trinity_state + */ +enum trinity_state { + TRINITY_STATE_UNKNOWN =3D -1, + TRINITY_STATE_PAUSE =3D 0, + TRINITY_STATE_READY, + TRINITY_STATE_END, +}; + +/** + * enum trinity_input_mode - Enum that describes an input source + * @TRINITY_INPUT_UNKNOWN: Unknown input mode + * @TRINITY_INPUT_CPU: Input feed by CPU + * @TRINITY_INPUT_HW: Input feed by third-party HW + * @TRINITY_INPUT_END: End of trinity_input_mode + */ +enum trinity_input_mode { + TRINITY_INPUT_UNKNOWN =3D -1, + TRINITY_INPUT_CPU =3D 0, + TRINITY_INPUT_HW, + TRINITY_INPUT_END, +}; + +/** + * enum trinity_output_mode - Enum that describes an output source + * @TRINITY_OUTPUT_UNKNOWN: Unknown output mode + * @TRINITY_OUTPUT_CPU_INTR: Output completion handling by interrupt + * @TRINITY_OUTPUT_CPU_POLL: Output completion handling by polling + * @TRINITY_OUTPUT_HW: Output completion handling by third-party HW + * @TRINITY_OUTPUT_END: End of trinity_output_mode + */ +enum trinity_output_mode { + TRINITY_OUTPUT_UNKNOWN =3D -1, + TRINITY_OUTPUT_CPU_INTR =3D 0, + TRINITY_OUTPUT_CPU_POLL, + TRINITY_OUTPUT_HW, + TRINITY_OUTPUT_END, +}; + +/** + * enum trinity_app_status - Enum that describes an app status + * @TRINITY_APP_STATUS_UNKNOWN: Unknown app status + * @TRINITY_APP_STATUS_ERROR: App has got some errors + * @TRINITY_APP_STATUS_PENDING: App is currently pending + * @TRINITY_APP_STATUS_STARTED: App was started + * @TRINITY_APP_STATUS_TERMINATED: App was terminated + */ +enum trinity_app_status { + TRINITY_APP_STATUS_UNKNOWN =3D 0, + TRINITY_APP_STATUS_ERROR =3D 1, + TRINITY_APP_STATUS_PENDING =3D 2, + TRINITY_APP_STATUS_STARTED =3D 3, + TRINITY_APP_STATUS_TERMINATED =3D 4 +}; + +/** + * enum trinity_req_status - Enum that describes a request status + * @TRINITY_REQ_STATUS_UNKNOWN: Unknown request status + * @TRINITY_REQ_STATUS_ERROR: Request has got some errors + * @TRINITY_REQ_STATUS_PENDING: Request is currently pending + * @TRINITY_REQ_STATUS_RUNING: Request is currently running + * @TRINITY_REQ_STATUS_FINISHED: Request was finished + */ +enum trinity_req_status { + TRINITY_REQ_STATUS_UNKNOWN =3D 0, + TRINITY_REQ_STATUS_ERROR =3D 1, + TRINITY_REQ_STATUS_PENDING =3D 2, /* A request is submitted */ + TRINITY_REQ_STATUS_RUNNING =3D 3, /* A request is running on NPU */ + TRINITY_REQ_STATUS_FINISHED =3D 4 /* A request is just finished */ +}; + +/** + * enum trinity_req_priority - Enum that describes a request priority + * @TRINITY_REQ_PRIORITY_LOW: Low priority + * @TRINITY_REQ_PRIORITY_MID: Mid priority scheduled with a higher chance = than low one + * @TRINITY_REQ_PRIORITY_HIGH: High priority preempting lower priority req= uests + */ +enum trinity_req_priority { + TRINITY_REQ_PRIORITY_LOW =3D 0, + TRINITY_REQ_PRIORITY_MID =3D 1, + TRINITY_REQ_PRIORITY_HIGH =3D 2, +}; + +/** + * enum trinity_hwmem_type - A type of DMA buffer allocation method. + * @TRINITY_HWMEM_DMA_CONT: Use CMA to allocate backing stroage of DMA buf= fers. + * @TRINITY_HWMEM_DMA_IOMMU: Use IOMMU to allocate backing stroage of DMA = buffers. + * @HWMEM_END: Sentinel. + */ +enum trinity_hwmem_type { + TRINITY_HWMEM_DMA_CONT =3D 0, + TRINITY_HWMEM_DMA_IOMMU, + TRINITY_HWMEM_END, +}; + +#ifndef TASK_COMM_LEN +#define TASK_COMM_LEN 16 +#endif + +#define TRINITY_APP_NAME_MAX TASK_COMM_LEN +#define TRINITY_APP_STAT_MAX 10 +#define TRINITY_REQ_STAT_MAX 10 + +/** + * struct trinity_ioctl_stat_app - Describes stat of the target app + * @app_id: Trinity app id (currently, equal to pid) + * @name: Trinity app name + * @status: Trinity app status + * @num_total_reqs: Number of total requests in app (including finished on= es) + * @num_active_reqs: Number of active (running or pending) requests in app + * @total_alloc_mem: Total size of allocated memory in the device + * @total_freed_mem: Total size of freed memory in the device + */ +struct trinity_ioctl_stat_app { + __s32 app_id; + + char name[TRINITY_APP_NAME_MAX]; + enum trinity_app_status status; + + __u32 num_total_reqs; + __u32 num_active_reqs; + + __u64 total_alloc_mem; + __u64 total_freed_mem; +} __packed; + +/** + * struct trinity_ioctl_stat_apps - Describes stats of the latest apps + * @num_apps: Number of apps for the stat list + * @stat: Stat of the latest apps + */ +struct trinity_ioctl_stat_apps { + __u32 num_apps; + struct trinity_ioctl_stat_app stat[TRINITY_APP_STAT_MAX]; +} __packed; + +/** + * struct trinity_ioctl_stat_req - Describes stat of the target request + * @req_id: Trinity req id + * @model_id: Trinity model id + * @priority: Request priority (low, mid, or high) + * @status: Request status + * @sched_time: scheduling time in ms + * @infer_time: inference time in ms + */ +struct trinity_ioctl_stat_req { + __s32 req_id; + __u64 model_id; + + enum trinity_req_priority priority; + enum trinity_req_status status; + + __u32 sched_time; + __u32 infer_time; +} __packed; + +/** + * struct trinity_ioctl_stat_reqs - Describes stats of the latest reqs + * @app_id: Trinity app id (0 means 'current') + * @num_reqs: Number of reqs for stat list + * @stat: Stat of the latest reqs + */ +struct trinity_ioctl_stat_reqs { + __s32 app_id; + __u32 num_reqs; + struct trinity_ioctl_stat_req stat[TRINITY_REQ_STAT_MAX]; +} __packed; + +/** + * struct trinity_ioctl_hwmem - A structure that Describes hardware memory= (hwmem) + * @type: The type of hwmem type + * @size: The size of hwmem + * @dbuf_fd: File descriptor for dmabuf representing hwmem + */ +struct trinity_ioctl_hwmem { + enum trinity_hwmem_type type; + __u64 size; + __s32 dbuf_fd; +} __packed; + +/** + * struct trinity_ioctl_profile_meta - Describes profiling meta info. + * @req_id: The target req id for profiling + * @total_cycles: The total number of cycles of the given req + * @total_ops: The total number of operations of the given req + * @input_footprint: The DRAM footprint of input data + * @output_footprint: The DRAM footprint of output data + * @profile_size: The size of profiling data + */ +struct trinity_ioctl_profile_meta { + __s32 req_id; + __s64 total_cycles; + __u32 total_ops; + __s64 input_footprint; + __s64 output_footprint; + __u32 profile_size; +} __packed; + +/** + * struct trinity_ioctl_profile_buff - Describes profiling buff info. + * @req_id: The target req id for profiling + * @profile_pos: The start position to extract profiling data + * @profile_size: The size of user-allocated profiling buffer + * @profile_buf: The profiling buffer which user allocated + */ +struct trinity_ioctl_profile_buff { + __s32 req_id; + __u32 profile_pos; + __u32 profile_size; + void __user *profile_buf; +} __packed; + +/** + * struct trinity_ioctl_model - A structure that configure a model registe= red on NPU + * @id: Id for NPU model to extract the base phys addr + * @dbuf_fd: File descriptor for dmabuf representing the model + * @program_offset_addr: Offset address for the instructions (NPU_PROG_BAS= E) + * @program_size: Size of the program instructions (NPU_PROG_SIZE) + * @version: The version of npubinfmt + * @endp_trnt_model_common: Indicator for the end of common model paramete= rs + * @weight_offset_addr: Offset address for storing weights (NPU_WGT_BASE) + * @metadata_dbuf_fd: File descriptor for dmabuf representing the metadata + * @metadata_extra_addr: Offset address for the metadata extra + * @metadata_extra_size: Size of the metadata extra + * @num_visa_insts: Number of virtual ISA instructions + */ +struct trinity_ioctl_model { + __u64 id; + __s32 dbuf_fd; + __u64 program_offset_addr; + __u64 program_size; + __u32 version; + union { + __u8 endp_trnt_model_common[0]; + struct { + __u64 weight_offset_addr; + } __packed; + struct { + __s32 metadata_dbuf_fd; + __s32 metadata_ext_dbuf_fd; + __u64 metadata_ext_size; + __u32 num_visa_insts; + } __packed; + }; +} __packed; + +/** + * struct trinity_ioctl_input - A structure that configure an input passed= to NPU + * @dbuf_fd: File descriptor for dmabuf of I/O buffer (or segment table) + * @model_id: Model id received when setting the model in the NPU + * @req_id: Request id to distinguish each run_input + * @timeout_ms: Timeout in ms, zero is regarded as preemption + * @priority: Priority (LOW: 0, MID: 1, HIGH: 2) + * @endp_trnt_input_common: Indicator for the end of common input paramete= rs + * @activation_offset_addr0: Offset address for storing weights (NPU_ACT_B= ASE0) + * @activation_offset_addr1: Offset address for storing weights (NPU_ACT_B= ASE1) + * @num_segments: Number of segments + * @input_mode: Input mode (who is supposed to feed input) + * @output_mode: Output mode (who is supposed to retrieve output) + * @hw_input_seg: Third-party HW's input segment idx + * @hw_output_seg: Third-party HW's output segment idx + * @task_handle: user requested task handle + * @subtask_idx: user requested subtask idx + * @task_id: kernel module requested task id + */ +struct trinity_ioctl_input { + __s32 dbuf_fd; + __u64 model_id; + __s32 req_id; + __s64 timeout_ms; + __u32 priority; + union { + __u8 endp_trnt_input_common[0]; + struct { + /* added for TRIV-1 */ + __u64 activation_offset_addr0; + __u64 activation_offset_addr1; + } __packed; + struct { + /* added for TRIV-2 */ + __u32 num_segments; + enum trinity_input_mode input_mode; + enum trinity_output_mode output_mode; + __s32 hw_input_seg; + __s32 hw_output_seg; + /* [optional] vd scheduler info */ + union { + struct { /* user request */ + __u32 task_handle; + __u32 subtask_idx; + } __packed; + struct { /* kernel request */ + __u32 task_id; + } __packed; + }; + } __packed; + }; +} __packed; + +#define TRINITY_MASK_DEV (0xFF000000) +#define TRINITY_MASK_MAJOR_VER (0x00FF0000) +#define TRINITY_MASK_MINOR_VER (0x0000FF00) +#define TRINITY_MASK_EXTRA_VER (0x000000FF) + +/** + * struct trinity_ioctl_fpga_memcpy - A structure that contains driver-ass= isted memcpy + * @dbuf_fd: File descriptor for dmabuf of the target buffer + * @dbuf_off: Offset from the dmabuf base address + * @user_addr: Address of user-level buffer + * @user_size: Size of user-level buffer + * + * @note: It's workaround structure for FPGA envionment + */ +struct trinity_ioctl_fpga_memcpy { + __s32 dbuf_fd; + __u32 dbuf_off; + void __user *user_addr; + __u64 user_size; +} __packed; + +/** + * struct trinity_ioctl_idu - A structure that Describes IDU + * @dbuf_cp_data: CP data dmabuf which is allocated with TRINITY_IOCTL_HWM= EM_ALLOC + * @dbuf_cp_code: CP code dmabuf which is allocated with TRINITY_IOCTL_HWM= EM_ALLOC + * @dbuf_cp_data: dsp data dmabuf which is allocated with TRINITY_IOCTL_HW= MEM_ALLOC + * @dbuf_dsp_code: dsp code dmabuf which is allocated with TRINITY_IOCTL_H= WMEM_ALLOC + */ +struct trinity_ioctl_idu { + __s32 dbuf_cp_data; + __s32 dbuf_cp_code; + __s32 dbuf_dsp_data; + __s32 dbuf_dsp_code; +} __attribute__((packed)); + +#define TRINITY_SHIFT_DEV (24) +#define TRINITY_SHIFT_MAJOR_VER (16) +#define TRINITY_SHIFT_MINOR_VER (8) +#define TRINITY_SHIFT_EXTRA_VER (0) +#define TRINITY_SHIFT_MODEL_ID (16) + +#define trinity_gen_ver(dev, mj, mn, ex) = \ + { \ + (dev << TRINITY_SHIFT_DEV) | (mj << TRINITY_SHIFT_MAJOR_VER) | \ + (mn << TRINITY_SHIFT_MINOR_VER) | \ + (ex << TRINITY_SHIFT_EXTRA_VER) \ + } + +/** + * enum trinity_dev_type - Enum that describes a trinity device type + * @TRINITY_DEV_UNKNOWN: Unknown device type + * @TRINITY_DEV_VISION: Trinity Vision (TRIV) + * @TRINITY_DEV_AUDIO: Trinity Asr (TRIA) + * @TRINITY_DEV_VISION2: Trinity Vision2 (TRIV2) + * @TRINITY_DEV_VISION2_CUSE: Trinity Vision2 (TRIV2), CUSE-based impl. + * @TRINITY_DEV_END: End of trinity_dev_type + */ +enum trinity_dev_type { + TRINITY_DEV_UNKNOWN =3D 0, + TRINITY_DEV_VISION, + TRINITY_DEV_AUDIO, + TRINITY_DEV_VISION2, + TRINITY_DEV_VISION2_CUSE, /* CUSE-based impl. for triv2 */ + TRINITY_DEV_END /* sentinel */ +}; + +/** + * Major number can not be dynamic as ioctls need it, + */ +#define TRINITY_DRIVER_MAGIC 0x88 + +#define TRINITY_IO(no) _IO(TRINITY_DRIVER_MAGIC, no) +#define TRINITY_IOR(no, data_type) _IOR(TRINITY_DRIVER_MAGIC, no, data_typ= e) +#define TRINITY_IOW(no, data_type) _IOW(TRINITY_DRIVER_MAGIC, no, data_typ= e) +#define TRINITY_IOWR(no, data_type) _IOWR(TRINITY_DRIVER_MAGIC, no, data_t= ype) + +/** Device Information */ + +/** Get the device version information from the driver */ +#define TRINITY_IOCTL_GET_VERSION TRINITY_IOR(1, __u32) +/** Get the device API level from the driver */ +#define TRINITY_IOCTL_GET_API_LEVEL TRINITY_IOR(2, __u32) +/** Get the device state from the driver */ +#define TRINITY_IOCTL_GET_STATE TRINITY_IOR(3, __s32) +/** Get the device tops information from the driver */ +#define TRINITY_IOCTL_GET_TOPS TRINITY_IOR(4, __u32) +/** Get the device dspm information from the driver */ +#define TRINITY_IOCTL_GET_DSPM TRINITY_IOR(5, __u32) +/** Get the next request ID from the driver */ +#define TRINITY_IOCTL_GET_NEXT_REQUEST TRINITY_IOR(6, __s32) + +/** Device Control */ + +/** Allocate driver-managed memory */ +#define TRINITY_IOCTL_HWMEM_ALLOC TRINITY_IOW(21, struct trinity_ioctl_hwm= em) + +/** De-allocate driver-managed memory */ +#define TRINITY_IOCTL_HWMEM_DEALLOC TRINITY_IOW(22, struct trinity_ioctl_h= wmem) + +/** Register the given model config in the device and return model id */ +#define TRINITY_IOCTL_REGISTER_MODEL \ + TRINITY_IOWR(23, struct trinity_ioctl_model) + +/** Unregister the model config associated with the given model_id */ +#define TRINITY_IOCTL_DEREGISTER_MODEL TRINITY_IOW(24, __u64) + +/** Run the device with the given input */ +#define TRINITY_IOCTL_RUN_INPUT TRINITY_IOWR(25, struct trinity_ioctl_inpu= t) + +/** Stop all requests submitted to the device */ +#define TRINITY_IOCTL_STOP_REQUESTS TRINITY_IO(26) + +/** Stop the target request with id returned by run_input */ +#define TRINITY_IOCTL_STOP_REQUEST TRINITY_IOW(27, __s32) + +/** Device Statistics/Profile */ + +/** Get the current app stat in the opened device */ +#define TRINITY_IOCTL_STAT_CURRENT_APP \ + TRINITY_IOR(51, struct trinity_ioctl_stat_app) + +/** Get latest apps' stat of the opened device */ +#define TRINITY_IOCTL_STAT_APPS TRINITY_IOR(52, struct trinity_ioctl_stat_= apps) + +/** Get latest reqs' stat in the target app */ +#define TRINITY_IOCTL_STAT_REQS TRINITY_IOR(53, struct trinity_ioctl_stat_= reqs) + +/** Get profiling metadata of the request */ +#define TRINITY_IOCTL_GET_PROFILE_META \ + TRINITY_IOWR(54, struct trinity_ioctl_profile_meta) + +/** Get profiling per-op data of the request */ +#define TRINITY_IOCTL_GET_PROFILE_BUFF \ + TRINITY_IOWR(55, struct trinity_ioctl_profile_buff) + +/** Set IDU binary */ +#define TRINITY_IOCTL_IDU_SET \ + TRINITY_IOW(56, struct trinity_ioctl_idu) + +/** Device Testing/Workaround */ + +/** Driver-assisted memory copy for FPGA env. */ +#define TRINITY_IOCTL_FPGA_MEMCPY \ + TRINITY_IOWR(91, struct trinity_ioctl_fpga_memcpy) + +/** A wrapper of trinity_run_internal_req() */ +#define TRINITY_IOCTL_RUN_INTERNAL_REQ TRINITY_IOW(92, dev_t) + +#ifdef __KERNEL__ +__s32 trinity_run_internal_req(dev_t); +#endif +#endif /* __TRINITY_H__ */ --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EE299ECAAD3 for ; Sat, 17 Sep 2022 07:24:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229484AbiIQHY0 (ORCPT ); Sat, 17 Sep 2022 03:24:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51886 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229479AbiIQHYJ (ORCPT ); Sat, 17 Sep 2022 03:24:09 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72B1E422DB for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p3.samsung.com (unknown [182.195.41.47]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220917072359epoutp03392c1d3d711fae2b36a63f7f609322ce~VlPosMtN31145111451epoutp03E for ; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220917072359epoutp03392c1d3d711fae2b36a63f7f609322ce~VlPosMtN31145111451epoutp03E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399439; bh=jiZzG4vFrxosmTJYB/0JAWBu8ckbz2PQUosr1RdVHDA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J5TcmBovO6O5WMscn4c459KDu1toVYoBzvV7qF7FUqEJaTK5hnL5SQF9fAmS+ECKl SitZqtIo2u/eitAFyybHeXR9oWVnC4qjPFeQDiOCmzCO3iLMKHLbIpyL5w70SS9gON jZqNT526Aq24eNsRYZfTxFpg0tAh3s4quDG5aQY0= Received: from epsnrtp3.localdomain (unknown [182.195.42.164]) by epcas1p4.samsung.com (KnoxPortal) with ESMTP id 20220917072358epcas1p45371dc7da50414e7cf19b1a78607611d~VlPoB6g_u2970529705epcas1p4O; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epsmges1p4.samsung.com (unknown [182.195.38.234]) by epsnrtp3.localdomain (Postfix) with ESMTP id 4MV2Vj65JJz4x9Pr; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epcas1p3.samsung.com ( [182.195.41.47]) by epsmges1p4.samsung.com (Symantec Messaging Gateway) with SMTP id B1.ED.07691.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas1p1.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epcas1p1bc8d924080c5dabafee1db779369078d~VlPmrWA9W0249502495epcas1p1S; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220917072357epsmtrp1f725e391d3d36a3346ac0516b1c22274~VlPmqqInW0556805568epsmtrp1b; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) X-AuditID: b6c32a38-31ffb70000021e0b-79-6325760dc465 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id 24.F0.18644.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epsmtip202868a444d99d97e1966c115e61422db~VlPmWQ11y2857028570epsmtip20; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 02/13] tirnity: Add memory module Date: Sat, 17 Sep 2022 16:23:45 +0900 Message-Id: <20220917072356.2255620-3-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupnk+LIzCtJLcpLzFFi42LZdlhTX5e3TDXZ4OYZTYu/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtKtsmIzUxJbVIITUvOT8lMy/dVsk7ON453tTMwFDX0NLCXEkh LzE31VbJxSdA1y0zB+gqJYWyxJxSoFBAYnGxkr6dTVF+aUmqQkZ+cYmtUmpBSk6BaYFecWJu cWleul5eaomVoYGBkSlQYUJ2xoX2WawFC+YyVtxf18zUwHi5kbGLkZNDQsBEYuvS+0xdjFwc QgI7GCXuX58B5XxilDjx+ToTSJWQwGdGiSdbtGE61n55wgpRtItRYkfnGzYIB6ios+8YG0gV m4CqxMwZa9hBbBGBconmjSfAbGaBHIknd5qYQWxhoElNs5qB6jk4WIDqL3cWg4R5Bawl1v68 AFbOKWAjcXNTEwtEXFDi5MwnLBBj5CWat85mBtkrIfCVXWLb+hMsENe5SLz/3skGYQtLvDq+ hR3ClpJ42d8GZWdLTOlYBFVfIHHu+VZmkBskBIwlLq5IATGZBTQl1u/Sh6hQlNj5ey4jxFo+ iXdfe1ghqnklOtqEIEqUJJb8OQw1XEJi6oxvTBC2h8T9vSCLQKHTzyixdPpqtgmM8rOQfDML yTezEDYvYGRexSiWWlCcm55abFhgAo/V5PzcTYzglKllsYNx7tsPeocYmTgYDzFKcDArifCq eqokC/GmJFZWpRblxxeV5qQWH2I0BQbvRGYp0eR8YNLOK4k3NLE0MDEzMjaxMDQzVBLn1dNm TBYSSE8sSc1OTS1ILYLpY+LglGpganW4OHXS03NOaQq5u+5V1wu5TPtbUMTs/tl+3VpJVlff WfeOy3tv5P84iytIRfx6kFPZ7wfPGlcvV27t3FM5VUJ+GvfJhW+c3i9/w5LSPnGr9ZPIK6X6 rIqLDY+JV6uoTjtpYrVzV0jku8q4d4m/XaX+cHq7SG2P0U53/vhM2MLjeQ/vlJypa9cn5Xye XW6SbiKq+sqKs8ahaH2Qoo5Fpl10QseORFaxBWd2dO1cwySzbfnj+ZOPWFf1PehIfpqwZ+bX DMGEqLxig138RfMPx24oM0pYtT+76Hna1rSfmjV/Z68XOs47yWz1xNDnIkp+saqSbSUZhj5n a+7KTN74wIHx8pyXM85wil6Kk7dXYinOSDTUYi4qTgQAlrct4iIEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrFLMWRmVeSWpSXmKPExsWy7bCSvC5vmWqywaMp/BZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAlfGhfZZrAUL5jJW3F/XzNTAeLmRsYuR k0NCwERi7ZcnrF2MXBxCAjsYJf6/P8EEkZCQ2HRvOXMXIweQLSxx+HAxRM1HRon1rU/YQWrY BFQlZs5YA2aLCNRKHDw6nxnEZhYokJj9dCYLiC0MtKBpVjMbyBwWoPrLncUgYV4Ba4m1Py+A tXIK2Ejc3NQEVi4EFJ89fS4TRI2gxMmZT1ggRspLNG+dzTyBkX8WktQsJKkFjEyrGCVTC4pz 03OLDQuM8lLL9YoTc4tL89L1kvNzNzGCg1tLawfjnlUf9A4xMnEwHmKU4GBWEuFV9VRJFuJN SaysSi3Kjy8qzUktPsQozcGiJM57oetkvJBAemJJanZqakFqEUyWiYNTqoEpka/1XeaEm1uX iTgIlXHNr/6xQOrJgtwczsLXKgeNfBVjLjPeetNauXHvGXXmHxcPzBJstJkiuYVvlvPfKfxP lG9LGU1oFw/UmWsf5FMWt9YoS/xyTX7XhPyEA08fsT+f4ZH5a0vc5kmftItvP3i/5czm5dEV +95u9NB44zGzcob0OkaTBP9LWRsf/XWuF+6xnL2/T3hLl/4MjQtHek30hT4c6FqbV75MoaFw a3OM+7fIv7FZtS7P5j6zdhc14FcK5ldxUq44wPBtwX/HhqeMTscz39z/vSvc4NRx+4uCxs2+ UWJv4u8fkVn4/xifIGvgsgXhNuWKOnPjfjb+THnf8GV7v9ENk4hP+d1Nh9OVWIozEg21mIuK EwHxEzJZ3QIAAA== X-CMS-MailID: 20220917072357epcas1p1bc8d924080c5dabafee1db779369078d X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072357epcas1p1bc8d924080c5dabafee1db779369078d References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch includes DMA memory modules. It handles DMA buffer using general DMA APIs with reserved area for NPU device. The reserved area is used for IDU binary, statistics and profiling data. Another hwmem modules are provided to handle user requests of memory allocation which are used for model data or inputa data. Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong Signed-off-by: Dongju Chae Signed-off-by: MyungJoo Ham --- drivers/misc/trinity/Makefile | 1 + drivers/misc/trinity/trinity.c | 1 + drivers/misc/trinity/trinity_dma.c | 83 ++++++ drivers/misc/trinity/trinity_dma.h | 87 ++++++ drivers/misc/trinity/trinity_hwmem.c | 380 +++++++++++++++++++++++++++ drivers/misc/trinity/trinity_hwmem.h | 81 ++++++ 6 files changed, 633 insertions(+) create mode 100644 drivers/misc/trinity/trinity_dma.c create mode 100644 drivers/misc/trinity/trinity_dma.h create mode 100644 drivers/misc/trinity/trinity_hwmem.c create mode 100644 drivers/misc/trinity/trinity_hwmem.h diff --git a/drivers/misc/trinity/Makefile b/drivers/misc/trinity/Makefile index a8e5697d6d85..5d2b75112482 100644 --- a/drivers/misc/trinity/Makefile +++ b/drivers/misc/trinity/Makefile @@ -3,5 +3,6 @@ obj-$(CONFIG_TRINITY_VISION2) +=3D trinity_vision2.o =20 trinity-y :=3D trinity.o +trinity-y +=3D trinity_dma.o trinity_hwmem.o =20 trinity_vision2-objs :=3D $(trinity-y) trinity_vision2_drv.o diff --git a/drivers/misc/trinity/trinity.c b/drivers/misc/trinity/trinity.c index 1704eecfc439..3a492eef011f 100644 --- a/drivers/misc/trinity/trinity.c +++ b/drivers/misc/trinity/trinity.c @@ -11,6 +11,7 @@ */ =20 #include +#include =20 #include "trinity_common.h" =20 diff --git a/drivers/misc/trinity/trinity_dma.c b/drivers/misc/trinity/trin= ity_dma.c new file mode 100644 index 000000000000..c93a9187ee9d --- /dev/null +++ b/drivers/misc/trinity/trinity_dma.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** + * DMA memory for Trinity device drivers + * + * Copyright (C) 2022 Samsung Electronics + * Copyright (C) 2022 Jiho Chu + */ + +#include +#include + +#include "trinity_dma.h" + +int trinity_dma_init(struct device *dev) +{ + return of_reserved_mem_device_init(dev); +} + +void trinity_dma_exit(struct device *dev) +{ + of_reserved_mem_device_release(dev); +} + +int trinity_dma_alloc(struct device *dev, size_t size, struct trinity_dma = *dma) +{ + void *addr; + dma_addr_t dma_handle; + size_t aligned_size; + + aligned_size =3D PAGE_ALIGN(size); + addr =3D dma_alloc_noncoherent(dev, aligned_size, &dma_handle, + DMA_BIDIRECTIONAL, GFP_ATOMIC); + + if (!addr) { + dev_err(dev, "Failed to alloc DMA memory"); + return -1; + } + + dma->addr =3D addr; + dma->dma_handle =3D dma_handle; + dma->size =3D aligned_size; + + memset(addr, '\x00', aligned_size); + return 0; +} + +void trinity_dma_free(struct device *dev, struct trinity_dma *dma) +{ + dma_free_noncoherent(dev, dma->size, dma->addr, dma->dma_handle, + DMA_BIDIRECTIONAL); +} + +int trinity_dma_alloc_coherent(struct device *dev, size_t size, struct tri= nity_dma *dma) +{ + void *addr; + dma_addr_t dma_handle; + size_t aligned_size; + + aligned_size =3D PAGE_ALIGN(size); + addr =3D dma_alloc_wc(dev, aligned_size, &dma_handle, GFP_KERNEL); + if (!addr) { + dev_err(dev, "Failed to alloc DMA memory"); + return -1; + } + + dma->addr =3D addr; + dma->dma_handle =3D dma_handle; + dma->size =3D aligned_size; + + memset(addr, '\x00', aligned_size); + return 0; +} + +void trinity_dma_free_coherent(struct device *dev, struct trinity_dma *dma) +{ + dma_free_wc(dev, dma->size, dma->addr, dma->dma_handle); +} + +int trinity_dma_mmap(struct device *dev, struct vm_area_struct *vma, void = *addr, + dma_addr_t dma_handle, size_t size) +{ + return dma_mmap_wc(dev, vma, addr, dma_handle, size); +} diff --git a/drivers/misc/trinity/trinity_dma.h b/drivers/misc/trinity/trin= ity_dma.h new file mode 100644 index 000000000000..a7824196ff15 --- /dev/null +++ b/drivers/misc/trinity/trinity_dma.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * DMA memory for Trinity device drivers + * + * Copyright (C) 2022 Samsung Electronics + * Copyright (C) 2022 Jiho Chu + */ + +#ifndef __DRIVERS_MISC_TRINITY_DMA_H__ +#define __DRIVERS_MISC_TRINITY_DMA_H__ + +/** + * struct trinity_dma - A data structure for DMA information + * + * @addr: A virtual address of memory + * @dma_handle: a handle for DMA + * @size: size of DMA memory + */ +struct trinity_dma { + void *addr; + dma_addr_t dma_handle; + size_t size; +}; + +/** + * trinity_dma_init() - Initialize DMA memory + * @dev: A pointer to the instance of the device + * + * Return: 0 on success. Otherwise, returns negative error. + */ +int trinity_dma_init(struct device *dev); + +/** + * trinity_dma_exit() - Allocate DMA memory + * @dev: A pointer to the instance of the device + * @fd: A file descriptor for a allocated memory + */ +void trinity_dma_exit(struct device *dev); + +/** + * trinity_dma_alloc() - Allocate DMA memory + * @dev: A pointer to the instance of the device + * @size: size of DMA memory + * @dma: A structure of DMA information + * + * Return: 0 on success. Otherwise, returns negative error. + */ +int trinity_dma_alloc(struct device *dev, size_t size, struct trinity_dma = *dma); + +/** + * trinity_dma_free() - Free DMA memory + * @dev: A pointer to the instance of the device + * @dma: A structure of DMA information + */ +void trinity_dma_free(struct device *dev, struct trinity_dma *dma); + +/** + * trinity_dma_alloc_coherent() - Allocate coherent DMA memory + * @dev: A pointer to the instance of the device + * @size: size of DMA memory + * @dma: A structure of DMA information + * + * Return: 0 on success. Otherwise, returns negative error. + */ +int trinity_dma_alloc_coherent(struct device *dev, size_t size, struct tri= nity_dma *dma); + +/** + * trinity_dma_free_coherent() - Free coherent DMA memory + * @dev: A pointer to the instance of the device + * @dma: A structure of DMA information + */ +void trinity_dma_free_coherent(struct device *dev, struct trinity_dma *dma= ); + +/** + * trinity_dma_mmap() - mmap for DMA memory + * @dev: A pointer to the instance of the device + * @vma: A struct for virtual memory area + * @addr: virtual address of memory + * @dma_handle: a handle for dma + * @size: size of mapped DMA memory + * + * Return: 0 on success. Otherwise, returns negative error. + */ +int trinity_dma_mmap(struct device *dev, struct vm_area_struct *vma, void = *addr, + dma_addr_t dma_handle, size_t size); + +#endif /* __DRIVERS_MISC_TRINITY_DMA_H__ */ diff --git a/drivers/misc/trinity/trinity_hwmem.c b/drivers/misc/trinity/tr= inity_hwmem.c new file mode 100644 index 000000000000..afc2cc9193c6 --- /dev/null +++ b/drivers/misc/trinity/trinity_hwmem.c @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** + * DMA memory buffers for Trinity device driver + * + * Copyright (C) 2020-2022 Samsung Electronics + * Copyright (C) 2020 Dongju Chae + * Copyright (C) 2020 Wook Song + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#include +#include +#include +#include +#include + +#include "trinity_dma.h" +#include "trinity_hwmem.h" + +#define dbuf_to_trnt_hwmem(d) ((struct trinity_hwmem *)d->priv) +#define vma_to_trnt_hwmem(v) ((struct trinity_hwmem *)v->vm_private_data) + +/** + * struct trinity_hwmem - A data structure for Trinity DMA buffer manageme= nt + * @dev: A pointer to device which this hwmem belongs to. + * @dbuf: The dma_buf instance. + * @refcnt: Reference counts. + * @direction: A variable indicating the DMA data direction in allocating = this + * dma_buf. + * @attrs: Attributes used in allocating this dma_buf. + * @req_size: The size of the DMA buffer that the user request to allocate. + * @alc_size: The size of the DMA buffer which is actually allocated. + * @addr: The DMA (physical) address of this dma_buf. + * @cookie: The DMA cookies. + */ +struct trinity_hwmem { + struct device *dev; + struct dma_buf *dbuf; + struct kref refcnt; + + enum dma_data_direction direction; + enum trinity_hwmem_type type; + + unsigned long attrs; + size_t req_size; + size_t alc_size; + + bool is_cont; + dma_addr_t addr; + void *cookie; +}; + +static void __trinity_hwmem_free(struct kref *refcnt) +{ + struct trinity_hwmem *mem =3D + container_of(refcnt, struct trinity_hwmem, refcnt); + /** + * when the dmabuf reference counter becomes zero, + * trinity_hwmem_dbuf_ops_release() is triggered. + */ + dma_buf_put(mem->dbuf); +} + +static void __trinity_hwmem_put(struct trinity_hwmem *mem) +{ + kref_put(&mem->refcnt, __trinity_hwmem_free); +} + +static void __trinity_hwmem_put_dmabuf(struct dma_buf *dbuf) +{ + __trinity_hwmem_put(dbuf_to_trnt_hwmem(dbuf)); +} + +static struct trinity_hwmem *__trinity_hwmem_get(struct trinity_hwmem *mem) +{ + kref_get(&mem->refcnt); + + return mem; +} + +static void trinity_hwmem_dbuf_ops_detach(struct dma_buf *dbuf, + struct dma_buf_attachment *attachment) +{ + struct trinity_hwmem *mem =3D dbuf_to_trnt_hwmem(dbuf); + + /* Decrease ref count of the backing storage */ + __trinity_hwmem_put(mem); +} + +static int trinity_hwmem_dbuf_ops_attach(struct dma_buf *dbuf, + struct dma_buf_attachment *attachment) +{ + struct trinity_hwmem *mem =3D dbuf_to_trnt_hwmem(dbuf); + + /* Increase ref count of the backing storage */ + mem =3D __trinity_hwmem_get(mem); + attachment->priv =3D mem; + + return 0; +} + +static struct sg_table * +trinity_hwmem_dbuf_ops_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction dir) +{ + return NULL; +} + +static void +trinity_hwmem_dbuf_ops_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *sgt, + enum dma_data_direction dir) +{ +} + +static void trinity_hwmem_vm_ops_open(struct vm_area_struct *vma) +{ + struct trinity_hwmem *mem =3D vma_to_trnt_hwmem(vma); + + __trinity_hwmem_get(mem); +} + +static void trinity_hwmem_vm_ops_close(struct vm_area_struct *vma) +{ + struct trinity_hwmem *mem =3D vma_to_trnt_hwmem(vma); + + __trinity_hwmem_put(mem); +} + +static const struct vm_operations_struct trinity_hwmem_vm_ops =3D { + .open =3D trinity_hwmem_vm_ops_open, + .close =3D trinity_hwmem_vm_ops_close, +}; + +static int32_t trinity_hwmem_dbuf_ops_mmap(struct dma_buf *dbuf, + struct vm_area_struct *vma) +{ + struct trinity_hwmem *mem; + int32_t ret; + + if (!dbuf) + return -EINVAL; + + mem =3D dbuf_to_trnt_hwmem(dbuf); + if (!mem) + return -EINVAL; + + vma->vm_pgoff =3D 0; + + ret =3D trinity_dma_mmap(mem->dev, vma, mem->cookie, mem->addr, mem->alc_= size); + if (ret) + return ret; + + vma->vm_flags |=3D VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_private_data =3D mem; + vma->vm_ops =3D &trinity_hwmem_vm_ops; + + vma->vm_ops->open(vma); + + return 0; +} + +static void trinity_hwmem_dbuf_ops_release(struct dma_buf *dbuf) +{ + struct trinity_dma dma_mem; + struct trinity_hwmem *mem =3D dbuf_to_trnt_hwmem(dbuf); + + dma_mem.addr =3D mem->cookie; + dma_mem.dma_handle =3D mem->addr; + dma_mem.size =3D mem->alc_size; + + if (mem->type =3D=3D TRINITY_HWMEM_DMA_CONT) + trinity_dma_free_coherent(mem->dev, &dma_mem); + else + trinity_dma_free(mem->dev, &dma_mem); + + put_device(mem->dev); + + mem->dbuf->priv =3D NULL; + + kfree(mem); +} + +static int trinity_hwmem_dbuf_ops_vmap(struct dma_buf *dbuf, + struct iosys_map *map) +{ + struct trinity_hwmem *mem; + + if (!dbuf) + return -EINVAL; + + mem =3D dbuf_to_trnt_hwmem(dbuf); + if (!mem) + return -ENOENT; + + map->vaddr =3D mem->cookie; + + return 0; +} + +static struct dma_buf_ops trinity_hwmem_dbuf_ops =3D { + .vmap =3D trinity_hwmem_dbuf_ops_vmap, + .attach =3D trinity_hwmem_dbuf_ops_attach, + .detach =3D trinity_hwmem_dbuf_ops_detach, + .map_dma_buf =3D trinity_hwmem_dbuf_ops_map_dma_buf, + .unmap_dma_buf =3D trinity_hwmem_dbuf_ops_unmap_dma_buf, + .release =3D trinity_hwmem_dbuf_ops_release, + .mmap =3D trinity_hwmem_dbuf_ops_mmap, +}; + +static void *__trinity_hwmem_alloc(struct device *dev, const size_t size, + const enum dma_data_direction dir, + const enum trinity_hwmem_type type) +{ + size_t aligned_size =3D ALIGN(size, PAGE_SIZE); + struct trinity_hwmem *mem; + struct trinity_dma dma_mem; + int ret; + + if (WARN_ON(!dev)) + return ERR_PTR(-EINVAL); + + mem =3D kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) + return ERR_PTR(-ENOMEM); + + mem->dev =3D get_device(dev); + mem->req_size =3D size; + mem->alc_size =3D aligned_size; + mem->direction =3D dir; + mem->type =3D TRINITY_HWMEM_DMA_IOMMU; + mem->is_cont =3D (type =3D=3D TRINITY_HWMEM_DMA_CONT); + + mem->attrs |=3D DMA_ATTR_WRITE_COMBINE; + mem->attrs |=3D DMA_ATTR_SKIP_CPU_SYNC; + + if (mem->is_cont) + ret =3D trinity_dma_alloc_coherent(dev, aligned_size, &dma_mem); + else + ret =3D trinity_dma_alloc(dev, aligned_size, &dma_mem); + + if (ret < 0) { + dev_err(mem->dev, + "Unable alloc memory: %d\n", ret); + kfree(mem); + return ERR_PTR(-ENOMEM); + } + + mem->addr =3D dma_mem.dma_handle; + mem->cookie =3D dma_mem.addr; + + kref_init(&mem->refcnt); + + return mem; +} + +static struct dma_buf *__trinity_hwmem_get_dmabuf(struct trinity_hwmem *me= m, + unsigned long flags) +{ + DEFINE_DMA_BUF_EXPORT_INFO(einfo); + struct dma_buf *dbuf; + + einfo.ops =3D &trinity_hwmem_dbuf_ops; + einfo.size =3D mem->alc_size; + einfo.flags =3D flags; + einfo.priv =3D (void *)mem; + + dbuf =3D dma_buf_export(&einfo); + if (IS_ERR(dbuf)) + return dbuf; + + /* Increase ref count of the backing storage */ + dbuf->priv =3D __trinity_hwmem_get(mem); + mem->dbuf =3D dbuf; + + return dbuf; +} + +int32_t trinity_hwmem_alloc(struct device *dev, const size_t size, + enum trinity_hwmem_type type) +{ + struct trinity_hwmem *mem; + struct dma_buf *dbuf; + int32_t ret; + + mem =3D __trinity_hwmem_alloc(dev, size, DMA_BIDIRECTIONAL, type); + if (IS_ERR(mem)) + return PTR_ERR(mem); + + dbuf =3D __trinity_hwmem_get_dmabuf(mem, O_CLOEXEC | O_RDWR); + if (IS_ERR(dbuf)) { + ret =3D PTR_ERR(dbuf); + goto err_put_mem; + } + + ret =3D dma_buf_fd(dbuf, O_CLOEXEC); + if (ret < 0) + goto err_put_mem; + + return ret; + +err_put_mem: + __trinity_hwmem_put(mem); + + return ret; +} + +int32_t trinity_hwmem_free(struct device *dev, const int32_t fd) +{ + struct dma_buf *dbuf; + struct trinity_hwmem *mem; + + dbuf =3D dma_buf_get(fd); + if (IS_ERR(dbuf)) { + dev_err(dev, + "failed to free the dma_buf structure with %ld\n", + PTR_ERR(dbuf)); + + return PTR_ERR(dbuf); + } + + mem =3D dbuf_to_trnt_hwmem(dbuf); + __trinity_hwmem_put_dmabuf(dbuf); + __trinity_hwmem_put(mem); + + dma_buf_put(dbuf); + return 0; +} + +int32_t +trinity_hwmem_import_dmabuf_begin(struct device *dev, const int32_t dbuf_f= d, + struct trinity_hwmem_import *import_info) +{ + struct dma_buf_attachment *attachment; + struct dma_buf *buf; + struct trinity_hwmem *mem; + struct iosys_map map; + int32_t ret; + + if (!import_info) + return -EINVAL; + + buf =3D dma_buf_get(dbuf_fd); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + attachment =3D dma_buf_attach(buf, dev); + if (IS_ERR(attachment)) { + ret =3D PTR_ERR(attachment); + goto err_dbuf_put; + } + + mem =3D attachment->priv; + import_info->dma_addr =3D mem->addr; + ret =3D dma_buf_vmap(buf, &map); + if (ret) + goto err_dbuf_put; + + import_info->addr =3D map.vaddr; + import_info->attachment =3D attachment; + import_info->buf =3D buf; + + return 0; + +err_dbuf_put: + dma_buf_put(buf); + + return ret; +} + +void trinity_hwmem_import_dmabuf_end(struct trinity_hwmem_import *import_i= nfo) +{ + if (!import_info || !import_info->buf) + return; + dma_buf_vunmap(import_info->buf, import_info->addr); + dma_buf_detach(import_info->buf, import_info->attachment); + dma_buf_put(import_info->buf); +} diff --git a/drivers/misc/trinity/trinity_hwmem.h b/drivers/misc/trinity/tr= inity_hwmem.h new file mode 100644 index 000000000000..b75f3f14c537 --- /dev/null +++ b/drivers/misc/trinity/trinity_hwmem.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * DMA memory buffers for Trinity device driver + * + * Copyright (C) 2020-2022 Samsung Electronics + * Copyright (C) 2020 Dongju Chae + * Copyright (C) 2020 Wook Song + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#ifndef __DRIVERS_MISC_TRINITY_HWMEM_H__ +#define __DRIVERS_MISC_TRINITY_HWMEM_H__ + +#include +#include +#include +#include + +/** + * struct trinity_hwmem_import - A data structure to maintain imported hwm= em + * (that is Trinity DMA buffer). + * @dma_addr: The physical DMA address of this DMA buffer. + * @addr: A virtual address of this DMA buffer. + * @attachment: A pointer to &struct dma_buf_attachment. + * @buf: &struct dma_buf that this hwmem wrapped. + */ +struct trinity_hwmem_import { + dma_addr_t dma_addr; + void *addr; + struct dma_buf_attachment *attachment; + struct dma_buf *buf; +}; + +/** + * trinity_hwmem_import_dmabuf_begin() - Defines the beginning of a sectio= n to + * import a given DMA buffer file descriptor. + * @dev: A pointer to the instance of the device to be attached the DMA bu= ffer + * @dbuf_fd: The file descriptor of the DMA buffer to be imported. + * @import_info: If importing is successful, information such as the DMA + * address, the virtual address which is mapped to the DMA address, + * &struct dma_buf_attachment, a scatter-gather table, and &struct + * dma_buf corresponding to the file descriptor will be passed + * using this parameter. + * + * Return: 0 on success. Otherwise, returns negative error. + */ +int32_t +trinity_hwmem_import_dmabuf_begin(struct device *dev, const int32_t dbuf_f= d, + struct trinity_hwmem_import *import_info); + +/** + * trinity_hwmem_import_dmabuf_end() - Defines the ending of the section r= elated + * to the given pointer to &strut trinity_hwmem_import. + * @import_info: Importing information related to the section to be ended. + */ +void trinity_hwmem_import_dmabuf_end(struct trinity_hwmem_import *import_i= nfo); + +/** + * trinity_hwmem_alloc() - Allocate Hardware memory according to type + * @dev: A pointer to the instance of the device to be attached the DMA bu= ffer + * @size: Requested memory size + * @type: Requested memory type. It will try to allocate from reserved mem= ory first + * + * Return: a file descriptor for the dma buffer on success. + * Otherwise, returns negative error. + */ +int32_t trinity_hwmem_alloc(struct device *dev, const size_t size, + enum trinity_hwmem_type type); + +/** + * trinity_hwmem_free() - Free Hardware memory + * @dev: A pointer to the instance of the device to be attached the DMA bu= ffer + * @fd: A file descriptor for a allocated memory + * + * Return: 0 on success. Otherwise, returns negative error. + */ +int32_t trinity_hwmem_free(struct device *dev, const int32_t fd); + +#endif /* __DRIVERS_MISC_TRINITY_HWMEM_H__ */ --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 921C1C6FA86 for ; Sat, 17 Sep 2022 07:24:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229614AbiIQHYM (ORCPT ); Sat, 17 Sep 2022 03:24:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51874 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229379AbiIQHYI (ORCPT ); Sat, 17 Sep 2022 03:24:08 -0400 Received: from mailout2.samsung.com (mailout2.samsung.com [203.254.224.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 76F3813CDD for ; Sat, 17 Sep 2022 00:24:04 -0700 (PDT) Received: from epcas1p1.samsung.com (unknown [182.195.41.45]) by mailout2.samsung.com (KnoxPortal) with ESMTP id 20220917072359epoutp0253500df326610f1dad80e209365b5005~VlPo8S7ja3089630896epoutp02e for ; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.samsung.com 20220917072359epoutp0253500df326610f1dad80e209365b5005~VlPo8S7ja3089630896epoutp02e DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399439; bh=7yWBJ/9IHKdlYcm4v5OsHGyN/js81fAPMnvaCu5X7H4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ClbsdrFNazPK5hGeUh02KtQCefXrLC61v9mk/EdYs9ECV+7j8SRgKfiHxcaLoECFz qTrQF9MFX7Oo54ddZ/zyVUYpOc8DUcBtsKRWgUUy6b0G/lkAR53JEeYE2EH8Tp4SJu MHU960742dds+LEvGIYqw/NrqgQqwPG+yVMD0P/g= Received: from epsnrtp3.localdomain (unknown [182.195.42.164]) by epcas1p4.samsung.com (KnoxPortal) with ESMTP id 20220917072359epcas1p49b7d9928999f60f8df79eebae569038e~VlPoQGD5y1033410334epcas1p4i; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) Received: from epsmges1p3.samsung.com (unknown [182.195.36.145]) by epsnrtp3.localdomain (Postfix) with ESMTP id 4MV2Vk1T4lz4x9Pt; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epcas1p4.samsung.com ( [182.195.41.48]) by epsmges1p3.samsung.com (Symantec Messaging Gateway) with SMTP id 54.1D.57013.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas1p4.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epcas1p4a5b3939adbe5e24c11bd2541f76f23f6~VlPmuRd1F2768227682epcas1p40; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220917072357epsmtrp22b139e55cce4ed635b250ab29f412aeb~VlPmteaMQ1654916549epsmtrp2u; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) X-AuditID: b6c32a37-ff5fb7000001deb5-18-6325760ea1e0 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id B1.45.14392.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epsmtip23cc9d7a40f7046462ccc1658e218e819~VlPmeTcBh3200932009epsmtip2W; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 03/13] trinity: Add IDU feature Date: Sat, 17 Sep 2022 16:23:46 +0900 Message-Id: <20220917072356.2255620-4-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFuplk+LIzCtJLcpLzFFi42LZdljTQJevTDXZ4MI0Vou/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtKtsmIzUxJbVIITUvOT8lMy/dVsk7ON453tTMwFDX0NLCXEkh LzE31VbJxSdA1y0zB+gqJYWyxJxSoFBAYnGxkr6dTVF+aUmqQkZ+cYmtUmpBSk6BaYFecWJu cWleul5eaomVoYGBkSlQYUJ2xu7ebraC6V2MFbv7e5gbGK8VdDFycEgImEgs/1rUxcjFISSw g1FixesTbBDOJ0aJHRNb2CGcb4wSq6Z9A8pwgnXsuD+PBSKxl1GiddIZJgjnM6PEkU/XGUGq 2ARUJWbOWMMOYosIlEs0bzwBZjML5Eg8udPEDGILCxhJbJ/eADaVBah+/sejTCA38QpYS3xY CRbmFLCRuLmpiQXE5hUQlDg58wkLxBh5ieats5khDvrILnH3fTGE7SIxZ9I/JghbWOLV8S3s ELaUxOd3e6EeyJaY0rGIBcIukDj3fCszJCiMJS6uSAExmQU0Jdbv0oeoUJTY+XsuI8RWPol3 X3tYIap5JTrahCBKlCSW/DkMtUhCYuqMb1AHeEhcv7gQGoT9jBJ7u7ewTGCUn4XkmVlInpmF sHkBI/MqRrHUguLc9NRiwwJjeJwm5+duYgSnSy3zHYzT3n7QO8TIxMF4iFGCg1lJhFfVUyVZ iDclsbIqtSg/vqg0J7X4EKMpMHQnMkuJJucDE3ZeSbyhiaWBiZmRsYmFoZmhkjivnjZjspBA emJJanZqakFqEUwfEwenVAPTSZc/Nmuf19+b95fFffYPNsuOL38T7CWqZ9+awMP5cMvOFd9/ G6n8MtVY+m/O+iyDfZ2qHHmX2EPYLnJ8OrGwOKss+CmPaJ3a2p1Ve/YvWJ532Ca27M/77jsh keZ1Gis0e3xe50QeOh50bbmAzfq6rXq5Hr8YDurdqHpXtLNCSsZbwzLys3yykKe5sO9663dT yjtrzROfdP0qkn/p9/rfbuecI/MEGkWuTq6TMuuW3CXmofJhjn4Mk8LUnCkf52WdsDm25/8c +RAj+Q2SWe912lt5Tf60C3lfvGk88Zogr3lWRn6Oqsc1pb73U88m6i7YfzuTK4Vh7b6Nu5bo /Mmcvnzr7LsMpcE3Z4jwa01QYinOSDTUYi4qTgQAPpTeliAEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrJLMWRmVeSWpSXmKPExsWy7bCSvC5vmWqywacmcYu/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtissmJTUnsyy1SN8ugStjd283W8H0LsaK3f09zA2M1wq6GDk5 JARMJHbcn8fSxcjFISSwm1Fiw4RLzBAJCYlN95YD2RxAtrDE4cPFEDUfGSUOTb/KBFLDJqAq MXPGGnYQW0SgVuLg0flgvcwCBRKzn85kAbGFBYwktk9vYAOxWYDq5388ygQyk1fAWuLDSrAw p4CNxM1NTWDlQkDh2dPngo3nFRCUODnzCQvESHmJ5q2zmScw8s9CkpqFJLWAkWkVo2RqQXFu em6xYYFhXmq5XnFibnFpXrpecn7uJkZwaGtp7mDcvuqD3iFGJg7GQ4wSHMxKIryqnirJQrwp iZVVqUX58UWlOanFhxilOViUxHkvdJ2MFxJITyxJzU5NLUgtgskycXBKNTCFLJJOSlLt+dN4 K6H0jbBATr3zfD0nhblveu/vUNt5snvRq4hdK5s+yloGM0gpXN7LLyxQEd1/qndHf3fs7Qdn WdedPKr/Simr61ToCpP1PjxT0haL8rUE7kvtmvcpXGvfdwlZHRmD/j+Ch+elrDB8WJT3t7zq p3TFvcXbA8zWGe6oqlq6LDRpVoD4y6Ct3ZF1HTNrU0W5eJdMtM1lXCI3feNsRWvOF9Hitb80 gmdUe77juFoXG6Kc3f7N+r/ZnVCeuotTrFbV7HuWtNRCImOV3u5/LXFnJ99+Fpi6S+DktE5x ZY3rFaYKTb8i1QOYp3/RCS/4rNYi4t32nJN3t49Qal/b3jv1fwXT/GIfK7EUZyQaajEXFScC AMrW++rcAgAA X-CMS-MailID: 20220917072357epcas1p4a5b3939adbe5e24c11bd2541f76f23f6 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072357epcas1p4a5b3939adbe5e24c11bd2541f76f23f6 References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch implements IDU set/unset works. Samsung NPU loads Instruction Decoder Unit (IDU) program, which can decode binary code generated by NPU compiler. The IDU program is loaded with ioctl mannager, and the NPU starts to execute the codes of compiled decoder binary. Then, all operations of the NPU is working with the decoder program which can fetch and execute predefined virtual ISA. Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong Signed-off-by: Dongju Chae Signed-off-by: MyungJoo Ham --- drivers/misc/trinity/trinity.c | 44 ++ drivers/misc/trinity/trinity_vision2_drv.c | 466 +++++++++++++++++++++ 2 files changed, 510 insertions(+) diff --git a/drivers/misc/trinity/trinity.c b/drivers/misc/trinity/trinity.c index 3a492eef011f..3e8157dd4664 100644 --- a/drivers/misc/trinity/trinity.c +++ b/drivers/misc/trinity/trinity.c @@ -36,6 +36,50 @@ int trinity_release(struct inode *inode, struct file *fi= le) return 0; } =20 +/** + * trinity_set_pause() - Pause trinity device + * + * @drv: an instance of trinity driver + * + * Returns 0 on success. Otherwise, returns negative error. + */ +int trinity_set_pause(struct trinity_driver *drv) +{ + drv->desc->set_state(drv, TRINITY_STATE_PAUSE); + + return 0; +} + +/** + * trinity_wait_ready() - Wait until trinity is ready state + * + * @drv: an instance of trinity driver + * + * Returns 0 on success. Otherwise, returns negative error. + */ +int trinity_wait_ready(struct trinity_driver *drv) +{ + const unsigned long time_out =3D HZ / 100UL; /* 1/100 seconds*/ + const unsigned int max_retry =3D 10; + unsigned int retry =3D 0; + wait_queue_head_t wq; + + drv->desc->set_state(drv, TRINITY_STATE_READY); + + init_waitqueue_head(&wq); + /* try to ensure that NPU is in the ready state */ + while (wait_event_timeout( + wq, drv->desc->get_state(drv) =3D=3D TRINITY_STATE_READY, + time_out) =3D=3D 0) { + /* regarded as failure */ + if (retry =3D=3D max_retry) + return -ETIMEDOUT; + retry++; + } + + return 0; +} + /** * trinity_open() - A common callback for open() in file_operations for a = Trinity * device node. If device-specific open() is required, this diff --git a/drivers/misc/trinity/trinity_vision2_drv.c b/drivers/misc/trin= ity/trinity_vision2_drv.c index bc43cafa39fb..4bfc7f97769c 100644 --- a/drivers/misc/trinity/trinity_vision2_drv.c +++ b/drivers/misc/trinity/trinity_vision2_drv.c @@ -88,6 +88,7 @@ struct triv2_cmd_info { =20 struct triv2_req *reqs[TRIV2_MAX_CMDSLOTS]; struct triv2_cmd cur_cmd; + struct trinity_dma buf; }; =20 struct triv2_hashed_cmd_info { @@ -107,6 +108,8 @@ struct triv2_kernel_req { struct triv2_req { struct trinity_req req; =20 + struct trinity_hwmem_import *seg_import; + int cmd_slot; =20 /** kernel requets */ @@ -120,13 +123,102 @@ struct triv2_req { uint32_t total_segment_size; }; =20 +struct triv2_idu { + phys_addr_t *addrs; + size_t addr_num; + struct trinity_hwmem_import data; + struct trinity_hwmem_import code; + dma_addr_t dspm; +}; + struct triv2_pdata { struct trinity_driver *drv; =20 + /* idu info */ + struct triv2_idu idu_cp; + struct triv2_idu idu_dsp; + uint32_t idu_version; + /* command info */ struct triv2_cmd_info cmd_info; + + /* back buffer for context switching */ + struct trinity_dma back_buf; }; =20 +static void triv2_idu_setup(struct trinity_driver *drv); +static void triv2_idu_unset(struct trinity_driver *drv); +static int32_t triv2_idu_set(struct trinity_driver *drv, + struct trinity_ioctl_idu *config); + +/** + * triv2_get_state() - Get state (TRINITY_STATE_READY/TRINITY_STATE_PAUSE)= of the device. + * @returns (enum triv2_state) TRINITY_STATE_READY (i.e., 1) or TRINITY_ST= ATE_PAUSE (i.e., 0 ) + * according to the state of the device + */ +int32_t triv2_get_state(const struct trinity_driver *drv) +{ + if (ioread32(drv->mmreg_vaddr[0] + OFFSET_NPU_CMD_READY) =3D=3D 1) + return TRINITY_STATE_READY; + + return TRINITY_STATE_PAUSE; +} + +/** + * triv2_set_state() - Set state of the device to TRINITY_STATE_READY (1) = or TRINITY_STATE_PAUSE (0) + */ +static void triv2_set_state(const struct trinity_driver *drv, + enum trinity_state state) +{ + void __iomem *addr; + + switch (state) { + case TRINITY_STATE_PAUSE: + /* CP */ + addr =3D trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_CP_PROC_SET); + trinity_set_bit(BIT_SET_PAUSE, addr); + iowrite32(0, addr); + + /* DSP */ + addr =3D trinity_get_iomem_addr(drv->mmreg_vaddr[1], + OFFSET_DSP_PROC_SET); + trinity_set_bit(BIT_SET_PAUSE, addr); + iowrite32(0, addr); + + break; + case TRINITY_STATE_READY: + /* CP */ + addr =3D trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_CP_PROC_CLR); + trinity_set_bit(BIT_CLR_PAUSE, addr); + iowrite32(0, addr); + + /* DSP */ + addr =3D trinity_get_iomem_addr(drv->mmreg_vaddr[1], + OFFSET_DSP_PROC_CLR); + trinity_set_bit(BIT_CLR_PAUSE, addr); + iowrite32(0, addr); + + /* Performance Counter */ + addr =3D trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_CP_CNT_CFG); + trinity_set_bit(BIT_CNT_IST_EN | BIT_CNT_FR_EN, addr); + break; + default: + dev_err(drv_to_dev_ptr(drv), + "failed to set state of the NPU state: %d", state); + } +} + +static void triv2_wakeup_cp(const struct trinity_driver *drv) +{ + void *addr =3D + trinity_get_iomem_addr(drv->mmreg_vaddr[0], OFFSET_CP_PROC_SET); + + trinity_set_bit(BIT_SET_SEND_EVT1, addr); +} + static void triv2_reset(struct trinity_driver *drv) { struct triv2_pdata *pdata =3D drv->pdata; @@ -136,6 +228,9 @@ static void triv2_reset(struct trinity_driver *drv) triv2_cancel_reqs(pdata->drv); msleep(100); =20 + triv2_setup_buffers(drv); + triv2_idu_unset(drv); + mutex_unlock(&pdata->drv->lock); } =20 @@ -159,15 +254,254 @@ static int triv2_release(struct inode *inode, struct= file *f) =20 static const struct file_operations triv2_fops =3D { .owner =3D THIS_MODULE, + .unlocked_ioctl =3D triv2_ioctl, .open =3D triv2_open, .release =3D triv2_release, .llseek =3D noop_llseek, }; =20 +static void triv2_setup_cp(struct trinity_driver *drv, phys_addr_t paddr) +{ + iowrite32(TRIV2_IDU_ADDR(paddr) >> 4, + drv->mmreg_vaddr[0] + OFFSET_CP_IMIF_BASE); + iowrite32(TRIV2_IDU_ADDR(drv->mmreg_paddr[2]), + drv->mmreg_vaddr[0] + OFFSET_NPU_CBOX_BASE); +} + +static void triv2_setup_dsp(struct trinity_driver *drv, phys_addr_t paddr) +{ + iowrite32(TRIV2_IDU_ADDR(paddr) >> 4, + drv->mmreg_vaddr[1] + OFFSET_DSP_IMIF_BASE); +} + +static void triv2_idu_free(struct device *dev, + struct trinity_hwmem_import *import) +{ + if (!import->addr) + return; + + trinity_hwmem_import_dmabuf_end(import); + import->addr =3D NULL; +} + +static int triv2_idu_version(struct trinity_driver *drv, uint32_t *major, + uint32_t *minor, uint32_t *extra) +{ + struct triv2_pdata *pdata; + uint32_t val; + + if (!drv || !major || !minor || !extra) + return -EINVAL; + + pdata =3D TRIV2_DRV_GET_PDATA(drv); + val =3D pdata->idu_version; + if (val !=3D 0) { + *major =3D (val & TRIV2_IDU_MASK_MAJOR) >> TRIV2_IDU_SHIFT_MAJOR; + *minor =3D (val & TRIV2_IDU_MASK_MINOR) >> TRIV2_IDU_SHIFT_MINOR; + *extra =3D val & TRIV2_IDU_MASK_EXTRA; + } else { + return -ENOENT; + } + + return 0; +} + +static void triv2_idu_check(struct trinity_driver *drv) +{ + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + struct device *dev =3D drv_to_dev_ptr(drv); + uint32_t major, minor, extra; + + if (trinity_wait_ready(drv) !=3D 0) { + dev_warn(dev, "Unable to load IDU properly"); + return; + } + + pdata->idu_version =3D + ioread32(drv->mmreg_vaddr[0] + OFFSET_NPU_IDU_VERSION); + if (triv2_idu_version(drv, &major, &minor, &extra) =3D=3D 0) + dev_info(dev, + "Instruction Decoder Unit (IDU) v%u.%u.%u detected", + major, minor, extra); + + /* paused until request created */ + triv2_set_state(drv, TRINITY_STATE_PAUSE); +} + +static void triv2_idu_fill_zero(struct trinity_driver *drv, phys_addr_t pa= ddr, + size_t size) +{ + void *__iomem vaddr; + + vaddr =3D memremap(paddr, PAGE_ALIGN(size), MEMREMAP_WT); + if (vaddr =3D=3D NULL) { + dev_err(drv_to_dev_ptr(drv), "Failed to do ioremap() for 0x%lx", + (unsigned long)paddr); + return; + } + memset(vaddr, 0, size); + + memunmap(vaddr); +} + +static void triv2_idu_fill_data(struct trinity_driver *drv, phys_addr_t pa= ddr, + struct trinity_hwmem_import *data) +{ + void *__iomem vaddr; + + vaddr =3D memremap(paddr, PAGE_ALIGN(data->buf->size), MEMREMAP_WT); + if (vaddr =3D=3D NULL) { + dev_err(drv_to_dev_ptr(drv), "Failed to do ioremap() for 0x%lx", + (unsigned long)paddr); + return; + } + memcpy(vaddr, data->addr, data->buf->size); + + memunmap(vaddr); +} + +static void triv2_idu_setup(struct trinity_driver *drv) +{ + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + struct triv2_idu *idu_cp; + struct triv2_idu *idu_dsp; + + idu_cp =3D &pdata->idu_cp; + idu_dsp =3D &pdata->idu_dsp; + + triv2_setup_cp(drv, idu_cp->addrs[TRIV2_IDU_CODEIDX]); + + if (idu_dsp->addrs) + triv2_setup_dsp(drv, idu_dsp->addrs[TRIV2_IDU_CODEIDX]); + + triv2_idu_check(drv); + + drv->idu_set =3D true; +} + +static void triv2_idu_unset(struct trinity_driver *drv) +{ + struct device *dev =3D drv_to_dev_ptr(drv); + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + + triv2_idu_free(dev, &pdata->idu_cp.data); + triv2_idu_free(dev, &pdata->idu_dsp.data); + + triv2_idu_free(dev, &pdata->idu_cp.code); + triv2_idu_free(dev, &pdata->idu_dsp.code); + + drv->idu_set =3D false; +} + +static int32_t triv2_idu_set(struct trinity_driver *drv, + struct trinity_ioctl_idu *config) +{ + struct device *dev; + struct triv2_pdata *pdata; + struct iommu_domain *domain; + struct triv2_idu *idu_cp; + struct triv2_idu *idu_dsp; + int ret; + + if (!drv | !config) + return -EINVAL; + + dev =3D drv_to_dev_ptr(drv); + pdata =3D TRIV2_DRV_GET_PDATA(drv); + domain =3D iommu_get_domain_for_dev(dev); + + idu_cp =3D &pdata->idu_cp; + idu_dsp =3D &pdata->idu_dsp; + + triv2_idu_unset(drv); + + ret =3D trinity_hwmem_import_dmabuf_begin(dev, config->dbuf_cp_data, + &idu_cp->data); + if (ret < 0) + return -EINVAL; + ret =3D trinity_hwmem_import_dmabuf_begin(dev, config->dbuf_cp_code, + &idu_cp->code); + if (ret < 0) + return -EINVAL; + ret =3D trinity_hwmem_import_dmabuf_begin(dev, config->dbuf_dsp_data, + &idu_dsp->data); + if (ret < 0) + return -EINVAL; + ret =3D trinity_hwmem_import_dmabuf_begin(dev, config->dbuf_dsp_code, + &idu_dsp->code); + if (ret < 0) + return -EINVAL; + + idu_cp->addrs[TRIV2_IDU_CODEIDX] =3D + trinity_get_paddr(domain, idu_cp->code.dma_addr); + triv2_idu_fill_zero(drv, idu_cp->addrs[TRIV2_IDU_ZEROIDX], + TRIV2_IDU_CP_DSPM_SIZE); + triv2_idu_fill_data(drv, idu_cp->addrs[TRIV2_IDU_DATAIDX], + &idu_cp->data); + + /* DSP is optional */ + if (idu_dsp->addrs) { + idu_dsp->addrs[TRIV2_IDU_CODEIDX] =3D + trinity_get_paddr(domain, idu_dsp->code.dma_addr); + triv2_idu_fill_zero(drv, idu_dsp->addrs[TRIV2_IDU_ZEROIDX], + drv->dspm + TRIV2_DSP_DSPM_OFFSET); + triv2_idu_fill_data(drv, idu_dsp->addrs[TRIV2_IDU_DATAIDX], + &idu_dsp->data); + } + + triv2_idu_setup(drv); + + /* iommu mapping for dspm segment */ + if (drv->dspm > 0) { + phys_addr_t paddr; + dma_addr_t daddr; + + domain =3D iommu_get_domain_for_dev(dev); + if (!domain) + return 0; + + paddr =3D idu_dsp->addrs[0] + TRIV2_DSP_DSPM_OFFSET; + daddr =3D dma_map_resource(dev, paddr, drv->dspm, + DMA_BIDIRECTIONAL, 0); + idu_dsp->dspm =3D daddr; + } + + return 0; +} + +static void triv2_setup_buffers(struct trinity_driver *drv) +{ + struct device *dev =3D drv_to_dev_ptr(drv); + struct iommu_domain *domain; + struct trinity_dma *cmd_buf; + struct trinity_dma *back_buf; + phys_addr_t paddr; + + domain =3D iommu_get_domain_for_dev(dev); + cmd_buf =3D TRIV2_DRV_GET_CMD_BUF(drv); + back_buf =3D TRIV2_DRV_GET_BACK_BUF(drv); + + /* command */ + paddr =3D trinity_get_paddr(domain, cmd_buf->dma_handle); + iowrite32(TRIV2_IDU_ADDR(paddr), + trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_CMD_BASE)); + /* backup */ + iowrite32(TRIV2_IDU_ADDR(back_buf->dma_handle), + trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_BACK_ADDR)); + iowrite32(back_buf->size, trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_BACK_SIZE)); +} + static int32_t triv2_init_pdata(struct trinity_driver *drv) { + struct device *dev =3D drv_to_dev_ptr(drv); struct triv2_pdata *pdata; struct triv2_cmd_info *cmd_info; + struct trinity_dma *cmd_buf; + struct trinity_dma *back_buf; + int status; =20 pdata =3D kzalloc(sizeof(struct triv2_pdata), GFP_KERNEL); if (!pdata) @@ -177,11 +511,105 @@ static int32_t triv2_init_pdata(struct trinity_drive= r *drv) pdata->drv =3D drv; =20 cmd_info =3D TRIV2_DRV_GET_CMD_INFO(drv); + cmd_buf =3D TRIV2_DRV_GET_CMD_BUF(drv); + back_buf =3D TRIV2_DRV_GET_BACK_BUF(drv); =20 spin_lock_init(&cmd_info->lock); /* init cmd bitmap */ bitmap_zero(cmd_info->bitmap, TRIV2_MAX_CMDSLOTS); =20 + /* alloc command buffer */ + status =3D trinity_dma_alloc(dev, PAGE_SIZE, cmd_buf); + if (status < 0) { + dev_err(dev, "Couldn't allocate memory for cmd slots"); + goto free_pdata; + } + /* ensure cmd buffer is null-initialized, which is visible in NPU as well= */ + memset(cmd_buf->addr, '\x00', PAGE_SIZE); + + /* alloc backup buffer for preemption (GBUF + DSPM) */ + status =3D trinity_dma_alloc(dev, TRIV2_DLA_GBUFFER_SIZE + drv->dspm, bac= k_buf); + if (status < 0) { + dev_err(dev, + "Couldn't allocate memory for context backup buffer"); + trinity_dma_free(dev, cmd_buf); + goto free_pdata; + } + + triv2_setup_buffers(drv); + + return 0; + +free_pdata: + kfree(drv->pdata); + drv->pdata =3D NULL; + + return status; +} + +static int32_t parse_idu_property(struct device *dev, + const struct device_node *np, + const char *prop_name, struct triv2_idu *idu) +{ + struct property *prop; + u64 values[TRIV2_IDU_MAX_SECTORS]; + size_t size; + int i, err; + + memset(idu, '\x00', sizeof(*idu)); + + prop =3D of_find_property(np, prop_name, NULL); + if (!prop) + return -EINVAL; + + size =3D prop->length / sizeof(u64); + if (size !=3D TRIV2_IDU_MAX_SECTORS) { + dev_err(dev, "idu requires %d values", TRIV2_IDU_MAX_SECTORS); + return -EINVAL; + } + + idu->addr_num =3D size; + idu->addrs =3D devm_kcalloc(dev, size, sizeof(*idu->addrs), GFP_KERNEL); + if (!idu->addrs) { + dev_err(dev, "failed to allocate memory for idu values"); + return -ENOMEM; + } + + err =3D of_property_read_u64_array(np, prop_name, values, size); + if (err < 0) { + dev_err(dev, "failed to read property u64 array: %d", err); + return err; + } + + for (i =3D 0; i < TRIV2_IDU_MAX_SECTORS; i++) + idu->addrs[i] =3D (unsigned long)values[i]; + + return 0; +} + +/** + * triv2_setup_idu() - Setup IDU (e.g., CP, DSP) sections for this device + */ +static int triv2_setup_idu(struct trinity_driver *drv) +{ + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + struct device *dev =3D drv_to_dev_ptr(drv); + struct device_node *np =3D dev->of_node; + int err; + + /* get Instruction Decode Unit (IDU) property */ + err =3D parse_idu_property(dev, np, "samsung,idu_cp", &pdata->idu_cp); + if (err < 0) { + dev_err(dev, "Failed to parse idu property: samsung,idu_cp"); + return err; + } + + err =3D parse_idu_property(dev, np, "samsung,idu_dsp", &pdata->idu_dsp); + if (err < 0) { + dev_err(dev, "DSP is not supported"); + pdata->idu_dsp.addrs =3D NULL; + } + return 0; } =20 @@ -190,9 +618,24 @@ static int32_t triv2_init_pdata(struct trinity_driver = *drv) */ static void triv2_cleanup(struct trinity_driver *drv) { + struct device *dev =3D drv_to_dev_ptr(drv); + struct trinity_dma *cmd_buf; + struct trinity_dma *back_buf; + if (!drv->pdata) return; =20 + triv2_idu_unset(drv); + + cmd_buf =3D TRIV2_DRV_GET_CMD_BUF(drv); + back_buf =3D TRIV2_DRV_GET_BACK_BUF(drv); + + if (cmd_buf->addr) + trinity_dma_free(dev, cmd_buf); + + if (back_buf->addr) + trinity_dma_free(dev, back_buf); + kfree(drv->pdata); drv->pdata =3D NULL; } @@ -203,6 +646,11 @@ static struct trinity_desc triv2_desc =3D { .fops =3D &triv2_fops, /* device management */ .reset =3D triv2_reset, + .idu_set =3D triv2_idu_set, + .idu_unset =3D triv2_idu_unset, + .idu_version =3D triv2_idu_version, + .get_state =3D triv2_get_state, + .set_state =3D triv2_set_state, /* req management */ .alloc_req =3D triv2_alloc_req, .dealloc_req =3D triv2_dealloc_req, @@ -229,10 +677,28 @@ static int trinity_triv2_probe(struct platform_device= *pdev) if (err < 0) return err; =20 + drv =3D platform_get_drvdata(pdev); + if (drv->dspm > 0) { + /* DSPM's some region is reserved for DSP kernel operations */ + if (drv->dspm < TRIV2_DSP_DSPM_OFFSET) { + dev_err(drv_to_dev_ptr(drv), + "Too small DSPM size.. wrong device tree?"); + err =3D -EINVAL; + goto out_remove; + } + drv->dspm -=3D TRIV2_DSP_DSPM_OFFSET; + } + err =3D triv2_init_pdata(drv); if (err < 0) goto out_remove; =20 + err =3D triv2_setup_idu(drv); + if (err < 0) { + triv2_cleanup(drv); + goto out_remove; + } + err =3D trinity_create_node(drv); if (err < 0) { triv2_cleanup(drv); --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 162F0ECAAD3 for ; Sat, 17 Sep 2022 07:24:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229645AbiIQHYa (ORCPT ); Sat, 17 Sep 2022 03:24:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51896 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229498AbiIQHYJ (ORCPT ); Sat, 17 Sep 2022 03:24:09 -0400 Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 97E3A45F50 for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p4.samsung.com (unknown [182.195.41.48]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20220917072359epoutp01bf5a9fd5a6eb45aa9a7a04fffc42f621~VlPonakec2066820668epoutp01S for ; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20220917072359epoutp01bf5a9fd5a6eb45aa9a7a04fffc42f621~VlPonakec2066820668epoutp01S DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399439; bh=pWnbGJMrRMt/R18/F7egoAjJXBuAmKd68mnyBNIgt5A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WJ1IIXxmyFmcAiEGGIpW1PqT4KOO42uS2iFoEZKrGs7uqJLuZLOS2hjG54UVBo/dF 4Hz0A0sjbLDGSDM07BIuUCf1QI71fSVB9tr1tfy/jeTaK9kRanqTgjFL4henS4DRIc kDV3DRGTyNuhJOmVrYG24M2S0CwH1Q5n70RexZis= Received: from epsnrtp4.localdomain (unknown [182.195.42.165]) by epcas1p4.samsung.com (KnoxPortal) with ESMTP id 20220917072358epcas1p4cd65db382a4a2ecf63c09b26bc9d751e~VlPoBuR-b2768227682epcas1p41; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epsmges1p1.samsung.com (unknown [182.195.38.237]) by epsnrtp4.localdomain (Postfix) with ESMTP id 4MV2Vj6bb7z4x9Pq; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epcas1p2.samsung.com ( [182.195.41.46]) by epsmges1p1.samsung.com (Symantec Messaging Gateway) with SMTP id 88.40.07146.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas1p3.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epcas1p378e13844913c3c80acd183ddd59de456~VlPm0IIsp0623006230epcas1p3M; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220917072357epsmtrp2a8bc9de9aa8d5ee4470a8bc46851f8c2~VlPmzer2l1654916549epsmtrp2w; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) X-AuditID: b6c32a35-47bfe70000021bea-7b-6325760d1e88 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id D1.45.14392.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epsmtip2584397d85f2187275bbf735582252e13~VlPml8Cba3199331993epsmtip2Y; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 04/13] trinity: Add schduler module Date: Sat, 17 Sep 2022 16:23:47 +0900 Message-Id: <20220917072356.2255620-5-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFuplk+LIzCtJLcpLzFFi42LZdlhTT5e3TDXZYMFuA4u/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtKtsmIzUxJbVIITUvOT8lMy/dVsk7ON453tTMwFDX0NLCXEkh LzE31VbJxSdA1y0zB+gqJYWyxJxSoFBAYnGxkr6dTVF+aUmqQkZ+cYmtUmpBSk6BaYFecWJu cWleul5eaomVoYGBkSlQYUJ2xp/mPuaC7wkVp/tmMTYwnvDvYuTkkBAwkVi/fA9zFyMXh5DA DkaJjU0LGEESQgKfGCVOrnSGSHwDSjxcygjTcWx/J1THXkaJRR+uQTmfGSVmb9rEDFLFJqAq MXPGGnYQW0SgXKJ54wkwm1kgR+LJnSawGmEBM4krt56xgNgsQPWfV3xhArF5BawldvVdB9vG KWAjcXNTEwtEXFDi5MwnLBBz5CWat84GWywh8JZdYsmeb0ANHECOi8SaByUQlwpLvDq+hR3C lpL4/G4vG4SdLTGlYxELhF0gce75VmaIVmOJiytSQExmAU2J9bv0ISoUJXb+nssIsZVP4t3X HlaIal6JjjYhiBIliSV/DkMtkpCYOuMbE4TtIdHT9wgaOv2MEm1vX7BOYJSfheSZWUiemYWw eQEj8ypGsdSC4tz01GLDAkN4nCbn525iBKdLLdMdjBPfftA7xMjEwXiIUYKDWUmEV9VTJVmI NyWxsiq1KD++qDQntfgQoykweCcyS4km5wMTdl5JvKGJpYGJmZGxiYWhmaGSOK+eNmOykEB6 YklqdmpqQWoRTB8TB6dUA9MKX6785X4+c0Mq3+YIJfld/RR0qnTRL8dKl5frzNhbyyX2eIbO 7OhUrjJy/n6puUXhk/z0zXME1qrder/idEopp+Ly+hBjuV8vv7P+DXWf49Wf+JtPyDvQQ2Bp na6KzlbG/dnSGa9enVOQn+DRvspE1JzffduRkgY5wQV6S7P/H5n2I+7cm+qcvKCtpat+5XXu /MoZ+brvQPuxazMFmS+Ephe6XLZfa+tyq6Db3S2X+1jUvo8blebGdG8LuCu7qHFh2Xor00W3 79v7LeEINZPL9L4t/XHaRcOiO8fdUs4phbaxJE/X6oi3XpWgwvw0aaY/qxsfS3laJKfvq85d ub5s3Qff7xA/8dmA41WLEktxRqKhFnNRcSIAbEvkryAEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrBLMWRmVeSWpSXmKPExsWy7bCSvC5vmWqywaStshZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAlfGn+Y+5oLvCRWn+2YxNjCe8O9i5OSQ EDCROLa/k7mLkYtDSGA3o0TP71NMEAkJiU33lgMlOIBsYYnDh4tBwkICHxkl1j2sALHZBFQl Zs5Yww5iiwjUShw8Op8ZxGYWKJCY/XQmC4gtLGAmceXWMzCbBaj+84ovYON5BawldvVdZwSx OQVsJG5uamKBmG8tMXv6XKgaQYmTM5+wQMyUl2jeOpt5AiP/LCSpWUhSCxiZVjFKphYU56bn FhsWGOallusVJ+YWl+al6yXn525iBAe2luYOxu2rPugdYmTiYDzEKMHBrCTCq+qpkizEm5JY WZValB9fVJqTWnyIUZqDRUmc90LXyXghgfTEktTs1NSC1CKYLBMHp1QDE8t+P/cXWbyS6oES XyobHHNVOOU7Vk/1nBAb1zk9YffGvhJdTnebQ/dfmxXVebwMzmOzf3TWZ73EjCSL7rdPLO49 jvopoqZU69u/OXWyfSvvJ0beyKhHdkoRa2OXW95e9+j82fu2dsstNKXaTzH+MJRL6tx9+rv0 royWVukdP0UPX+Ob8DXIemKyIYN4iHuOyoa9c/P/59lebPM692ZJWeqT1ybpJeL+RatFLvtv cu2IjNL7Lmy+8viSje8Pue8RPZ9n75C8xF8mWu7DofQN6t5OTj43hRo2lmr+KvMMs+5lt/GJ 3qMj9PJyX4NsL7PDUeVQn6Jnh6LztPTjzXjnvy96fT7UTK+3oZVVTImlOCPRUIu5qDgRAOzl BYvbAgAA X-CMS-MailID: 20220917072357epcas1p378e13844913c3c80acd183ddd59de456 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072357epcas1p378e13844913c3c80acd183ddd59de456 References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch includes NPU scheduler interface. Tasks can be pushed to the NPU in order by the scheduler. The default schduling algorithm is provided using Priority policy. When the requests are invoked, it calculates priority with remained time to timeout, and it submits requests to NPU in priority order. It waits until complete interrupt arrives from NPU, and pushes a next request. Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong Signed-off-by: Dongju Chae Signed-off-by: MyungJoo Ham --- drivers/misc/trinity/Makefile | 1 + drivers/misc/trinity/trinity.c | 1 + drivers/misc/trinity/trinity_sched.c | 338 +++++++++++++++++++++ drivers/misc/trinity/trinity_sched.h | 24 ++ drivers/misc/trinity/trinity_vision2_drv.c | 1 + 5 files changed, 365 insertions(+) create mode 100644 drivers/misc/trinity/trinity_sched.c create mode 100644 drivers/misc/trinity/trinity_sched.h diff --git a/drivers/misc/trinity/Makefile b/drivers/misc/trinity/Makefile index 5d2b75112482..2a8c4fed135e 100644 --- a/drivers/misc/trinity/Makefile +++ b/drivers/misc/trinity/Makefile @@ -4,5 +4,6 @@ obj-$(CONFIG_TRINITY_VISION2) +=3D trinity_vision2.o =20 trinity-y :=3D trinity.o trinity-y +=3D trinity_dma.o trinity_hwmem.o +trinity-y +=3D trinity_sched.o =20 trinity_vision2-objs :=3D $(trinity-y) trinity_vision2_drv.o diff --git a/drivers/misc/trinity/trinity.c b/drivers/misc/trinity/trinity.c index 3e8157dd4664..0c75eb13967c 100644 --- a/drivers/misc/trinity/trinity.c +++ b/drivers/misc/trinity/trinity.c @@ -14,6 +14,7 @@ #include =20 #include "trinity_common.h" +#include "trinity_sched.h" =20 #define TRINITY_PADDR_BASE (0x0) =20 diff --git a/drivers/misc/trinity/trinity_sched.c b/drivers/misc/trinity/tr= inity_sched.c new file mode 100644 index 000000000000..6e19841b345d --- /dev/null +++ b/drivers/misc/trinity/trinity_sched.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NPU scheduler for trinity requests + * + * Copyright (C) 2021-2022 Samsung Electronics + * Copyright (C) 2021 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#include +#include + +#include "trinity_common.h" + +struct trinity_sched_data { + struct llist_head req_queue; + wait_queue_head_t wait_queue; + struct task_struct *sched_thread; + struct mutex lock; + unsigned long suspended; +}; + +/** + * sched_calc_pri() - Calculate priority using timeout + */ +static unsigned long sched_calc_pri(struct trinity_req *req) +{ + ktime_t elapsed_time; + int64_t priority; + + if (req->input.config.timeout_ms =3D=3D 0) + return 0; /** @todo need preemption */ + + elapsed_time =3D ktime_to_ms(ktime_sub(ktime_get(), req->time_started)); + WARN_ON(elapsed_time < 0); + + /** + * if the elapsed time exceeds the timeout of req, + * its priority value is set to the minimum (highest). + */ + priority =3D req->input.config.timeout_ms - elapsed_time; + if (priority < 0) + priority =3D 0; + + return priority; +} + +/** + * sched_pick_req() - Pick the top-priority request from request queue + */ +static struct trinity_req *sched_pick_req(struct llist_head *queue) +{ + struct trinity_req *req, *req_prev; + struct trinity_req *top_req, *top_req_prev; + int64_t top_priority =3D S64_MAX; + unsigned long priority; + + if (llist_empty(queue)) + return NULL; + + req =3D req_prev =3D NULL; + top_req =3D top_req_prev =3D NULL; + + /** + * llist is not a double linked list, and sorting is not easy + * because llist provides only limited APIs. + * it could be better than sorting if there are a few pending reqs. + * Note that each user application can submit only one req at once. + */ + llist_for_each_entry(req, queue->first, llist) { + priority =3D sched_calc_pri(req); + if (top_priority > priority) { + top_priority =3D priority; + top_req =3D req; + top_req_prev =3D req_prev; + } + + req_prev =3D req; + } + + if (top_req_prev) { + WARN_ON(!top_req); + top_req_prev->llist.next =3D top_req->llist.next; + } else { + /** it's first entry */ + top_req =3D llist_entry(llist_del_first(queue), typeof(*(req)), + llist); + } + + return top_req; +} + +/** + * llist_last() - Get latest node from list + */ +static struct llist_node *llist_last(struct llist_node *first) +{ + struct llist_node *last =3D first; + + while (first && first->next) { + last =3D first->next; + first =3D last; + } + + return last; +} + +/** + * trinity_sched_run_req() - Schedules a req to the target from the req qu= eue + * + * @req: Request information to be submitted. + * + * Return: 0 on success. Otherwise, returns negative error. Additional sta= tus of + * the submitted req could be passed by req->status. + */ +static int32_t sched_run_req(struct trinity_req *req, struct trinity_sched= _data *sched) +{ + struct trinity_driver *drv =3D req->drv; + struct device *dev =3D drv_to_dev_ptr(drv); + int32_t err =3D 0; + int32_t ready; + + /** setup is only allowed in ready state */ + ready =3D drv->desc->get_state(drv); + if (ready !=3D TRINITY_STATE_READY) { + dev_err(dev, + "Cannot setup NPU when it's in a non-ready state"); + err =3D -EPERM; + goto out; + } + + if (req->stat->status !=3D TRINITY_REQ_STATUS_PENDING && + req->stat->status !=3D TRINITY_REQ_STATUS_FINISHED) { + dev_err(dev, "Invalid req status: %d", + req->stat->status); + err =3D -EINVAL; + goto out; + } + + req->stat->status =3D TRINITY_REQ_STATUS_RUNNING; + err =3D drv->desc->invoke_req(drv, req, NULL); +out: + if (err !=3D 0) + req->stat->status =3D TRINITY_REQ_STATUS_ERROR; + + return err; +} + +/** + * sched_thread_func() - Scheduler thread function + */ +static int sched_thread_func(void *data) +{ + const unsigned long MAX_RETRY_COUNT =3D 100; + struct trinity_sched_data *sched; + struct llist_head local_queue; + struct llist_node *new_first; + + sched =3D data; + init_llist_head(&local_queue); + +repeat: + if (kthread_should_stop()) + return 0; + + /** extract requests from global queue without locking */ + new_first =3D llist_del_all(&sched->req_queue); + /** new and pending requests could be located together */ + if (new_first) { + struct llist_node *new_last =3D llist_last(new_first); + + llist_add_batch(new_first, new_last, &local_queue); + } + + /** flush requests in the queue */ + while (!llist_empty(&local_queue)) { + struct trinity_req *req; + int32_t ret; + + /** + * pick the top-priority request from the queue. + * first and last node pointers are updated + */ + req =3D sched_pick_req(&local_queue); + if (!req) + goto repeat; + + mutex_lock(&sched->lock); + ret =3D sched_run_req(req, sched); + mutex_unlock(&sched->lock); + + /** do not modify or access for 'req' except on an error case. + * it could be released by the interrupt. + */ + if (ret =3D=3D -EBUSY) { + if (req->submit_retry >=3D MAX_RETRY_COUNT) { + /** give up to handling this req*/ + complete_all(&req->complete); + } else { + req->submit_retry++; + /** push again and restart the loop */ + llist_add(&req->llist, &local_queue); + } + goto repeat; + } else if (ret !=3D 0) { + /** let's notify this unknown error */ + complete_all(&req->complete); + } + } + + /** ensure the local queue is empty */ + WARN_ON(!llist_empty(&local_queue)); + + wait_event_interruptible( + sched->wait_queue, + kthread_should_stop() || + !llist_empty(&sched->req_queue)); + goto repeat; +} + +/** + * tirnity_sched_ready() - Check scheduler is ready + * + * @drv: an instance of trinity driver + */ +bool trinity_sched_ready(struct trinity_driver *drv) +{ + struct trinity_sched_data *sched =3D drv->sched_pdata; + + return (test_bit(1, &sched->suspended) !=3D 1); +} + +/** + * trinity_sched_submit() - Submit request to scheduler + * + * @drv: an instance of trinity driver + * @req: request to be submitted + * + * Return: returns 0 on Success, otherwise returns negative error + */ +int32_t trinity_sched_submit(struct trinity_driver *drv, struct trinity_re= q *req) +{ + struct trinity_sched_data *sched =3D drv->sched_pdata; + + if (!req) + return -EINVAL; + + if (!trinity_sched_ready(drv)) + return -EAGAIN; + + llist_add(&req->llist, &sched->req_queue); + wake_up(&sched->wait_queue); + + return 0; +} + +/** + * trinity_sched_notify() - finishes and notify the request handled + */ +void trinity_sched_notify(struct trinity_req *req, bool timeout) +{ + req->scheduled =3D false; + req->timeout =3D timeout; +} + +/** + * trinity_sched_suspend() - Suspend scheduler + * + * @drv: an instance of trinity driver + */ +void trinity_sched_suspend(struct trinity_driver *drv) +{ + struct trinity_sched_data *sched =3D drv->sched_pdata; + + if (!test_and_set_bit(1, &sched->suspended)) + mutex_lock(&sched->lock); +} + +/** + * trinity_sched_resume() - Resume scheduler + * + * @drv: an instance of trinity driver + */ +void trinity_sched_resume(struct trinity_driver *drv) +{ + struct trinity_sched_data *sched =3D drv->sched_pdata; + + if (test_and_clear_bit(1, &sched->suspended)) + mutex_unlock(&sched->lock); +} + +/** + * trinity_sched_init() - Initialize trinity task schedulers + * + * @dev: an instance of the device + * Return: returns 0 on Success, otherwise returns negative error + */ +int trinity_sched_init(struct device *dev) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + struct trinity_sched_data *sched; + + sched =3D devm_kzalloc(dev, sizeof(*sched), GFP_KERNEL); + if (!sched) + return -ENOMEM; + + init_llist_head(&sched->req_queue); + init_waitqueue_head(&sched->wait_queue); + + mutex_init(&sched->lock); + clear_bit(1, &sched->suspended); + + sched->sched_thread =3D + kthread_run(sched_thread_func, sched, "trinity_sched_thread"); + if (IS_ERR(sched->sched_thread)) { + dev_err(dev, + "Failed to create a thread for scheduler"); + return PTR_ERR(sched->sched_thread); + } + drv->sched_pdata =3D sched; + + return 0; +} + +/** + * trinity_sched_exit() - Exit trinity task schedulers + * + * @dev: an instance of the device + */ +void trinity_sched_exit(struct device *dev) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + if (drv->sched_pdata) + devm_kfree(dev, drv->sched_pdata); +} diff --git a/drivers/misc/trinity/trinity_sched.h b/drivers/misc/trinity/tr= inity_sched.h new file mode 100644 index 000000000000..751d82d4374e --- /dev/null +++ b/drivers/misc/trinity/trinity_sched.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * NPU scheduler for trinity requests + * + * Copyright (C) 2021-2022 Samsung Electronics + * Copyright (C) 2021 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#ifndef __DRIVERS_MISC_TRINITY_SCHED_H__ +#define __DRIVERS_MISC_TRINITY_SCHED_H__ + +bool trinity_sched_ready(struct trinity_driver *drv); +int32_t trinity_sched_submit(struct trinity_driver *drv, + struct trinity_req *req); +void trinity_sched_notify(struct trinity_req *req, bool timeout); +void trinity_sched_suspend(struct trinity_driver *drv); +void trinity_sched_resume(struct trinity_driver *drv); +int32_t trinity_sched_init(struct device *dev); +void trinity_sched_exit(struct device *dev); + +#endif /* __DRIVERS_MISC_TRINITY_SCHED_H__ */ diff --git a/drivers/misc/trinity/trinity_vision2_drv.c b/drivers/misc/trin= ity/trinity_vision2_drv.c index 4bfc7f97769c..70b8b6fd5843 100644 --- a/drivers/misc/trinity/trinity_vision2_drv.c +++ b/drivers/misc/trinity/trinity_vision2_drv.c @@ -16,6 +16,7 @@ #include =20 #include "trinity_common.h" +#include "trinity_sched.h" #include "trinity_vision2_regs.h" =20 #define TRIV2_DRV_GET_PDATA(drv) ((struct triv2_pdata *)(drv->pdata)) --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CCE0DC6FA86 for ; Sat, 17 Sep 2022 07:24:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229695AbiIQHYh (ORCPT ); Sat, 17 Sep 2022 03:24:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51894 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229511AbiIQHYJ (ORCPT ); Sat, 17 Sep 2022 03:24:09 -0400 Received: from mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 97B66459A7 for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p2.samsung.com (unknown [182.195.41.46]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20220917072400epoutp04e616ddd2340aec131aa65dae9d23e00a~VlPpW-9_q2904629046epoutp04b for ; Sat, 17 Sep 2022 07:24:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20220917072400epoutp04e616ddd2340aec131aa65dae9d23e00a~VlPpW-9_q2904629046epoutp04b DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399440; bh=DuFz+YEWnDIdkeK1uiAdaI/h/uWoctHlSqnVpakc+l8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GJtk19CQhNlDrUjvYeiGwU8WuLUhfi1YkW/60m00BzmjUwdWYiY+tXxLzfBLiz3O3 NEjqco0gxu26YNw5Pm6PhrqV9/QvgY7AxZJKWPrbLDAZkKFBlH07Y5WFQqmaWxqAmR d8zE9NEMSRlVxecIFew7/ijgI/oHLVi7bEtDNhJQ= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas1p2.samsung.com (KnoxPortal) with ESMTP id 20220917072359epcas1p22a6a93e9f3e736ff5b91b4e5b87bb03b~VlPoX7oGz2419324193epcas1p22; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) Received: from epsmges1p1.samsung.com (unknown [182.195.38.231]) by epsnrtp2.localdomain (Postfix) with ESMTP id 4MV2Vk1KJYz4x9Pt; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epcas1p4.samsung.com ( [182.195.41.48]) by epsmges1p1.samsung.com (Symantec Messaging Gateway) with SMTP id 29.40.07146.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas1p2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epcas1p2735d98b043e2382aba1173c6b52af81a~VlPm6WE6y1789517895epcas1p2r; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220917072357epsmtrp1aaca354cfaf1c1d6cba3416536df1c79~VlPm5kpeX0556805568epsmtrp1c; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) X-AuditID: b6c32a35-205ff70000021bea-7c-6325760e5cb1 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 23.45.14392.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epsmtip2d6d8624ef35a44bed66c02c90b0a6a9c~VlPmsIjF93199931999epsmtip2U; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 05/13] trinity: Add debugfs module Date: Sat, 17 Sep 2022 16:23:48 +0900 Message-Id: <20220917072356.2255620-6-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupik+LIzCtJLcpLzFFi42LZdljTQJevTDXZ4OEmVou/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtKtsmIzUxJbVIITUvOT8lMy/dVsk7ON453tTMwFDX0NLCXEkh LzE31VbJxSdA1y0zB+gqJYWyxJxSoFBAYnGxkr6dTVF+aUmqQkZ+cYmtUmpBSk6BaYFecWJu cWleul5eaomVoYGBkSlQYUJ2xvq9vewFf30r1v7+wt7AONehi5GDQ0LARGLVtLAuRi4OIYEd jBIr921gh3A+MUpMft/M1MXICeR8Y5SYusURxAZpuN52kRmiaC+jxMML7SwQRZ+BnD0CIDab gKrEzBlr2EFsEYFyieaNJ8BsZoEciSd3mphBNgsLmEocmxIKEmYBKv99dh4jiM0rYC1x6Np0 NhCbU8BG4uamJhaIuKDEyZlPWCDGyEs0b50NdoOEwFd2icNf7zNDfOMi8e2+D8SdwhKvjm9h h7ClJF72t0HZ2RJTOhaxQNgFEueeb4VqNZa4uCIFxGQW0JRYv0sfokJRYufvuYwQW/kk3n3t YYWo5pXoaBOCKFGSWPLnMNRwCYmpM74xQdgeEuu+PGGCBFQ/o8T3fw2MExjlZyF5ZhaSZ2Yh bF7AyLyKUSy1oDg3PbXYsMAQHqHJ+bmbGMGJUst0B+PEtx/0DjEycTAeYpTgYFYS4VX1VEkW 4k1JrKxKLcqPLyrNSS0+xGgKDN6JzFKiyfnAVJ1XEm9oYmlgYmZkbGJhaGaoJM6rp82YLCSQ nliSmp2aWpBaBNPHxMEp1cBUdaNUbKHzsxTGOxON/oaf41G6PeEkR3b/BDXF1HzuaCOp1TOK LXtmuO5pPJ0+VaVlYU27KotKFNcx7zjfJOu79/V0HG5VN7+J7xdTslrSIMytJMpgz3nrT/gc 21NrZXmnev49n7SSd73FDFPes3e+KmXue+Bc9X2J+XZTl7VhFft3vujvtyr/5GGx9N2rkrZt D77ve2N5utrjzaLDk3Q0VKWyRW/P4lhsItS0e1n0qdlXOG0XFurm/A3Wv/JzZpxdePuRhZsT 5mzSqZ23lXF+v3Zk4KXMyE7x629PXOYOSUl5ovkmbPn0oNwWTa1/q3Nc3/0TLd/lfVx21+f3 Oj8s7Jm+mxVsStP8OW/57ctKLMUZiYZazEXFiQAR30hmHQQAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrBLMWRmVeSWpSXmKPExsWy7bCSvC5vmWqywbQlKhZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAlfG+r297AV/fSvW/v7C3sA416GLkZND QsBE4nrbReYuRi4OIYHdjBKbFjWzQSQkJDbdWw6U4ACyhSUOHy6GqPnIKLHw0iN2kBo2AVWJ mTPWgNkiArUSB4/OZwaxmQUKJGY/nckC0issYCpxbEooSJgFqPz32XmMIDavgLXEoWvTwVZx CthI3NzUxAJiCwHFZ0+fywRRIyhxcuYTFoiR8hLNW2czT2Dkn4UkNQtJagEj0ypGydSC4tz0 3GLDAsO81HK94sTc4tK8dL3k/NxNjODA1tLcwbh91Qe9Q4xMHIyHGCU4mJVEeFU9VZKFeFMS K6tSi/Lji0pzUosPMUpzsCiJ817oOhkvJJCeWJKanZpakFoEk2Xi4JRqYMo4OiUlas2asH79 whBTk0Xd0+cc0374qnrCx2N/7gbw7qx89219WRyLY6Xo/8bt3UFWv2t2amz0vrfo951lx3lE txisnp1xWfnf4sab8y3X6d2W+pvhteXs3r/18yS/ej88Mn3esbXb66WVZu9hk5aOE9X+p7iW 1+NJJy//m9Pth/YcKnngvH7Gv4TGsrRA57isxlWZzPebDuR8WOXt69q29knWW55TP3ujWc5t 1zl6bK308q2KbjbOV/Zq8GtmhXIsuB+fHdA44++Rji6t3/UFxu+let+ET1yYXPFb8tkEt9p0 u/V9OkWMR8/8vleaNUk2I37bZfF1c5ZonlxZ+iJhwgaW2t5dLgtd25xuSP1UYinOSDTUYi4q TgQAsy/wu9sCAAA= X-CMS-MailID: 20220917072357epcas1p2735d98b043e2382aba1173c6b52af81a X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072357epcas1p2735d98b043e2382aba1173c6b52af81a References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch provides debugfs feature. It create debugfs entry for driver and provides apis to print out messages, model info and input info. Default directory of debugfs is named 'trinity', and each driver has own debug file. Signed-off-by: Jiho Chu --- drivers/misc/trinity/Makefile | 1 + drivers/misc/trinity/trinity_debug.c | 331 +++++++++++++++++++++++++++ 2 files changed, 332 insertions(+) create mode 100644 drivers/misc/trinity/trinity_debug.c diff --git a/drivers/misc/trinity/Makefile b/drivers/misc/trinity/Makefile index 2a8c4fed135e..5d3e89dd0dd7 100644 --- a/drivers/misc/trinity/Makefile +++ b/drivers/misc/trinity/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_TRINITY_VISION2) +=3D trinity_vision2.o trinity-y :=3D trinity.o trinity-y +=3D trinity_dma.o trinity_hwmem.o trinity-y +=3D trinity_sched.o +trinity-y +=3D trinity_debug.o =20 trinity_vision2-objs :=3D $(trinity-y) trinity_vision2_drv.o diff --git a/drivers/misc/trinity/trinity_debug.c b/drivers/misc/trinity/tr= inity_debug.c new file mode 100644 index 000000000000..9add728a101b --- /dev/null +++ b/drivers/misc/trinity/trinity_debug.c @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** + * Implementation of debug functions for trinity drivers + * + * Copyright (C) 2020-2022 Samsung Electronics + * Copyright (C) 2020 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#include +#include +#include +#include + +#include "trinity_common.h" + +#define TRINITY_DEVVER(drv) (drv->desc->ver >> TRINITY_SHIFT_DEV) +#define TRINITY_DEBUGFS_DIR ("trinity") +#define TRINITY_DEBUGFS_MAX (1024UL) +#define TRINITY_DEBUGFS_LENGTH (255) + +struct trinity_debugfs_msg { + char msg[TRINITY_DEBUGFS_LENGTH + 1]; /* including NULL */ +}; + +struct trinity_debugfs_entry { + struct dentry *dentry; + spinlock_t lock; + + unsigned long msg_max; + unsigned long msg_num; + unsigned long msg_off; + + struct trinity_dma msg_buf; +}; + +static struct dentry *trinity_debugfs; + +static size_t trinity_debug_append_app_id(struct trinity_driver *drv, char= *msg) +{ + return snprintf(msg, TRINITY_DEBUGFS_LENGTH, "[%d] ", + trinity_get_app_id()); +} + +static char *trinity_debug_get_msg_buf(struct trinity_driver *drv) +{ + struct trinity_debugfs_entry *entry =3D drv->debugfs_pdata; + struct trinity_debugfs_msg *buf; + + if (!entry || entry->msg_max =3D=3D 0) + return NULL; + + spin_lock(&entry->lock); + if (entry->msg_num =3D=3D entry->msg_max) { + buf =3D &((struct trinity_debugfs_msg *) + entry->msg_buf.addr)[entry->msg_off]; + entry->msg_off =3D (entry->msg_off + 1) % entry->msg_max; + } else { + buf =3D &((struct trinity_debugfs_msg *) + entry->msg_buf.addr)[entry->msg_num++]; + } + spin_unlock(&entry->lock); + + memset(buf, '\x00', sizeof(*buf)); + return buf->msg; +} + +/** + * trinity_debug_dump_msg() - Dump trinity debug message + * + * @drv: an instance of the trinity driver + * @fmt: tag message format + */ +void trinity_debug_dump_msg(struct trinity_driver *drv, const char *fmt, .= ..) +{ + char *msg; + size_t len; + va_list args; + + msg =3D trinity_debug_get_msg_buf(drv); + if (msg =3D=3D NULL) + return; + + len =3D trinity_debug_append_app_id(drv, msg); + + va_start(args, fmt); + len +=3D vsnprintf(msg + len, TRINITY_DEBUGFS_LENGTH - len, fmt, args); + va_end(args); +} + +/** + * trinity_debug_dump_input() - Dump trinity input data + * + * @drv: an instance of the trinity driver + * @input: an instance of the trinity model + * @fmt: tag message format + */ +void trinity_debug_dump_model(struct trinity_driver *drv, + const struct trinity_model *model, + const char *fmt, ...) +{ + char *msg; + size_t len; + va_list args; + + msg =3D trinity_debug_get_msg_buf(drv); + if (msg =3D=3D NULL) + return; + + len =3D trinity_debug_append_app_id(drv, msg); + + va_start(args, fmt); + len +=3D vsnprintf(msg + len, TRINITY_DEBUGFS_LENGTH - len, fmt, args); + va_end(args); + + len +=3D snprintf(msg + len, TRINITY_DEBUGFS_LENGTH - len, + "\n\tid(0x%llx) dbuf_fd(%d) program_offset_addr(0x%llx) program_size(0x= %llx)\n", + model->config.id, model->config.dbuf_fd, + model->config.program_offset_addr, model->config.program_size); + len +=3D snprintf(msg + len, TRINITY_DEBUGFS_LENGTH - len, + "\tmetadata_dbuf_fd(%d) metadata_ext_dbuf_fd(%d) metadata_ext_size(0x%l= lx)", + model->config.metadata_dbuf_fd, + model->config.metadata_ext_dbuf_fd, + model->config.metadata_ext_size); +} + +/** + * trinity_debug_dump_input() - Dump trinity input data + * + * @drv: an instance of the trinity driver + * @input: an instance of the trinity input + * @fmt: tag message format + */ +void trinity_debug_dump_input(struct trinity_driver *drv, + const struct trinity_input *input, + const char *fmt, ...) +{ + char *msg; + size_t len; + va_list args; + + msg =3D trinity_debug_get_msg_buf(drv); + if (msg =3D=3D NULL) + return; + + len =3D trinity_debug_append_app_id(drv, msg); + + va_start(args, fmt); + len +=3D vsnprintf(msg + len, TRINITY_DEBUGFS_LENGTH - len, fmt, args); + va_end(args); + + len +=3D snprintf(msg + len, TRINITY_DEBUGFS_LENGTH - len, + "\n\tdbuf_fd(%d) model_id(0x%llx)\n", + input->config.dbuf_fd, input->config.model_id); + len +=3D snprintf(msg + len, TRINITY_DEBUGFS_LENGTH - len, + "\ttimeout_ms(%lld) priority(%u) num_segments(%u) input_mode(%d) output= _mode(%d)", + input->config.timeout_ms, input->config.priority, + input->config.num_segments, input->config.input_mode, + input->config.output_mode); +} + +static int trinity_debugfs_show(struct seq_file *s, void *unsed) +{ + struct trinity_driver *drv =3D s->private; + struct trinity_debugfs_entry *entry =3D drv->debugfs_pdata; + struct trinity_debugfs_msg *msg; + unsigned long i, offset; + + spin_lock(&entry->lock); + for (i =3D 0; i < entry->msg_num; i++) { + offset =3D (entry->msg_off + i) % entry->msg_max; + msg =3D &((struct trinity_debugfs_msg *) + entry->msg_buf.addr)[offset]; + + seq_puts(s, msg->msg); + seq_puts(s, "\n"); + } + spin_unlock(&entry->lock); + + return 0; +} + +static int trinity_debugfs_open(struct inode *inode, struct file *file) +{ + return single_open(file, trinity_debugfs_show, inode->i_private); +} + +static const struct file_operations trinity_debugfs_fops =3D { + .open =3D trinity_debugfs_open, + .read =3D seq_read, + .llseek =3D seq_lseek, + .release =3D single_release, +}; + +/** + * trinity_debug_add() - Add trinity debug file system entry + * + * @drv: an instance of the trinity driver + */ +int trinity_debug_add(struct trinity_driver *drv) +{ + struct trinity_debugfs_entry *entry; + struct dentry *dentry; + const char *name =3D drv->name; + + if (name =3D=3D NULL) + return -EINVAL; + + entry =3D kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + dentry =3D debugfs_create_file_unsafe(name, 0400, trinity_debugfs, drv, + &trinity_debugfs_fops); + if (IS_ERR(dentry)) { + kfree(entry); + return PTR_ERR(dentry); + } + + entry->dentry =3D dentry; + spin_lock_init(&entry->lock); + + drv->debugfs_pdata =3D entry; + + return 0; +} + +/** + * trinity_debug_remove() - Remove trinity debug file system entry + * + * @drv: an instance of the trinity driver + */ +void trinity_debug_remove(struct trinity_driver *drv) +{ + struct trinity_debugfs_entry *entry =3D drv->debugfs_pdata; + + trinity_debug_clear(drv, 0); + + debugfs_remove(entry->dentry); + kfree(entry); + + drv->debugfs_pdata =3D NULL; +} + +/** + * trinity_debug_clear() - Clear debug message entity + * + * @drv: an instance of the trinity driver + * @msg_max: reset max size of debug message entity + */ +void trinity_debug_clear(struct trinity_driver *drv, unsigned long msg_max) +{ + struct trinity_debugfs_entry *entry =3D drv->debugfs_pdata; + struct device *dev =3D drv_to_dev_ptr(drv); + size_t size; + + /* maximum size limit: 256KiB */ + if (msg_max > TRINITY_DEBUGFS_MAX) { + dev_err(dev, "Too much debugfs entries (limit: %lu)", + TRINITY_DEBUGFS_MAX); + return; + } + + spin_lock(&entry->lock); + + /* disable debugfs temporally */ + trinity_dma_free(dev, &entry->msg_buf); + entry->msg_max =3D 0; + entry->msg_num =3D 0; + entry->msg_off =3D 0; + + if (msg_max =3D=3D 0) + goto out; + + /* reallocate debugfs buffer */ + size =3D PAGE_ALIGN(msg_max * sizeof(struct trinity_debugfs_msg)); + if (trinity_dma_alloc(dev, size, &entry->msg_buf) < 0) { + dev_warn(dev, "No available memory for debugfs"); + goto out; + } + /* more available entries due to page size alignment */ + entry->msg_max =3D size / sizeof(struct trinity_debugfs_msg); + +out: + spin_unlock(&entry->lock); +} + +/** + * trinity_debug_exit() - Get max size of debug message entity + * + * @drv: an instance of the trinity driver + * + * Return: max size of debug message entity + */ +unsigned long trinity_debug_get_max(struct trinity_driver *drv) +{ + struct trinity_debugfs_entry *entry =3D drv->debugfs_pdata; + unsigned long msg_max; + + spin_lock(&entry->lock); + msg_max =3D entry->msg_max; + spin_unlock(&entry->lock); + + return msg_max; +} + +/** + * trinity_debug_exit() - Initialize debug file system + */ +int trinity_debug_init(void) +{ + struct dentry *entry; + + entry =3D debugfs_create_dir(TRINITY_DEBUGFS_DIR, NULL); + if (IS_ERR(entry)) + return PTR_ERR(entry); + + trinity_debugfs =3D entry; + + return 0; +} + +/** + * trinity_debug_exit() - Exit debug file system + */ +void trinity_debug_exit(void) +{ + debugfs_remove_recursive(trinity_debugfs); +} --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1ACC2C6FA86 for ; Sat, 17 Sep 2022 07:24:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229556AbiIQHYz (ORCPT ); Sat, 17 Sep 2022 03:24:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51920 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229595AbiIQHYL (ORCPT ); Sat, 17 Sep 2022 03:24:11 -0400 Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A078C45F6A for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p2.samsung.com (unknown [182.195.41.46]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20220917072400epoutp015dea7465cec7cb880a0b95246269f124~VlPpdzDYj1986719867epoutp01u for ; Sat, 17 Sep 2022 07:24:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20220917072400epoutp015dea7465cec7cb880a0b95246269f124~VlPpdzDYj1986719867epoutp01u DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399440; bh=MS0X37V41L2Pc/Buc3rhEH64RqFWy7WaL2u7nSoQVyM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qRNUbGdNz1FuZ+AnhNr+QS5ybA9KcpDKS3ztEzmhkYeJ/KO0mfrly2wkad32mH2ti Se5ek8c92h58CvFO0Hrqbe5xzt8aS05+o4jHAE24qE9dA++o9Jsd1jKfzyWgHu+diJ /BNtv4h+kEJZk0dIjmon+KtFevfQ1D0DlKNtnp2s= Received: from epsnrtp1.localdomain (unknown [182.195.42.162]) by epcas1p3.samsung.com (KnoxPortal) with ESMTP id 20220917072359epcas1p321fdba5115a4e3ae156ea439954cdb53~VlPod6cSn0623006230epcas1p3O; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) Received: from epsmges1p1.samsung.com (unknown [182.195.36.134]) by epsnrtp1.localdomain (Postfix) with ESMTP id 4MV2Vk2lTmz4x9Pr; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epcas1p3.samsung.com ( [182.195.41.47]) by epsmges1p1.samsung.com (Symantec Messaging Gateway) with SMTP id C9.40.07146.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas1p2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epcas1p2ec70909280eee82b0db5ad454247daf8~VlPnJZ01Q2419324193epcas1p21; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220917072357epsmtrp28c6b5b2d1da246c47af521560fe1b6b8~VlPnIjl3W1654916549epsmtrp2x; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) X-AuditID: b6c32a35-47bfe70000021bea-7d-6325760e8cc2 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id C4.F0.18644.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epsmtip2f274a021c71b9ec66f1e3ad7fb01d64c~VlPmz3xFz2357323573epsmtip2e; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 06/13] trinity: add statistics module Date: Sat, 17 Sep 2022 16:23:49 +0900 Message-Id: <20220917072356.2255620-7-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupnk+LIzCtJLcpLzFFi42LZdlhTX5evTDXZoPkhn8XfScfYLaY+fMJm 0bx4PZvF++7dzBZ7X29lt7i8aw6bxe3GFWwW+3o+Mlo8n3adxYHT4/evSYwem1Z1snncubaH zWP/3DXsHn1bVjF6fN4kF8AWlW2TkZqYklqkkJqXnJ+SmZduq+QdHO8cb2pmYKhraGlhrqSQ l5ibaqvk4hOg65aZA3SVkkJZYk4pUCggsbhYSd/Opii/tCRVISO/uMRWKbUgJafAtECvODG3 uDQvXS8vtcTK0MDAyBSoMCE7o2fGUeaC9leMFXNnXWFuYFx+mLGLkZNDQsBEYs+6eWxdjFwc QgI7GCVWnbvHDOF8YpQ4+XofO4TzmVFiyv//cC3T5xxjB7GFBHYxSjy/LgBX1DC3ASzBJqAq MXPGGjBbRKBconnjCTCbWSBH4smdJmYQW1jAQuLjx2dANgcHC1D9+tNxIGFeAWuJ1Qfmgu3i FLCRuLmpiQUiLihxcuYTFogx8hLNW2eDXSoh8JNd4sKcI+wQx7lIXLz3kw3CFpZ4dXwLVFxK 4vO7vVDxbIkpHYtYIOwCiXPPt4LdICFgLHFxRQqIySygKbF+lz5EhaLEzt8Q5zAL8Em8+9rD ClHNK9HRJgRRoiSx5M9hqEUSElNnfGOCsD0k1q1ugwZhP6PEvh39bBMY5Wch+WYWkm9mIWxe wMi8ilEstaA4Nz212LDAEB6ryfm5mxjBKVPLdAfjxLcf9A4xMnEwHmKU4GBWEuFV9VRJFuJN SaysSi3Kjy8qzUktPsRoCgzeicxSosn5wKSdVxJvaGJpYGJmZGxiYWhmqCTOq6fNmCwkkJ5Y kpqdmlqQWgTTx8TBKdXAJMGR5xGcfD273ELtIwNXk1akrU51WuFS62dsa677F6y7+m/FHjPf 2d192z5sCMio3tI0w0n4nWRKYZTUPvuqqsqEV0YWEZx7dJ/KuB3Ka+mVf6TkWHSu3v646Z3X T18duR2cKH3sy7NfMi46XzUWMD/4eLypPtpONUM6ZVOE0+83L21OOrxoEJbSm7bvSqFG4xWZ rBKLw3z1y/9PFzWqTHO/f2z9gyY//kwT3cUtt+YueBWc6XNeW0o4i23a33fii9OKfebdnnJw a3NDxQ3ZnaeYvs78fyp4jmt9pXOGbu/xG5c51Vsfdc72nXr14SIFjXM7XpgfkDG7t/zYk4BY FwVerk7XP6+NMvdf97qpxFKckWioxVxUnAgAhALRHiIEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrFLMWRmVeSWpSXmKPExsWy7bCSvC5vmWqywfW3uhZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAldGz4yjzAXtrxgr5s66wtzAuPwwYxcj J4eEgInE9DnH2LsYuTiEBHYwSjw59wMqISGx6d5y5i5GDiBbWOLw4WKImo+MEmceHmMCqWET UJWYOWMNO4gtIlArcfDofGYQm1mgQGL205ksILawgIXEx4/PwOawANWvPx0HEuYVsJZYfWAu 2CpOARuJm5uawMqFgOKzp89lgqgRlDg58wkLxEh5ieats5knMPLPQpKahSS1gJFpFaNkakFx bnpusWGBUV5quV5xYm5xaV66XnJ+7iZGcHBrae1g3LPqg94hRiYOxkOMEhzMSiK8qp4qyUK8 KYmVValF+fFFpTmpxYcYpTlYlMR5L3SdjBcSSE8sSc1OTS1ILYLJMnFwSjUwqWW8qczimHzt hxan/GbflUpfcwudXPXP3jgb2St+5fPEj49sLxuaRXgHTg/aOIU116DqdetOIcF/iYU3hBrf R22ctFxvpz3nuRkFf2tNmKUStE/Zb5o4fecp1+8LM49Kf+v4+/ZvfDLbg0cZ+44dinSN+NoU oXs9/t+Hs8J7m/boT4+si743bQ2TS7vY3aAfmUdkbt27WSXw6sfWWceerpPcod55q6V23gOR urV7AjzFjus/bUtN3MkocnCa7pytp3nviuvvtQs89Tb81Z1Z/1QLJ7llvTlyq519b/bX+F6P xxlX+fm5yyRVdA/NXzb5ivimp38vpgQ+cnvVPEV590WrV+0np7b+jMkQ7TjQ7qzEUpyRaKjF XFScCAAj+wI03QIAAA== X-CMS-MailID: 20220917072357epcas1p2ec70909280eee82b0db5ad454247daf8 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072357epcas1p2ec70909280eee82b0db5ad454247daf8 References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch includes statistics information module. The information includes per-application statistics and per-request statistics. The app statistics records total number of requests, active requests, allocated memory and freed memory. For request statistics, it counts number of runs and total consumed time, and it also keeps profile data for the requests. Signed-off-by: Jiho Chu --- drivers/misc/trinity/Makefile | 1 + drivers/misc/trinity/trinity.c | 3 + drivers/misc/trinity/trinity_stat.c | 898 ++++++++++++++++++++++++++++ drivers/misc/trinity/trinity_stat.h | 56 ++ 4 files changed, 958 insertions(+) create mode 100644 drivers/misc/trinity/trinity_stat.c create mode 100644 drivers/misc/trinity/trinity_stat.h diff --git a/drivers/misc/trinity/Makefile b/drivers/misc/trinity/Makefile index 5d3e89dd0dd7..b475938a0db6 100644 --- a/drivers/misc/trinity/Makefile +++ b/drivers/misc/trinity/Makefile @@ -6,5 +6,6 @@ trinity-y :=3D trinity.o trinity-y +=3D trinity_dma.o trinity_hwmem.o trinity-y +=3D trinity_sched.o trinity-y +=3D trinity_debug.o +trinity-y +=3D trinity_stat.o =20 trinity_vision2-objs :=3D $(trinity-y) trinity_vision2_drv.o diff --git a/drivers/misc/trinity/trinity.c b/drivers/misc/trinity/trinity.c index 0c75eb13967c..a785a5dca4d9 100644 --- a/drivers/misc/trinity/trinity.c +++ b/drivers/misc/trinity/trinity.c @@ -15,6 +15,7 @@ =20 #include "trinity_common.h" #include "trinity_sched.h" +#include "trinity_stat.h" =20 #define TRINITY_PADDR_BASE (0x0) =20 @@ -100,6 +101,8 @@ int trinity_open(struct inode *inode, struct file *f) drv =3D container_of(miscdev, struct trinity_driver, mdev); f->private_data =3D drv; =20 + trinity_stat_app_set_status(drv, TRINITY_APP_STATUS_STARTED); + return 0; } =20 diff --git a/drivers/misc/trinity/trinity_stat.c b/drivers/misc/trinity/tri= nity_stat.c new file mode 100644 index 000000000000..0cbba08ee0b0 --- /dev/null +++ b/drivers/misc/trinity/trinity_stat.c @@ -0,0 +1,898 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Providing statistics for Samsung Trinity device family support + * + * Copyright (C) 2021-2022 Samsung Electronics + * Copyright (C) 2021 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#include "trinity_stat.h" +#include "trinity_common.h" + +#include +#include + +/* maximum number of stats configurable from sysfs */ +#define TRINITY_STAT_MAX_APPS (128UL) +#define TRINITY_STAT_MAX_REQS (4096UL) +#define TRINITY_STAT_MAX_REQS_PER_APP (128UL) + +/* default number of stats */ +#define TRINITY_STAT_DEF_APPS (32UL) +#define TRINITY_STAT_DEF_REQS (128UL) +#define TRINITY_STAT_DEF_REQS_PER_APP (32UL) + +/** + * struct trinity_stat_pool - Statistics pool which maintain statistics fo= r device + * + * @bitmap_app: bitmap for app + * @bitmap_req: bitmap for request + * @mem_app: reserved memory for applications + * @mem_req: reserved memory for request + * @max_stat_apps: max statistics size of applications + * @max_stat_reqs: max statistics size of requests. + * @max_stat_reqs_per_app: max statistics size of request per application + * @cur_stat_apps: current statistics for applications + * @cur_stat_reqs: current statistics for requests + * @drv: an instance of the trinity driver + */ +struct trinity_stat_pool { + DECLARE_BITMAP(bitmap_app, TRINITY_STAT_MAX_APPS); + DECLARE_BITMAP(bitmap_req, TRINITY_STAT_MAX_REQS); + + struct trinity_dma mem_app; + struct trinity_dma mem_req; + + unsigned long max_stat_apps; + unsigned long max_stat_reqs; + unsigned long max_stat_reqs_per_app; + + unsigned long cur_stat_apps; + unsigned long cur_stat_reqs; + + struct trinity_driver *drv; +}; + +/** + * trinity_stat_pool_init(): Initialize trinity statistics pool + * + * @drv: an instance of the trinity driver + * + * Returns: 0 on success. Otherwise, returns negative error. + */ +int trinity_stat_pool_init(struct trinity_driver *drv) +{ + struct trinity_stat_pool *pool; + + pool =3D kzalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) + return -ENOMEM; + + pool->drv =3D drv; + + drv->stat.pdata =3D pool; + + return 0; +} + +/** + * trinity_stat_pool_init(): finish trinity statistics pool + * + * @drv: an instance of the trinity driver + */ +void trinity_stat_pool_fini(struct trinity_driver *drv) +{ + struct device *dev =3D drv_to_dev_ptr(drv); + struct trinity_stat_pool *pool =3D drv->stat.pdata; + + if (!pool) + return; + + trinity_dma_free(dev, &pool->mem_app); + trinity_dma_free(dev, &pool->mem_req); + kfree(pool); + + drv->stat.pdata =3D NULL; +} + +static void trinity_stat_pool_resize_apps(struct trinity_stat_pool *pool, + unsigned long num_apps) +{ + struct device *dev =3D drv_to_dev_ptr(pool->drv); + struct trinity_dma mem; + unsigned long size; + int err; + + if (num_apps > TRINITY_STAT_MAX_APPS) { + dev_err(dev, "The maximum number of stat apps: %lu", + TRINITY_STAT_MAX_APPS); + return; + } + + size =3D sizeof(struct trinity_stat_app) * num_apps; + err =3D trinity_dma_alloc(dev, size, &mem); + if (err < 0) { + dev_warn(dev, "Unable to allocate stats for apps"); + return; + } + + trinity_dma_free(dev, &pool->mem_app); + + bitmap_fill(pool->bitmap_app, TRINITY_STAT_MAX_APPS); + bitmap_zero(pool->bitmap_app, num_apps); + + pool->max_stat_apps =3D num_apps; + pool->mem_app =3D mem; +} + +static void trinity_stat_pool_resize_reqs(struct trinity_stat_pool *pool, + unsigned long num_reqs) +{ + struct device *dev =3D drv_to_dev_ptr(pool->drv); + struct trinity_dma mem; + unsigned long size; + int err; + + if (num_reqs > TRINITY_STAT_MAX_REQS) { + dev_err(dev, "The maximum number of stat reqs: %lu", + TRINITY_STAT_MAX_REQS); + return; + } + + size =3D sizeof(struct trinity_stat_req) * num_reqs; + err =3D trinity_dma_alloc(dev, size, &mem); + if (err < 0) { + dev_warn(dev, "Unable to allocate stats for apps"); + return; + } + trinity_dma_free(dev, &pool->mem_req); + + bitmap_fill(pool->bitmap_req, TRINITY_STAT_MAX_REQS); + bitmap_zero(pool->bitmap_req, num_reqs); + + pool->max_stat_reqs =3D num_reqs; + pool->mem_req =3D mem; +} + +static struct trinity_stat_app * +trinity_stat_pool_get_app(struct trinity_driver *drv) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_pool *pool =3D stat->pdata; + struct trinity_stat_app *app =3D NULL; + unsigned long slot; + bool retried =3D false; + + /* ensured that the lock is acquired */ +retry: + slot =3D find_first_zero_bit(pool->bitmap_app, TRINITY_STAT_MAX_APPS); + if (slot < TRINITY_STAT_MAX_APPS) { + app =3D &((struct trinity_stat_app *)pool->mem_app.addr)[slot]; + memset(app, '\x00', sizeof(*app)); + set_bit(slot, pool->bitmap_app); + app->slot =3D slot; + } else if (!retried) { + /* retry after destroy old stats */ + retried =3D true; + trinity_destroy_stats(stat, true); + goto retry; + } else { + dev_warn(drv_to_dev_ptr(pool->drv), + "Please increase stat pool limit for apps"); + } + + return app; +} + +static void trinity_stat_pool_put_app(struct trinity_driver *drv, + struct trinity_stat_app *app) +{ + struct trinity_stat_pool *pool =3D drv->stat.pdata; + + /* ensured that the lock is acquired */ + clear_bit(app->slot, pool->bitmap_app); +} + +static struct trinity_stat_req * +trinity_stat_pool_get_req(struct trinity_driver *drv) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_pool *pool =3D stat->pdata; + struct trinity_stat_req *req =3D NULL; + unsigned long slot; + bool retried =3D false; + + /* ensured that the lock is acquired */ +retry: + slot =3D find_first_zero_bit(pool->bitmap_req, TRINITY_STAT_MAX_REQS); + if (slot < TRINITY_STAT_MAX_REQS) { + req =3D &((struct trinity_stat_req *)pool->mem_req.addr)[slot]; + memset(req, '\x00', sizeof(*req)); + set_bit(slot, pool->bitmap_req); + req->slot =3D slot; + } else if (!retried) { + /* retry after destroy old stats */ + retried =3D true; + trinity_destroy_stats(stat, true); + goto retry; + } else { + dev_warn(drv_to_dev_ptr(pool->drv), + "Please increase stat pool limit for reqs"); + } + + return req; +} + +static void trinity_stat_pool_put_req(struct trinity_driver *drv, + struct trinity_stat_req *req) +{ + struct trinity_stat_pool *pool =3D drv->stat.pdata; + + /* ensured that the lock is acquired */ + clear_bit(req->slot, pool->bitmap_req); +} + +/** + * trinity_stat_init(): Initialize trinity statistics + * + * @drv: an instance of the trinity driver + */ +void trinity_stat_init(struct trinity_driver *drv) +{ + unsigned long i; + + spin_lock_init(&drv->stat.lock); + + INIT_LIST_HEAD(&drv->stat.list); + for (i =3D 0; i < TRINITY_STAT_HASH_SIZE; ++i) + INIT_HLIST_BL_HEAD(&drv->stat.hlist[i]); + + trinity_stat_pool_init(drv); + /* initialize to default values */ + trinity_stat_resize(drv, TRINITY_STAT_DEF_APPS, TRINITY_STAT_DEF_REQS, + TRINITY_STAT_DEF_REQS_PER_APP); +} + +/** + * trinity_stat_fini(): Finish trinity statistics + * + * @drv: an instance of the trinity driver + */ +void trinity_stat_fini(struct trinity_driver *drv) +{ + trinity_stat_resize(drv, 0, 0, 0); + trinity_stat_pool_fini(drv); +} + +/** + * trinity_stat_fini(): Finish trinity statistics + * + * @drv: an instance of the trinity driver + * @num_apps: a number of applications + * @num_reqs: a number of requests + * @num_reqs_per_app: a number of requests per application + */ +void trinity_stat_resize(struct trinity_driver *drv, unsigned long num_app= s, + unsigned long num_reqs, unsigned long num_reqs_per_app) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_pool *pool =3D stat->pdata; + unsigned long i; + + if (!pool) + return; + + trinity_stat_lock(&drv->stat); + + for (i =3D 0; i < TRINITY_STAT_HASH_SIZE; i++) { + struct trinity_stat_app *stat_app; + struct hlist_bl_node *hn; + + hlist_bl_lock(&(stat->hlist[i])); + hlist_bl_for_each_entry(stat_app, hn, &(stat->hlist[i]), + hnode) { + if (stat_app->status !=3D TRINITY_APP_STATUS_TERMINATED) { + dev_warn(drv_to_dev_ptr(drv), + "Still busy apps detected.. waiting"); + hlist_bl_unlock(&(stat->hlist[i])); + goto unlock; + } + } + hlist_bl_unlock(&(stat->hlist[i])); + } + + trinity_destroy_stats(stat, true); + + /* re-allocate each stat buffer */ + if (num_apps > 0) + trinity_stat_pool_resize_apps(pool, num_apps); + + if (num_reqs > 0) + trinity_stat_pool_resize_reqs(pool, num_reqs); + + if (num_reqs_per_app > 0) + pool->max_stat_reqs_per_app =3D num_reqs_per_app; + +unlock: + trinity_stat_unlock(&drv->stat); +} + +/** + * trinity_stat_get_max_apps(): Get max statistics size for application + * + * @drv: an instance of the trinity driver + * + * Returns max number of statistics for applications. 0 on error. + */ +unsigned long trinity_stat_get_max_apps(struct trinity_driver *drv) +{ + struct trinity_stat_pool *pool =3D drv->stat.pdata; + unsigned long num; + + if (!pool) + return 0; + + trinity_stat_lock(&drv->stat); + num =3D pool->max_stat_apps; + trinity_stat_unlock(&drv->stat); + + return num; +} + +/** + * trinity_stat_get_max_reqs(): Get max statistics size for requests + * + * @drv: an instance of the trinity driver + * + * Returns max number of statistics for requests. 0 on error. + */ +unsigned long trinity_stat_get_max_reqs(struct trinity_driver *drv) +{ + struct trinity_stat_pool *pool =3D drv->stat.pdata; + unsigned long num; + + if (!pool) + return 0; + + trinity_stat_lock(&drv->stat); + num =3D pool->max_stat_reqs; + trinity_stat_unlock(&drv->stat); + + return num; +} + +/** + * trinity_stat_get_max_reqs(): Get max statistics size for requests per a= pplication + * + * @drv: an instance of the trinity driver + * + * Returns max number of statistics for requests per application. 0 on err= or. + */ +unsigned long trinity_stat_get_max_reqs_per_app(struct trinity_driver *drv) +{ + struct trinity_stat_pool *pool =3D drv->stat.pdata; + unsigned long num; + + if (!pool) + return 0; + + trinity_stat_lock(&drv->stat); + num =3D pool->max_stat_reqs_per_app; + trinity_stat_unlock(&drv->stat); + + return num; +} + +/** + * trinity_stat_lock(): Lock for trinity statistics + * + * @stat: an instance of trinity statistics + */ +void trinity_stat_lock(struct trinity_stat *stat) +{ + if (stat) + spin_lock(&stat->lock); +} + +/** + * trinity_stat_unlock(): Unlock for trinity statistics + * + * @stat: an instance of trinity statistics + */ +void trinity_stat_unlock(struct trinity_stat *stat) +{ + if (stat) + spin_unlock(&stat->lock); +} + +/** + * trinity_create_stat_app() - Create a stat structure for the opened app + * + * @drv: An instance of the trinity driver. + * + * Return: 0 on success. Otherwise, returns negative error. + */ +static int trinity_create_stat_app(struct trinity_driver *drv) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_pool *pool =3D stat->pdata; + struct trinity_stat_app *stat_app; + unsigned long key; + + trinity_stat_lock(stat); + stat_app =3D trinity_stat_pool_get_app(drv); + if (IS_ERR_OR_NULL(stat_app)) { + trinity_stat_unlock(stat); + dev_err(drv_to_dev_ptr(drv), + "Unable to allocate stat of request"); + return -ENOMEM; + } + + stat_app->parent =3D stat; + stat_app->app_id =3D trinity_get_app_id(); + stat_app->total_alloc_mem =3D 0; + stat_app->total_freed_mem =3D 0; + stat_app->num_total_reqs =3D 0; + stat_app->num_kept_reqs =3D 0; + stat_app->num_active_reqs =3D 0; + stat_app->status =3D TRINITY_APP_STATUS_STARTED; + + strncpy(stat_app->name, current->comm, TASK_COMM_LEN); + stat_app->name[TASK_COMM_LEN - 1] =3D '\x00'; + + INIT_HLIST_BL_NODE(&stat_app->hnode); + INIT_LIST_HEAD(&stat_app->reqs); + + key =3D hash_long(stat_app->app_id, TRINITY_STAT_HASH_BITS); + + hlist_bl_lock(&(stat->hlist[key])); + hlist_bl_add_head(&stat_app->hnode, &(stat->hlist[key])); + hlist_bl_unlock(&(stat->hlist[key])); + + list_add_tail(&stat_app->lnode, &stat->list); + pool->cur_stat_apps++; + + /* Remove terminated stats if the number reaches the maximum */ + trinity_destroy_stats(stat, false); + + trinity_stat_unlock(stat); + + return 0; +} + +static void trinity_destroy_stat_req(struct trinity_stat_req *stat_req) +{ + struct trinity_stat_app *stat_app =3D stat_req->parent; + struct trinity_stat *stat =3D stat_app->parent; + struct trinity_driver *drv =3D + container_of(stat, struct trinity_driver, stat); + + if (stat_req->profile) + drv->desc->destroy_profile(drv, stat_req->profile); + list_del(&stat_req->list); + trinity_stat_pool_put_req(drv, stat_req); +} + +static void trinity_destroy_stat_reqs(struct trinity_stat_app *stat_app) +{ + struct trinity_stat_req *stat_req, *tmp; + + list_for_each_entry_safe(stat_req, tmp, &stat_app->reqs, list) + trinity_destroy_stat_req(stat_req); +} + +/** + * trinity_destroy_stats - Destroy terminated stat structures + * + * @drv: An instance of the trinity driver + * @force: force destroy + */ +void trinity_destroy_stats(struct trinity_stat *stat, bool force) +{ + struct trinity_driver *drv =3D + container_of(stat, struct trinity_driver, stat); + struct trinity_stat_pool *pool =3D stat->pdata; + struct trinity_stat_app *stat_app; + struct hlist_bl_node *hn, *tmp; + int i; + + /* lock should be acquired before */ + if (!force && pool->cur_stat_apps <=3D pool->max_stat_apps) + return; + + for (i =3D 0; i < TRINITY_STAT_HASH_SIZE; i++) { + hlist_bl_lock(&stat->hlist[i]); + hlist_bl_for_each_entry_safe(stat_app, hn, tmp, + &(stat->hlist[i]), hnode) { + enum trinity_app_status status =3D stat_app->status; + + if (status =3D=3D TRINITY_APP_STATUS_TERMINATED) { + hlist_bl_del(&stat_app->hnode); + list_del(&stat_app->lnode); + + pool->cur_stat_apps--; + + trinity_destroy_stat_reqs(stat_app); + trinity_stat_pool_put_app(drv, stat_app); + } + } + hlist_bl_unlock(&stat->hlist[i]); + } +} + +static struct trinity_stat_app * +trinity_get_stat_by_id(struct trinity_driver *drv, int32_t app_id) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_app *stat_app; + struct hlist_bl_node *hn; + unsigned long key; + + key =3D hash_long(app_id, TRINITY_STAT_HASH_BITS); + + hlist_bl_lock(&stat->hlist[key]); + hlist_bl_for_each_entry(stat_app, hn, &stat->hlist[key], hnode) { + if (stat_app->app_id =3D=3D app_id) + goto out; + } + stat_app =3D NULL; +out: + hlist_bl_unlock(&stat->hlist[key]); + + return stat_app; +} + +/** + * trinity_get_stat_app() - Get a status structure for the target app + * + * @drv: an instance of the trinity driver. + * + * Returns statistics for application on success. Otherwise, returns NULL. + * + * @note: If the stat is not allocated yet, try to create and return it. + */ +struct trinity_stat_app *trinity_get_stat_app(struct trinity_driver *drv) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_app *stat_app; + int app_id =3D trinity_get_app_id(); + +retry: + trinity_stat_lock(stat); + stat_app =3D trinity_get_stat_by_id(drv, app_id); + trinity_stat_unlock(stat); + + if (!IS_ERR_OR_NULL(stat_app)) + return stat_app; + + if (trinity_create_stat_app(drv) !=3D 0) + return NULL; + + goto retry; +} + +/** + * trinity_stat_app_set_status() - Set a status structure for the target a= pp + * + * @drv: an instance of the trinity driver. + * @status: application status + */ +void trinity_stat_app_set_status(struct trinity_driver *drv, + enum trinity_app_status status) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_app *stat_app; + int app_id =3D trinity_get_app_id(); + + trinity_stat_lock(stat); + stat_app =3D trinity_get_stat_by_id(drv, app_id); + trinity_stat_unlock(stat); + + if (IS_ERR_OR_NULL(stat_app)) + return; + + stat_app->status =3D status; +} + +/** + * trinity_stat_append_req() - Append request information for statistics + * + * @drv: an instance of the trinity driver. + * @req: an instance of request + * + * Return: 0 on success. Otherwise, returns negative error. + */ +int trinity_stat_append_req(struct trinity_driver *drv, struct trinity_req= *req) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_pool *pool =3D stat->pdata; + struct trinity_stat_app *stat_app; + struct trinity_stat_req *stat_req; + + stat_app =3D trinity_get_stat_app(drv); + if (IS_ERR_OR_NULL(stat_app)) + return -ENOMEM; + + trinity_stat_lock(stat); + stat_req =3D trinity_stat_pool_get_req(drv); + if (!stat_req) { + trinity_stat_unlock(stat); + dev_err(drv_to_dev_ptr(drv), + "Unable to allocate stat of request"); + return -ENOMEM; + } + + stat_req->parent =3D stat_app; + stat_req->app_id =3D stat_app->app_id; + stat_req->req_id =3D req->input.config.req_id; + stat_req->model_id =3D req->input.config.model_id; + stat_req->submitted =3D ktime_get(); + stat_req->status =3D TRINITY_REQ_STATUS_PENDING; + stat_req->priority =3D + (enum trinity_req_priority)req->input.config.priority; + stat_req->is_kernel =3D req->is_kernel; + + req->stat =3D stat_req; + + list_add_tail(&stat_req->list, &stat_app->reqs); + + /* don't count kernel requests */ + if (!req->is_kernel) { + if (stat_app->num_kept_reqs =3D=3D pool->max_stat_reqs_per_app) { + struct trinity_stat_req *old_stat; + + old_stat =3D list_first_entry( + &stat_app->reqs, struct trinity_stat_req, list); + /* skip any kernel or unfinished request */ + while (old_stat->is_kernel || + (old_stat->status !=3D + TRINITY_REQ_STATUS_FINISHED && + old_stat->status !=3D TRINITY_REQ_STATUS_ERROR)) + old_stat =3D list_next_entry(old_stat, list); + + WARN_ON(old_stat =3D=3D NULL); + + trinity_destroy_stat_req(old_stat); + stat_app->num_total_reqs--; + } else { + /* total number of user requests kepted */ + stat_app->num_kept_reqs++; + } + } + + stat_app->num_total_reqs++; + stat_app->num_active_reqs++; + + trinity_stat_unlock(stat); + return 0; +} + +/** + * trinity_stat_remove_req() - Remove request information for statistics + * + * @drv: an instance of the trinity driver. + * @req: an instance of the request to be used for statistics + * @rollback: rollback statistics + */ +void trinity_stat_remove_req(struct trinity_driver *drv, + struct trinity_req *req, bool rollback) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_req *stat_req =3D req->stat; + struct trinity_stat_app *stat_app =3D stat_req->parent; + + trinity_stat_lock(stat); + + trinity_destroy_stat_req(stat_req); + + if (!req->is_kernel) { + WARN_ON(stat_app->num_kept_reqs =3D=3D 0); + stat_app->num_kept_reqs--; + } + + if (rollback) { + WARN_ON(stat_app->num_total_reqs =3D=3D 0); + stat_app->num_total_reqs--; + WARN_ON(stat_app->num_active_reqs =3D=3D 0); + stat_app->num_active_reqs--; + } + + trinity_stat_unlock(stat); +} + +/** + * trinity_stat_finish_req() - Finish request for statistics + * + * @drv: an instance of the trinity driver. + * @req: an instance of the request to be used for statistics + */ +void trinity_stat_finish_req(struct trinity_driver *drv, + struct trinity_req *req) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_req *stat_req =3D req->stat; + struct trinity_stat_app *stat_app =3D stat_req->parent; + + trinity_stat_lock(stat); + if (stat_app->num_active_reqs !=3D 0) + stat_app->num_active_reqs--; + else + dev_err(drv_to_dev_ptr(drv), + "Fail to keep track of the active reqs"); + trinity_stat_unlock(stat); +} + +static void copy_stat_app_ioctl(struct trinity_stat_app *stat_app, + struct trinity_ioctl_stat_app *ioctl_stat_app) +{ + ioctl_stat_app->app_id =3D stat_app->app_id; + ioctl_stat_app->status =3D stat_app->status; + ioctl_stat_app->num_total_reqs =3D stat_app->num_total_reqs; + ioctl_stat_app->num_active_reqs =3D stat_app->num_active_reqs; + ioctl_stat_app->total_alloc_mem =3D stat_app->total_alloc_mem; + ioctl_stat_app->total_freed_mem =3D stat_app->total_freed_mem; + + strncpy(ioctl_stat_app->name, stat_app->name, TASK_COMM_LEN); + ioctl_stat_app->name[TASK_COMM_LEN - 1] =3D '\x00'; +} + +static void copy_stat_req_ioctl(struct trinity_stat_req *stat_req, + struct trinity_ioctl_stat_req *ioctl_stat_req) +{ + ktime_t cur_time =3D ktime_get(); + ktime_t submitted, scheduled, completed; + + submitted =3D stat_req->submitted; + scheduled =3D stat_req->scheduled ? stat_req->scheduled : cur_time; + completed =3D stat_req->completed ? stat_req->completed : cur_time; + + ioctl_stat_req->req_id =3D stat_req->req_id; + ioctl_stat_req->model_id =3D stat_req->model_id; + ioctl_stat_req->priority =3D stat_req->priority; + ioctl_stat_req->status =3D stat_req->status; + + if (stat_req->priority =3D=3D TRINITY_REQ_PRIORITY_HIGH) + ioctl_stat_req->sched_time =3D 0; + else + ioctl_stat_req->sched_time =3D TIME_DIFF(scheduled, submitted); + ioctl_stat_req->infer_time =3D TIME_DIFF(completed, scheduled); +} + +/** + * trinity_stat_app_copy_ioctl() - Copy an application's statistics inform= ation to ioctl info + * + * @drv: an instance of the trinity driver. + * @ioctl_stat_app: ioctl statistics information for an application + */ +void trinity_stat_app_copy_ioctl(struct trinity_driver *drv, + struct trinity_ioctl_stat_app *ioctl_stat_app) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_app *stat_app; + int app_id =3D trinity_get_app_id(); + + trinity_stat_lock(stat); + + stat_app =3D trinity_get_stat_by_id(drv, app_id); + if (IS_ERR_OR_NULL(stat_app)) { + ioctl_stat_app->app_id =3D app_id; + ioctl_stat_app->status =3D TRINITY_APP_STATUS_PENDING; + ioctl_stat_app->num_total_reqs =3D 0; + ioctl_stat_app->num_active_reqs =3D 0; + ioctl_stat_app->total_alloc_mem =3D 0; + ioctl_stat_app->total_freed_mem =3D 0; + + strncpy(ioctl_stat_app->name, current->comm, TASK_COMM_LEN); + ioctl_stat_app->name[TASK_COMM_LEN - 1] =3D '\x00'; + } else { + copy_stat_app_ioctl(stat_app, ioctl_stat_app); + } + + trinity_stat_unlock(stat); +} + +/** + * trinity_stat_apps_copy_ioctl() - Copy applications' statistics informat= ion to ioctl info + * + * @drv: an instance of the trinity driver. + * @ioctl_stat_apps: ioctl statistics information for applications + */ +void trinity_stat_apps_copy_ioctl( + struct trinity_driver *drv, + struct trinity_ioctl_stat_apps *ioctl_stat_apps) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_ioctl_stat_app *ioctl_stat_app; + struct trinity_stat_app *stat_app; + uint32_t idx =3D 0; + + trinity_stat_lock(stat); + + list_for_each_entry(stat_app, &stat->list, lnode) { + if (idx >=3D TRINITY_APP_STAT_MAX) + break; + ioctl_stat_app =3D &ioctl_stat_apps->stat[idx++]; + copy_stat_app_ioctl(stat_app, ioctl_stat_app); + } + ioctl_stat_apps->num_apps =3D idx; + + trinity_stat_unlock(stat); +} + +/** + * trinity_stat_app_copy_ioctl() - Copy requests' statistics information t= o ioctl info + * + * @drv: an instance of the trinity driver. + * @ioctl_stat_reqs: ioctl statistics information for requests + */ +void trinity_stat_reqs_copy_ioctl( + struct trinity_driver *drv, + struct trinity_ioctl_stat_reqs *ioctl_stat_reqs) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_ioctl_stat_req *ioctl_stat_req; + struct trinity_stat_app *stat_app; + struct trinity_stat_req *stat_req; + uint32_t idx =3D 0; + + trinity_stat_lock(stat); + stat_app =3D trinity_get_stat_by_id(drv, ioctl_stat_reqs->app_id); + if (IS_ERR_OR_NULL(stat_app)) { + ioctl_stat_reqs->num_reqs =3D 0; + trinity_stat_unlock(stat); + return; + } + + list_for_each_entry(stat_req, &stat_app->reqs, list) { + if (idx >=3D TRINITY_REQ_STAT_MAX) + break; + ioctl_stat_req =3D &ioctl_stat_reqs->stat[idx++]; + copy_stat_req_ioctl(stat_req, ioctl_stat_req); + } + ioctl_stat_reqs->num_reqs =3D idx; + + trinity_stat_unlock(stat); +} + +/** + * trinity_stat_app_total_alloc() - Append allocated size to application's= total memory size + * + * @drv: an instance of the trinity driver. + * @size: allocated memory size + */ +void trinity_stat_app_total_alloc(struct trinity_driver *drv, size_t size) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_app *stat_app; + + stat_app =3D trinity_get_stat_app(drv); + if (IS_ERR_OR_NULL(stat_app)) + return; + + trinity_stat_lock(stat); + stat_app->total_alloc_mem +=3D size; + trinity_stat_unlock(stat); +} + +/** + * trinity_stat_app_total_alloc() - Append freed size to application's tot= al memory size + * + * @drv: an instance of the trinity driver. + * @size: freed memory size + */ +void trinity_stat_app_total_freed(struct trinity_driver *drv, size_t size) +{ + struct trinity_stat *stat =3D &drv->stat; + struct trinity_stat_app *stat_app; + + stat_app =3D trinity_get_stat_app(drv); + if (IS_ERR_OR_NULL(stat_app)) + return; + + trinity_stat_lock(stat); + stat_app->total_freed_mem +=3D size; + trinity_stat_unlock(stat); +} diff --git a/drivers/misc/trinity/trinity_stat.h b/drivers/misc/trinity/tri= nity_stat.h new file mode 100644 index 000000000000..8ae02769efa0 --- /dev/null +++ b/drivers/misc/trinity/trinity_stat.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Statistics header for trinity devices + * + * Copyright (C) 2021-2022 Samsung Electronics + * Copyright (C) 2021 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#ifndef __DRIVERS_MISC_TRINITY_STAT_H__ +#define __DRIVERS_MISC_TRINITY_STAT_H__ + +#include "trinity_common.h" + +void trinity_stat_init(struct trinity_driver *drv); +void trinity_stat_fini(struct trinity_driver *drv); +void trinity_stat_resize(struct trinity_driver *drv, unsigned long num_app= s, + unsigned long num_reqs, + unsigned long num_reqs_per_app); + +void trinity_stat_lock(struct trinity_stat *stat); +void trinity_stat_unlock(struct trinity_stat *stat); +void trinity_destroy_stats(struct trinity_stat *stat, bool force); + +unsigned long trinity_stat_get_max_apps(struct trinity_driver *drv); +unsigned long trinity_stat_get_max_reqs(struct trinity_driver *drv); +unsigned long trinity_stat_get_max_reqs_per_app(struct trinity_driver *drv= ); + +struct trinity_stat_app *trinity_get_stat_app(struct trinity_driver *drv); + +void trinity_stat_app_total_alloc(struct trinity_driver *drv, size_t size); +void trinity_stat_app_total_freed(struct trinity_driver *drv, size_t size); +void trinity_stat_app_set_status(struct trinity_driver *drv, + enum trinity_app_status status); + +int trinity_stat_append_req(struct trinity_driver *drv, + struct trinity_req *req); +void trinity_stat_remove_req(struct trinity_driver *drv, + struct trinity_req *req, bool rollback); +void trinity_stat_finish_req(struct trinity_driver *drv, + struct trinity_req *req); + +void trinity_stat_app_copy_ioctl(struct trinity_driver *drv, + struct trinity_ioctl_stat_app *ioctl_stat_app); + +void trinity_stat_apps_copy_ioctl( + struct trinity_driver *drv, + struct trinity_ioctl_stat_apps *ioctl_stat_apps); + +void trinity_stat_reqs_copy_ioctl( + struct trinity_driver *drv, + struct trinity_ioctl_stat_reqs *ioctl_stat_reqs); + +#endif /* __DRIVERS_MISC_TRINITY_STAT_H__ */ --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8F3CBC6FA86 for ; Sat, 17 Sep 2022 07:25:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229784AbiIQHZG (ORCPT ); Sat, 17 Sep 2022 03:25:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51912 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229586AbiIQHYL (ORCPT ); Sat, 17 Sep 2022 03:24:11 -0400 Received: from mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BF3574660A for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p4.samsung.com (unknown [182.195.41.48]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20220917072400epoutp04e9eb24ac7c989968d5d2bd5ec2cf0816~VlPpVXqey2922529225epoutp04a for ; Sat, 17 Sep 2022 07:24:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20220917072400epoutp04e9eb24ac7c989968d5d2bd5ec2cf0816~VlPpVXqey2922529225epoutp04a DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399440; bh=5a/BnlnQRTvHHNMfzW0p6Kh/TK/IEGj6x3FCiDvaWAY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Noklfz0/FKyX+BApegXpNZJ2UewOrTFVj+NXIvtdzkrdp8YFhoK1Zp/hiKr/5lWW6 bCnqMXsQUIeoDICtnrA93x37VwPypAhTgrgrQuLKf99ry8tnda0sOjSlgLpkXTWoot auf90EMUbRWzXlzfAc9niyzghjJZYLVvT9NZkHkY= Received: from epsnrtp3.localdomain (unknown [182.195.42.164]) by epcas1p1.samsung.com (KnoxPortal) with ESMTP id 20220917072359epcas1p1a8c1c62d85e7ac1d7472c6af6ca9bbdf~VlPouCTi10249402494epcas1p1T; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) Received: from epsmges1p2.samsung.com (unknown [182.195.36.136]) by epsnrtp3.localdomain (Postfix) with ESMTP id 4MV2Vk5MQzz4x9Pw; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epcas1p4.samsung.com ( [182.195.41.48]) by epsmges1p2.samsung.com (Symantec Messaging Gateway) with SMTP id 1C.71.51827.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas1p4.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epcas1p485a1cdcb71cc01274db1c8d00aec197c~VlPnMPIew2368123681epcas1p4P; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220917072357epsmtrp206e5927fc66f6671fd38d22df9072977~VlPnLl12g1654916549epsmtrp2y; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) X-AuditID: b6c32a36-f25ff7000000ca73-29-6325760e3850 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id C3.45.14392.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epsmtip21404d459ae3a75a49891fe7cd5f1c788~VlPm75ucJ3200932009epsmtip2X; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 07/13] trinity: Add sysfs module Date: Sat, 17 Sep 2022 16:23:50 +0900 Message-Id: <20220917072356.2255620-8-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupnk+LIzCtJLcpLzFFi42LZdljTQJevTDXZoKdJ3eLvpGPsFlMfPmGz aF68ns3iffduZou9r7eyW1zeNYfN4nbjCjaLfT0fGS2eT7vO4sDp8fvXJEaPTas62TzuXNvD 5rF/7hp2j74tqxg9Pm+SC2CLyrbJSE1MSS1SSM1Lzk/JzEu3VfIOjneONzUzMNQ1tLQwV1LI S8xNtVVy8QnQdcvMAbpKSaEsMacUKBSQWFyspG9nU5RfWpKqkJFfXGKrlFqQklNgWqBXnJhb XJqXrpeXWmJlaGBgZApUmJCdsevETqaC+bsZK64tX8TcwPhsCmMXIyeHhICJxLkzs4FsLg4h gR2MEh07+5hBEkICnxglVl1UgEh8Y5Q49mMBexcjB1jH37VlEPG9jBJXez+zQTifGSV2LP7O DtLNJqAqMXPGGjBbRKBconnjCTCbWSBH4smdJrANwgLGEjMOfwGzWYDq33xeAmbzClhLzLtw hQnE5hSwkbi5qYkFIi4ocXLmExaIOfISzVtnM4MslhD4yS4xtbeXCeIfF4kt85czQ9jCEq+O b2GHsKUkPr/bywZhZ0tM6VjEAmEXSJx7vpUZ4jNjiYsrUkBMZgFNifW79CEqFCV2/p7LCLGW T+Ld1x5WiGpeiY42IYgSJYklfw5DLZKQmDrjG9QxHhLdj7ezQIKnn1Hi+MZvrBMY5Wch+WYW km9mIWxewMi8ilEstaA4Nz212LDACB6ryfm5mxjBKVPLbAfjpLcf9A4xMnEwHmKU4GBWEuFV 9VRJFuJNSaysSi3Kjy8qzUktPsRoCgzficxSosn5wKSdVxJvaGJpYGJmZGxiYWhmqCTOq6fN mCwkkJ5YkpqdmlqQWgTTx8TBKdXAJOKYu2Szi+vttPDzYjWciqcKbs9RW7XM6pKAXNuFCx/+ PGPq5GFY4azYJrkuUPEVj97+76I5LE2i8VbGNr+2/f/MJOz0J2W32szKFhm/+xPOzyuvuzkh 9L5N3HT7aYGpy1LuPHM4auvpv0okk7t7HvdVjRbt7eesL/85orY3T2nTv5czWn0SQ2a4m2j/ fzo3MCbx9tTl6T/mveNKWfJvaUL6ylztqbVpM8IkY9dcqhE4yflwrWnRgX9e4oF5D+NfcVj8 CYms9uvPO6Wkv40r9am/uJ3v6VWMJ2v+M9bMuu9flpHzVOnYBpMAo+fsRmKt/3RXuB1e8r/7 5hY57Z8m9zPXbpzT1cYxT3VOdG+qEktxRqKhFnNRcSIA/fDP6yIEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrFLMWRmVeSWpSXmKPExsWy7bCSvC5vmWqywcL1phZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAlfGrhM7mQrm72asuLZ8EXMD47MpjF2M HBwSAiYSf9eWdTFycQgJ7GaUmDx/DksXIydQXEJi073lzBA1whKHDxdD1HxklGia8JYJpIZN QFVi5ow17CC2iECtxMGj85lBbGaBAonZT2eCzREWMJaYcfgLWJwFqP7N5yVgNq+AtcS8C1fA 5nAK2Ejc3NQEVi8EFJ89fS4TRI2gxMmZT1ggZspLNG+dzTyBkX8WktQsJKkFjEyrGCVTC4pz 03OLDQsM81LL9YoTc4tL89L1kvNzNzGCg1tLcwfj9lUf9A4xMnEwHmKU4GBWEuFV9VRJFuJN SaysSi3Kjy8qzUktPsQozcGiJM57oetkvJBAemJJanZqakFqEUyWiYNTqoFp2a1nwpY/Xv+9 rmHk8uq27g+Z9YuWtT1M2rKgxXPD985P0TeEpr+t3PP5WHhatOX9tQU980+vWHnst96Ljyxr LTIL/+ruOvPUbPOFp1zPZdlVkvL7ApW8Qu8tONG15d0sFR2L3jQOt7UVBny1q9nO/GBoCio3 uj5joWdeSK3Pe47nTmLvtrydd91cN9I66PzXat5jx5jmXVcNfr30xN3EeIkdgjWJ/vNOLJys kc1vXnmkyOz688pP53fsPPX3t/pK81URnq+FplxZLrJcenq56F+t89cPN3kt9HG7/E1Oe4KB s2HDpC2tHEeXBs89cMTlRdA9zro3e3gZudKeb6t3exUX9Y899kTfm6pPh8If2SixFGckGmox FxUnAgDt1Ozw3QIAAA== X-CMS-MailID: 20220917072357epcas1p485a1cdcb71cc01274db1c8d00aec197c X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072357epcas1p485a1cdcb71cc01274db1c8d00aec197c References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch includes sysfs interfaces. sysfs interface provides NPU's internal statistics, status and control attribes. The sysfs information provided by the Trinity are: - IDU version - profiling result - allocated debugfs buffer The control attributes are including: - initialize profile operation - NPU control (suspend/resume/stop) Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong Signed-off-by: Dongju Chae Signed-off-by: MyungJoo Ham --- .../ABI/testing/sysfs-driver-trinity | 55 ++ drivers/misc/trinity/Makefile | 1 + drivers/misc/trinity/trinity_sysfs.c | 667 ++++++++++++++++++ 3 files changed, 723 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-trinity create mode 100644 drivers/misc/trinity/trinity_sysfs.c diff --git a/Documentation/ABI/testing/sysfs-driver-trinity b/Documentation= /ABI/testing/sysfs-driver-trinity new file mode 100644 index 000000000000..754e6f36a1dc --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-trinity @@ -0,0 +1,55 @@ +What: /sys/devices/platform/trinity/*.triv2/debug/debugfs_max +Date: July 2022 +KernelVersion: 5.19-rc8 +Contact: Jiho Chu +Description: Shows current allocated debugfs entry size. + Note that, Writing max entry size allocates NPU's hardware + memory for debugfs entries. + +What: /sys/devices/platform/trinity/*.triv2/debug/idu_version +Date: July 2022 +KernelVersion: 5.19-rc8 +Contact: Jiho Chu +Description: Shows IDU version + +What: /sys/devices/platform/trinity/*.triv2/debug/show_profile +Date: July 2022 +Contact: Jiho Chu +KernelVersion: 5.19-rc8 +Description: Shows profile information. + After writing Request ID, it shows information for the + request. This includes number of total cycles, number of + total operations and further information + (read/write count etc.) for each operation. + +What: /sys/devices/platform/trinity/*.triv2/control/profile +Date: July 2022 +Contact: Jiho Chu +Description: Initialize NPU profile operation with profile size. + It allocates NPU's hardware memory and activate profile + operation in NPU. Note that, write memory size in Byte. + +What: /sys/devices/platform/trinity/*.triv2/control/reset +Date: July 2022 +KernelVersion: 5.19-rc8 +Contact: Jiho Chu +Description: Resets NPU and reload IDU binary. + +What: /sys/devices/platform/trinity/*.triv2/control/resume +Date: July 2022 +KernelVersion: 5.19-rc8 +Contact: Jiho Chu +Description: Resume NPU operation + +What: /sys/devices/platform/trinity/*.triv2/control/suspend +Date: July 2022 +KernelVersion: 5.19-rc8 +Contact: Jiho Chu +Description: Enter suspend state + +What: /sys/devices/platform/trinity/*.triv2/control/stop +Date: July 2022 +KernelVersion: 5.19-rc8 +Contact: Jiho Chu +Description: Cancels all NPU workloads. + diff --git a/drivers/misc/trinity/Makefile b/drivers/misc/trinity/Makefile index b475938a0db6..462b7c61f39f 100644 --- a/drivers/misc/trinity/Makefile +++ b/drivers/misc/trinity/Makefile @@ -7,5 +7,6 @@ trinity-y +=3D trinity_dma.o trinity_hwmem.o trinity-y +=3D trinity_sched.o trinity-y +=3D trinity_debug.o trinity-y +=3D trinity_stat.o +trinity-y +=3D trinity_sysfs.o =20 trinity_vision2-objs :=3D $(trinity-y) trinity_vision2_drv.o diff --git a/drivers/misc/trinity/trinity_sysfs.c b/drivers/misc/trinity/tr= inity_sysfs.c new file mode 100644 index 000000000000..d716607efa28 --- /dev/null +++ b/drivers/misc/trinity/trinity_sysfs.c @@ -0,0 +1,667 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Sysfs interface for Samsung Research Trinity device family + * + * Copyright (C) 2020-2022 Samsung Electronics + * Copyright (C) 2020 Dongju Chae + * Copyright (C) 2020 Wook Song + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#include +#include + +#include "trinity_common.h" +#include "trinity_stat.h" + +enum trinity_sysfs_msg { + SYSFS_MSG_NORMAL =3D 0, + SYSFS_MSG_PROLOGUE, + SYSFS_MSG_EPILOGUE, + SYSFS_MSG_EMIT, +}; + +static ssize_t debugfs_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + unsigned long msg_max; + int32_t ret =3D 0; + + ret =3D kstrtoul(buf, 10, &msg_max); + if (ret !=3D 0) + return -EINVAL; + + trinity_debug_clear(drv, msg_max); + + return count; +} + +static ssize_t debugfs_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%lu\n", trinity_debug_get_max(drv)); +} +static DEVICE_ATTR_RW(debugfs_max); + +static ssize_t show_profile_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + unsigned long val; + int32_t ret =3D 0; + + ret =3D kstrtoul(buf, 10, &val); + if (ret !=3D 0) + return -EINVAL; + + drv->profile_req_id =3D val; + + return count; +} + +static ssize_t show_profile_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + if (!drv->desc->get_profile) + return snprintf(buf, PAGE_SIZE, "profile is not supported\n"); + + if (drv->profile_req_id < 0) + return snprintf(buf, PAGE_SIZE, "invalid request id(%d)\n", + drv->profile_req_id); + + return drv->desc->get_profile(drv, buf, drv->profile_req_id); +} +static DEVICE_ATTR_RW(show_profile); + +static ssize_t idu_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + if (drv->desc->idu_version) { + uint32_t major, minor, extra; + + if (drv->desc->idu_version(drv, &major, &minor, &extra) =3D=3D 0) + return snprintf(buf, PAGE_SIZE, "v%u.%u.%u\n", major, + minor, extra); + } + + return snprintf(buf, PAGE_SIZE, + "Unknown... v0.30.7 or higher version required.\n"); +} +static DEVICE_ATTR_RO(idu_version); + +static struct attribute *trinity_attrs_debug[] =3D { + &dev_attr_debugfs_max.attr, &dev_attr_show_profile.attr, + &dev_attr_idu_version.attr, NULL +}; + +/* e.g, /sys/devices/platform/304f0000.triv2/debug/ */ +static struct attribute_group trinity_attrs_debug_group =3D { + .name =3D "debug", + .attrs =3D trinity_attrs_debug +}; + +static ssize_t max_stat_apps_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + unsigned long val; + int32_t ret =3D 0; + + ret =3D kstrtoul(buf, 10, &val); + if (ret !=3D 0) + return -EINVAL; + + trinity_stat_resize(drv, val, 0, 0); + + return count; +} + +static ssize_t max_stat_apps_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%lu\n", + trinity_stat_get_max_apps(drv)); +} +static DEVICE_ATTR_RW(max_stat_apps); + +static ssize_t max_stat_reqs_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + unsigned long val; + int32_t ret =3D 0; + + ret =3D kstrtoul(buf, 10, &val); + if (ret !=3D 0) + return -EINVAL; + + trinity_stat_resize(drv, 0, val, 0); + + return count; +} + +static ssize_t max_stat_reqs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%lu\n", + trinity_stat_get_max_reqs(drv)); +} +static DEVICE_ATTR_RW(max_stat_reqs); + +static ssize_t max_stat_reqs_per_app_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + unsigned long val; + int32_t ret =3D 0; + + ret =3D kstrtoul(buf, 10, &val); + if (ret !=3D 0) + return -EINVAL; + + trinity_stat_resize(drv, 0, 0, val); + + return count; +} + +static ssize_t max_stat_reqs_per_app_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%lu\n", + trinity_stat_get_max_reqs_per_app(drv)); +} +static DEVICE_ATTR_RW(max_stat_reqs_per_app); + +static ssize_t mem_usage_show(struct device *dev, struct device_attribute = *attr, + char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + struct trinity_stat_app *stat_app; + ssize_t pos =3D 0; + bool first =3D true; + + trinity_stat_lock(&drv->stat); + + list_for_each_entry(stat_app, &drv->stat.list, lnode) { + if (first) { + pos +=3D snprintf( + buf + pos, PAGE_SIZE, + "Memory usage statistics for all opened devices\n"); + first =3D false; + } + + pos +=3D snprintf( + buf + pos, PAGE_SIZE, + " [%d] total_alloc: %llu bytes, total_freed: %llu bytes\n", + stat_app->app_id, stat_app->total_alloc_mem, + stat_app->total_freed_mem); + } + + if (first) + pos +=3D snprintf(buf + pos, PAGE_SIZE, "No active devices\n"); + + trinity_stat_unlock(&drv->stat); + + return pos; +} +static DEVICE_ATTR_RO(mem_usage); + +#define MODEL_REGISTERED_PROLOGUE \ + "\n Model statistics registered in all opened devices\n" \ + "+--------------+--------------+-----------+------------+\n" \ + "| Model ID | Model Size | Dmabuf FD | Offset |\n" \ + "+--------------+--------------+-----------+------------+\n" +#define MODEL_REGISTERED_NORMAL "| %#12llx | %#12llx | %9d | %#10llx |\n" +#define MODEL_REGISTERED_EPILOGUE \ + "+--------------+--------------+-----------+------------+\n" + +static ssize_t print_registered_models(const struct trinity_model *model, + char *buf, enum trinity_sysfs_msg msg) +{ + ssize_t pos =3D 0; + + switch (msg) { + case SYSFS_MSG_PROLOGUE: + pos =3D snprintf(buf, PAGE_SIZE, MODEL_REGISTERED_PROLOGUE); + break; + case SYSFS_MSG_NORMAL: + pos =3D snprintf(buf, PAGE_SIZE, MODEL_REGISTERED_NORMAL, + model->config.id, model->config.program_size, + model->config.dbuf_fd, + model->config.program_offset_addr); + break; + case SYSFS_MSG_EPILOGUE: + pos =3D snprintf(buf, PAGE_SIZE, MODEL_REGISTERED_EPILOGUE); + break; + default: + break; + } + + return pos; +} + +static ssize_t registered_models_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + struct hlist_bl_head *model_htable; + struct trinity_model *model; + struct hlist_bl_node *hn; + ssize_t pos; + int i, num_printed =3D 0; + + model_htable =3D drv->model_htable; + + pos =3D print_registered_models(NULL, buf, SYSFS_MSG_PROLOGUE); + + for (i =3D 0; i < TRINITY_MODEL_HASH_SIZE; i++) { + hlist_bl_lock(model_htable + i); + hlist_bl_for_each_entry(model, hn, model_htable + i, hnode) { + pos +=3D print_registered_models(model, buf + pos, + SYSFS_MSG_NORMAL); + num_printed++; + } + hlist_bl_unlock(model_htable + i); + } + + if (num_printed > 0) + pos +=3D print_registered_models(NULL, buf + pos, + SYSFS_MSG_EPILOGUE); + + return pos; +} +static DEVICE_ATTR_RO(registered_models); + +static const char *priority_to_string(enum trinity_req_priority priority) +{ + static const char *const priority_strings[] =3D { + [TRINITY_REQ_PRIORITY_LOW] =3D "Low", + [TRINITY_REQ_PRIORITY_MID] =3D "Mid", + [TRINITY_REQ_PRIORITY_HIGH] =3D "High", + }; + return priority_strings[priority]; +} + +static const char *status_to_string(enum trinity_req_status status) +{ + static const char *const status_strings[] =3D { + [TRINITY_REQ_STATUS_UNKNOWN] =3D "Unknown", + [TRINITY_REQ_STATUS_ERROR] =3D "Error", + [TRINITY_REQ_STATUS_PENDING] =3D "Pending", + [TRINITY_REQ_STATUS_RUNNING] =3D "Running", + [TRINITY_REQ_STATUS_FINISHED] =3D "Finished", + }; + return status_strings[status]; +} + +#define APP_STATUS_LENGTH (77) +#define USER_APP_STATUS_PROLOGUE = \ + "\n\tUser-level request statistics running in %s\n" = \ + "+-------+--------+----------+------+----------+--------------+----------= ---+\n" \ + "| PID | Req ID | Model ID | Prio | Status | Sched (us) | Infer (u= s) |\n" \ + "+-------+--------+----------+------+----------+--------------+----------= ---+\n" +#define USER_APP_STATUS_NORMAL \ + "| %5d | %6d | %#8llx | %4s | %8s | %12lld | %11lld |\n" +#define USER_APP_STATUS_EMIT \ + "| ... (emitted) ... = |\n" +#define USER_APP_STATUS_EPILOGUE \ + "+-------+--------+----------+------+----------+--------------+----------= ---+\n" + +static ssize_t print_user_app_status(struct device *dev, + const struct trinity_stat_req *req, + char *buf, enum trinity_sysfs_msg msg) +{ + ssize_t pos =3D 0; + + switch (msg) { + case SYSFS_MSG_PROLOGUE: + pos =3D snprintf(buf, APP_STATUS_LENGTH * 4 + 1, + USER_APP_STATUS_PROLOGUE, dev_name(dev)); + break; + case SYSFS_MSG_NORMAL: { + ktime_t cur_time =3D ktime_get(); + ktime_t submitted =3D req->submitted; + ktime_t scheduled =3D req->scheduled ? req->scheduled : cur_time; + ktime_t completed =3D req->completed ? req->completed : cur_time; + + int64_t sched_diff =3D TIME_DIFF_US(scheduled, submitted); + int64_t infer_diff =3D TIME_DIFF_US(completed, scheduled); + + if (req->status =3D=3D TRINITY_REQ_STATUS_ERROR) { + sched_diff =3D 0; + infer_diff =3D 0; + } + + pos =3D snprintf(buf, APP_STATUS_LENGTH + 1, + USER_APP_STATUS_NORMAL, req->app_id, req->req_id, + req->model_id, priority_to_string(req->priority), + status_to_string(req->status), sched_diff, + infer_diff); + } break; + case SYSFS_MSG_EMIT: + pos =3D snprintf(buf, APP_STATUS_LENGTH + 1, + USER_APP_STATUS_EMIT); + break; + case SYSFS_MSG_EPILOGUE: + pos =3D snprintf(buf, APP_STATUS_LENGTH + 1, + USER_APP_STATUS_EPILOGUE); + break; + default: + break; + } + + return pos; +} + +#define KERNEL_APP_STATUS_PROLOGUE = \ + "\n\tKernel-level request statistics running in %s\n" = \ + "+-------+--------+----------+------+----------+------------+------------= ---+\n" \ + "| PID | Req ID | Model ID | Prio | Status | # Runs | Avg. Lat (u= s) |\n" \ + "+-------+--------+----------+------+----------+------------+------------= ---+\n" +#define KERNEL_APP_STATUS_NORMAL \ + "| %5d | %6d | %#8llx | %4s | %8s | %10u | %13u |\n" +#define KERNEL_APP_STATUS_EMIT \ + "| ... (emitted) ... = |\n" +#define KERNEL_APP_STATUS_EPILOGUE \ + "+-------+--------+----------+------+----------+------------+------------= ---+\n" + +static ssize_t print_kernel_app_status(struct device *dev, + const struct trinity_stat_req *req, + char *buf, enum trinity_sysfs_msg msg) +{ + ssize_t pos =3D 0; + + switch (msg) { + case SYSFS_MSG_PROLOGUE: + pos =3D snprintf(buf, APP_STATUS_LENGTH * 4 + 1, + KERNEL_APP_STATUS_PROLOGUE, dev_name(dev)); + break; + case SYSFS_MSG_NORMAL: { + uint32_t avg_latency =3D 0; + + if (req->num_runs > 0) + avg_latency =3D req->total_time / req->num_runs; + + pos =3D snprintf(buf, APP_STATUS_LENGTH + 1, + KERNEL_APP_STATUS_NORMAL, req->app_id, + req->req_id, req->model_id, + priority_to_string(req->priority), + status_to_string(req->status), req->num_runs, + avg_latency); + } break; + case SYSFS_MSG_EMIT: + pos =3D snprintf(buf, APP_STATUS_LENGTH + 1, + KERNEL_APP_STATUS_EMIT); + break; + case SYSFS_MSG_EPILOGUE: + pos =3D snprintf(buf, APP_STATUS_LENGTH + 1, + KERNEL_APP_STATUS_EPILOGUE); + break; + default: + break; + } + + return pos; +} + +static ssize_t app_status_user_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + struct trinity_stat_app *stat_app; + struct trinity_stat_req *stat_req; + int num_printed =3D 0; + ssize_t pos; + + pos =3D print_user_app_status(dev, NULL, buf, SYSFS_MSG_PROLOGUE); + + trinity_stat_lock(&drv->stat); + list_for_each_entry(stat_app, &drv->stat.list, lnode) { + list_for_each_entry(stat_req, &stat_app->reqs, list) { + if (stat_req->is_kernel) + continue; + + pos +=3D print_user_app_status(dev, stat_req, buf + pos, + SYSFS_MSG_NORMAL); + num_printed++; + + /* buffer size limit: PAGE_SIZE (also need reserved bytes) */ + if (pos + APP_STATUS_LENGTH > + PAGE_SIZE - 2 * APP_STATUS_LENGTH) { + pos +=3D print_user_app_status( + dev, NULL, buf + pos, SYSFS_MSG_EMIT); + /* clear old stats */ + trinity_destroy_stats(&drv->stat, true); + goto out; + } + } + } +out: + trinity_stat_unlock(&drv->stat); + + if (num_printed > 0) + pos +=3D print_user_app_status(dev, NULL, buf + pos, + SYSFS_MSG_EPILOGUE); + + return pos; +} +static DEVICE_ATTR_RO(app_status_user); + +static ssize_t app_status_kernel_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + struct trinity_stat_app *stat_app; + struct trinity_stat_req *stat_req; + int num_printed =3D 0; + ssize_t pos; + + pos =3D print_kernel_app_status(dev, NULL, buf, SYSFS_MSG_PROLOGUE); + + trinity_stat_lock(&drv->stat); + list_for_each_entry(stat_app, &drv->stat.list, lnode) { + list_for_each_entry(stat_req, &stat_app->reqs, list) { + if (!stat_req->is_kernel) + continue; + + pos +=3D print_kernel_app_status(dev, stat_req, buf + pos, + SYSFS_MSG_NORMAL); + num_printed++; + + /* buffer size limit: PAGE_SIZE (also need reserved bytes) */ + if (pos + APP_STATUS_LENGTH > + PAGE_SIZE - 2 * APP_STATUS_LENGTH) { + pos +=3D print_kernel_app_status( + dev, NULL, buf + pos, SYSFS_MSG_EMIT); + /* clear old stats */ + trinity_destroy_stats(&drv->stat, true); + goto out; + } + } + } +out: + trinity_stat_unlock(&drv->stat); + + if (num_printed > 0) + pos +=3D print_kernel_app_status(dev, NULL, buf + pos, + SYSFS_MSG_EPILOGUE); + + return pos; +} +static DEVICE_ATTR_RO(app_status_kernel); + +static ssize_t num_total_reqs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + struct trinity_stat_app *stat_app; + uint32_t num_total_reqs =3D 0; + + trinity_stat_lock(&drv->stat); + list_for_each_entry(stat_app, &drv->stat.list, lnode) { + num_total_reqs +=3D stat_app->num_total_reqs; + } + trinity_stat_unlock(&drv->stat); + + return snprintf(buf, PAGE_SIZE, "%u\n", num_total_reqs); +} +static DEVICE_ATTR_RO(num_total_reqs); + +static ssize_t num_active_reqs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + struct trinity_stat_app *stat_app; + uint32_t num_active_reqs =3D 0; + + trinity_stat_lock(&drv->stat); + list_for_each_entry(stat_app, &drv->stat.list, lnode) { + num_active_reqs +=3D stat_app->num_active_reqs; + } + trinity_stat_unlock(&drv->stat); + + return snprintf(buf, PAGE_SIZE, "%u\n", num_active_reqs); +} +static DEVICE_ATTR_RO(num_active_reqs); + +static struct attribute *trinity_attrs_stat[] =3D { + &dev_attr_max_stat_apps.attr, &dev_attr_max_stat_reqs.attr, + &dev_attr_max_stat_reqs_per_app.attr, &dev_attr_mem_usage.attr, + &dev_attr_registered_models.attr, &dev_attr_app_status_user.attr, + &dev_attr_app_status_kernel.attr, &dev_attr_num_total_reqs.attr, + &dev_attr_num_active_reqs.attr, NULL +}; + +/* e.g, /sys/devices/platform/304f0000.triv2/stat/ */ +static struct attribute_group trinity_attrs_stat_group =3D { + .name =3D "stat", + .attrs =3D trinity_attrs_stat +}; + +static ssize_t stop_store(struct device *dev, struct device_attribute *att= r, + const char *buf, size_t count) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + if (drv->desc->stop_reqs) + schedule_work(&drv->work_stop); + + return count; +} +static DEVICE_ATTR_WO(stop); + +static ssize_t suspend_store(struct device *dev, struct device_attribute *= attr, + const char *buf, size_t count) +{ + if (dev->driver->pm) + dev->driver->pm->runtime_suspend(dev); + + return count; +} +static DEVICE_ATTR_WO(suspend); + +static ssize_t resume_store(struct device *dev, struct device_attribute *a= ttr, + const char *buf, size_t count) +{ + if (dev->driver->pm) + dev->driver->pm->runtime_resume(dev); + + return count; +} +static DEVICE_ATTR_WO(resume); + +static ssize_t profile_store(struct device *dev, struct device_attribute *= attr, + const char *buf, size_t count) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + unsigned long profile; + + if (kstrtoul(buf, 10, &profile) !=3D 0) + return 0; + + /** Note that this interface is used only for testing purpose */ + if (drv->desc->init_profile) + drv->desc->init_profile(drv, profile); + + return count; +} +static DEVICE_ATTR_WO(profile); + +static ssize_t reset_store(struct device *dev, struct device_attribute *at= tr, + const char *buf, size_t count) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + unsigned long reset; + + if (kstrtoul(buf, 10, &reset) !=3D 0) + return 0; + + if (reset =3D=3D 1 && drv->desc->reset) + drv->desc->reset(drv); + + return count; +} +static DEVICE_ATTR_WO(reset); + +static struct attribute *trinity_attrs_control[] =3D { &dev_attr_stop.attr, + &dev_attr_suspend.attr, + &dev_attr_resume.attr, + &dev_attr_profile.attr, + &dev_attr_reset.attr, + NULL }; + +/* e.g, /sys/devices/platform/304f0000.triv2/control/ */ +static struct attribute_group trinity_attrs_control_group =3D { + .name =3D "control", + .attrs =3D trinity_attrs_control +}; + +static const struct attribute_group *trinity_attrs_groups[] =3D { + &trinity_attrs_debug_group, &trinity_attrs_stat_group, + &trinity_attrs_control_group, NULL +}; + +int trinity_sysfs_init(struct trinity_driver *drv) +{ + struct device *dev =3D drv_to_dev_ptr(drv); + int err; + + err =3D device_add_groups(dev, trinity_attrs_groups); + if (err < 0) { + dev_err(dev, "failed to create sysfs groups\n"); + return err; + } + + return 0; +} + +int trinity_sysfs_cleanup(struct trinity_driver *drv) +{ + struct device *dev =3D drv_to_dev_ptr(drv); + + device_remove_groups(dev, trinity_attrs_groups); + + return 0; +} --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D387C6FA86 for ; Sat, 17 Sep 2022 07:25:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229803AbiIQHZN (ORCPT ); Sat, 17 Sep 2022 03:25:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51922 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229609AbiIQHYL (ORCPT ); Sat, 17 Sep 2022 03:24:11 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CF3C1476DA for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p3.samsung.com (unknown [182.195.41.47]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220917072400epoutp039ceba28de3c67ead0b3c47740b47b259~VlPps8gLG1145411454epoutp03A for ; Sat, 17 Sep 2022 07:24:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220917072400epoutp039ceba28de3c67ead0b3c47740b47b259~VlPps8gLG1145411454epoutp03A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399440; bh=+ZbMTYZdc/DppQc8gTghPumZLSaPGhkJy35PEUzyPbY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=euOfVxRax6j7Gh4yMqsPjtxVQcjVujSrkdYsOztboVK/zpNpF8+CDJYL2oBmDMwq0 sDRfsNcqDN29zhJygmJa5BIpBNgj9gX7MFv97rM9N8jRuX5tirlXOj7O4f7Wn39j5i kXgpqwEz7yyspKZnxFqyLwjrIpx2pQOqQHRvz9c0= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas1p3.samsung.com (KnoxPortal) with ESMTP id 20220917072359epcas1p335f20463169d487198d531be5ee88a01~VlPozHWEd0974609746epcas1p3T; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) Received: from epsmges1p5.samsung.com (unknown [182.195.36.134]) by epsnrtp2.localdomain (Postfix) with ESMTP id 4MV2Vk5SPqz4x9Pv; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epcas1p4.samsung.com ( [182.195.41.48]) by epsmges1p5.samsung.com (Symantec Messaging Gateway) with SMTP id DA.6D.64988.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas1p1.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epcas1p14543c842bdf0b6f719d4e0d2ed3bf33c~VlPnVUmM00249402494epcas1p1R; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220917072358epsmtrp2ec28762b123305909a1758346f9b0539~VlPnUl4um1654916549epsmtrp2z; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) X-AuditID: b6c32a39-8d3fa7000001fddc-77-6325760e7ea5 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id 65.F0.18644.D0675236; Sat, 17 Sep 2022 16:23:57 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epsmtip20edd88af62c0bb48c9a7c507ca4e7b7b~VlPnDfWyK3199331993epsmtip2Z; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 08/13] trinity: Add ioctl feature Date: Sat, 17 Sep 2022 16:23:51 +0900 Message-Id: <20220917072356.2255620-9-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprAJsWRmVeSWpSXmKPExsWy7bCmgS5fmWqywaI2dYu/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtKtsmIzUxJbVIITUvOT8lMy/dVsk7ON453tTMwFDX0NLCXEkh LzE31VbJxSdA1y0zB+gqJYWyxJxSoFBAYnGxkr6dTVF+aUmqQkZ+cYmtUmpBSk6BaYFecWJu cWleul5eaomVoYGBkSlQYUJ2xry7D1kL9rYyVmw99pK1gXFZdhcjJ4eEgInEkf6JzF2MXBxC AjsYJU7uvMQI4XxilLi7YQMrhPOZUeLLoV/sMC031xxjg0jsYpS4teIbO1zVh8n/warYBFQl Zs5YA2aLCJRLNG88AWYzC+RIPLnTxAxiCwNNWt30DizOAlQ/bVYjC4jNK2AtseptL1icU8BG 4uamJqi4oMTJmU9YIObISzRvnQ12uITAR3aJrX+mMEOc5yLxfflrVghbWOLV8S1QZ0tJfH63 lw3CzpaY0rGIBcIukDj3fCtQLweQbSxxcUUKiMksoCmxfpc+RIWixM7fcxkh1vJJvPvawwpR zSvR0SYEUaIkseTPYahFEhJTZ3xjgrA9JM49PAAN0X5GiZXTDzNPYJSfheSbWUi+mYWweQEj 8ypGsdSC4tz01GLDAlN4tCbn525iBCdNLcsdjNPfftA7xMjEwXiIUYKDWUmEV9VTJVmINyWx siq1KD++qDQntfgQoykwfCcyS4km5wPTdl5JvKGJpYGJmZGxiYWhmaGSOK+eNmOykEB6Yklq dmpqQWoRTB8TB6dUA9NuyWX39vStn3ttqRtnGuPyWZ+uRzlnTXz5yOvhKh9uiQen/jTeD1M0 eP7z33L7B0UpU5cm7J7WunTm8WtbLoQK3FM40x55mffXNKXX39O/lp9aM3Hxf4WzZvPafhb1 SjzcWbnl5MITEaz71HdPvpLG+a1YmGOmaOo0L8UE90383vcD95qycwY3KLSLHelWzJid1ruq +scX3syGAx0h2juq7/S5WXzaK8nG+eDviffSLAnPm7TmXr24Jm5G4dU8Po5b2a8ezhJbYv3V W0t8XdIhdY1y9gVutZP7jGJ0rGZ0dGr9NJ1VU5/sszNua86Or0+XfRMumdbOZ9p5xGdDdYzF v2QrFu1q0QPl9b9PyDgpsRRnJBpqMRcVJwIA8MB1ViMEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrJLMWRmVeSWpSXmKPExsWy7bCSvC5fmWqywV4Ri7+TjrFbTH34hM2i efF6Nov33buZLfa+3spucXnXHDaL240r2Cz29XxktHg+7TqLA6fH71+TGD02repk87hzbQ+b x/65a9g9+rasYvT4vEkugC2KyyYlNSezLLVI3y6BK2Pe3YesBXtbGSu2HnvJ2sC4LLuLkZND QsBE4uaaY2xdjFwcQgI7GCW6Xmxkg0hISGy6t5y5i5EDyBaWOHy4GKLmI6PE9LknmUBq2ARU JWbOWMMOYosI1EocPDqfGcRmFiiQmP10JguILQy0YHXTO7AaFqD6abMaweK8AtYSq972gsU5 BWwkbm5qAosLAcVnT5/LBFEjKHFy5hMWiJnyEs1bZzNPYOSfhSQ1C0lqASPTKkbJ1ILi3PTc YsMCo7zUcr3ixNzi0rx0veT83E2M4NDW0trBuGfVB71DjEwcjIcYJTiYlUR4VT1VkoV4UxIr q1KL8uOLSnNSiw8xSnOwKInzXug6GS8kkJ5YkpqdmlqQWgSTZeLglGpg4mXxcNWSFlGyYOue G1zvHM9wX758z9HHPUvfal2eJrnP2NNkx+/1ck+uRbJypvt8qdyWbu9QyLJFKoFlcn7yn70T S8J2BJVtutX1VDlT9/+pE7fF10rd38Vv+qd30yJ1yfpnX9IrBSduYGD58ltz1e2pPA9V/lt1 KHy8t/TL/xlhD8KvNxzROBGhUSFZmJl/l38FR8e0PjmHS2rbCrbyLPt63LlFKpw94e35ZTnS x8NEOgpuGM9fd2Z1fc037ZjXkwUU577jjdpk/lzs0iPPFV4X5/6rqnFuP3Cat1Ppytxp2eVT tRTZyy9avdlUzCSjX+bdVWlyJNSlo+sP8/W392ZrRBa8r9G0c7A9fHOXEktxRqKhFnNRcSIA lb/53NwCAAA= X-CMS-MailID: 20220917072358epcas1p14543c842bdf0b6f719d4e0d2ed3bf33c X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072358epcas1p14543c842bdf0b6f719d4e0d2ed3bf33c References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch implements ioctl operations. The ioctl routines are added to give controls to the user library. TRINITY_IOCTL_HWMEM_ALLOC/DEALLOC is for memory allocation for the model load, RUN/STOP operations are provided to control NPU works. And several STAT controls can provide statistics of the NPU. Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong Signed-off-by: Dongju Chae Signed-off-by: MyungJoo Ham --- drivers/misc/trinity/trinity.c | 629 +++++++++++++++++++++++++++++++++ 1 file changed, 629 insertions(+) diff --git a/drivers/misc/trinity/trinity.c b/drivers/misc/trinity/trinity.c index a785a5dca4d9..0fb5ccf9f035 100644 --- a/drivers/misc/trinity/trinity.c +++ b/drivers/misc/trinity/trinity.c @@ -22,6 +22,635 @@ static DEFINE_IDA(dev_nrs); static DEFINE_IDA(model_ids); =20 +static uint64_t trinity_gen_model_id(int32_t dbuf_fd) +{ + uint64_t mid; + + mid =3D ida_alloc_max(&model_ids, ((1 << TRINITY_SHIFT_MODEL_ID) - 1), GF= P_KERNEL); + if (mid < 0) + return mid; + + mid |=3D (dbuf_fd << TRINITY_SHIFT_MODEL_ID); + + return mid; +} + +static void trinity_release_model_id(uint64_t mid) +{ + ida_free(&model_ids, mid & ((1 << TRINITY_SHIFT_MODEL_ID) - 1)); +} + +static int32_t trinity_model_id_to_dbuf_fd(uint64_t id) +{ + return (id >> TRINITY_SHIFT_MODEL_ID) & UINT_MAX; +} + +static void trinity_model_htable_init(const struct device *dev) +{ + int i; + struct trinity_driver *drv; + + drv =3D dev_get_drvdata(dev); + for (i =3D 0; i < TRINITY_MODEL_HASH_SIZE; ++i) + INIT_HLIST_BL_HEAD(drv->model_htable + i); +} + +static struct trinity_model * +trinity_get_model_by_id(const struct trinity_driver *drv, const uint64_t i= d) +{ + struct hlist_bl_head *model_hlist; + struct hlist_bl_node *hn; + struct trinity_model *hm; + unsigned long key; + int32_t dbuf_fd; + + dbuf_fd =3D trinity_model_id_to_dbuf_fd(id); + key =3D hash_long(dbuf_fd, TRINITY_MODEL_HASH_BITS); + model_hlist =3D (struct hlist_bl_head *)(drv->model_htable + key); + + hlist_bl_lock(model_hlist); + hlist_bl_for_each_entry(hm, hn, model_hlist, hnode) { + if (hm->config.id !=3D id) + continue; + + hlist_bl_unlock(model_hlist); + return hm; + } + hlist_bl_unlock(model_hlist); + + return NULL; +} + +/** + * trinity_register_model() - Registers a model to the internal hashtable.= Note + * that the device is responsible for the hashtable maintenance. + * + * @drv: An instance of the trinity driver + * @model: Model information to be registered + * + * Returns 0 and sets model->id with a valid value, which is unique system= -wide, + * on success. Otherwise, returns negative error. + */ +int32_t trinity_register_model(struct trinity_driver *drv, + struct trinity_model *model) +{ + struct hlist_bl_head *model_hlist; + unsigned long key; + int32_t ret; + + ret =3D trinity_hwmem_import_dmabuf_begin(drv_to_dev_ptr(drv), + model->config.dbuf_fd, + &model->import_info); + if (ret) + return ret; + +#ifdef ARM + /* sync model program data */ + __cpuc_flush_dcache_area(model->import_info.addr, + model->import_info.buf->size); +#endif + + model->config.id =3D trinity_gen_model_id(model->config.dbuf_fd); + model->owner_id =3D trinity_get_app_id(); + + INIT_HLIST_BL_NODE(&model->hnode); + + key =3D hash_long(model->config.dbuf_fd, TRINITY_MODEL_HASH_BITS); + model_hlist =3D (struct hlist_bl_head *)(drv->model_htable + key); + + hlist_bl_lock(model_hlist); + hlist_bl_add_head(&model->hnode, model_hlist); + hlist_bl_unlock(model_hlist); + + kref_init(&model->refcnt); + + return 0; +} + +static void trinity_destroy_model(struct kref *refcnt) +{ + struct trinity_model *model =3D + container_of(refcnt, struct trinity_model, refcnt); + + trinity_release_model_id(model->config.id); + trinity_hwmem_import_dmabuf_end(&model->import_info); + kfree(model); +} + +static void trinity_model_get(struct trinity_model *model) +{ + if (!model) + return; + + kref_get(&model->refcnt); +} + +static void trinity_model_put(struct trinity_model *model) +{ + if (!model) + return; + + kref_put(&model->refcnt, trinity_destroy_model); +} + +phys_addr_t trinity_get_paddr(struct iommu_domain *domain, dma_addr_t dadd= r) +{ + if (domain) + return iommu_iova_to_phys(domain, daddr); + + return TRINITY_PADDR_BASE + daddr; +} + +void trinity_finish_req(struct trinity_driver *drv, struct trinity_req *re= q) +{ + if (drv->desc->check_profile(drv, req) < 0) + dev_warn(drv_to_dev_ptr(drv), + "Unable to get profile data from NPU\n"); + trinity_hwmem_import_dmabuf_end(&req->input.import_info); + trinity_stat_finish_req(drv, req); + trinity_model_put(req->model); +} + +/** + * trinity_deregister_model() - Deregisters the model with a given id from= the + * table + * + * @drv: An instance of the trinity driver + * @id: An id of the model to be deregistered + * + * Returns 0 on success. Otherwise, returns negative error. + */ +int32_t trinity_deregister_model(const struct trinity_driver *drv, + const uint64_t id) +{ + struct hlist_bl_head *model_hlist; + int32_t dbuf_fd; + unsigned long key; + struct hlist_bl_node *hn; + struct trinity_model *hm =3D NULL; + + dbuf_fd =3D trinity_model_id_to_dbuf_fd(id); + key =3D hash_long(dbuf_fd, TRINITY_MODEL_HASH_BITS); + model_hlist =3D (struct hlist_bl_head *)(drv->model_htable + key); + + hlist_bl_lock(model_hlist); + hlist_bl_for_each_entry(hm, hn, model_hlist, hnode) { + if (hm->config.id =3D=3D id) { + hlist_bl_del_init(&hm->hnode); + break; + } + } + hlist_bl_unlock(model_hlist); + + if (!hm) + return -ENOENT; + + trinity_model_put(hm); + + return 0; +} + +/** + * trinity_deregister_models_owned() - Deregisters models owned + * + * @drv: An instance of the trinity driver + */ +void trinity_deregister_models_owned(struct trinity_driver *drv) +{ + struct hlist_bl_head *model_htable; + struct trinity_model *hm; + struct hlist_bl_node *hn; + int i, app_id; + + app_id =3D trinity_get_app_id(); + model_htable =3D drv->model_htable; +retry: + for (i =3D 0; i < TRINITY_MODEL_HASH_SIZE; i++) { + hlist_bl_lock(model_htable + i); + hlist_bl_for_each_entry(hm, hn, model_htable + i, hnode) { + if (hm->owner_id =3D=3D app_id) { + hlist_bl_del_init(&hm->hnode); + hlist_bl_unlock(model_htable + i); + + trinity_model_put(hm); + + goto retry; + } + } + hlist_bl_unlock(model_htable + i); + } +} + +static int32_t trinity_submit_req(struct trinity_driver *drv, + struct trinity_req *req) +{ + struct device *dev; + wait_queue_head_t wq; + unsigned long timeout, timeout_ms; + unsigned long retry; + int ret =3D 0; + + dev =3D drv_to_dev_ptr(drv); + + /* optional req setup before submission */ + if (drv->desc->prepare_req) { + ret =3D drv->desc->prepare_req(drv, req); + if (ret < 0) { + dev_err(dev, "Unable to prepare req submission: %d", + ret); + return ret; + } + } + + req->submit_retry =3D 0; + timeout_ms =3D req->input.config.timeout_ms; + /* use the default timeout if a user didn't set */ + if (timeout_ms =3D=3D 0) + timeout_ms =3D TRINITY_RUN_TIMEOUT_MSEC; + + retry =3D 0; + init_waitqueue_head(&wq); + init_completion(&req->complete); + + timeout =3D msecs_to_jiffies(timeout_ms); + while (wait_event_interruptible_timeout(wq, trinity_sched_ready(drv), + timeout / 10) =3D=3D 0) { + if (retry =3D=3D 10) { + ret =3D -ETIMEDOUT; + break; + } + retry++; + } + + if (ret =3D=3D 0) { + ret =3D trinity_stat_append_req(drv, req); + if (ret < 0) { + dev_err(dev, "Unable to append request stat: %d", ret); + return ret; + } + + ret =3D trinity_sched_submit(drv, req); + if (ret < 0) + trinity_stat_remove_req(drv, req, true); + } + + if (ret < 0) { + dev_err(dev, "Unable to submit req to scheduler: %d", ret); + return ret; + } + + if (req->input.config.output_mode !=3D TRINITY_OUTPUT_HW) { + timeout =3D wait_for_completion_timeout(&req->complete, timeout); + /* Check and handle the timeout if its handler exists */ + if (timeout =3D=3D 0) { + drv->desc->handle_timeout(drv, req); + + req->stat->status =3D TRINITY_REQ_STATUS_ERROR; + ret =3D -ECANCELED; + } else if (req->stat->status =3D=3D TRINITY_REQ_STATUS_ERROR) { + ret =3D -ECANCELED; + } + + trinity_finish_req(drv, req); + } + + return ret; +} + +static int32_t trinity_run_input(struct trinity_driver *drv, + struct trinity_input *input, + struct trinity_req *req) +{ + struct trinity_model *model; + int32_t err; + + model =3D trinity_get_model_by_id(drv, input->config.model_id); + if (!model) { + dev_err(drv_to_dev_ptr(drv), "Unable to find the model"); + return -EINVAL; + } + + /* skip to submit this req */ + if (model->config.program_size =3D=3D 0 && + input->config.output_mode !=3D TRINITY_OUTPUT_HW) + return 0; + + trinity_model_get(model); + + err =3D trinity_hwmem_import_dmabuf_begin(drv_to_dev_ptr(drv), + input->config.dbuf_fd, + &input->import_info); + if (err < 0) + return err; + + req->model =3D model; + err =3D trinity_submit_req(drv, req); + if (err =3D=3D 0) + return 0; + + if (err !=3D -ECANCELED) + trinity_hwmem_import_dmabuf_end(&input->import_info); + return err; +} + +/** + * trinity_ioctl() - A common callback for unlocked_ioctl() in file_operat= ions for + * a Trinity device node. + * + * @f: A file instance of the opened device node + * @cmd: The target IOCTL command to be handled + * @arg: A user argument + * + * Returns 0 on success. Otherwise, returns negative error. + */ +long trinity_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + struct trinity_driver *drv =3D f->private_data; + const struct trinity_desc *desc =3D drv->desc; + ssize_t err =3D 0L; + + switch (cmd) { + case TRINITY_IOCTL_GET_VERSION: { + if (copy_to_user((uint32_t __user *)arg, &(desc->ver), + sizeof((desc->ver)))) + return -EFAULT; + + break; + } + case TRINITY_IOCTL_GET_API_LEVEL: { + uint32_t api_level =3D TRINITY_API_LEVEL; + + if (copy_to_user((uint32_t __user *)arg, &api_level, + sizeof(api_level))) + return -EFAULT; + + break; + } + case TRINITY_IOCTL_GET_STATE: { + enum trinity_state ready; + + ready =3D drv->desc->get_state(drv); + if (copy_to_user((enum trinity_state __user *)arg, &ready, + sizeof(ready))) + return -EFAULT; + + break; + } + case TRINITY_IOCTL_GET_TOPS: { + if (copy_to_user((uint32_t __user *)arg, &(drv->tops), + sizeof((drv->tops)))) + return -EFAULT; + + break; + } + case TRINITY_IOCTL_GET_DSPM: { + if (copy_to_user((uint32_t __user *)arg, &(drv->dspm), + sizeof((drv->dspm)))) + return -EFAULT; + + break; + } + case TRINITY_IOCTL_GET_NEXT_REQUEST: { + int32_t req_id =3D atomic_inc_return(&drv->global_req_id); + + if (copy_to_user((int32_t __user *)arg, &req_id, + sizeof(req_id))) + return -EFAULT; + + break; + } + case TRINITY_IOCTL_HWMEM_ALLOC: { + struct trinity_ioctl_hwmem hwmem; + + if (copy_from_user(&hwmem, (size_t __user *)arg, sizeof(hwmem))) + return -EFAULT; + + err =3D trinity_hwmem_alloc(drv_to_dev_ptr(drv), hwmem.size, + hwmem.type); + if (err >=3D 0) + trinity_stat_app_total_alloc(drv, hwmem.size); + + break; + } + case TRINITY_IOCTL_HWMEM_DEALLOC: { + struct trinity_ioctl_hwmem hwmem; + struct dma_buf *dbuf; + + if (copy_from_user(&hwmem, (size_t __user *)arg, sizeof(hwmem))) + return -EFAULT; + + dbuf =3D dma_buf_get(hwmem.dbuf_fd); + if (IS_ERR(dbuf)) + return PTR_ERR(dbuf); + + err =3D trinity_hwmem_free(drv_to_dev_ptr(drv), hwmem.dbuf_fd); + if (err =3D=3D 0) + trinity_stat_app_total_freed(drv, dbuf->size); + + break; + } + case TRINITY_IOCTL_REGISTER_MODEL: { + struct trinity_model *model =3D + kzalloc(sizeof(struct trinity_model), GFP_KERNEL); + + if (IS_ERR_OR_NULL(model)) + return -ENOMEM; + + if (copy_from_user(&model->config, + (struct trinity_model __user *)arg, + sizeof(model->config))) { + kfree(model); + return -EFAULT; + } + + err =3D trinity_register_model(drv, model); + if (err < 0) + break; + + if (copy_to_user((struct trinity_model __user *)arg, + &model->config, sizeof(model->config))) + return -EFAULT; + + break; + } + case TRINITY_IOCTL_DEREGISTER_MODEL: { + uint64_t id; + + if (copy_from_user(&id, (uint64_t __user *)arg, sizeof(id))) + return -EFAULT; + + err =3D trinity_deregister_model(drv, id); + + break; + } + case TRINITY_IOCTL_RUN_INPUT: { + struct trinity_req *req; + struct trinity_input *input; + + if (!IDU_LOADED(drv)) + return -EFAULT; + + req =3D drv->desc->alloc_req(drv); + if (!req) + return -ENOMEM; + req->drv =3D drv; + req->time_started =3D ktime_get(); + + input =3D &(req->input); + /** run input based on config received from the user */ + if (copy_from_user(&input->config, + (struct trinity_input __user *)arg, + sizeof(input->config))) { + drv->desc->dealloc_req(drv, req); + return -EACCES; + } + + err =3D trinity_run_input(drv, input, req); + if (err < 0) { + drv->desc->dealloc_req(drv, req); + return err; + } + + if (copy_to_user((struct trinity_input __user *)arg, + &input->config, sizeof(input->config))) { + drv->desc->dealloc_req(drv, req); + return -EACCES; + } + + /* this will be freed when stop request is called */ + if (!req->is_kernel) + drv->desc->dealloc_req(drv, req); + + break; + } + case TRINITY_IOCTL_STOP_REQUESTS: { + if (!IDU_LOADED(drv)) + return -EFAULT; + + if (drv->desc->stop_reqs) + schedule_work(&drv->work_stop); + + break; + } + case TRINITY_IOCTL_STAT_CURRENT_APP: { + struct trinity_ioctl_stat_app ioctl_stat_app; + + if (copy_from_user(&ioctl_stat_app, + (struct trinity_ioctl_stat_app __user *)arg, + sizeof(ioctl_stat_app))) + return -EACCES; + + trinity_stat_app_copy_ioctl(drv, &ioctl_stat_app); + + if (copy_to_user((struct trinity_ioctl_stat_app __user *)arg, + &ioctl_stat_app, sizeof(ioctl_stat_app))) + return -EACCES; + + break; + } + case TRINITY_IOCTL_STAT_APPS: { + struct trinity_ioctl_stat_apps ioctl_stat_apps; + + if (copy_from_user(&ioctl_stat_apps, + (struct trinity_ioctl_stat_apps __user *)arg, + sizeof(ioctl_stat_apps))) + return -EACCES; + + trinity_stat_apps_copy_ioctl(drv, &ioctl_stat_apps); + + if (copy_to_user((struct trinity_ioctl_stat_apps __user *)arg, + &ioctl_stat_apps, sizeof(ioctl_stat_apps))) + return -EACCES; + + break; + } + case TRINITY_IOCTL_STAT_REQS: { + struct trinity_ioctl_stat_reqs ioctl_stat_reqs; + + if (copy_from_user(&ioctl_stat_reqs, + (struct trinity_ioctl_stat_reqs __user *)arg, + sizeof(ioctl_stat_reqs))) + return -EACCES; + + if (ioctl_stat_reqs.app_id =3D=3D 0) + ioctl_stat_reqs.app_id =3D trinity_get_app_id(); + + trinity_stat_reqs_copy_ioctl(drv, &ioctl_stat_reqs); + + if (copy_to_user((struct trinity_ioctl_stat_reqs __user *)arg, + &ioctl_stat_reqs, sizeof(ioctl_stat_reqs))) + return -EACCES; + + break; + } + case TRINITY_IOCTL_GET_PROFILE_META: { + struct trinity_ioctl_profile_meta profile; + + if (copy_from_user( + &profile, + (struct trinity_ioctl_profile_meta __user *)arg, + sizeof(profile))) + return -EACCES; + + if (drv->desc->get_profile_meta) { + err =3D drv->desc->get_profile_meta(drv, &profile); + } else { + profile.total_cycles =3D -1; + profile.total_ops =3D 0; + profile.profile_size =3D 0; + profile.input_footprint =3D -1; + profile.output_footprint =3D -1; + } + + if (copy_to_user((struct trinity_ioctl_profile_meta __user *)arg, + &profile, sizeof(profile))) + return -EACCES; + + break; + } + case TRINITY_IOCTL_GET_PROFILE_BUFF: { + struct trinity_ioctl_profile_buff profile; + + if (copy_from_user( + &profile, + (struct trinity_ioctl_profile_buff __user *)arg, + sizeof(profile))) + return -EACCES; + + if (drv->desc->get_profile_buff) + err =3D drv->desc->get_profile_buff(drv, &profile); + + if (copy_to_user((struct trinity_ioctl_profile_buff __user *)arg, + &profile, sizeof(profile))) + return -EACCES; + + break; + } + case TRINITY_IOCTL_IDU_SET: { + struct trinity_ioctl_idu idu; + + if ((struct trinity_ioctl_idu __user *)arg =3D=3D NULL) { + drv->desc->idu_unset(drv); + break; + } + + if (copy_from_user(&idu, + (struct trinity_ioctl_idu __user *)arg, + sizeof(idu))) { + return -EACCES; + } + + err =3D drv->desc->idu_set(drv, &idu); + + break; + } + default: + return -ENOTTY; + } + + return err; +} + /** * trinity_release() - A common callback for close() in file_operations fo= r a * Trinity device node. If there are device-specific data to be --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2F3FFC6FA86 for ; Sat, 17 Sep 2022 07:24:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229627AbiIQHYP (ORCPT ); Sat, 17 Sep 2022 03:24:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229458AbiIQHYJ (ORCPT ); Sat, 17 Sep 2022 03:24:09 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 723CE41D14 for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p3.samsung.com (unknown [182.195.41.47]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220917072401epoutp03ede988bfb6a221ea701b07d0613c5324~VlPqCZeZY1103511035epoutp03c for ; Sat, 17 Sep 2022 07:24:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220917072401epoutp03ede988bfb6a221ea701b07d0613c5324~VlPqCZeZY1103511035epoutp03c DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399441; bh=ld0pLQgQWwivgiMuA7b/lAdhy1p1R8eW5UBQBUnhI9c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=o5qghSUjxgqvnAvrQF/7iQHokrJIycrCVArFCFG5+NUPLKgjn+HD8LTyFLEz9Ulqn ml47Eo1Iwwg7C11OdchQBX+ggSWm2f+W+Nxysz+JN2cXcBlPL+Q8T2++7oyvYJAmA+ 9jDIXMA/93Q12v9OM5HRvJgN6IQ9uVE6HUgIUarI= Received: from epsnrtp4.localdomain (unknown [182.195.42.165]) by epcas1p3.samsung.com (KnoxPortal) with ESMTP id 20220917072400epcas1p3eccbd6d3d5ba874dd10602a06f4d5666~VlPpfEd7w0623006230epcas1p3Q; Sat, 17 Sep 2022 07:24:00 +0000 (GMT) Received: from epsmges1p4.samsung.com (unknown [182.195.38.233]) by epsnrtp4.localdomain (Postfix) with ESMTP id 4MV2Vk6q6fz4x9Pq; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epcas1p1.samsung.com ( [182.195.41.45]) by epsmges1p4.samsung.com (Symantec Messaging Gateway) with SMTP id 52.ED.07691.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas1p2.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epcas1p2ae33a31333089ea7b10844e42e14323b~VlPnefG1-1789517895epcas1p2s; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220917072358epsmtrp14dbd1a9aaa9dad63885c465cf2aed7b2~VlPndm3VD0556805568epsmtrp1d; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) X-AuditID: b6c32a38-0cdff70000021e0b-7c-6325760ebd18 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 64.45.14392.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072357epsmtip2556e4aee8624dce1117620409974d5bc~VlPnLHRFw2357323573epsmtip2f; Sat, 17 Sep 2022 07:23:57 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 09/13] trinity: Add request and pm feature Date: Sat, 17 Sep 2022 16:23:52 +0900 Message-Id: <20220917072356.2255620-10-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupnk+LIzCtJLcpLzFFi42LZdlhTV5evTDXZYMkjU4u/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtKtsmIzUxJbVIITUvOT8lMy/dVsk7ON453tTMwFDX0NLCXEkh LzE31VbJxSdA1y0zB+gqJYWyxJxSoFBAYnGxkr6dTVF+aUmqQkZ+cYmtUmpBSk6BaYFecWJu cWleul5eaomVoYGBkSlQYUJ2xo1ZLxkLrq9lrLi4cCV7A+OvXsYuRk4OCQETiXXfnrB3MXJx CAnsYJR4vOI4C4TziVHixcWbUJlvjBKzvs9hhWl58OE9G4gtJLCXUeLKHBOIos+MEoufLGQG SbAJqErMnLGGHcQWESiXaN54AsxmFsiReHKnCaxGWMBWYtnyf2CDWIDqd198CHYTr4CNRPf2 BhYQmxPIvrmpiQUiLihxcuYTFog58hLNW2czgyyWEPjJLvFr+homiOtcJNoetUDZwhKvjm9h h7ClJF72t0HZ2RJTOhaxQNgFEueebwUaxAFkG0tcXJECYjILaEqs36UPUaEosfP3XEaItXwS 7772sEJU80p0tAlBlChJLPlzGGq4hMTUGd+gDvCQOLf/OiMkqPoZJRo3V09glJ+F5JlZSJ6Z hbB4ASPzKkax1ILi3PTUYsMCE3isJufnbmIEp0wtix2Mc99+0DvEyMTBeIhRgoNZSYRX1VMl WYg3JbGyKrUoP76oNCe1+BCjKTB4JzJLiSbnA5N2Xkm8oYmlgYmZkbGJhaGZoZI4r542Y7KQ QHpiSWp2ampBahFMHxMHp1QDU5VyRPSK34ukfq0IZ3/as/6L5boVuycrCSqYsNbffSIt0bvB tffv/py9ui9/fuGxeJZ7XaZLf2moBd+NJvPf21xeTZ3ywPfSBLasrBn+v07F7LnQ4N3kZxUg s+dYR5eJlpjLti2Tn1l+jir8IzJNLW0v13vt7ZwFabzvJjeJq8RtnWP2TV0wKrZQZr6j9iJt piPMxu137AUKnu67FJVi8Xnmw+4/J8uKfhx8dU+rqv6e/ccLYctkatm29z5kPWe4jv3Tsedc Mlk7pZRs1iUrtd+tjOu4tfqPW4Ga6W6dlquqJvzRe4+53hVeZ8GqzPR/ycQ4xpB/rPcLDx9S vNXQN2fv6tUBQp7HHovwWqVuUWIpzkg01GIuKk4EAB7HAfkiBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrNLMWRmVeSWpSXmKPExsWy7bCSvC5fmWqyQfMxDou/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtissmJTUnsyy1SN8ugSvjxqyXjAXX1zJWXFy4kr2B8VcvYxcj J4eEgInEgw/v2boYuTiEBHYzStx694gVIiEhsenecuYuRg4gW1ji8OFiiJqPjBIXzs0Ca2YT UJWYOWMNO4gtIlArcfDofGYQm1mgQGL205ksILawgK3EsuX/2EBsFqD63RcfgvXyCthIdG9v AKvhBLJvbmoCs4UErCVmT5/LBFEjKHFy5hMWiJnyEs1bZzNPYOSfhSQ1C0lqASPTKkbJ1ILi 3PTcYsMCw7zUcr3ixNzi0rx0veT83E2M4PDW0tzBuH3VB71DjEwcjIcYJTiYlUR4VT1VkoV4 UxIrq1KL8uOLSnNSiw8xSnOwKInzXug6GS8kkJ5YkpqdmlqQWgSTZeLglGpgOtywelft8inK TqG7gzZfs6+XFD4mn/K/935gR9qRcNfzqvd3si24c6uzKqRgY1LyWY7VFyzS5Fb/9tV0XKbq d3/Pk997hd3fB/WzsZbsWZDes359oNljl4tRSzd1vnGxrDnw7fCrE31fJx5YtDV7gfZ59ycq bJ9qTa4aTvvdEpvqtuSMPYPFW6e5UeJ/7qQ/Tco/dOvX9lmdftsCxK7Yzc58bO08YVmZ8Vkp +Ts3Q3/HfQ54+9vxTPiD0kVmHdePf6kXuOAgtWrP9J87GS5pr1n+pXnbWSmJ2b0tfivtWiQD 5XJivYW2sf77EJYkPv1CqviL93x2QQZ5z6+GzrWP9D79eUlkyIPPb6wLxK6KmCixFGckGmox FxUnAgAiiCaO3gIAAA== X-CMS-MailID: 20220917072358epcas1p2ae33a31333089ea7b10844e42e14323b X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072358epcas1p2ae33a31333089ea7b10844e42e14323b References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch implements request and PM features. trinity requests are created by ioctl, and it's invoked by the scheduler. Each request is prepared to run on the NPU including segment allocation and command setup. Requests are managed by the command structure, which keeps inforamtion of the request to manage its lifecycle. Power management operations are also provided, it works suspend mode with pm_runtime_allow and pm_runtime_forbid. Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong Signed-off-by: Dongju Chae Signed-off-by: MyungJoo Ham --- drivers/misc/trinity/trinity.c | 62 +++ drivers/misc/trinity/trinity_vision2_drv.c | 605 +++++++++++++++++++++ 2 files changed, 667 insertions(+) diff --git a/drivers/misc/trinity/trinity.c b/drivers/misc/trinity/trinity.c index 0fb5ccf9f035..0463140c0ae6 100644 --- a/drivers/misc/trinity/trinity.c +++ b/drivers/misc/trinity/trinity.c @@ -664,6 +664,23 @@ long trinity_ioctl(struct file *f, unsigned int cmd, u= nsigned long arg) */ int trinity_release(struct inode *inode, struct file *file) { + struct trinity_driver *drv; + + drv =3D file->private_data; + + trinity_stat_app_set_status(drv, TRINITY_APP_STATUS_TERMINATED); + /* block newly incoming requests */ + trinity_sched_suspend(drv); + + /* wait already submitted requests */ + if (drv->desc->drain_reqs) + drv->desc->drain_reqs(drv); + + /* deregister models owned by this device handle */ + trinity_deregister_models_owned(drv); + + trinity_sched_resume(drv); + return 0; } =20 @@ -735,6 +752,27 @@ int trinity_open(struct inode *inode, struct file *f) return 0; } =20 +static void trinity_common_init(struct device *dev) +{ + trinity_model_htable_init(dev); + + if (trinity_debug_init() < 0) + dev_warn(dev, "Unable to initialize debugfs\n"); + + if (trinity_sched_init(dev) < 0) + dev_warn(dev, "Unable to initialize scheduler\n"); + + if (trinity_dma_init(dev) < 0) + dev_warn(dev, "Failed to init DMA memory\n"); +} + +static void trinity_common_exit(struct device *dev) +{ + trinity_dma_exit(dev); + trinity_debug_exit(); + trinity_sched_exit(dev); +} + /** * trinity_create_node() - Create trinity node * @@ -868,9 +906,27 @@ int trinity_probe(struct platform_device *pdev, const = struct trinity_desc *desc) mutex_init(&drv->lock); INIT_WORK(&drv->work_stop, desc->stop_reqs); =20 + trinity_common_init(dev); + + err =3D trinity_sysfs_init(drv); + if (err < 0) { + dev_err(dev, "failed to initialize sysfs for a trinity device"); + goto err_cleanup_common; + } + + err =3D trinity_debug_add(drv); + if (err < 0) { + dev_err(dev, + "failed to add a debugging feature to the trinity device"); + trinity_sysfs_cleanup(drv); + goto err_cleanup_common; + } + trinity_stat_init(drv); + return 0; =20 err_cleanup_common: + trinity_common_exit(dev); devm_free_irq(dev, drv->irq, &drv->mdev); =20 err_cleanup: @@ -895,6 +951,12 @@ int trinity_remove(struct platform_device *pdev, struct trinity_driver *drv =3D platform_get_drvdata(pdev); struct device *dev =3D drv_to_dev_ptr(drv); =20 + trinity_stat_fini(drv); + trinity_debug_remove(drv); + trinity_sysfs_cleanup(drv); + + trinity_common_exit(dev); + ida_free(&dev_nrs, drv->dev_id); devm_free_irq(dev, drv->irq, &drv->mdev); devm_kfree(dev, drv); diff --git a/drivers/misc/trinity/trinity_vision2_drv.c b/drivers/misc/trin= ity/trinity_vision2_drv.c index 70b8b6fd5843..3dd89920cdf5 100644 --- a/drivers/misc/trinity/trinity_vision2_drv.c +++ b/drivers/misc/trinity/trinity_vision2_drv.c @@ -13,6 +13,7 @@ #include #include #include +#include #include =20 #include "trinity_common.h" @@ -151,6 +152,9 @@ static void triv2_idu_setup(struct trinity_driver *drv); static void triv2_idu_unset(struct trinity_driver *drv); static int32_t triv2_idu_set(struct trinity_driver *drv, struct trinity_ioctl_idu *config); +static void triv2_handle_cmd_done(struct trinity_driver *drv, + struct triv2_cmd *cmd, bool timeout); +static void triv2_setup_buffers(struct trinity_driver *drv); =20 /** * triv2_get_state() - Get state (TRINITY_STATE_READY/TRINITY_STATE_PAUSE)= of the device. @@ -212,6 +216,31 @@ static void triv2_set_state(const struct trinity_drive= r *drv, } } =20 +/** + * triv2_sync_segt_entries() - synchronize the segment table entries + */ +static int triv2_sync_segt_entries(const struct trinity_driver *drv, + struct triv2_req *req) +{ +#ifdef ARM + struct trinity_input *input =3D &(req->req.input); + int i; + + /* flush all caches for heavy models */ + if (req->total_segment_size > TRIV2_CACHE_FLUSH_THRESHOLD || + /* cannot handle external segments for kernel requests */ + req->kernel !=3D NULL) { + flush_cache_all(); + return 0; + } + + for (i =3D 0; i < input->config.num_segments; ++i) + __cpuc_flush_dcache_area(req->seg_import[i].addr, + req->seg_import[i].buf->size); +#endif + return 0; +} + static void triv2_wakeup_cp(const struct trinity_driver *drv) { void *addr =3D @@ -220,36 +249,552 @@ static void triv2_wakeup_cp(const struct trinity_dri= ver *drv) trinity_set_bit(BIT_SET_SEND_EVT1, addr); } =20 +static void triv2_cancel_reqs(struct trinity_driver *drv) +{ + struct triv2_cmd_info *info; + struct triv2_cmd *cmd; + unsigned long flags; + int slot; + + info =3D TRIV2_DRV_GET_CMD_INFO(drv); + spin_lock_irqsave(&info->lock, flags); + + slot =3D find_first_bit(info->bitmap, TRIV2_MAX_CMDSLOTS); + while (slot < TRIV2_MAX_CMDSLOTS) { + cmd =3D TRIV2_GET_CMD_FROM_SLOT(info, slot); + triv2_handle_cmd_done(drv, cmd, true); + slot =3D find_next_bit(info->bitmap, TRIV2_MAX_CMDSLOTS, + slot + 1); + } + + spin_unlock_irqrestore(&info->lock, flags); +} + +static void triv2_drain_reqs(struct trinity_driver *drv) +{ + struct triv2_cmd_info *info; + unsigned long flags; + int cur_retries, max_retries =3D 1000; /* 1-sec */ + int slot; + + cur_retries =3D 0; + info =3D TRIV2_DRV_GET_CMD_INFO(drv); +retry: + spin_lock_irqsave(&info->lock, flags); + + /* wait until all bits are unset */ + slot =3D find_first_bit(info->bitmap, TRIV2_MAX_CMDSLOTS); + if (slot < TRIV2_MAX_CMDSLOTS) { + spin_unlock_irqrestore(&info->lock, flags); + + usleep_range(900, 1100); + if (cur_retries++ < max_retries) + goto retry; + + spin_lock_irqsave(&info->lock, flags); + } + + spin_unlock_irqrestore(&info->lock, flags); +} + static void triv2_reset(struct trinity_driver *drv) { + struct device *dev =3D drv_to_dev_ptr(drv); struct triv2_pdata *pdata =3D drv->pdata; =20 mutex_lock(&pdata->drv->lock); =20 + /* block runtime pm suspend */ + pm_runtime_forbid(dev); + + /* block new incoming requests first */ + trinity_sched_suspend(drv); + triv2_cancel_reqs(pdata->drv); msleep(100); =20 triv2_setup_buffers(drv); triv2_idu_unset(drv); =20 + /* resume scheduler */ + trinity_sched_resume(drv); + + pm_runtime_allow(dev); + mutex_unlock(&pdata->drv->lock); } =20 +/** + * triv2_run_trigger() - trigger memory-mapped register for inference runn= ing + */ +static void triv2_run_trigger(const struct trinity_driver *drv, int slot) +{ + struct triv2_cmd_info *cmd_info =3D TRIV2_DRV_GET_CMD_INFO(drv); + struct triv2_req *t_req =3D cmd_info->reqs[slot]; + + if (!t_req) { + dev_err(drv_to_dev_ptr(drv), + "Unable to find the corresponding req"); + return; + } + + if (triv2_sync_segt_entries(drv, t_req) < 0) + dev_err(drv_to_dev_ptr(drv), + "Unable to sync the segment table"); + + /* sync the current bitmap */ + iowrite32(*cmd_info->bitmap, + trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_CMD_REQ)); + + t_req->req.stat->scheduled =3D ktime_get(); + t_req->req.stat->completed =3D 0; + t_req->req.scheduled =3D true; + t_req->req.timeout =3D false; + + /* trigger the event (we do not assume that IDU always accepts this event= ) */ + triv2_wakeup_cp(drv); +} + +static void triv2_clear_cmd(struct trinity_driver *drv, struct triv2_req *= req, + struct triv2_cmd *cmd) +{ + struct triv2_cmd_info *cmd_info =3D TRIV2_DRV_GET_CMD_INFO(drv); + + cmd_info->reqs[req->cmd_slot] =3D NULL; + clear_bit(req->cmd_slot, cmd_info->bitmap); + req->cmd_slot =3D -1; + + memset(cmd, '\x00', sizeof(struct triv2_cmd)); +} + +static void triv2_handle_cmd_done(struct trinity_driver *drv, + struct triv2_cmd *cmd, bool timeout) +{ + struct device *dev =3D drv_to_dev_ptr(drv); + struct triv2_cmd_info *cmd_info =3D TRIV2_DRV_GET_CMD_INFO(drv); + struct triv2_req *t_req; + struct trinity_req *req; + uint32_t slot =3D cmd->slot; + int64_t time_diff; + + t_req =3D cmd_info->reqs[slot]; + if (!t_req) { + dev_err(dev, "Failed to find the req\n"); + return; + } + + req =3D &(t_req->req); + req->stat->completed =3D ktime_get(); + req->stat->status =3D TRINITY_REQ_STATUS_FINISHED; + + time_diff =3D TIME_DIFF_US(req->stat->completed, req->stat->scheduled); + if (time_diff < 0) { + dev_warn(dev, "Detected invalid inference time of request\n"); + } else { + req->stat->prev_time =3D (uint32_t)time_diff; + req->stat->prev_cycles =3D cmd->total_cycles; + req->stat->num_runs++; + req->stat->total_time +=3D req->stat->prev_time; + } + + t_req->total_cycles =3D cmd->total_cycles; + t_req->profile_offset =3D cmd->profile_offset; + + triv2_clear_cmd(drv, t_req, cmd); + + /* notify to the scheduler */ + trinity_sched_notify(req, timeout); + + /* notify to the caller */ + if (!req->is_kernel) + complete_all(&req->complete); +} + +static void triv2_handle_timeout(struct trinity_driver *drv, + struct trinity_req *req) +{ + struct triv2_cmd_info *cmd_info =3D TRIV2_DRV_GET_CMD_INFO(drv); + struct triv2_cmd *cmd; + struct triv2_req *t; + unsigned long flags; + + t =3D TRIV2_GET_REQ(req); + + spin_lock_irqsave(&cmd_info->lock, flags); + if (t->cmd_slot >=3D 0) { + /* Timeout! check whether it's not handled in irq handler */ + cmd =3D TRIV2_GET_CMD_FROM_SLOT(cmd_info, t->cmd_slot); + triv2_handle_cmd_done(drv, cmd, true); + } + spin_unlock_irqrestore(&cmd_info->lock, flags); +} + +/** + * triv2_stop_reqs() - stop the submitted reqs to the driver + * + * In case of already-executed req, each device needs to determine the pol= icy + * depending its capability to terminate the running one. + */ +static void triv2_stop_reqs(struct work_struct *work) +{ + struct trinity_driver *drv; + + drv =3D container_of(work, struct trinity_driver, work_stop); + if (drv =3D=3D NULL) + return; + + triv2_cancel_reqs(drv); +} + +static void triv2_handle_irq_cmds(struct trinity_driver *drv) +{ + struct triv2_cmd_info *info; + struct triv2_cmd *cmd; + unsigned long flags; + int slot; + + info =3D TRIV2_DRV_GET_CMD_INFO(drv); + spin_lock_irqsave(&info->lock, flags); + + /** Search the bitmap to find the completed CMDs */ + slot =3D find_first_bit(info->bitmap, TRIV2_MAX_CMDSLOTS); + while (slot < TRIV2_MAX_CMDSLOTS) { + cmd =3D TRIV2_GET_CMD_FROM_SLOT(info, slot); + if (cmd->status =3D=3D STATUS_CMD_DONE) + triv2_handle_cmd_done(drv, cmd, false); + slot =3D find_next_bit(info->bitmap, TRIV2_MAX_CMDSLOTS, + slot + 1); + } + + spin_unlock_irqrestore(&info->lock, flags); +} + +/** + * triv2_handle_irq() - An IRQ handler to be called when a registered IRQ = (IRQ_OUT) occurs. + */ +static irqreturn_t triv2_handle_irq(int irq_no, void *dev_id) +{ + struct miscdevice *_mdev; + struct trinity_driver *drv; + void __iomem *addr; + uint32_t interrupt; + uint32_t reg; + + _mdev =3D (struct miscdevice *)dev_id; + drv =3D container_of(_mdev, struct trinity_driver, mdev); + + /** + * Verify that the IRQ is actually from the NPU + * This is required as IRQ_SHARED is used when setting up IRQ + */ + addr =3D trinity_get_iomem_addr(drv->mmreg_vaddr[2], + OFFSET_CBOX_EXT_IRQ_STA); + reg =3D ioread32(addr); + + interrupt =3D reg & MASK_CP_SWI_STA; + if (interrupt =3D=3D 0) + return IRQ_NONE; + + /** Clear the interrupt first */ + addr =3D trinity_get_iomem_addr(drv->mmreg_vaddr[2], + OFFSET_CBOX_CP_SWI_CLR); + iowrite32(1, addr); + + triv2_handle_irq_cmds(drv); + return IRQ_HANDLED; +} + +/** + * triv2_prepare_req() - evaluate the physical address of entries in the s= egment table + */ +static int32_t triv2_prepare_req(struct trinity_driver *drv, + struct trinity_req *req) +{ + struct triv2_req *t =3D TRIV2_GET_REQ(req); + struct trinity_input *input =3D &(req->input); + struct trinity_hwmem_import *segt_import =3D &(input->import_info); + int32_t *segtable_dbuffd_base; + uint32_t *segtable_extra_base; + int ret, i; + + if (input->config.num_segments =3D=3D 0) + return -EINVAL; + + if (input->config.num_segments > TRIV2_MAX_SEGMENTS) + return -ERANGE; + + t->seg_import =3D kcalloc(input->config.num_segments, + sizeof(struct trinity_hwmem_import), + GFP_KERNEL); + if (!t->seg_import) + return -ENOMEM; + + /* dmabuf fd to be resolved */ + segtable_dbuffd_base =3D segt_import->addr; + /* extra value (e.g., offset or size) */ + segtable_extra_base =3D segt_import->addr + HALF_PAGE_SIZE; + +#ifdef ARM + /* sync segment table */ + __cpuc_flush_dcache_area(input->import_info.addr, + input->import_info.buf->size); +#endif + + for (i =3D 0; i < input->config.num_segments; ++i) { + struct trinity_hwmem_import *import; + int32_t fd =3D segtable_dbuffd_base[i]; + dma_addr_t daddr; + + if (fd < 0) { + uint32_t idx =3D (uint32_t)((fd + 1) * -1); + struct triv2_kernel_req *kreq; + + /* it's for kernel input/output */ + if (!req->is_kernel) { + req->is_kernel =3D true; + kreq =3D kzalloc(sizeof(*kreq), GFP_KERNEL); + if (!kreq) { + ret =3D -ENOMEM; + goto err; + } + t->kernel =3D kreq; + } + + kreq =3D t->kernel; + if (idx < TRIV2_MAX_TENSORS) { + kreq->in_seg_idx[idx] =3D i; + kreq->in_seg_size[idx] =3D segtable_extra_base[i]; + t->total_segment_size +=3D kreq->in_seg_size[idx]; + } else if (idx < TRIV2_MAX_TENSORS * 2) { + idx -=3D TRIV2_MAX_TENSORS; + kreq->out_seg_idx[idx] =3D i; + kreq->out_seg_size[idx] =3D + segtable_extra_base[i]; + t->total_segment_size +=3D + kreq->out_seg_size[idx]; + } else { + dev_err(drv_to_dev_ptr(drv), + "Invalid external segment (idx: %u)", + idx); + ret =3D -EINVAL; + goto err; + } + continue; + } + + import =3D &(t->seg_import[i]); + ret =3D trinity_hwmem_import_dmabuf_begin(drv_to_dev_ptr(drv), fd, + import); + if (ret) { + dev_err(drv_to_dev_ptr(drv), + "%d-th segment with fd (%d) seems invalid: %d", + i, fd, ret); + goto err; + } + + t->total_segment_size +=3D import->buf->size; + + /** @todo Use a local ptr variable */ + daddr =3D import->dma_addr; + daddr +=3D segtable_extra_base[i]; + + iowrite32(TRIV2_IDU_ADDR(daddr), + segt_import->addr + i * sizeof(u32)); + } + + /* set the dma address of DSPM (reserved index: TRIV2_MAX_SEGMENTS - 1) */ + if (drv->dspm > 0) { + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + + iowrite32(TRIV2_IDU_ADDR(pdata->idu_dsp.dspm), + segt_import->addr + + (TRIV2_MAX_SEGMENTS - 1) * sizeof(u32)); + } + + return 0; + +err: + kfree(t->seg_import); + t->seg_import =3D NULL; + return ret; +} + +/** + * triv2_prepare_cmd() - Prepare command info. for the target req before i= nvoking + */ +static int32_t triv2_prepare_cmd(struct trinity_driver *drv, + struct trinity_req *req) +{ + struct triv2_cmd_info *cmd_info; + struct triv2_cmd cmd =3D { 0 }; + struct triv2_req *t; + + const struct trinity_model *model =3D req->model; + const struct trinity_input *input =3D &req->input; + + int32_t slot; + struct iommu_domain *domain; + phys_addr_t paddr; + unsigned long flags; + + /** Note that the program base is not behind iommu */ + domain =3D iommu_get_domain_for_dev(drv_to_dev_ptr(drv)); + + paddr =3D trinity_get_paddr(domain, model->import_info.dma_addr); + cmd.prog_addr =3D TRIV2_IDU_ADDR(paddr); + cmd.prog_addr +=3D model->config.program_offset_addr; + cmd.prog_size =3D model->config.program_size; + + paddr =3D trinity_get_paddr(domain, input->import_info.dma_addr); + cmd.segt_addr =3D TRIV2_IDU_ADDR(paddr); + cmd.num_visa =3D model->config.num_visa_insts; + + cmd.priority =3D input->config.priority; + cmd.input_mode =3D input->config.input_mode; + cmd.output_mode =3D input->config.output_mode; + + /** Find a empty cmd slot in bitmap (need a spin lock) */ + cmd_info =3D TRIV2_DRV_GET_CMD_INFO(drv); + t =3D TRIV2_GET_REQ(req); + + spin_lock_irqsave(&cmd_info->lock, flags); + + slot =3D find_first_zero_bit(cmd_info->bitmap, TRIV2_MAX_CMDSLOTS); + if (slot < TRIV2_MAX_CMDSLOTS) { + set_bit(slot, cmd_info->bitmap); + cmd_info->reqs[slot] =3D t; + t->cmd_slot =3D slot; + } + + spin_unlock_irqrestore(&cmd_info->lock, flags); + + /** Will be retried (rely on platform device's scheduling) */ + if (slot >=3D TRIV2_MAX_CMDSLOTS) + return -EBUSY; + + cmd.slot =3D slot; + cmd.status =3D STATUS_CMD_READY; + + memcpy(cmd_info->buf.addr + slot * sizeof(struct triv2_cmd), &cmd, + sizeof(struct triv2_cmd)); + + return slot; +} + +/** + * triv2_invoke_req() - Invoke a req on the device. Note that all configur= ations + * required by running should be done before invocation of this function. + */ +static int32_t triv2_invoke_req(struct trinity_driver *drv, + struct trinity_req *req, void *sched_data) +{ + enum trinity_output_mode mode; + int32_t slot; + + mode =3D req->input.config.output_mode; + slot =3D triv2_prepare_cmd(drv, req); + if (slot < 0) + return slot; + + if (mode =3D=3D TRINITY_OUTPUT_HW || mode =3D=3D TRINITY_OUTPUT_CPU_POLL = || + mode =3D=3D TRINITY_OUTPUT_CPU_INTR) { + triv2_run_trigger(drv, slot); + } else { + dev_err(drv_to_dev_ptr(drv), "Invalid output mode: %d\n", mode); + return -EINVAL; + } + + return 0; +} + +static struct trinity_req *triv2_alloc_req(struct trinity_driver *drv) +{ + struct triv2_req *t_req; + + t_req =3D kzalloc(sizeof(struct triv2_req), GFP_KERNEL); + if (!t_req) + return NULL; + + t_req->cmd_slot =3D -1; + + if (atomic_fetch_inc(&drv->active_reqs) =3D=3D 0) + trinity_wait_ready(drv); + + return &(t_req->req); +} + +static void triv2_dealloc_req(struct trinity_driver *drv, + struct trinity_req *req) +{ + struct triv2_req *t_req =3D TRIV2_GET_REQ(req); + + if (atomic_dec_return(&drv->active_reqs) =3D=3D 0) + trinity_set_pause(drv); + + if (t_req->seg_import) { + struct trinity_hwmem_import *import; + uint32_t i; + + for (i =3D 0; i < req->input.config.num_segments; i++) { + import =3D &(t_req->seg_import[i]); + if (import->addr) + trinity_hwmem_import_dmabuf_end(import); + } + kfree(t_req->seg_import); + } + + kfree(t_req->kernel); + kfree(t_req); +} + +static long triv2_ioctl(struct file *f, unsigned int cmd, unsigned long ar= g) +{ + struct trinity_driver *drv =3D f->private_data; + struct device *dev =3D drv_to_dev_ptr(drv); + long ret; + + pm_runtime_forbid(dev); + + ret =3D trinity_ioctl(f, cmd, arg); + + pm_runtime_allow(dev); + + return ret; +} + static int triv2_open(struct inode *inode, struct file *f) { + struct miscdevice *miscdev; + struct trinity_driver *drv; + struct device *dev; int ret; =20 + miscdev =3D (struct miscdevice *)f->private_data; + drv =3D container_of(miscdev, struct trinity_driver, mdev); + dev =3D drv_to_dev_ptr(drv); + + pm_runtime_forbid(dev); + ret =3D trinity_open(inode, f); =20 + pm_runtime_allow(dev); + return ret; } =20 static int triv2_release(struct inode *inode, struct file *f) { + struct trinity_driver *drv =3D f->private_data; + struct device *dev =3D drv_to_dev_ptr(drv); int ret; =20 + pm_runtime_forbid(dev); + ret =3D trinity_release(inode, f); =20 + pm_runtime_allow(dev); + return ret; } =20 @@ -515,6 +1060,7 @@ static int32_t triv2_init_pdata(struct trinity_driver = *drv) cmd_buf =3D TRIV2_DRV_GET_CMD_BUF(drv); back_buf =3D TRIV2_DRV_GET_BACK_BUF(drv); =20 + mutex_init(&pdata->prof_lock); spin_lock_init(&cmd_info->lock); /* init cmd bitmap */ bitmap_zero(cmd_info->bitmap, TRIV2_MAX_CMDSLOTS); @@ -657,6 +1203,64 @@ static struct trinity_desc triv2_desc =3D { .dealloc_req =3D triv2_dealloc_req, .prepare_req =3D triv2_prepare_req, .invoke_req =3D triv2_invoke_req, + /* etc. */ + .handle_timeout =3D triv2_handle_timeout, + .stop_reqs =3D triv2_stop_reqs, + .drain_reqs =3D triv2_drain_reqs, + .handle_irq =3D triv2_handle_irq, +}; + +static int triv2_suspend(struct device *dev) +{ + return 0; +} + +static int triv2_resume(struct device *dev) +{ + return 0; +} + +static int triv2_runtime_suspend(struct device *dev) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + mutex_lock(&drv->lock); + + /* 1) Ensure that the scheduler was suspended */ + trinity_sched_suspend(drv); + + /* 2) Set pause state if it's in ready state */ + if (triv2_get_state(drv) =3D=3D TRINITY_STATE_READY) + triv2_set_state(drv, TRINITY_STATE_PAUSE); + + mutex_unlock(&drv->lock); + + return 0; +} + +static int triv2_runtime_resume(struct device *dev) +{ + struct trinity_driver *drv =3D dev_get_drvdata(dev); + + mutex_lock(&drv->lock); + + /* 1) Restore IDU setup */ + triv2_setup_buffers(drv); + triv2_idu_setup(drv); + + /* 2) Resume the req scheduler */ + trinity_sched_resume(drv); + + mutex_unlock(&drv->lock); + + return 0; +} + +static const struct dev_pm_ops triv2_dev_pm_ops =3D { + // clang-format off + SET_SYSTEM_SLEEP_PM_OPS(triv2_suspend, triv2_resume) + SET_RUNTIME_PM_OPS(triv2_runtime_suspend, triv2_runtime_resume, NULL) + // clang-format on }; =20 static const struct of_device_id trinity_match[] =3D { @@ -734,6 +1338,7 @@ static struct platform_driver trinity_triv2 =3D { .name =3D "triv2", .owner =3D THIS_MODULE, .of_match_table =3D of_match_ptr(trinity_match), + .pm =3D &triv2_dev_pm_ops, }, }; =20 --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E7756ECAAD3 for ; Sat, 17 Sep 2022 07:24:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229732AbiIQHYu (ORCPT ); Sat, 17 Sep 2022 03:24:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51908 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229557AbiIQHYK (ORCPT ); Sat, 17 Sep 2022 03:24:10 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C831746D9B for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p1.samsung.com (unknown [182.195.41.45]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220917072401epoutp038f3de2f5b47ac7bbf07cdc9b00b7eebf~VlPqPRuK51395913959epoutp03d for ; Sat, 17 Sep 2022 07:24:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220917072401epoutp038f3de2f5b47ac7bbf07cdc9b00b7eebf~VlPqPRuK51395913959epoutp03d DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399441; bh=7oqjZ1Z/LaVMkbr+/m9xMFwzVniafNx0UvQT1oyf8Nk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Sq05CxXS4TcQk5gBLfMoSRApPAtMbvyPKccX8ztBWL19Qc2D21Z8I1JuKK/M5VtJT uZZoPzJXaKG+M++43fs3t7WHRZ7mRePs0Q/olcWDSS/DK8j5ShPKkOp2qWt0Nk5H1q YFVLT1sAYehoTFM6swWRJwilqBeneKWlJ2PJgxnA= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas1p2.samsung.com (KnoxPortal) with ESMTP id 20220917072400epcas1p23895082738cb62ee8fb72b15105595a9~VlPpZdeBs1789517895epcas1p2v; Sat, 17 Sep 2022 07:24:00 +0000 (GMT) Received: from epsmges1p3.samsung.com (unknown [182.195.36.136]) by epsnrtp2.localdomain (Postfix) with ESMTP id 4MV2Vl3DJFz4x9Px; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) Received: from epcas1p2.samsung.com ( [182.195.41.46]) by epsmges1p3.samsung.com (Symantec Messaging Gateway) with SMTP id 95.1D.57013.F0675236; Sat, 17 Sep 2022 16:23:59 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas1p1.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epcas1p14997459c7add27bf7b4e9333cbf21b72~VlPnkYgG30249502495epcas1p1T; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220917072358epsmtrp1635e9fd7499fd8a9aedab5439ad31c11~VlPnjnzo10556805568epsmtrp1e; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) X-AuditID: b6c32a37-ff5fb7000001deb5-1c-6325760fe916 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 74.45.14392.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epsmtip2428353bfdbf88f60ee1d98f49f887f56~VlPnTWC5t3200232002epsmtip2V; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 10/13] trinity: Add profile module Date: Sat, 17 Sep 2022 16:23:53 +0900 Message-Id: <20220917072356.2255620-11-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprAJsWRmVeSWpSXmKPExsWy7bCmni5/mWqywebFohZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbVLZNRmpiSmqRQmpecn5KZl66rZJ3cLxzvKmZgaGuoaWFuZJC XmJuqq2Si0+ArltmDtBVSgpliTmlQKGAxOJiJX07m6L80pJUhYz84hJbpdSClJwC0wK94sTc 4tK8dL281BIrQwMDI1OgwoTsjMk93UwF/xcyVrTM6mNqYDzUytjFyMkhIWAi0fP+NnMXIxeH kMAORom1XR1sEM4nRolJnw6wQzjfGCUuHPwF13L98nYWiMReRollF/qYIJzPjBIzp75nA6li E1CVmDljDTuILSJQLtG88QSYzSyQI/HkThMziC0sYCrR9XMymM0CVL9jwQ+wGl4BG4lrJ0+D xTmB7Jubmlgg4oISJ2c+YYGYIy/RvHU22OESAl/ZJRY0LmSCOM9F4v/no1CnCku8Or6FHcKW knjZ3wZlZ0tM6VjEAmEXSJx7vhVoEAeQbSxxcUUKiMksoCmxfpc+RIWixM7fcxkh1vJJvPva wwpRzSvR0SYEUaIkseTPYajhEhJTZ3xjgijxkGhZ4w0JnX5Gicv7fzFNYJSfheSZWUiemYWw eAEj8ypGsdSC4tz01GLDAmN4tCbn525iBCdNLfMdjNPeftA7xMjEwXiIUYKDWUmEV9VTJVmI NyWxsiq1KD++qDQntfgQoykweCcyS4km5wPTdl5JvKGJpYGJmZGxiYWhmaGSOK+eNmOykEB6 YklqdmpqQWoRTB8TB6dUA5P4BJOf88578v/8bPGd8YTlEa/LH0UmC9rzbU8SPbNx6ZxLL/W2 fpA58zl67qa+X/WMT/gz5vkfzJl0b9v294fmR07+MzF4N6Ph3hbVjpZX4VUfFn993MZbeLqh eVJGAVNbbOfuFUv/Kzkdfuu0xU7KTlTt+J2ySdJfunjYz2mxOuu0/5rgomu3Ucj8469Qj2MC y4+0if+9s7A7qeR6slPXMl5dlZl195T0OfiUdVzLxLz76zqV3z0I3aY0x+vP5S8MjF3MXX9z Zp7tmsbR8m5FvWPQCe0Xx/beXvVcZMdnYYF5n3aFTLWb37s68ur39GNpxec9TTr/qe5f6nX+ xfYiLrdtP98czf469brkCu14JZbijERDLeai4kQAtvoLgCMEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrNLMWRmVeSWpSXmKPExsWy7bCSvC5fmWqywbSlAhZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAlfG5J5upoL/CxkrWmb1MTUwHmpl7GLk 5JAQMJG4fnk7SxcjF4eQwG5GiXVXLrJBJCQkNt1bztzFyAFkC0scPlwMUfORUeLP9mNgzWwC qhIzZ6xhB7FFBGolDh6dzwxiMwsUSMx+OpMFxBYWMJXo+jkZLM4CVL9jwQ+wel4BG4lrJ0+D xTmB7JubmsDqhQSsJWZPn8sEUSMocXLmExaImfISzVtnM09g5J+FJDULSWoBI9MqRsnUguLc 9NxiwwLDvNRyveLE3OLSvHS95PzcTYzg8NbS3MG4fdUHvUOMTByMhxglOJiVRHhVPVWShXhT EiurUovy44tKc1KLDzFKc7AoifNe6DoZLySQnliSmp2aWpBaBJNl4uCUamDqv3DQ9dNr+RgO 4+PbPnWss7p2+6rj12v29UExMhe0DXbMUUlabK+9VuXPMe4W40e6nKvPemjv1Ba19KqqFD4e OzeVf1GlIavrFdntT2KSlxb5np807VJAvmRexpOvHW09Fq9vsOyP+SF1zE+de+6Fp8WRS7/f /bchK31uYsiO8youPuqLP//+zyUoq8Utmmhes6zkUGDXl2t7ej44PYhZbnPiaO6sOJs6T7+b N941+p1bvvDmbTHz3dOWe0SwZVZEPjATenbo/qcJ4sV80kIMOk4LnTWk30QX8jydZ/WS7++F FLOdLcdvF/Lo+D39d+3h+5DcPWvK5fjDMz9axtrH3OS6IGM0Kd7WTOdZ8SElluKMREMt5qLi RABhXMhe3gIAAA== X-CMS-MailID: 20220917072358epcas1p14997459c7add27bf7b4e9333cbf21b72 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072358epcas1p14997459c7add27bf7b4e9333cbf21b72 References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch is for profile module. The samsung NPU provides internal statistics data, and it includes memory read/write counts, consumed clock cycle for each operation. This statistics can be read by ioctl control command. Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong Signed-off-by: Dongju Chae Signed-off-by: MyungJoo Ham --- drivers/misc/trinity/trinity_vision2_drv.c | 326 ++++++++++++++++++ .../misc/trinity/trinity_vision2_profile.h | 324 +++++++++++++++++ 2 files changed, 650 insertions(+) create mode 100644 drivers/misc/trinity/trinity_vision2_profile.h diff --git a/drivers/misc/trinity/trinity_vision2_drv.c b/drivers/misc/trin= ity/trinity_vision2_drv.c index 3dd89920cdf5..111623322895 100644 --- a/drivers/misc/trinity/trinity_vision2_drv.c +++ b/drivers/misc/trinity/trinity_vision2_drv.c @@ -18,6 +18,7 @@ =20 #include "trinity_common.h" #include "trinity_sched.h" +#include "trinity_vision2_profile.h" #include "trinity_vision2_regs.h" =20 #define TRIV2_DRV_GET_PDATA(drv) ((struct triv2_pdata *)(drv->pdata)) @@ -146,6 +147,11 @@ struct triv2_pdata { =20 /* back buffer for context switching */ struct trinity_dma back_buf; + + /* profiling */ + struct trinity_dma prof_buf; + struct mutex prof_lock; + DECLARE_HASHTABLE(prof_htable, TRIV2_PROFILE_HASH_BITS); }; =20 static void triv2_idu_setup(struct trinity_driver *drv); @@ -156,6 +162,150 @@ static void triv2_handle_cmd_done(struct trinity_driv= er *drv, struct triv2_cmd *cmd, bool timeout); static void triv2_setup_buffers(struct trinity_driver *drv); =20 +static const char *const triv2_op_names[] =3D + TRIV2_FOREACH_OPNAME(TRIV2_GENERATE_OPNAME); + +static struct triv2_profile * +triv2_find_profile(const struct trinity_driver *drv, int req_id) +{ + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + unsigned long key =3D TRIV2_PROFILE_HASH_KEY(req_id); + struct triv2_profile *profile =3D NULL; + + hash_for_each_possible(pdata->prof_htable, profile, hlist, key) { + if (profile->req_id =3D=3D req_id) + break; + } + + return profile; +} + +static void triv2_fini_profile(struct device *dev, struct trinity_dma *pro= f_buf) +{ + if (!prof_buf->addr) + return; + + trinity_dma_free(dev, prof_buf); + memset(prof_buf, '\x00', sizeof(*prof_buf)); +} + +static void triv2_init_profile(struct trinity_driver *drv, + unsigned long profile_size) +{ + struct device *dev =3D drv_to_dev_ptr(drv); + struct trinity_dma *prof_buf =3D TRIV2_DRV_GET_PROF_BUF(drv); + + if (profile_size > 0) { + /* allocate profile buffer and enable it */ + struct iommu_domain *domain; + phys_addr_t paddr; + int status; + + triv2_fini_profile(dev, prof_buf); + + status =3D trinity_dma_alloc(dev, profile_size, prof_buf); + if (status < 0) { + dev_err(dev, + "Couldn't allocate memory for profiling buffer: %d", + status); + return; + } + + domain =3D iommu_get_domain_for_dev(drv_to_dev_ptr(drv)); + paddr =3D trinity_get_paddr(domain, prof_buf->dma_handle); + iowrite32(TRIV2_IDU_ADDR(paddr), + trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_PROF_ADDR)); + iowrite32(prof_buf->size, + trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_PROF_SIZE)); + } else { + /* disable profiling */ + triv2_fini_profile(dev, prof_buf); + + iowrite32(0, trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_PROF_ADDR)); + iowrite32(0, trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_PROF_SIZE)); + } +} + +static void triv2_assign_opnames(struct triv2_cmd_profile *cmd) +{ + struct triv2_op_profile *ops =3D cmd->profile_ops; + uint32_t i; + + for (i =3D 0; i < cmd->total_ops; i++) + snprintf(ops[i].op_name, TRIV2_MAX_OPNAME, "%s", + triv2_op_names[ops[i].opcode]); +} + +static int32_t triv2_check_profile(struct trinity_driver *drv, + struct trinity_req *req) +{ + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + struct triv2_req *t_req =3D TRIV2_GET_REQ(req); + struct trinity_dma *profile_buf; + struct triv2_cmd_profile *profile_cmd; + struct triv2_cmd_profile *profile_cmd_new; + struct triv2_profile *profile; + + uint32_t offset =3D t_req->profile_offset; + uint32_t total_ops, total_size; + + profile_buf =3D TRIV2_DRV_GET_PROF_BUF(drv); + if (!profile_buf->addr) + return 0; + + if (profile_buf->size <=3D offset) { + dev_err(drv_to_dev_ptr(drv), + "Invalid profile offset detected: 0x%x", offset); + return -EINVAL; + } + + profile_cmd =3D (struct triv2_cmd_profile *)((char *)profile_buf->addr + + offset); + profile_cmd->total_cycles =3D t_req->total_cycles; + + total_ops =3D profile_cmd->total_ops; + total_size =3D sizeof(struct triv2_cmd_profile) + + total_ops * sizeof(struct triv2_op_profile); + + profile_cmd_new =3D vzalloc(total_size); + if (!profile_cmd_new) + return -ENOMEM; + + mutex_lock(&pdata->prof_lock); + + profile =3D req->stat->profile; + if (profile) { + WARN_ON(!profile->data); + vfree(profile->data); + profile->data =3D profile_cmd_new; + } else { + int req_id =3D req->input.config.req_id; + unsigned long key =3D TRIV2_PROFILE_HASH_KEY(req_id); + + profile =3D vzalloc(sizeof(struct triv2_profile)); + if (!profile) { + vfree(profile_cmd_new); + mutex_unlock(&pdata->prof_lock); + return -ENOMEM; + } + profile->req_id =3D req_id; + profile->data =3D profile_cmd_new; + + hash_add(pdata->prof_htable, &profile->hlist, key); + + req->stat->profile =3D profile; + } + memcpy(profile_cmd_new, profile_cmd, total_size); + triv2_assign_opnames(profile_cmd_new); + + mutex_unlock(&pdata->prof_lock); + return 0; +} + /** * triv2_get_state() - Get state (TRINITY_STATE_READY/TRINITY_STATE_PAUSE)= of the device. * @returns (enum triv2_state) TRINITY_STATE_READY (i.e., 1) or TRINITY_ST= ATE_PAUSE (i.e., 0 ) @@ -447,6 +597,157 @@ static void triv2_stop_reqs(struct work_struct *work) triv2_cancel_reqs(drv); } =20 +/** + * triv2_get_profile_meta() - get profile metadata for the target req + */ +static int32_t triv2_get_profile_meta(const struct trinity_driver *drv, + struct trinity_ioctl_profile_meta *meta) +{ + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + struct triv2_profile *profile; + struct triv2_cmd_profile *profile_data; + int ret =3D 0; + + mutex_lock(&pdata->prof_lock); + + profile =3D triv2_find_profile(drv, meta->req_id); + if (!profile) { + ret =3D -ENOENT; + goto out; + } + + profile_data =3D profile->data; + WARN_ON(!profile_data); + + meta->total_cycles =3D profile_data->total_cycles; + meta->total_ops =3D profile_data->total_ops; + meta->profile_size =3D + profile_data->total_ops * sizeof(struct triv2_op_profile); + /* unsupported for now */ + meta->input_footprint =3D -1; + meta->output_footprint =3D -1; + +out: + mutex_unlock(&pdata->prof_lock); + + return ret; +} + +/** + * triv2_get_profile_buff() - get profile buffer for the target req + */ +static int32_t triv2_get_profile_buff(const struct trinity_driver *drv, + struct trinity_ioctl_profile_buff *buff) +{ + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + struct triv2_profile *profile; + struct triv2_cmd_profile *profile_data; + uint32_t total_size; + int ret =3D 0; + + mutex_lock(&pdata->prof_lock); + + profile =3D triv2_find_profile(drv, buff->req_id); + if (!profile) { + ret =3D -ENOENT; + goto out; + } + + profile_data =3D profile->data; + WARN_ON(!profile_data); + + profile_data =3D profile->data; + total_size =3D profile_data->total_ops * sizeof(struct triv2_op_profile); + + if (buff->profile_pos + buff->profile_size > total_size) { + dev_err(drv_to_dev_ptr(drv), + "Profile data out-of-range! pos(%u) size(%u) > total_size(%u)", + buff->profile_pos, buff->profile_size, total_size); + ret =3D -ERANGE; + goto out; + } + + /* consider partial memory copies */ + if (copy_to_user((char __user *)buff->profile_buf, + (char *)profile_data->profile_ops + buff->profile_pos, + buff->profile_size)) + ret =3D -EACCES; + +out: + mutex_unlock(&pdata->prof_lock); + + return ret; +} + +static ssize_t triv2_get_profile(const struct trinity_driver *drv, char *b= uf, int req_id) +{ + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + struct triv2_profile *profile; + struct triv2_cmd_profile *profile_data; + uint32_t i; + ssize_t len =3D 0; + + mutex_lock(&pdata->prof_lock); + + profile =3D triv2_find_profile(drv, req_id); + if (!profile) { + len +=3D snprintf(buf, PAGE_SIZE, "Unable to find the profile data (req_= id %d)", + req_id); + goto out; + } + + profile_data =3D profile->data; + WARN_ON(!profile_data); + + len +=3D snprintf(buf, PAGE_SIZE, "Total cycles: %lld", profile_data->tot= al_cycles); + len +=3D snprintf(buf, PAGE_SIZE, "Total ops: %u", profile_data->total_op= s); + + for (i =3D 0; i < profile_data->total_ops; i++) { + struct triv2_op_profile *op =3D &profile_data->profile_ops[i]; + + len +=3D snprintf(buf, PAGE_SIZE, "[%u] opcode: %u name:%s", i, op->opco= de, + op->op_name); + len +=3D snprintf(buf, PAGE_SIZE, "\tcycles: %lld", op->cycles); + len +=3D snprintf(buf, PAGE_SIZE, "\tprog_seq: %lld", op->prog_seq); + len +=3D snprintf(buf, PAGE_SIZE, "\texec_seq: %lld", op->exec_seq); + if (op->dram_read > 0) + len +=3D snprintf(buf, PAGE_SIZE, "\tdram_read: %lld", op->dram_read); + if (op->dram_write > 0) + len +=3D snprintf(buf, PAGE_SIZE, "\tdram_write: %lld", op->dram_write); + if (op->sram_read > 0) + len +=3D snprintf(buf, PAGE_SIZE, "\tsram_read: %lld", op->sram_read); + if (op->sram_write > 0) + len +=3D snprintf(buf, PAGE_SIZE, "\tsram_write: %lld", op->sram_write); + } +out: + mutex_unlock(&pdata->prof_lock); + return len; +} + +/** + * triv2_destroy_profile() - destroy profile data + */ +static void triv2_destroy_profile(const struct trinity_driver *drv, void *= data) +{ + struct triv2_pdata *pdata =3D TRIV2_DRV_GET_PDATA(drv); + struct triv2_profile *profile =3D data; + struct triv2_cmd_profile *profile_data; + + if (!profile) + return; + + mutex_lock(&pdata->prof_lock); + + profile_data =3D profile->data; + WARN_ON(!profile_data); + vfree(profile_data); + + hash_del(&profile->hlist); + vfree(profile); + + mutex_unlock(&pdata->prof_lock); +} + static void triv2_handle_irq_cmds(struct trinity_driver *drv) { struct triv2_cmd_info *info; @@ -1021,11 +1322,13 @@ static void triv2_setup_buffers(struct trinity_driv= er *drv) struct iommu_domain *domain; struct trinity_dma *cmd_buf; struct trinity_dma *back_buf; + struct trinity_dma *prof_buf; phys_addr_t paddr; =20 domain =3D iommu_get_domain_for_dev(dev); cmd_buf =3D TRIV2_DRV_GET_CMD_BUF(drv); back_buf =3D TRIV2_DRV_GET_BACK_BUF(drv); + prof_buf =3D TRIV2_DRV_GET_PROF_BUF(drv); =20 /* command */ paddr =3D trinity_get_paddr(domain, cmd_buf->dma_handle); @@ -1038,6 +1341,22 @@ static void triv2_setup_buffers(struct trinity_drive= r *drv) OFFSET_NPU_BACK_ADDR)); iowrite32(back_buf->size, trinity_get_iomem_addr(drv->mmreg_vaddr[0], OFFSET_NPU_BACK_SIZE)); + + /* profile */ + if (prof_buf->size > 0) { + paddr =3D trinity_get_paddr(domain, prof_buf->dma_handle); + iowrite32(TRIV2_IDU_ADDR(paddr), + trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_PROF_ADDR)); + iowrite32(prof_buf->size, + trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_PROF_SIZE)); + } else { + iowrite32(0, trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_PROF_ADDR)); + iowrite32(0, trinity_get_iomem_addr(drv->mmreg_vaddr[0], + OFFSET_NPU_PROF_SIZE)); + } } =20 static int32_t triv2_init_pdata(struct trinity_driver *drv) @@ -1203,6 +1522,13 @@ static struct trinity_desc triv2_desc =3D { .dealloc_req =3D triv2_dealloc_req, .prepare_req =3D triv2_prepare_req, .invoke_req =3D triv2_invoke_req, + /* profile */ + .init_profile =3D triv2_init_profile, + .check_profile =3D triv2_check_profile, + .get_profile_meta =3D triv2_get_profile_meta, + .get_profile_buff =3D triv2_get_profile_buff, + .get_profile =3D triv2_get_profile, + .destroy_profile =3D triv2_destroy_profile, /* etc. */ .handle_timeout =3D triv2_handle_timeout, .stop_reqs =3D triv2_stop_reqs, diff --git a/drivers/misc/trinity/trinity_vision2_profile.h b/drivers/misc/= trinity/trinity_vision2_profile.h new file mode 100644 index 000000000000..7e5b169eca6b --- /dev/null +++ b/drivers/misc/trinity/trinity_vision2_profile.h @@ -0,0 +1,324 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Profile header for TRIV2 devices + * + * Copyright (C) 2021-2022 Samsung Electronics + * Copyright (C) 2021 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#ifndef __DRIVERS_MISC_TRINITY_VISION2_PROFILE_H__ +#define __DRIVERS_MISC_TRINITY_VISION2_PROFILE_H__ + +#include + +#define TRIV2_MAX_OPNAME (128) +#define TRIV2_MAX_PROFILE_SIZE (256) + +/** + * struct triv2_op_profile - A profile data per operation + * + * @op_name: The physical DMA address of this DMA buffer. + * @cycles: total number of cycles + * @dram_read: a count for dram read + * @dram_write: a count for dram write + * @sram_read: a count for sram read + * @sram_write: a count for sram write + * @start_cycles: a count for starting cycles + * @end_cycles: a cont for ending cycles + * @opcode: operation code + * @prog_seq: program sequence number + * @exec_seq: execution sequence number + * @reserved: reserved + */ +struct triv2_op_profile { + union { + struct { + char op_name[TRIV2_MAX_OPNAME]; + + int64_t cycles; + + int64_t dram_read; + int64_t dram_write; + + int64_t sram_read; + int64_t sram_write; + + int64_t start_cycles; + int64_t end_cycles; + + uint32_t opcode; + int64_t prog_seq; + int64_t exec_seq; + } __packed; + uint8_t reserved[TRIV2_MAX_PROFILE_SIZE]; + }; +}; + +/** + * struct triv2_cmd_profile - A profile data per command + * + * @total_cycles: total number of cycles for a command + * @total_ops: total operations of command + * @profile_ops: list of profile data for operations + */ +struct triv2_cmd_profile { + int64_t total_cycles; + uint32_t total_ops; + /* zero-length array */ + struct triv2_op_profile profile_ops[]; +} __packed; + +/** + * struct triv2_profile - A profile data + * + * @req_id: total number of cycles for a command + * @hlist: list of profile data + * @data: command profile data + */ +struct triv2_profile { + int req_id; + struct hlist_node hlist; + struct triv2_cmd_profile *data; +}; + +enum { + NOP =3D 0x00, + HALT =3D 0x01, + ADMA_IN =3D 0x02, + ADMA_OUT =3D 0x03, + RESCALE_I8 =3D 0x04, + RESCALE_I16 =3D 0x05, + CONVERT_I16_I8 =3D 0x06, + CONVERT_I8_I16 =3D 0x07, + RELUN_I8 =3D 0x08, + RELUN_I16 =3D 0x09, + PRELU_I8 =3D 0x0A, + PRELU_I16 =3D 0x0B, + ADD_I8 =3D 0x0C, + ADD_I16 =3D 0x0D, + REDUCE_MEAN_I8 =3D 0x0E, + REDUCE_MEAN_I16 =3D 0x0F, + MAX_POOL_I8 =3D 0x10, + MAX_POOL_I16 =3D 0x11, + AVG_POOL_I8 =3D 0x12, + AVG_POOL_I16 =3D 0x13, + CONV_I8 =3D 0x14, + CONV_I16 =3D 0x15, + CONVE_I8 =3D 0x16, + CONVE_I16 =3D 0x17, + TCONV_I8 =3D 0x18, + TCONV_I16 =3D 0x19, + MUL_I8 =3D 0x1A, + MUL_I16 =3D 0x1B, + DCONV_I8 =3D 0x1C, + DCONV_I16 =3D 0x1D, + DCONVE_I8 =3D 0x1E, + DCONVE_I16 =3D 0x1F, + CONV_I8_P =3D 0x20, + CONV_I16_P =3D 0x21, + PDMA_IN =3D 0x40, + PDMA_OUT =3D 0x41, + ARGMAX_I8 =3D 0x42, + ARGMAX_I16 =3D 0x43, + RESHAPE_I8 =3D 0x44, + RESHAPE_I16 =3D 0x45, + TRANSPOSE_I8 =3D 0x46, + TRANSPOSE_I16 =3D 0x47, + CONCAT_I8 =3D 0x48, + CONCAT_I16 =3D 0x49, + PAD_I8 =3D 0x4A, + PAD_I16 =3D 0x4B, + STRIDED_SLICE_I8 =3D 0x4C, + STRIDED_SLICE_I16 =3D 0x4D, + CONVERT_FORMAT_I8 =3D 0x4E, + CONVERT_FORMAT_I16 =3D 0x4F, + SIGMOID_I8 =3D 0x50, + SIGMOID_I16 =3D 0x51, + TANH_I8 =3D 0x52, + TANH_I16 =3D 0x53, + ELU_I8 =3D 0x54, + ELU_I16 =3D 0x55, + FLOOR_I8 =3D 0x56, + FLOOR_I16 =3D 0x57, + RSQRT_I8 =3D 0x58, + RSQRT_I16 =3D 0x59, + SQRT_I8 =3D 0x5A, + SQRT_I16 =3D 0x5B, + SOFTMAX_I8 =3D 0x5C, + SOFTMAX_I16 =3D 0x5D, + DIVIDE_I8 =3D 0x60, + DIVIDE_I16 =3D 0x61, + FLOORDIV_I8 =3D 0x62, + FLOORDIV_I16 =3D 0x63, + LOGICAL_OR_I8 =3D 0x64, + LOGICAL_OR_I16 =3D 0x65, + GREATER_I8 =3D 0x66, + GREATER_I16 =3D 0x67, + GREATER_EQUAL_I8 =3D 0x68, + GREATER_EQUAL_I16 =3D 0x69, + POW_I8 =3D 0x6A, + POW_I16 =3D 0x6B, + EXP_I8 =3D 0x6C, + EXP_I16 =3D 0x6D, + NOT_EQUAL_I8 =3D 0x6E, + NOT_EQUAL_I16 =3D 0x6F, + BATCH_TO_SPACE_I8 =3D 0x70, + BATCH_TO_SPACE_I16 =3D 0x71, + SPACE_TO_BATCH_I8 =3D 0x72, + SPACE_TO_BATCH_I16 =3D 0x73, + DEPTH_TO_SPACE_I8 =3D 0x74, + DEPTH_TO_SPACE_I16 =3D 0x75, + SPACE_TO_DEPTH_I8 =3D 0x76, + SPACE_TO_DEPTH_I16 =3D 0x77, + YUV_TO_RGB_I8 =3D 0x7A, + YUV_TO_RGB_I16 =3D 0x7B, + RESIZE_BILINEAR_I8 =3D 0x7C, + RESIZE_BILINEAR_I16 =3D 0x7D, + RESIZE_NEAREST_NEIGHBOR_I8 =3D 0x7E, + RESIZE_NEAREST_NEIGHBOR_I16 =3D 0x7F, + LOCAL_RESPONSE_NORM_I8 =3D 0x80, + LOCAL_RESPONSE_NORM_I16 =3D 0x81, + INSTANCE_NORM_I8 =3D 0x82, + INSTANCE_NORM_I16 =3D 0x83, + REDUCED_SUM_SSUM_I8 =3D 0x84, + REDUCED_SUM_SSUM_I16 =3D 0x85, + REDUCED_SUM_SSUM_ACC_I8 =3D 0x86, + REDUCED_SUM_SSUM_ACC_I16 =3D 0x87, + REDUCED_SUM_2SUM_I8 =3D 0x88, + REDUCED_SUM_2SUM_I16 =3D 0x89, + REDUCED_MEAN_DEV_WSUM_I8 =3D 0x8A, + REDUCED_MEAN_DEV_WSUM_I16 =3D 0x8B, + REDUCED_MEAN_DEV_I8 =3D 0x8C, + REDUCED_MEAN_DEV_I16 =3D 0x8D, + RESCALE_CW_I8 =3D 0x8E, + RESCALE_CW_I16 =3D 0x8F, + REDUCED_MEAN_SCALE_WSUM_I8 =3D 0x90, + REDUCED_MEAN_SCALE_WSUM_I16 =3D 0x91, + RESCALE_CHANNELWISE_I8 =3D 0x92, + RESCALE_CHANNELWISE_I16 =3D 0x93, +}; + +/** generate opnames */ +#define TRIV2_GENERATE_OPNAME(OPNAME) \ + [OPNAME] =3D #OPNAME, + +#define TRIV2_FOREACH_OPNAME(GEN) {\ + GEN(NOP) \ + GEN(HALT) \ + GEN(ADMA_IN) \ + GEN(ADMA_OUT) \ + GEN(RESCALE_I8) \ + GEN(RESCALE_I16) \ + GEN(CONVERT_I16_I8) \ + GEN(CONVERT_I8_I16) \ + GEN(RELUN_I8) \ + GEN(RELUN_I16) \ + GEN(PRELU_I8) \ + GEN(PRELU_I16) \ + GEN(ADD_I8) \ + GEN(ADD_I16) \ + GEN(REDUCE_MEAN_I8) \ + GEN(REDUCE_MEAN_I16) \ + GEN(MAX_POOL_I8) \ + GEN(MAX_POOL_I16) \ + GEN(AVG_POOL_I8) \ + GEN(AVG_POOL_I16) \ + GEN(CONV_I8) \ + GEN(CONV_I16) \ + GEN(CONVE_I8) \ + GEN(CONVE_I16) \ + GEN(TCONV_I8) \ + GEN(TCONV_I16) \ + GEN(MUL_I8) \ + GEN(MUL_I16) \ + GEN(DCONV_I8) \ + GEN(DCONV_I16) \ + GEN(DCONVE_I8) \ + GEN(DCONVE_I16) \ + GEN(CONV_I8_P) \ + GEN(CONV_I16_P) \ + GEN(PDMA_IN) \ + GEN(PDMA_OUT) \ + GEN(ARGMAX_I8) \ + GEN(ARGMAX_I16) \ + GEN(RESHAPE_I8) \ + GEN(RESHAPE_I16) \ + GEN(TRANSPOSE_I8) \ + GEN(TRANSPOSE_I16) \ + GEN(CONCAT_I8) \ + GEN(CONCAT_I16) \ + GEN(PAD_I8) \ + GEN(PAD_I16) \ + GEN(STRIDED_SLICE_I8) \ + GEN(STRIDED_SLICE_I16) \ + GEN(CONVERT_FORMAT_I8) \ + GEN(CONVERT_FORMAT_I16) \ + GEN(SIGMOID_I8) \ + GEN(SIGMOID_I16) \ + GEN(TANH_I8) \ + GEN(TANH_I16) \ + GEN(ELU_I8) \ + GEN(ELU_I16) \ + GEN(FLOOR_I8) \ + GEN(FLOOR_I16) \ + GEN(RSQRT_I8) \ + GEN(RSQRT_I16) \ + GEN(SQRT_I8) \ + GEN(SQRT_I16) \ + GEN(SOFTMAX_I8) \ + GEN(SOFTMAX_I16) \ + GEN(DIVIDE_I8) \ + GEN(DIVIDE_I16) \ + GEN(FLOORDIV_I8) \ + GEN(FLOORDIV_I16) \ + GEN(LOGICAL_OR_I8) \ + GEN(LOGICAL_OR_I16) \ + GEN(GREATER_I8) \ + GEN(GREATER_I16) \ + GEN(GREATER_EQUAL_I8) \ + GEN(GREATER_EQUAL_I16) \ + GEN(POW_I8) \ + GEN(POW_I16) \ + GEN(EXP_I8) \ + GEN(EXP_I16) \ + GEN(NOT_EQUAL_I8) \ + GEN(NOT_EQUAL_I16) \ + GEN(BATCH_TO_SPACE_I8) \ + GEN(BATCH_TO_SPACE_I16) \ + GEN(SPACE_TO_BATCH_I8) \ + GEN(SPACE_TO_BATCH_I16) \ + GEN(DEPTH_TO_SPACE_I8) \ + GEN(DEPTH_TO_SPACE_I16) \ + GEN(SPACE_TO_DEPTH_I8) \ + GEN(SPACE_TO_DEPTH_I16) \ + GEN(YUV_TO_RGB_I8) \ + GEN(YUV_TO_RGB_I16) \ + GEN(RESIZE_BILINEAR_I8) \ + GEN(RESIZE_BILINEAR_I16) \ + GEN(RESIZE_NEAREST_NEIGHBOR_I8) \ + GEN(RESIZE_NEAREST_NEIGHBOR_I16) \ + GEN(LOCAL_RESPONSE_NORM_I8) \ + GEN(LOCAL_RESPONSE_NORM_I16) \ + GEN(INSTANCE_NORM_I8) \ + GEN(INSTANCE_NORM_I16) \ + GEN(REDUCED_SUM_SSUM_I8) \ + GEN(REDUCED_SUM_SSUM_I16) \ + GEN(REDUCED_SUM_SSUM_ACC_I8) \ + GEN(REDUCED_SUM_SSUM_ACC_I16) \ + GEN(REDUCED_SUM_2SUM_I8) \ + GEN(REDUCED_SUM_2SUM_I16) \ + GEN(REDUCED_MEAN_DEV_WSUM_I8) \ + GEN(REDUCED_MEAN_DEV_WSUM_I16) \ + GEN(REDUCED_MEAN_DEV_I8) \ + GEN(REDUCED_MEAN_DEV_I16) \ + GEN(RESCALE_CW_I8) \ + GEN(RESCALE_CW_I16) \ + GEN(REDUCED_MEAN_SCALE_WSUM_I8) \ + GEN(REDUCED_MEAN_SCALE_WSUM_I16) \ + GEN(RESCALE_CHANNELWISE_I8) \ + GEN(RESCALE_CHANNELWISE_I16) \ +} +#endif /* __DRIVERS_MISC_TRINITY_VISION2_PROFILE_H__ */ --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E96A6C6FA86 for ; Sat, 17 Sep 2022 07:25:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229771AbiIQHZA (ORCPT ); Sat, 17 Sep 2022 03:25:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51914 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229588AbiIQHYL (ORCPT ); Sat, 17 Sep 2022 03:24:11 -0400 Received: from mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 979A64505B for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p4.samsung.com (unknown [182.195.41.48]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20220917072400epoutp04ef478883371c646aae660d0607465e98~VlPpcUHFp2922529225epoutp04b for ; Sat, 17 Sep 2022 07:24:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20220917072400epoutp04ef478883371c646aae660d0607465e98~VlPpcUHFp2922529225epoutp04b DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399440; bh=5J299PNSV9On+DufuXExL84p/AfLlL1SenNEX0X8or4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=B9q9DvGjxIaErtl16VRRmIjhGr895jTK/Fy+apGqzRigYibQnSDLoB+yH5rAxrbdc sspRBLiL+kYEyEeA8YCNP3CBfPh5e+EwBR+V09pGfu64ta97RfglWbrLMQkmnStJgC dOTmPzFJw2/xMtm3N4X/3MUAHMa2lKKvS6B0VgcE= Received: from epsnrtp1.localdomain (unknown [182.195.42.162]) by epcas1p2.samsung.com (KnoxPortal) with ESMTP id 20220917072359epcas1p2d9b7ef80c3493647e29a81fa5d7abe5c~VlPo_wbFk1789517895epcas1p2t; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) Received: from epsmges1p2.samsung.com (unknown [182.195.36.134]) by epsnrtp1.localdomain (Postfix) with ESMTP id 4MV2Vk6npRz4x9Pp; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epcas1p1.samsung.com ( [182.195.41.45]) by epsmges1p2.samsung.com (Symantec Messaging Gateway) with SMTP id BC.71.51827.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas1p4.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epcas1p4e110e2025c90d78fad2182ec5cd66eb7~VlPntQZGs1033410334epcas1p4h; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220917072358epsmtrp27d0b9fe1cd6cc7eda09db09231f2b2c4~VlPnsh0xp1654916549epsmtrp20; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) X-AuditID: b6c32a36-f25ff7000000ca73-2b-6325760ecef9 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id 06.F0.18644.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epsmtip2a5a45b3e87b2b4e50bbce6907deddf5d~VlPna_s6Y2357323573epsmtip2g; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 11/13] trinity: Add trace module Date: Sat, 17 Sep 2022 16:23:54 +0900 Message-Id: <20220917072356.2255620-12-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupjk+LIzCtJLcpLzFFi42LZdlhTV5evTDXZYO8cM4u/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtKtsmIzUxJbVIITUvOT8lMy/dVsk7ON453tTMwFDX0NLCXEkh LzE31VbJxSdA1y0zB+gqJYWyxJxSoFBAYnGxkr6dTVF+aUmqQkZ+cYmtUmpBSk6BaYFecWJu cWleul5eaomVoYGBkSlQYUJ2xoxn/cwFX6cwVsz5LdjA+LS6i5GTQ0LARGLvhFmMXYxcHEIC Oxgl+hd/YINwPjFKvFr7mxXC+cwoMWHLHFaYliV9m5ghErsYJb73zGCHq9q3fyEbSBWbgKrE zBlr2EFsEYFyieaNJ8BsZoEciSd3mphBbGEBY4nZqxsZQWwWoPr2FfNYQGxeARuJmW27weo5 geybm5qg4oISJ2c+YYGYIy/RvHU22BUSAh/ZJX68WQo0iAPIcZE49KwW4lJhiVfHt7BD2FIS n9/tZYOwsyWmdCxigbALJM4938oM0WoscXFFCojJLKApsX6XPkSFosTO33MZIbbySbz72sMK Uc0r0dEmBFGiJLHkz2GoRRISU2d8Y4KwPSQWXe2EhmE/o8SDPb0sExjlZyF5ZhaSZ2YhbF7A yLyKUSy1oDg3PbXYsMAIHqnJ+bmbGMEJU8tsB+Oktx/0DjEycTAeYpTgYFYS4VX1VEkW4k1J rKxKLcqPLyrNSS0+xGgKDN6JzFKiyfnAlJ1XEm9oYmlgYmZkbGJhaGaoJM6rp82YLCSQnliS mp2aWpBaBNPHxMEp1cBkEbTs0r+UvAL5CbeCAtV14x95dBxcqPV1p7TxjisLLBN0jBtn9Ofm Vu2a4Gq0wv/2hNrMpSXF630CrY1kfjRfDD8assN2JuNXPc7ZiVlXFqldNz6n2fV34vO3HTMM m9ucjS9N23Rsc1Zc/cnDKtds+iv/7FvDfY7jTFvWlDAZu+Bqk3Dfm2s5Zda82xphsGCjnYhM wGQT5kvfM27v/fW5xyL10JvSyVN7tDYr73PNSN6h68CZqCy5g3HXK2O9kxdzGQ80q1iFss02 OrUu0rExJq6RN7yj2aV2gfJ6W6VYm8BTNwN/bJ/xcK/g/Ept1fzDkV+TxW9/ZdEwO7D/wvcT yS6ffwXP3nxsXYZwnJQSS3FGoqEWc1FxIgD/9Lx/IQQAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrJLMWRmVeSWpSXmKPExsWy7bCSvC5fmWqywZ694hZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAlfGjGf9zAVfpzBWzPkt2MD4tLqLkZND QsBEYknfJuYuRi4OIYEdjBK3Xzxnh0hISGy6txwowQFkC0scPlwMUfORUeLHqXdsIDVsAqoS M2esAasXEaiVOHh0PjOIzSxQIDH76UwWEFtYwFhi9upGRhCbBai+fcU8sDivgI3EzLbdYL2c QPbNTU1gcSEBa4nZ0+cyQdQISpyc+YQFYqa8RPPW2cwTGPlnIUnNQpJawMi0ilEytaA4Nz23 2LDAKC+1XK84Mbe4NC9dLzk/dxMjOLS1tHYw7ln1Qe8QIxMH4yFGCQ5mJRFeVU+VZCHelMTK qtSi/Pii0pzU4kOM0hwsSuK8F7pOxgsJpCeWpGanphakFsFkmTg4pRqY5lpPulwX+/ISXy8D Q82KdZsdxQ3WMButmCfSO/vCrB98vo3+t62cv63cfOel8MO4N1JJiw47a5873cWeGWz5YFlW WH5scviOdXNlwu+l3HvWPGNNrPHfbClhSbbysr1MEruDvi2rLbn6KvWpxlrHw/vVm9YkN/9I 3L3ozHyr8l9uWxdbaqbLR+xx+yP66Kla8ue9Znrd71V+V7BM/G6qG6jMsF3y21aHjNQTqW/4 vmbr/sx/bTcnMe1v/5ubl87tXPNXWePcmsiP5hOZXsj7f9OQ0dQSi9pYq+rtP5H9wf1bb5cY +mqe+BWuYOLxRkr37qvlM7Pa89wue68uFLOezdvhsHcv34bei44SyT9ylViKMxINtZiLihMB MU8TF9wCAAA= X-CMS-MailID: 20220917072358epcas1p4e110e2025c90d78fad2182ec5cd66eb7 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072358epcas1p4e110e2025c90d78fad2182ec5cd66eb7 References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch is for trace declaration. 'trinity' ftrace module added several trace points. The points are located on each ioctl control, wakeup, irq, and run trigger. Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong Signed-off-by: Dongju Chae Signed-off-by: MyungJoo Ham --- drivers/misc/trinity/Makefile | 1 + drivers/misc/trinity/trinity.c | 58 +++- drivers/misc/trinity/trinity_trace.c | 15 + drivers/misc/trinity/trinity_trace.h | 329 +++++++++++++++++++++ drivers/misc/trinity/trinity_vision2_drv.c | 9 + 5 files changed, 410 insertions(+), 2 deletions(-) create mode 100644 drivers/misc/trinity/trinity_trace.c create mode 100644 drivers/misc/trinity/trinity_trace.h diff --git a/drivers/misc/trinity/Makefile b/drivers/misc/trinity/Makefile index 462b7c61f39f..ac747bdbf46d 100644 --- a/drivers/misc/trinity/Makefile +++ b/drivers/misc/trinity/Makefile @@ -8,5 +8,6 @@ trinity-y +=3D trinity_sched.o trinity-y +=3D trinity_debug.o trinity-y +=3D trinity_stat.o trinity-y +=3D trinity_sysfs.o +trinity-y +=3D trinity_trace.o =20 trinity_vision2-objs :=3D $(trinity-y) trinity_vision2_drv.o diff --git a/drivers/misc/trinity/trinity.c b/drivers/misc/trinity/trinity.c index 0463140c0ae6..53c6ab92c26d 100644 --- a/drivers/misc/trinity/trinity.c +++ b/drivers/misc/trinity/trinity.c @@ -16,6 +16,7 @@ #include "trinity_common.h" #include "trinity_sched.h" #include "trinity_stat.h" +#include "trinity_trace.h" =20 #define TRINITY_PADDR_BASE (0x0) =20 @@ -375,6 +376,8 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) sizeof((desc->ver)))) return -EFAULT; =20 + trace_trinity_ioctl_msg(drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_GET_VERSION"); break; } case TRINITY_IOCTL_GET_API_LEVEL: { @@ -384,6 +387,8 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) sizeof(api_level))) return -EFAULT; =20 + trace_trinity_ioctl_msg(drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_GET_API_LEVEL"); break; } case TRINITY_IOCTL_GET_STATE: { @@ -394,6 +399,8 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) sizeof(ready))) return -EFAULT; =20 + trace_trinity_ioctl_msg(drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_GET_STATE"); break; } case TRINITY_IOCTL_GET_TOPS: { @@ -401,6 +408,9 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) sizeof((drv->tops)))) return -EFAULT; =20 + trace_trinity_ioctl_msg(drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_GET_TOPS"); + break; } case TRINITY_IOCTL_GET_DSPM: { @@ -408,6 +418,9 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) sizeof((drv->dspm)))) return -EFAULT; =20 + trace_trinity_ioctl_msg(drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_GET_DSPM"); + break; } case TRINITY_IOCTL_GET_NEXT_REQUEST: { @@ -417,6 +430,9 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) sizeof(req_id))) return -EFAULT; =20 + trace_trinity_ioctl_next_req(drv->dev_id, trinity_get_app_id(), + req_id); + break; } case TRINITY_IOCTL_HWMEM_ALLOC: { @@ -430,6 +446,9 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) if (err >=3D 0) trinity_stat_app_total_alloc(drv, hwmem.size); =20 + trace_trinity_ioctl_hwmem_alloc( + drv->dev_id, trinity_get_app_id(), hwmem.size, err); + break; } case TRINITY_IOCTL_HWMEM_DEALLOC: { @@ -447,6 +466,9 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) if (err =3D=3D 0) trinity_stat_app_total_freed(drv, dbuf->size); =20 + trace_trinity_ioctl_hwmem_dealloc( + drv->dev_id, trinity_get_app_id(), hwmem.dbuf_fd); + break; } case TRINITY_IOCTL_REGISTER_MODEL: { @@ -471,6 +493,11 @@ long trinity_ioctl(struct file *f, unsigned int cmd, u= nsigned long arg) &model->config, sizeof(model->config))) return -EFAULT; =20 + trace_trinity_ioctl_register_model( + model->config.metadata_dbuf_fd, + model->config.metadata_ext_dbuf_fd, + model->config.metadata_ext_size); + break; } case TRINITY_IOCTL_DEREGISTER_MODEL: { @@ -481,6 +508,8 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) =20 err =3D trinity_deregister_model(drv, id); =20 + trace_trinity_ioctl_msg(drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_DEREGISTER_MODEL"); break; } case TRINITY_IOCTL_RUN_INPUT: { @@ -511,6 +540,11 @@ long trinity_ioctl(struct file *f, unsigned int cmd, u= nsigned long arg) return err; } =20 + trace_trinity_ioctl_run_input( + input->config.timeout_ms, input->config.priority, + input->config.num_segments, input->config.input_mode, + input->config.output_mode); + if (copy_to_user((struct trinity_input __user *)arg, &input->config, sizeof(input->config))) { drv->desc->dealloc_req(drv, req); @@ -527,9 +561,16 @@ long trinity_ioctl(struct file *f, unsigned int cmd, u= nsigned long arg) if (!IDU_LOADED(drv)) return -EFAULT; =20 - if (drv->desc->stop_reqs) + if (drv->desc->stop_reqs) { schedule_work(&drv->work_stop); - + trace_trinity_ioctl_msg(drv->dev_id, + trinity_get_app_id(), + "TRINITY_IOCTL_STOP_REQUESTS"); + } else { + trace_trinity_ioctl_msg( + drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_STOP_REQUESTS: not supported"); + } break; } case TRINITY_IOCTL_STAT_CURRENT_APP: { @@ -546,6 +587,8 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) &ioctl_stat_app, sizeof(ioctl_stat_app))) return -EACCES; =20 + trace_trinity_ioctl_msg(drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_STAT_CURRENT_APP"); break; } case TRINITY_IOCTL_STAT_APPS: { @@ -562,6 +605,8 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) &ioctl_stat_apps, sizeof(ioctl_stat_apps))) return -EACCES; =20 + trace_trinity_ioctl_msg(drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_STAT_APPS"); break; } case TRINITY_IOCTL_STAT_REQS: { @@ -581,6 +626,8 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) &ioctl_stat_reqs, sizeof(ioctl_stat_reqs))) return -EACCES; =20 + trace_trinity_ioctl_msg(drv->dev_id, trinity_get_app_id(), + "TRINITY_IOCTL_STAT_REQS"); break; } case TRINITY_IOCTL_GET_PROFILE_META: { @@ -606,6 +653,10 @@ long trinity_ioctl(struct file *f, unsigned int cmd, u= nsigned long arg) &profile, sizeof(profile))) return -EACCES; =20 + trace_trinity_ioctl_get_profile_meta(drv->dev_id, + trinity_get_app_id(), + profile.req_id, + profile.profile_size); break; } case TRINITY_IOCTL_GET_PROFILE_BUFF: { @@ -624,6 +675,9 @@ long trinity_ioctl(struct file *f, unsigned int cmd, un= signed long arg) &profile, sizeof(profile))) return -EACCES; =20 + trace_trinity_ioctl_get_profile_buff( + drv->dev_id, trinity_get_app_id(), profile.req_id, + profile.profile_pos, profile.profile_size); break; } case TRINITY_IOCTL_IDU_SET: { diff --git a/drivers/misc/trinity/trinity_trace.c b/drivers/misc/trinity/tr= inity_trace.c new file mode 100644 index 000000000000..d5721273eeb1 --- /dev/null +++ b/drivers/misc/trinity/trinity_trace.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** + * Trace source for trinity devices + * + * Copyright (C) 2021-2022 Samsung Electronics + * Copyright (C) 2021 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "trinity_trace.h" +#endif diff --git a/drivers/misc/trinity/trinity_trace.h b/drivers/misc/trinity/tr= inity_trace.h new file mode 100644 index 000000000000..c4f03deeee90 --- /dev/null +++ b/drivers/misc/trinity/trinity_trace.h @@ -0,0 +1,329 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Trace header for trinity devices + * + * Copyright (C) 2021-2022 Samsung Electronics + * Copyright (C) 2021 Dongju Chae + * Copyright (C) 2022 MyungJoo Ham + * Copyright (C) 2022 Yelin Jeong + * Copyright (C) 2022 Jiho Chu + */ + +#if !defined(__DRIVERS_MISC_TRINITY_TRACE_H__) || defined(TRACE_HEADER_MUL= TI_READ) +#define __DRIVERS_MISC_TRINITY_TRACE_H__ + +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM trinity +#define TRACE_INCLUDE_FILE trinity_trace + +// clang-format off +TRACE_EVENT(triv2_run_trigger, + TP_PROTO(u32 device_id, s32 slot), + TP_ARGS(device_id, slot), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, slot) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->slot =3D slot; + ), + TP_printk("device_id=3D%u slot=3D%d", + __entry->device_id, + __entry->slot) +); +TRACE_EVENT(triv2_wakeup_cp, + TP_PROTO(u32 device_id), + TP_ARGS(device_id), + TP_STRUCT__entry( + __field(u32, device_id) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + ), + TP_printk("device_id=3D%u", + __entry->device_id) +); +TRACE_EVENT(triv2_handle_irq, + TP_PROTO(u32 device_id, s32 irq), + TP_ARGS(device_id, irq), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, irq) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->irq =3D irq; + ), + TP_printk("device_id=3D%u irq=3D%d", + __entry->device_id, + __entry->irq) +); +TRACE_EVENT(triv2_handle_threaded_irq, + TP_PROTO(u32 device_id, s32 irq), + TP_ARGS(device_id, irq), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, irq) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->irq =3D irq; + ), + TP_printk("device_id=3D%u irq=3D%d", + __entry->device_id, + __entry->irq) +); +TRACE_EVENT(triv2_handle_cmd_done, + TP_PROTO(u32 device_id, s32 slot, u32 cycles, u32 time), + TP_ARGS(device_id, slot, cycles, time), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, slot) + __field(u32, cycles) + __field(u32, time) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->slot =3D slot; + __entry->cycles =3D cycles; + __entry->time =3D time; + ), + TP_printk("device_id=3D%u slot=3D%d cycles=3D%u time(us)=3D%u", + __entry->device_id, + __entry->slot, + __entry->cycles, + __entry->time) +); +TRACE_EVENT(triv2_map_sched_data, + TP_PROTO(u32 device_id, s32 slot, u32 batch_size, u32 in_cnt, u32 out_cnt= ), + TP_ARGS(device_id, slot, batch_size, in_cnt, out_cnt), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, slot) + __field(u32, batch_size) + __field(u32, in_cnt) + __field(u32, out_cnt) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->slot =3D slot; + __entry->batch_size =3D batch_size; + __entry->in_cnt =3D in_cnt; + __entry->out_cnt =3D out_cnt; + ), + TP_printk("device_id=3D%u slot=3D%d batch_size=3D%u in_cnt=3D%u out_cnt= =3D%u", + __entry->device_id, + __entry->slot, + __entry->batch_size, + __entry->in_cnt, + __entry->out_cnt) +); +TRACE_EVENT(triv2_unmap_sched_data, + TP_PROTO(u32 device_id, s32 slot), + TP_ARGS(device_id, slot), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, slot) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->slot =3D slot; + ), + TP_printk("device_id=3D%u slot=3D%d", + __entry->device_id, + __entry->slot) +); +TRACE_EVENT(trinity_ioctl_msg, + TP_PROTO(u32 device_id, s32 app_id, char *msg), + TP_ARGS(device_id, app_id, msg), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, app_id) + __field(char*, msg) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->app_id =3D app_id; + __entry->msg =3D msg; + ), + TP_printk("device_id=3D%u app_id=3D%d msg=3D%s", + __entry->device_id, + __entry->app_id, + __entry->msg) +); +TRACE_EVENT(trinity_ioctl_next_req, + TP_PROTO(u32 device_id, s32 app_id, s32 req_id), + TP_ARGS(device_id, app_id, req_id), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, app_id) + __field(s32, req_id) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->app_id =3D app_id; + __entry->req_id =3D req_id; + ), + TP_printk("device_id=3D%u app_id=3D%d req_id=3D%d", + __entry->device_id, + __entry->app_id, + __entry->req_id) +); +TRACE_EVENT(trinity_ioctl_stop_req, + TP_PROTO(u32 device_id, s32 app_id, s32 req_id), + TP_ARGS(device_id, app_id, req_id), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, app_id) + __field(s32, req_id) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->app_id =3D app_id; + __entry->req_id =3D req_id; + ), + TP_printk("device_id=3D%u app_id=3D%d req_id=3D%d", + __entry->device_id, + __entry->app_id, + __entry->req_id) +); +TRACE_EVENT(trinity_ioctl_hwmem_alloc, + TP_PROTO(u32 device_id, s32 app_id, s64 size, s32 dbuf_fd), + TP_ARGS(device_id, app_id, size, dbuf_fd), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, app_id) + __field(s64, size) + __field(s32, dbuf_fd) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->app_id =3D app_id; + __entry->size =3D size; + __entry->dbuf_fd =3D dbuf_fd; + ), + TP_printk("device_id=3D%u app_id=3D%d size=3D%lld dbuf_fd=3D%d", + __entry->device_id, + __entry->app_id, + __entry->size, + __entry->dbuf_fd) +); +TRACE_EVENT(trinity_ioctl_hwmem_dealloc, + TP_PROTO(u32 device_id, s32 app_id, s32 dbuf_fd), + TP_ARGS(device_id, app_id, dbuf_fd), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, app_id) + __field(s32, dbuf_fd) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->app_id =3D app_id; + __entry->dbuf_fd =3D dbuf_fd; + ), + TP_printk("device_id=3D%u app_id=3D%d dbuf_fd=3D%d", + __entry->device_id, + __entry->app_id, + __entry->dbuf_fd) +); +TRACE_EVENT(trinity_ioctl_get_profile_meta, + TP_PROTO(u32 device_id, s32 app_id, s32 req_id, u32 profile_size), + TP_ARGS(device_id, app_id, req_id, profile_size), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, app_id) + __field(s32, req_id) + __field(u32, profile_size) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->app_id =3D app_id; + __entry->req_id =3D req_id; + __entry->profile_size =3D profile_size; + ), + TP_printk("device_id=3D%u app_id=3D%d req_id=3D%d profile_size=3D%u", + __entry->device_id, + __entry->app_id, + __entry->req_id, + __entry->profile_size) +); +TRACE_EVENT(trinity_ioctl_get_profile_buff, + TP_PROTO(u32 device_id, s32 app_id, s32 req_id, u32 profile_pos, + u32 profile_size), + TP_ARGS(device_id, app_id, req_id, profile_pos, profile_size), + TP_STRUCT__entry( + __field(u32, device_id) + __field(s32, app_id) + __field(s32, req_id) + __field(u32, profile_pos) + __field(u32, profile_size) + ), + TP_fast_assign( + __entry->device_id =3D device_id; + __entry->app_id =3D app_id; + __entry->req_id =3D req_id; + __entry->profile_pos =3D profile_pos; + __entry->profile_size =3D profile_size; + ), + TP_printk("device_id=3D%u app_id=3D%d req_id=3D%d profile_pos=3D%u profil= e_size=3D%u", + __entry->device_id, + __entry->app_id, + __entry->req_id, + __entry->profile_pos, + __entry->profile_size) +); +TRACE_EVENT(trinity_ioctl_register_model, + TP_PROTO(s32 metadata_dbuf_fd, s32 metadata_ext_dbuf_fd, + u64 metadata_ext_size), + TP_ARGS(metadata_dbuf_fd, metadata_ext_dbuf_fd, metadata_ext_size), + TP_STRUCT__entry( + __field(s32, metadata_dbuf_fd) + __field(s32, metadata_ext_dbuf_fd) + __field(u64, metadata_ext_size) + ), + TP_fast_assign( + __entry->metadata_dbuf_fd =3D metadata_dbuf_fd; + __entry->metadata_ext_dbuf_fd =3D metadata_ext_dbuf_fd; + __entry->metadata_ext_size =3D metadata_ext_size; + ), + TP_printk("metadata_dbuf_fd=3D%d metadata_ext_dbuf_fd=3D%d metadata_ext_s= ize=3D0x%llx", + __entry->metadata_dbuf_fd, + __entry->metadata_ext_dbuf_fd, + __entry->metadata_ext_size) +); +TRACE_EVENT(trinity_ioctl_run_input, + TP_PROTO(s64 timeout_ms, u32 priority, u32 num_segments, s32 input_mode, + s32 output_mode), + TP_ARGS(timeout_ms, priority, num_segments, input_mode, output_mode), + TP_STRUCT__entry( + __field(s64, timeout_ms) + __field(u32, priority) + __field(u32, num_segments) + __field(s32, input_mode) + __field(s32, output_mode) + ), + TP_fast_assign( + __entry->timeout_ms =3D timeout_ms; + __entry->priority =3D priority; + __entry->num_segments =3D num_segments; + __entry->input_mode =3D input_mode; + __entry->output_mode =3D output_mode; + ), + TP_printk("timeout_ms=3D%lld priority=3D%u num_segments=3D%u input_mode= =3D%d output_mode=3D%d", + __entry->timeout_ms, + __entry->priority, + __entry->num_segments, + __entry->input_mode, + __entry->output_mode) +); +// clang-format on + +#endif /* __DRIVERS_MISC_TRINITY_TRACE_H__ */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ../../drivers/misc/trinity +#include diff --git a/drivers/misc/trinity/trinity_vision2_drv.c b/drivers/misc/trin= ity/trinity_vision2_drv.c index 111623322895..8299cb3e25c1 100644 --- a/drivers/misc/trinity/trinity_vision2_drv.c +++ b/drivers/misc/trinity/trinity_vision2_drv.c @@ -18,6 +18,7 @@ =20 #include "trinity_common.h" #include "trinity_sched.h" +#include "trinity_trace.h" #include "trinity_vision2_profile.h" #include "trinity_vision2_regs.h" =20 @@ -396,6 +397,8 @@ static void triv2_wakeup_cp(const struct trinity_driver= *drv) void *addr =3D trinity_get_iomem_addr(drv->mmreg_vaddr[0], OFFSET_CP_PROC_SET); =20 + trace_triv2_wakeup_cp(drv->dev_id); + trinity_set_bit(BIT_SET_SEND_EVT1, addr); } =20 @@ -482,6 +485,8 @@ static void triv2_run_trigger(const struct trinity_driv= er *drv, int slot) struct triv2_cmd_info *cmd_info =3D TRIV2_DRV_GET_CMD_INFO(drv); struct triv2_req *t_req =3D cmd_info->reqs[slot]; =20 + trace_triv2_run_trigger(drv->dev_id, slot); + if (!t_req) { dev_err(drv_to_dev_ptr(drv), "Unable to find the corresponding req"); @@ -546,6 +551,10 @@ static void triv2_handle_cmd_done(struct trinity_drive= r *drv, req->stat->prev_cycles =3D cmd->total_cycles; req->stat->num_runs++; req->stat->total_time +=3D req->stat->prev_time; + + trace_triv2_handle_cmd_done(drv->dev_id, cmd->slot, + cmd->total_cycles, + req->stat->prev_time); } =20 t_req->total_cycles =3D cmd->total_cycles; --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE914C6FA86 for ; Sat, 17 Sep 2022 07:24:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229722AbiIQHYq (ORCPT ); Sat, 17 Sep 2022 03:24:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51904 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229553AbiIQHYK (ORCPT ); Sat, 17 Sep 2022 03:24:10 -0400 Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AFE3246217 for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p1.samsung.com (unknown [182.195.41.45]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20220917072401epoutp0161f67a9a9d9feff6810e89d6d1df0bd0~VlPqRf85J2007820078epoutp01c for ; Sat, 17 Sep 2022 07:24:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20220917072401epoutp0161f67a9a9d9feff6810e89d6d1df0bd0~VlPqRf85J2007820078epoutp01c DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399441; bh=uIG1Ab2hwSuc2OnMPQIs1HHNtvMtYsH7j0lr/KbeZwg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YBT3yzpkQsCeSa9J+4QIckytRdOy+Le2RiWqcByg2yoz5TUaNvOiE7ImFLByRRDRU fKdfwZgNd4bSW5+CvLVvlkDMMcIzWb1McBUe/ayzgp9NlD3diR+wUs3DjCGGmOrZge gHiZ0cfURcZIjsDQgQd0+IGh1TBP0GFa3IX94Dag= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas1p4.samsung.com (KnoxPortal) with ESMTP id 20220917072400epcas1p410367dd6f8ad959e503576a0e5674128~VlPpGZZTy2768227682epcas1p43; Sat, 17 Sep 2022 07:24:00 +0000 (GMT) Received: from epsmges1p1.samsung.com (unknown [182.195.36.135]) by epsnrtp2.localdomain (Postfix) with ESMTP id 4MV2Vl2mKYz4x9Pt; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) Received: from epcas1p2.samsung.com ( [182.195.41.46]) by epsmges1p1.samsung.com (Symantec Messaging Gateway) with SMTP id 6A.40.07146.F0675236; Sat, 17 Sep 2022 16:23:59 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas1p3.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epcas1p30b24a99cbf5a0ae7175efc794c5d218d~VlPnxGGxt0623006230epcas1p3N; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220917072358epsmtrp1188c2b6e8a05a6525dbdf45ab750f8cf~VlPnwY6CP0556805568epsmtrp1f; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) X-AuditID: b6c32a35-205ff70000021bea-80-6325760f1cd3 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id A6.F0.18644.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epsmtip23409063fa42f0515fafc25b3eac731ea~VlPniMp0Y2858228582epsmtip27; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 12/13] MAINTAINERS: add TRINITY driver Date: Sat, 17 Sep 2022 16:23:55 +0900 Message-Id: <20220917072356.2255620-13-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFuplk+LIzCtJLcpLzFFi42LZdlhTT5e/TDXZoHOmqMXfScfYLaY+fMJm 0bx4PZvF++7dzBZ7X29lt7i8aw6bxe3GFWwW+3o+Mlo8n3adxYHT4/evSYwem1Z1snncubaH zWP/3DXsHn1bVjF6fN4kF8AWlW2TkZqYklqkkJqXnJ+SmZduq+QdHO8cb2pmYKhraGlhrqSQ l5ibaqvk4hOg65aZA3SVkkJZYk4pUCggsbhYSd/Opii/tCRVISO/uMRWKbUgJafAtECvODG3 uDQvXS8vtcTK0MDAyBSoMCE74/e3WawFDewVt3/NZG5g/M/axcjBISFgIvHtS00XIxeHkMAO RonOO+2MEM4nRonWtk5mCOczo8SsWzOYYDoWz3SGiO9ilDg7eQ4LXNHXN0eBxnJysAmoSsyc sYYdxBYRKJdo3ngCzGYWyJF4cqeJGcQWFrCU+HP+JVg9C1D99YkHWUBsXgEbieO7doHVcALZ Nzc1QcUFJU7OfMICMUdeonnrbLDrJAS+skvcmH8DrEFCwEXi6L5FULawxKvjW9ghbCmJl/1t UHa2xJSORSwQdoHEuedbmSE+M5a4uCIFxGQW0JRYv0sfokJRYufvuYwQa/kk3n3tgYYcr0RH mxBEiZLEkj+HoYZLSEyd8Y0JwvaQOL7jDjRA+xkl+jo+MU5glJ+F5JtZSL6ZhbB5ASPzKkax 1ILi3PTUYsMCQ3icJufnbmIEp0st0x2ME99+0DvEyMTBeIhRgoNZSYRX1VMlWYg3JbGyKrUo P76oNCe1+BCjKTB8JzJLiSbnAxN2Xkm8oYmlgYmZkbGJhaGZoZI4r542Y7KQQHpiSWp2ampB ahFMHxMHp1QD0+q+9te60stnzp1aX3/6za3fXl7iMu7KfK/lnuyfU/f6/z+XSgenDa4/Wc9s SmLI6XnR8Ctg2SyP9jOlAcXSH9pu2mwXmrCTe8UVtYMVKxLVgu7F/DUJfyrzd5q33sR/AjXt zDWVWhqMx24lTIvyM3sT5mj/SLZo48WrKu0fVq3LVHBcrNBmpXvq7KPfj10cr60TiVxUPjH9 nvtswfqOnL/1G56XNG9e6dHGkbjP69WjLcJWHeoFoV+sZc5f9Vl+myMj5reU3YOXUq6zTDZd u7LplcJ0lZvRsx8LPUzwy5Gq2Hj4f8VxbosasZ+dIoEqi42khQ1mOb4MfzZ3V9K5jqb5dY8X 7BS4srh956+QFCWW4oxEQy3mouJEAO6bJa4gBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrBLMWRmVeSWpSXmKPExsWy7bCSvC5fmWqyweyb8hZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAlfG72+zWAsa2Ctu/5rJ3MD4n7WLkYND QsBEYvFM5y5GLg4hgR2MEr/+z2TrYuQEiktIbLq3nBmiRlji8OFiiJqPjBKL/zSA1bAJqErM nLGGHcQWEaiVOHh0PjOIzSxQIDH76UwWEFtYwFLiz/mXrCA2C1D99YkHweK8AjYSx3ftAqvn BLJvbmoCiwsJWEvMnj6XCaJGUOLkzCcsEDPlJZq3zmaewMg/C0lqFpLUAkamVYySqQXFuem5 xYYFRnmp5XrFibnFpXnpesn5uZsYwYGtpbWDcc+qD3qHGJk4GA8xSnAwK4nwqnqqJAvxpiRW VqUW5ccXleakFh9ilOZgURLnvdB1Ml5IID2xJDU7NbUgtQgmy8TBKdXA5Bi92bB8/+ywE7aK r+8zLYusfviRpbSt7Phrk4Nrg6/cddDfJH1RdPmefwtq2UOjD3Ey1TpMsjVfWmR+39L1hbre 239Kk5szPwlYVp55/U/Ps0Y81ff9fMvV98tmPLD4cCdDf0qodXB6+JuQKs3potPv3DbbpNIa 9TO9yqxSJe2mWrjPyken79kHqeZsFBZ/9PR1Oq+YknPdKu17WfEL1tSummmw8uqRqMVzD+89 OOXYarclxqE8x7g3z0w4vKFT5IOb+LbVTX0fkh9ZLYqTexo4Z8m72S0hZoUpTV9WKxY2z5ae 53dCJG3b4gU+kxjqWR+8zJtqO1nWeYIFl/fprR9q1OZP/aTz5+ruTwd2ViuxFGckGmoxFxUn AgBnWdp22wIAAA== X-CMS-MailID: 20220917072358epcas1p30b24a99cbf5a0ae7175efc794c5d218d X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072358epcas1p30b24a99cbf5a0ae7175efc794c5d218d References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add SAMSUNG TRINITY DRIVER. Jiho Chu and Yelin Jeong is added as the maintainers. Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3cf9842d9233..e166558e693e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17690,6 +17690,14 @@ S: Maintained F: Documentation/devicetree/bindings/thermal/samsung,exynos-thermal.yaml F: drivers/thermal/samsung/ =20 +SAMSUNG TRINITY DRIVER +M: Jiho Chu +M: Yelin Jeong +S: Supported +F: Documentation/devicetree/bindings/arm/samsung,trinity.yaml +F: drivers/misc/trinity/ +F: include/uapi/misc/trinity.h + SAMSUNG USB2 PHY DRIVER M: Sylwester Nawrocki L: linux-kernel@vger.kernel.org --=20 2.25.1 From nobody Fri Apr 3 02:24:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 44FFFC6FA8B for ; Sat, 17 Sep 2022 07:24:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229492AbiIQHYT (ORCPT ); Sat, 17 Sep 2022 03:24:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51888 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229483AbiIQHYJ (ORCPT ); Sat, 17 Sep 2022 03:24:09 -0400 Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B736046232 for ; Sat, 17 Sep 2022 00:24:05 -0700 (PDT) Received: from epcas1p3.samsung.com (unknown [182.195.41.47]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20220917072401epoutp011469c2497a80242fb0014915496e3735~VlPqOFPuN1986719867epoutp01w for ; Sat, 17 Sep 2022 07:24:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20220917072401epoutp011469c2497a80242fb0014915496e3735~VlPqOFPuN1986719867epoutp01w DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1663399441; bh=EkOlsbEEebMKOcL/bv6fterDUppNnHaI9G4AA5NT3wo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MmDAU+ExtBie0WQyQtyCYJmOAQrHr+/L24K2MSoGmTgQr/OlydDrPk7vY58xsHYwZ 3tgdYqHpjieuZ2L6r0exK5D+TnJLtQ7wkqgQO1yOegnK/2c9JUX6hGYz2sRA0h4j72 FPsC8IR6uD3Nn6yBIjtibwp6TtfJnUdcN/F1n7eA= Received: from epsnrtp1.localdomain (unknown [182.195.42.162]) by epcas1p3.samsung.com (KnoxPortal) with ESMTP id 20220917072400epcas1p3099fcbc6d8f64307611b5a65afd1ca30~VlPp0UKGs0974609746epcas1p3V; Sat, 17 Sep 2022 07:24:00 +0000 (GMT) Received: from epsmges1p3.samsung.com (unknown [182.195.38.232]) by epsnrtp1.localdomain (Postfix) with ESMTP id 4MV2Vl2VdFz4x9Ps; Sat, 17 Sep 2022 07:23:59 +0000 (GMT) Received: from epcas1p3.samsung.com ( [182.195.41.47]) by epsmges1p3.samsung.com (Symantec Messaging Gateway) with SMTP id F4.1D.57013.F0675236; Sat, 17 Sep 2022 16:23:59 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas1p1.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epcas1p15d18d4cf27694f894332f975bb971bef~VlPn8VPHN0249402494epcas1p1S; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220917072358epsmtrp21fac72e221d8a275023714fb8b11bfec~VlPn7nmMM1654916549epsmtrp21; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) X-AuditID: b6c32a37-da3ff7000001deb5-1b-6325760f584d Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id A5.45.14392.E0675236; Sat, 17 Sep 2022 16:23:58 +0900 (KST) Received: from localhost.localdomain (unknown [10.113.113.58]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220917072358epsmtip2502024b537cf289bca380d327e8ce165~VlPnqkoTO3199331993epsmtip2a; Sat, 17 Sep 2022 07:23:58 +0000 (GMT) From: Jiho Chu To: gregkh@linuxfoundation.org, arnd@arndb.de, ogabbay@kernel.org, krzysztof.kozlowski@linaro.org, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, yelini.jeong@samsung.com, myungjoo.ham@samsung.com, jiho.chu@samsung.com Subject: [PATCH v2 13/13] dt-bindings: arm: Add Samsung Trinity bindings Date: Sat, 17 Sep 2022 16:23:56 +0900 Message-Id: <20220917072356.2255620-14-jiho.chu@samsung.com> In-Reply-To: <20220917072356.2255620-1-jiho.chu@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupjk+LIzCtJLcpLzFFi42LZdlhTX5e/TDXZ4MU8Pou/k46xW0x9+ITN onnxejaL9927mS32vt7KbnF51xw2i9uNK9gs9vV8ZLR4Pu06iwOnx+9fkxg9Nq3qZPO4c20P m8f+uWvYPfq2rGL0+LxJLoAtKtsmIzUxJbVIITUvOT8lMy/dVsk7ON453tTMwFDX0NLCXEkh LzE31VbJxSdA1y0zB+gqJYWyxJxSoFBAYnGxkr6dTVF+aUmqQkZ+cYmtUmpBSk6BaYFecWJu cWleul5eaomVoYGBkSlQYUJ2xs+Pa9gKfitVTJzzmrGB8YZUFyMnh4SAicTBlRdZuxi5OIQE djBKTHi/mR3C+cQoce/YH2YI5xuQ86+VBaZl29qlUC17GSX6r++AavnMKDH16EewKjYBVYmZ M9awg9giAuUSzRtPgNnMAjkST+40AY3l4BAW8JBY2S4OEmYBKv//8BATiM0rYCMx7dpksDGc QPbNTU0sEHFBiZMzn7BAjJGXaN46G+w6CYGP7BIbT5yBus5F4vHyQ4wQtrDEq+Nb2CFsKYnP 7/ayQdjZElM6FkHVF0ice74V7B4JAWOJiytSQExmAU2J9bv0ISoUJXb+nssIsZZP4t3XHlaI al6JjjYhiBIliSV/DkMtkpCYOuMbE4TtIfGg+z0TJHT6GSVOzNzDNIFRfhaSb2Yh+WYWwuYF jMyrGMVSC4pz01OLDQuM4ZGanJ+7iRGcMLXMdzBOe/tB7xAjEwfjIUYJDmYlEV5VT5VkId6U xMqq1KL8+KLSnNTiQ4ymwPCdyCwlmpwPTNl5JfGGJpYGJmZGxiYWhmaGSuK8etqMyUIC6Ykl qdmpqQWpRTB9TBycUg1Md/pPJFwN7zu9Ldb/hagB495fRW7txYkzle50iVw85sMr8ifC/J7t klQTk0ufyvcyG516GObY9m0f843uP7NWuSX3Jay5aWx+597NrvDU5iOObLv+fXnnE7r9M1P6 Qrv9VzNbFZk3ZF52yXw5bWldrlHJpbJ4BoW+f1PORewXdQ7mtlv4Mi/u7Ndqu8KNPD+lD5cd LXj92cJl6eLALeLrjTgv/pz1YOUFzcvzJl+r/SAemyr9utuGgy/GPGkTp/lsvgen2+7/t7CQ 7H3LtL93cXd2arDG6/O3v2s/XTcnfUtg0MzZeTlnV3kuMivK/SjeOKdAfHn1tcy7XGeTLX55 3DXx+eP4RPTeLMkO4QvvlFiKMxINtZiLihMBFT+NGiEEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrOLMWRmVeSWpSXmKPExsWy7bCSvC5fmWqywZGJWhZ/Jx1jt5j68Amb RfPi9WwW77t3M1vsfb2V3eLyrjlsFrcbV7BZ7Ov5yGjxfNp1FgdOj9+/JjF6bFrVyeZx59oe No/9c9ewe/RtWcXo8XmTXABbFJdNSmpOZllqkb5dAlfGz49r2Ap+K1VMnPOasYHxhlQXIyeH hICJxLa1S1m7GLk4hAR2M0ocmdnBDJGQkNh0bzmQzQFkC0scPlwMEhYS+Mgo8X2VJ4jNJqAq MXPGGnYQW0SgVuLg0flgrcwCBRKzn85kAWkVFvCQWNkuDhJmASr///AQE4jNK2AjMe3aZBYQ mxPIvrmpiQVivLXE7OlzoWoEJU7OfMICMVJeonnrbOYJjPyzkKRmIUktYGRaxSiZWlCcm55b bFhgmJdarlecmFtcmpeul5yfu4kRHNZamjsYt6/6oHeIkYmD8RCjBAezkgivqqdKshBvSmJl VWpRfnxRaU5q8SFGaQ4WJXHeC10n44UE0hNLUrNTUwtSi2CyTBycUg1MKxbvuBR8xWfRHOfT 5ttOhv6PnSt/4bkSu/w9HZZ2X+s/t2X0t7/+YpnbltYye0Z0vOj+LfVJoTVc/oysdoqJLAq7 19i7ZVV2yH4VVFvgdulU4nY98dXtKpHXMoqU9z47+7FCf95pIyXlX8yX5sm+dq6uzavJqZae dVdbMV/kT6W+YbNynLr+o3rx52dUyg+r8lWfEygvfB3/7JC1m9cKKfnmZf+vTVn0ftFBvWei L/ZsEd+aMedKdENqiPdj1iyXcJa6oxeSxayv5pw8dWqqfDjjPJsDBZcEIw6ecJRZXz6l/tVh z8TrnDV51iZa2xgur3hjVxYlpHLN+sSObYwVV1/e+5XGuiv8x9w3f34psRRnJBpqMRcVJwIA 5R/ODdoCAAA= X-CMS-MailID: 20220917072358epcas1p15d18d4cf27694f894332f975bb971bef X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: SVC_REQ_APPROVE CMS-TYPE: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220917072358epcas1p15d18d4cf27694f894332f975bb971bef References: <20220917072356.2255620-1-jiho.chu@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The Trinity Neural Processing Unit (NPU) is a hardware IP for providing hardware acceleration for neural network processing workloads. It has own virtual ISA decoder unit, and controlled by memory mapped control registers. The IP is composed of Common Processor (CP), Digital Signal Processor (DSP) and Deep Learning Accelerator (DLA). ComBox is register set to control IRQ or check overall status of the IP. Signed-off-by: Jiho Chu Signed-off-by: Yelin Jeong Signed-off-by: MyungJoo Ham --- .../bindings/arm/samsung,trinity.yaml | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/samsung,trinity.y= aml diff --git a/Documentation/devicetree/bindings/arm/samsung,trinity.yaml b/D= ocumentation/devicetree/bindings/arm/samsung,trinity.yaml new file mode 100644 index 000000000000..cd79ec040162 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/samsung,trinity.yaml @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/samsung,trinity.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung Trinity NPU Family + +maintainers: + - Jiho Chu + +description: | + The Trinity Neural Processing Unit (NPU) is a hardware IP for providing + hardware acceleration for neural network processing workloads. It has + own virtual ISA decoder unit, and controlled by memory mapped control + registers. The IP is composed of Common Processor (CP), Digital Signal + Processor (DSP) and Deep Learning Accelerator (DLA). ComBox is register + set to control IRQ or check overall status of the IP. + +properties: + compatible: + const: samsung,trinity + + samsung,trinity-type: + description: type of trinity family + enum: ['triv2'] + + samsung,tops: + description: Performance metric (Tera Operation Per Seconds) + enum: [2, 8] + + samsung,idu_cp: + items: + - description: Address of zero data of CP + - description: Address of IDU data of CP + - description: Maximum size of CP's IDU binary + + samsung,idu_dsp: + items: + - description: Address of zero data of DSP + - description: Address of IDU data of DSP + - description: Maximum size of DSP's IDU binary + + samsung,dspm: + description: The size of Data Scratch-Pad Memory + + memory-region: + description: + phandle to the reserved memory node to be associated + with the trinity device. The reserved memory node + can be a CMA memory node. + Documentation/devicetree/bindings/reserved-memory/reserved-memory.ya= ml + + dma-coherent: true + + reg: + items: + - description: Memory mapped register of CP + - description: Memory mapped register of DSP + - description: Memory mapped register of ComBox + + reg-names: + items: + - const: cp-mmreg + - const: dsp-mmreg + - const: cbox-mmreg + + interrupts: + description: workload complete interrupt + maxItems: 1 + +required: + - compatible + - samsung,trinity-type + - samsung,tops + - samsung,idu_cp + - samsung,idu_dsp + - samsung,dspm + - memory-region + - dma-coherent + - reg + - reg-names + - interrupts + +examples: + - | + reserved-memory { + #address-cells =3D <2>; + #size-cells =3D <1>; + trinity_dram_0: memory@80000000 { + compatible =3D "shared-dma-pool"; + no-map; + reg =3D <0x0 0x80000000 0x10000000>; + }; + }; + + triv2@0x30C00000 { + compatible =3D "samsung,trinity"; + samsung,trinity-type =3D "triv2"; + samsung,tops =3D <8>; + samsung,idu_cp =3D /bits/ 64 <0x30400000 0x30400010 0x10000>; + samsung,idu_dsp =3D /bits/ 64 <0x30500000 0x30500010 0x10000>; + samsung,dspm =3D <0x40000>; + + memory-region =3D <&trinity_dram_0> + + dma-coherent; + + reg =3D <0x0 0x30C10000 0x0 0x10000>, /* CP MMREG base */ + <0x0 0x30D40000 0x0 0x10000>, /* DSP MMREG base */ + <0x0 0x30DF0000 0x0 0x01000>; /* ComBox MMREG base */ + reg-names =3D "cp-mmreg", "dsp-mmreg", "cbox-mmreg"; + + interrupts =3D ; + }; --=20 2.25.1