From patchwork Sat Oct 22 21:46:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oded Gabbay X-Patchwork-Id: 13016069 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 83057C433FE for ; Sat, 22 Oct 2022 21:47:23 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3AE2C10E032; Sat, 22 Oct 2022 21:47:20 +0000 (UTC) Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by gabe.freedesktop.org (Postfix) with ESMTPS id CBDB010E027 for ; Sat, 22 Oct 2022 21:46:39 +0000 (UTC) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 534CC60B2A; Sat, 22 Oct 2022 21:46:39 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C717EC43470; Sat, 22 Oct 2022 21:46:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1666475198; bh=TdjCoZ4FJ+aLY/5yyYbGnM3YqwZ2I6wju2Ck5ByPiJg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=k3jw+Cpr368TcCfXa/pufj2ilReVLWCc5TiGVbKmjg1H1mcarij7qaognVkhfK7vb n04AYuwGT2QgCVU6YKmgraxLWr6yNXYBRUOAT5yGTZWzcpQT5DRmxN/YVgyxiRdJn6 EXy2dUEFqXZBIA3tVsfqv11iVD3P/snbTfBqqQQ7Amy+cT7Sh/dgv514azaLuG0Vvr FL/6Lf00FFYQ0aHp6GR6JoisQyLKDUbI/mAivE9qlNgsnO1dmJk7MDZjXudAcQJdBS U7YmJtj+7IQbeWjGEx1tVZu3bMyanaQHbs/ITHLOiBt1V0+3L1Xxp/UAztS/IUBiDb BCeO8JNaJ5IdQ== From: Oded Gabbay To: David Airlie , Daniel Vetter , Arnd Bergmann , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Jason Gunthorpe , John Hubbard , Alex Deucher Subject: [RFC PATCH 1/3] drivers/accel: add new kconfig and update MAINTAINERS Date: Sun, 23 Oct 2022 00:46:20 +0300 Message-Id: <20221022214622.18042-2-ogabbay@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221022214622.18042-1-ogabbay@kernel.org> References: <20221022214622.18042-1-ogabbay@kernel.org> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tvrtko Ursulin , Jacek Lawrynowicz , Jeffrey Hugo , Jiho Chu , Christoph Hellwig , Thomas Zimmermann , Kevin Hilman , Yuji Ishikawa , Maciej Kwapulinski , Jagan Teki Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Add a new Kconfig for the accel subsystem. The Kconfig currently contains only the basic CONFIG_ACCEL option that will be used to decide whether to compile the accel registration code as part of the drm core functionality. I have taken the liberty to appropriate the dri-devel mailing list and the dri-devel IRC channel for the accel subsystem. Signed-off-by: Oded Gabbay --- MAINTAINERS | 8 ++++++++ drivers/Kconfig | 2 ++ drivers/accel/Kconfig | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 drivers/accel/Kconfig diff --git a/MAINTAINERS b/MAINTAINERS index cf0f18502372..790d472801d5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6820,6 +6820,14 @@ F: include/drm/drm* F: include/linux/vga* F: include/uapi/drm/drm* +DRM COMPUTE ACCELERATORS DRIVERS AND FRAMEWORK +M: Oded Gabbay +L: dri-devel@lists.freedesktop.org +S: Maintained +C: irc://irc.oftc.net/dri-devel +T: git https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/accel.git +F: drivers/accel/ + DRM DRIVERS FOR ALLWINNER A10 M: Maxime Ripard M: Chen-Yu Tsai diff --git a/drivers/Kconfig b/drivers/Kconfig index 19ee995bd0ae..968bd0a6fd78 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -99,6 +99,8 @@ source "drivers/media/Kconfig" source "drivers/video/Kconfig" +source "drivers/accel/Kconfig" + source "sound/Kconfig" source "drivers/hid/Kconfig" diff --git a/drivers/accel/Kconfig b/drivers/accel/Kconfig new file mode 100644 index 000000000000..282ea24f90c5 --- /dev/null +++ b/drivers/accel/Kconfig @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Compute Acceleration device configuration +# +# This framework provides support for compute acceleration devices, such +# as, but not limited to, Machine-Learning and Deep-Learning acceleration +# devices +# +menuconfig ACCEL + tristate "Compute Acceleration Framework" + depends on DRM + help + Framework for device drivers of compute acceleration devices, such + as, but not limited to, Machine-Learning and Deep-Learning + acceleration devices. + If you say Y here, you need to select the module that's right for + your acceleration device from the list below. + This framework is integrated with the DRM subsystem as compute + accelerators and GPUs share a lot in common and can use almost the + same infrastructure code. + Having said that, acceleration devices will have a different + major number than GPUs, and will be exposed to user-space using + different device files, called accel/accel* (in /dev, sysfs + and debugfs) From patchwork Sat Oct 22 21:46:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oded Gabbay X-Patchwork-Id: 13016068 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 700DEC433FE for ; Sat, 22 Oct 2022 21:47:07 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7A46E10E027; Sat, 22 Oct 2022 21:47:00 +0000 (UTC) Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0610E10E027 for ; Sat, 22 Oct 2022 21:46:48 +0000 (UTC) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 7426AB80B2B; Sat, 22 Oct 2022 21:46:46 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4F8E7C433B5; Sat, 22 Oct 2022 21:46:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1666475205; bh=JT2MdfhPjVKgCMdlk30ipJOMxC3nOP4IAilx6SwpDDU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pEBsdeAa58flKMA4VionziKr3zqsUSRY1cnJyKDgbsF0LJSFfqgdMtY6cw9V+lOYx TnRf+pvMjZESTeAPoZyoK2FilsWtWaGIMI6wczbzcPQDSk/uRK/bEG2lRDwAAcDZnr rYgFoxaSLFlLgEIVlzamAF7mFQzMvtoKTx4WjbS6KZgm8+lYsOhw1UVjpfOS3iLoBc cvHpc/yqKNglXaLh0WR3sPx3gTTDEWjsEw3FWNT52adPZRmMACdY3aVuyi4GTNsoKN S0q4ej1oEXoQ9CIhkzziHO3ZjECZgvY6c8yzPXSGX2G1XqSi/mdK44I+jMM1faz2A1 Bibmi/RfaFYeQ== From: Oded Gabbay To: David Airlie , Daniel Vetter , Arnd Bergmann , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Jason Gunthorpe , John Hubbard , Alex Deucher Subject: [RFC PATCH 2/3] drm: define new accel major and register it Date: Sun, 23 Oct 2022 00:46:21 +0300 Message-Id: <20221022214622.18042-3-ogabbay@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221022214622.18042-1-ogabbay@kernel.org> References: <20221022214622.18042-1-ogabbay@kernel.org> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tvrtko Ursulin , Jacek Lawrynowicz , Jeffrey Hugo , Jiho Chu , Christoph Hellwig , Thomas Zimmermann , Kevin Hilman , Yuji Ishikawa , Maciej Kwapulinski , Jagan Teki Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The accelerator devices will be exposed to the user space with a new, dedicated major number - 261. The drm core registers the new major number as a char device and create corresponding sysfs and debugfs root entries, same as for the drm major. In case CONFIG_ACCEL is not selected, this code is not compiled in. Signed-off-by: Oded Gabbay --- Documentation/admin-guide/devices.txt | 5 +++ drivers/gpu/drm/drm_drv.c | 45 +++++++++++++++++++++++ drivers/gpu/drm/drm_internal.h | 3 ++ drivers/gpu/drm/drm_sysfs.c | 52 +++++++++++++++++++++++++++ include/drm/drm_ioctl.h | 1 + 5 files changed, 106 insertions(+) diff --git a/Documentation/admin-guide/devices.txt b/Documentation/admin-guide/devices.txt index 9764d6edb189..06c525e01ea5 100644 --- a/Documentation/admin-guide/devices.txt +++ b/Documentation/admin-guide/devices.txt @@ -3080,6 +3080,11 @@ ... 255 = /dev/osd255 256th OSD Device + 261 char Compute Acceleration Devices + 0 = /dev/accel/accel0 First acceleration device + 1 = /dev/accel/accel1 Second acceleration device + ... + 384-511 char RESERVED FOR DYNAMIC ASSIGNMENT Character devices that request a dynamic allocation of major number will take numbers starting from 511 and downward, diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 8214a0b1ab7f..b58ffb1433d6 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -67,6 +67,10 @@ static bool drm_core_init_complete; static struct dentry *drm_debugfs_root; +#ifdef CONFIG_ACCEL +static struct dentry *accel_debugfs_root; +#endif + DEFINE_STATIC_SRCU(drm_unplug_srcu); /* @@ -1031,9 +1035,19 @@ static const struct file_operations drm_stub_fops = { .llseek = noop_llseek, }; +static void accel_core_exit(void) +{ +#ifdef CONFIG_ACCEL + unregister_chrdev(ACCEL_MAJOR, "accel"); + debugfs_remove(accel_debugfs_root); + accel_sysfs_destroy(); +#endif +} + static void drm_core_exit(void) { drm_privacy_screen_lookup_exit(); + accel_core_exit(); unregister_chrdev(DRM_MAJOR, "drm"); debugfs_remove(drm_debugfs_root); drm_sysfs_destroy(); @@ -1041,6 +1055,33 @@ static void drm_core_exit(void) drm_connector_ida_destroy(); } +static int __init accel_core_init(void) +{ +#ifdef CONFIG_ACCEL + int ret; + + ret = accel_sysfs_init(); + if (ret < 0) { + DRM_ERROR("Cannot create ACCEL class: %d\n", ret); + goto error; + } + + accel_debugfs_root = debugfs_create_dir("accel", NULL); + + ret = register_chrdev(ACCEL_MAJOR, "accel", &drm_stub_fops); + if (ret < 0) + goto error; + +error: + /* Any cleanup will be done in drm_core_exit() that will call + * to accel_core_exit() + */ + return ret; +#else + return 0; +#endif +} + static int __init drm_core_init(void) { int ret; @@ -1061,6 +1102,10 @@ static int __init drm_core_init(void) if (ret < 0) goto error; + ret = accel_core_init(); + if (ret < 0) + goto error; + drm_privacy_screen_lookup_init(); drm_core_init_complete = true; diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 7bb98e6a446d..cbeb9bd3c312 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -147,9 +147,12 @@ void drm_master_internal_release(struct drm_device *dev); /* drm_sysfs.c */ extern struct class *drm_class; +extern struct class *accel_class; int drm_sysfs_init(void); void drm_sysfs_destroy(void); +int accel_sysfs_init(void); +void accel_sysfs_destroy(void); struct device *drm_sysfs_minor_alloc(struct drm_minor *minor); int drm_sysfs_connector_add(struct drm_connector *connector); void drm_sysfs_connector_remove(struct drm_connector *connector); diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 430e00b16eec..70b2a28f55c4 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -56,6 +56,7 @@ static struct device_type drm_sysfs_device_connector = { }; struct class *drm_class; +struct class *accel_class; #ifdef CONFIG_ACPI static bool drm_connector_acpi_bus_match(struct device *dev) @@ -148,6 +149,57 @@ static void drm_sysfs_release(struct device *dev) kfree(dev); } +static char *accel_devnode(struct device *dev, umode_t *mode) +{ + return kasprintf(GFP_KERNEL, "accel/%s", dev_name(dev)); +} + +static CLASS_ATTR_STRING(accel_version, 0444, "accel 1.0.0 20221018"); + +/** + * accel_sysfs_init - initialize sysfs helpers + * + * This is used to create the ACCEL class, which is the implicit parent of any + * other top-level ACCEL sysfs objects. + * + * You must call accel_sysfs_destroy() to release the allocated resources. + * + * Return: 0 on success, negative error code on failure. + */ +int accel_sysfs_init(void) +{ + int err; + + accel_class = class_create(THIS_MODULE, "accel"); + if (IS_ERR(accel_class)) + return PTR_ERR(accel_class); + + err = class_create_file(accel_class, &class_attr_accel_version.attr); + if (err) { + class_destroy(accel_class); + accel_class = NULL; + return err; + } + + accel_class->devnode = accel_devnode; + + return 0; +} + +/** + * accel_sysfs_destroy - destroys ACCEL class + * + * Destroy the ACCEL device class. + */ +void accel_sysfs_destroy(void) +{ + if (IS_ERR_OR_NULL(accel_class)) + return; + class_remove_file(accel_class, &class_attr_accel_version.attr); + class_destroy(accel_class); + accel_class = NULL; +} + /* * Connector properties */ diff --git a/include/drm/drm_ioctl.h b/include/drm/drm_ioctl.h index 6ed61c371f6c..88e4926208e7 100644 --- a/include/drm/drm_ioctl.h +++ b/include/drm/drm_ioctl.h @@ -70,6 +70,7 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, #define DRM_IOCTL_NR(n) _IOC_NR(n) #define DRM_IOCTL_TYPE(n) _IOC_TYPE(n) #define DRM_MAJOR 226 +#define ACCEL_MAJOR 261 /** * enum drm_ioctl_flags - DRM ioctl flags From patchwork Sat Oct 22 21:46:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oded Gabbay X-Patchwork-Id: 13016070 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E89F5C433FE for ; Sat, 22 Oct 2022 21:47:38 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9DB6310E039; Sat, 22 Oct 2022 21:47:36 +0000 (UTC) Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2DCEF10E027 for ; Sat, 22 Oct 2022 21:46:54 +0000 (UTC) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 6A3EA60B35; Sat, 22 Oct 2022 21:46:53 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CBD3BC43470; Sat, 22 Oct 2022 21:46:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1666475212; bh=xeTBNUS1yJ8fc02OPNA8l/J4d0SGkzeo5LKZwIGkp5g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i/rt+2Ormdyue9xspQi0odG3Jh6dm7z1E7ixUoqmt2vmvbemk7uKHH6aDE6oDnmAC qqYWu6VfvtJ8gzL6k40Tt8fNHt8Zct3exKkvN7cnM5ETxBWpp0XNJ88AmYT/Sl+m+E YRMP0PwD2MbpmmuKv8XYae8CL4aPsSnBIZeX9U7WPhuIJETlMzBnuiMX+KqM1BpKcy JK6LmkMwE9pXvC6Wxw+Exp0aT8G+vDUYZ7DkRoDKug+2ktu88oDFboWSIVGtnIlu/a sXGdaXSM+wPxKD+LwHniw4ybiz0oqWRVNZBIhlwq8b+oy3Oxm8Pgkxk+9QK/zThPH+ 0YU1VO0W9s7Xg== From: Oded Gabbay To: David Airlie , Daniel Vetter , Arnd Bergmann , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Jason Gunthorpe , John Hubbard , Alex Deucher Subject: [RFC PATCH 3/3] drm: add dedicated minor for accelerator devices Date: Sun, 23 Oct 2022 00:46:22 +0300 Message-Id: <20221022214622.18042-4-ogabbay@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221022214622.18042-1-ogabbay@kernel.org> References: <20221022214622.18042-1-ogabbay@kernel.org> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tvrtko Ursulin , Jacek Lawrynowicz , Jeffrey Hugo , Jiho Chu , Christoph Hellwig , Thomas Zimmermann , Kevin Hilman , Yuji Ishikawa , Maciej Kwapulinski , Jagan Teki Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The accelerator devices are exposed to user-space using a dedicated major. In addition, they are represented in /dev with new, dedicated device char names: /dev/accel/accel*. This is done to make sure any user-space software that tries to open a graphic card won't open the accelerator device by mistake. The above implies that the minor numbering should be separated from the rest of the drm devices. However, to avoid code duplication, we want the drm_minor structure to be able to represent the accelerator device. To achieve this, we add a new drm_minor* to drm_device that represents the accelerator device. This pointer is initialized for drivers that declare they handle compute accelerator, using a new driver feature flag called DRIVER_COMPUTE_ACCEL. It is important to note that this driver feature is mutually exclusive with DRIVER_RENDER. Devices that want to expose both graphics and compute device char files should be handled by two drivers that are connected using the auxiliary bus framework. In addition, we define a different idr to handle the accelerators minors. This is done to make the minor's index be identical to the device index in /dev/. In most places, this is hidden inside the drm core functions except when calling drm_minor_acquire(), where I had to add an extra parameter to specify the idr to use (because the accelerators minors index and the drm primary minor index both begin at 0). Signed-off-by: Oded Gabbay --- drivers/gpu/drm/drm_drv.c | 171 +++++++++++++++++++++++++-------- drivers/gpu/drm/drm_file.c | 69 +++++++++---- drivers/gpu/drm/drm_internal.h | 2 +- drivers/gpu/drm/drm_sysfs.c | 29 ++++-- include/drm/drm_device.h | 3 + include/drm/drm_drv.h | 8 ++ include/drm/drm_file.h | 21 +++- 7 files changed, 235 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b58ffb1433d6..c13701a8d4be 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -56,6 +56,9 @@ MODULE_LICENSE("GPL and additional rights"); static DEFINE_SPINLOCK(drm_minor_lock); static struct idr drm_minors_idr; +static DEFINE_SPINLOCK(accel_minor_lock); +static struct idr accel_minors_idr; + /* * If the drm core fails to init for whatever reason, * we should prevent any drivers from registering with it. @@ -94,6 +97,8 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev, return &dev->primary; case DRM_MINOR_RENDER: return &dev->render; + case DRM_MINOR_ACCEL: + return &dev->accel; default: BUG(); } @@ -108,9 +113,15 @@ static void drm_minor_alloc_release(struct drm_device *dev, void *data) put_device(minor->kdev); - spin_lock_irqsave(&drm_minor_lock, flags); - idr_remove(&drm_minors_idr, minor->index); - spin_unlock_irqrestore(&drm_minor_lock, flags); + if (minor->type == DRM_MINOR_ACCEL) { + spin_lock_irqsave(&accel_minor_lock, flags); + idr_remove(&accel_minors_idr, minor->index); + spin_unlock_irqrestore(&accel_minor_lock, flags); + } else { + spin_lock_irqsave(&drm_minor_lock, flags); + idr_remove(&drm_minors_idr, minor->index); + spin_unlock_irqrestore(&drm_minor_lock, flags); + } } static int drm_minor_alloc(struct drm_device *dev, unsigned int type) @@ -127,13 +138,23 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type) minor->dev = dev; idr_preload(GFP_KERNEL); - spin_lock_irqsave(&drm_minor_lock, flags); - r = idr_alloc(&drm_minors_idr, - NULL, - 64 * type, - 64 * (type + 1), - GFP_NOWAIT); - spin_unlock_irqrestore(&drm_minor_lock, flags); + if (type == DRM_MINOR_ACCEL) { + spin_lock_irqsave(&accel_minor_lock, flags); + r = idr_alloc(&accel_minors_idr, + NULL, + 64 * (type - DRM_MINOR_ACCEL), + 64 * (type - DRM_MINOR_ACCEL + 1), + GFP_NOWAIT); + spin_unlock_irqrestore(&accel_minor_lock, flags); + } else { + spin_lock_irqsave(&drm_minor_lock, flags); + r = idr_alloc(&drm_minors_idr, + NULL, + 64 * type, + 64 * (type + 1), + GFP_NOWAIT); + spin_unlock_irqrestore(&drm_minor_lock, flags); + } idr_preload_end(); if (r < 0) @@ -167,7 +188,11 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type) ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root); if (ret) { - DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n"); + if (minor->type == DRM_MINOR_ACCEL) + DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/accel.\n"); + else + DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n"); + goto err_debugfs; } @@ -176,9 +201,15 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type) goto err_debugfs; /* replace NULL with @minor so lookups will succeed from now on */ - spin_lock_irqsave(&drm_minor_lock, flags); - idr_replace(&drm_minors_idr, minor, minor->index); - spin_unlock_irqrestore(&drm_minor_lock, flags); + if (minor->type == DRM_MINOR_ACCEL) { + spin_lock_irqsave(&accel_minor_lock, flags); + idr_replace(&accel_minors_idr, minor, minor->index); + spin_unlock_irqrestore(&accel_minor_lock, flags); + } else { + spin_lock_irqsave(&drm_minor_lock, flags); + idr_replace(&drm_minors_idr, minor, minor->index); + spin_unlock_irqrestore(&drm_minor_lock, flags); + } DRM_DEBUG("new minor registered %d\n", minor->index); return 0; @@ -198,9 +229,15 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type) return; /* replace @minor with NULL so lookups will fail from now on */ - spin_lock_irqsave(&drm_minor_lock, flags); - idr_replace(&drm_minors_idr, NULL, minor->index); - spin_unlock_irqrestore(&drm_minor_lock, flags); + if (minor->type == DRM_MINOR_ACCEL) { + spin_lock_irqsave(&accel_minor_lock, flags); + idr_replace(&accel_minors_idr, NULL, minor->index); + spin_unlock_irqrestore(&accel_minor_lock, flags); + } else { + spin_lock_irqsave(&drm_minor_lock, flags); + idr_replace(&drm_minors_idr, NULL, minor->index); + spin_unlock_irqrestore(&drm_minor_lock, flags); + } device_del(minor->kdev); dev_set_drvdata(minor->kdev, NULL); /* safety belt */ @@ -216,16 +253,24 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type) * minor->dev pointer will stay valid! However, the device may get unplugged and * unregistered while you hold the minor. */ -struct drm_minor *drm_minor_acquire(unsigned int minor_id) +struct drm_minor *drm_minor_acquire(unsigned int minor_id, bool is_accel_minor) { struct drm_minor *minor; unsigned long flags; - spin_lock_irqsave(&drm_minor_lock, flags); - minor = idr_find(&drm_minors_idr, minor_id); - if (minor) - drm_dev_get(minor->dev); - spin_unlock_irqrestore(&drm_minor_lock, flags); + if (is_accel_minor) { + spin_lock_irqsave(&accel_minor_lock, flags); + minor = idr_find(&accel_minors_idr, minor_id); + if (minor) + drm_dev_get(minor->dev); + spin_unlock_irqrestore(&accel_minor_lock, flags); + } else { + spin_lock_irqsave(&drm_minor_lock, flags); + minor = idr_find(&drm_minors_idr, minor_id); + if (minor) + drm_dev_get(minor->dev); + spin_unlock_irqrestore(&drm_minor_lock, flags); + } if (!minor) { return ERR_PTR(-ENODEV); @@ -607,6 +652,14 @@ static int drm_dev_init(struct drm_device *dev, /* no per-device feature limits by default */ dev->driver_features = ~0u; + if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL) && + (drm_core_check_feature(dev, DRIVER_RENDER) || + drm_core_check_feature(dev, DRIVER_MODESET))) { + + DRM_ERROR("DRM driver can't be both a compute acceleration and graphics driver\n"); + return -EINVAL; + } + drm_legacy_init_members(dev); INIT_LIST_HEAD(&dev->filelist); INIT_LIST_HEAD(&dev->filelist_internal); @@ -632,15 +685,21 @@ static int drm_dev_init(struct drm_device *dev, dev->anon_inode = inode; - if (drm_core_check_feature(dev, DRIVER_RENDER)) { - ret = drm_minor_alloc(dev, DRM_MINOR_RENDER); + if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL)) { + ret = drm_minor_alloc(dev, DRM_MINOR_ACCEL); if (ret) goto err; - } + } else { + if (drm_core_check_feature(dev, DRIVER_RENDER)) { + ret = drm_minor_alloc(dev, DRM_MINOR_RENDER); + if (ret) + goto err; + } - ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY); - if (ret) - goto err; + ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY); + if (ret) + goto err; + } ret = drm_legacy_create_map_hash(dev); if (ret) @@ -887,6 +946,10 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (ret) goto err_minors; + ret = drm_minor_register(dev, DRM_MINOR_ACCEL); + if (ret) + goto err_minors; + ret = create_compat_control_link(dev); if (ret) goto err_minors; @@ -906,12 +969,13 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->dev ? dev_name(dev->dev) : "virtual device", - dev->primary->index); + dev->primary ? dev->primary->index : dev->accel->index); goto out_unlock; err_minors: remove_compat_control_link(dev); + drm_minor_unregister(dev, DRM_MINOR_ACCEL); drm_minor_unregister(dev, DRM_MINOR_PRIMARY); drm_minor_unregister(dev, DRM_MINOR_RENDER); out_unlock: @@ -954,6 +1018,7 @@ void drm_dev_unregister(struct drm_device *dev) drm_legacy_rmmaps(dev); remove_compat_control_link(dev); + drm_minor_unregister(dev, DRM_MINOR_ACCEL); drm_minor_unregister(dev, DRM_MINOR_PRIMARY); drm_minor_unregister(dev, DRM_MINOR_RENDER); } @@ -999,18 +1064,11 @@ EXPORT_SYMBOL(drm_dev_set_unique); * registered minor. */ -static int drm_stub_open(struct inode *inode, struct file *filp) +static int stub_open(struct inode *inode, struct file *filp, struct drm_minor *minor) { const struct file_operations *new_fops; - struct drm_minor *minor; int err; - DRM_DEBUG("\n"); - - minor = drm_minor_acquire(iminor(inode)); - if (IS_ERR(minor)) - return PTR_ERR(minor); - new_fops = fops_get(minor->dev->driver->fops); if (!new_fops) { err = -ENODEV; @@ -1029,18 +1087,51 @@ static int drm_stub_open(struct inode *inode, struct file *filp) return err; } +static int drm_stub_open(struct inode *inode, struct file *filp) +{ + struct drm_minor *minor; + + DRM_DEBUG("\n"); + + minor = drm_minor_acquire(iminor(inode), false); + if (IS_ERR(minor)) + return PTR_ERR(minor); + + return stub_open(inode, filp, minor); +} + +static int accel_stub_open(struct inode *inode, struct file *filp) +{ + struct drm_minor *minor; + + DRM_DEBUG("\n"); + + minor = drm_minor_acquire(iminor(inode), true); + if (IS_ERR(minor)) + return PTR_ERR(minor); + + return stub_open(inode, filp, minor); +} + static const struct file_operations drm_stub_fops = { .owner = THIS_MODULE, .open = drm_stub_open, .llseek = noop_llseek, }; +static const struct file_operations accel_stub_fops = { + .owner = THIS_MODULE, + .open = accel_stub_open, + .llseek = noop_llseek, +}; + static void accel_core_exit(void) { #ifdef CONFIG_ACCEL unregister_chrdev(ACCEL_MAJOR, "accel"); debugfs_remove(accel_debugfs_root); accel_sysfs_destroy(); + idr_destroy(&accel_minors_idr); #endif } @@ -1060,6 +1151,8 @@ static int __init accel_core_init(void) #ifdef CONFIG_ACCEL int ret; + idr_init(&accel_minors_idr); + ret = accel_sysfs_init(); if (ret < 0) { DRM_ERROR("Cannot create ACCEL class: %d\n", ret); @@ -1068,7 +1161,7 @@ static int __init accel_core_init(void) accel_debugfs_root = debugfs_create_dir("accel", NULL); - ret = register_chrdev(ACCEL_MAJOR, "accel", &drm_stub_fops); + ret = register_chrdev(ACCEL_MAJOR, "accel", &accel_stub_fops); if (ret < 0) goto error; diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index a8b4d918e9a3..d9c60108ab7b 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -389,30 +389,12 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) return 0; } -/** - * drm_open - open method for DRM file - * @inode: device inode - * @filp: file pointer. - * - * This function must be used by drivers as their &file_operations.open method. - * It looks up the correct DRM device and instantiates all the per-file - * resources for it. It also calls the &drm_driver.open driver callback. - * - * RETURNS: - * - * 0 on success or negative errno value on failure. - */ -int drm_open(struct inode *inode, struct file *filp) +static int __drm_open(struct inode *inode, struct file *filp, struct drm_minor *minor) { struct drm_device *dev; - struct drm_minor *minor; int retcode; int need_setup = 0; - minor = drm_minor_acquire(iminor(inode)); - if (IS_ERR(minor)) - return PTR_ERR(minor); - dev = minor->dev; if (drm_dev_needs_global_mutex(dev)) mutex_lock(&drm_global_mutex); @@ -446,8 +428,57 @@ int drm_open(struct inode *inode, struct file *filp) drm_minor_release(minor); return retcode; } + +/** + * drm_open - open method for DRM file + * @inode: device inode + * @filp: file pointer. + * + * This function must be used by drivers as their &file_operations.open method. + * It looks up the correct DRM device and instantiates all the per-file + * resources for it. It also calls the &drm_driver.open driver callback. + * + * RETURNS: + * + * 0 on success or negative errno value on failure. + */ +int drm_open(struct inode *inode, struct file *filp) +{ + struct drm_minor *minor; + + minor = drm_minor_acquire(iminor(inode), false); + if (IS_ERR(minor)) + return PTR_ERR(minor); + + return __drm_open(inode, filp, minor); +} EXPORT_SYMBOL(drm_open); +/** + * accel_open - open method for ACCEL file + * @inode: device inode + * @filp: file pointer. + * + * This function must be used by drivers as their &file_operations.open method. + * It looks up the correct ACCEL device and instantiates all the per-file + * resources for it. It also calls the &drm_driver.open driver callback. + * + * RETURNS: + * + * 0 on success or negative errno value on failure. + */ +int accel_open(struct inode *inode, struct file *filp) +{ + struct drm_minor *minor; + + minor = drm_minor_acquire(iminor(inode), true); + if (IS_ERR(minor)) + return PTR_ERR(minor); + + return __drm_open(inode, filp, minor); +} +EXPORT_SYMBOL(accel_open); + void drm_lastclose(struct drm_device * dev) { DRM_DEBUG("\n"); diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index cbeb9bd3c312..e12efc243527 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -78,7 +78,7 @@ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, uint32_t handle); /* drm_drv.c */ -struct drm_minor *drm_minor_acquire(unsigned int minor_id); +struct drm_minor *drm_minor_acquire(unsigned int minor_id, bool is_accel_minor); void drm_minor_release(struct drm_minor *minor); /* drm_managed.c */ diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 70b2a28f55c4..1335476ad373 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -51,6 +51,10 @@ static struct device_type drm_sysfs_device_minor = { .name = "drm_minor" }; +static struct device_type accel_sysfs_device_minor = { + .name = "accel_minor" +}; + static struct device_type drm_sysfs_device_connector = { .name = "drm_connector", }; @@ -523,19 +527,28 @@ struct device *drm_sysfs_minor_alloc(struct drm_minor *minor) struct device *kdev; int r; - if (minor->type == DRM_MINOR_RENDER) - minor_str = "renderD%d"; - else - minor_str = "card%d"; - kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); if (!kdev) return ERR_PTR(-ENOMEM); device_initialize(kdev); - kdev->devt = MKDEV(DRM_MAJOR, minor->index); - kdev->class = drm_class; - kdev->type = &drm_sysfs_device_minor; + + if (minor->type == DRM_MINOR_ACCEL) { + minor_str = "accel%d"; + kdev->devt = MKDEV(ACCEL_MAJOR, minor->index); + kdev->class = accel_class; + kdev->type = &accel_sysfs_device_minor; + } else { + if (minor->type == DRM_MINOR_RENDER) + minor_str = "renderD%d"; + else + minor_str = "card%d"; + + kdev->devt = MKDEV(DRM_MAJOR, minor->index); + kdev->class = drm_class; + kdev->type = &drm_sysfs_device_minor; + } + kdev->parent = minor->dev->dev; kdev->release = drm_sysfs_release; dev_set_drvdata(kdev, minor); diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 9923c7a6885e..933ce2048e20 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -93,6 +93,9 @@ struct drm_device { /** @render: Render node */ struct drm_minor *render; + /** @accel: Compute Acceleration node */ + struct drm_minor *accel; + /** * @registered: * diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index f6159acb8856..4f64102ba8d9 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -94,6 +94,14 @@ enum drm_driver_feature { * synchronization of command submission. */ DRIVER_SYNCOBJ_TIMELINE = BIT(6), + /** + * @DRIVER_COMPUTE_ACCEL: + * + * Driver supports compute acceleration devices. This flag is mutually exclusive with + * @DRIVER_RENDER and @DRIVER_MODESET. Devices that support both graphics and compute + * acceleration should be handled by two drivers that are connected using auxiliry bus. + */ + DRIVER_COMPUTE_ACCEL = BIT(7), /* IMPORTANT: Below are all the legacy flags, add new ones above. */ diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index d780fd151789..e0895a90f394 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -51,11 +51,15 @@ struct file; /* Note that the order of this enum is ABI (it determines * /dev/dri/renderD* numbers). + * + * Setting DRM_MINOR_ACCEL to 32 gives enough space for more drm minors to + * be implemented before we hit any future */ enum drm_minor_type { DRM_MINOR_PRIMARY, DRM_MINOR_CONTROL, DRM_MINOR_RENDER, + DRM_MINOR_ACCEL = 32, }; /** @@ -70,7 +74,7 @@ enum drm_minor_type { struct drm_minor { /* private: */ int index; /* Minor device number */ - int type; /* Control or render */ + int type; /* Control or render or accel */ struct device *kdev; /* Linux device */ struct drm_device *dev; @@ -397,7 +401,22 @@ static inline bool drm_is_render_client(const struct drm_file *file_priv) return file_priv->minor->type == DRM_MINOR_RENDER; } +/** + * drm_is_accel_client - is this an open file of the compute acceleration node + * @file_priv: DRM file + * + * Returns true if this is an open file of the compute acceleration node, i.e. + * &drm_file.minor of @file_priv is a accel minor. + * + * See also the :ref:`section on accel nodes `. + */ +static inline bool drm_is_accel_client(const struct drm_file *file_priv) +{ + return file_priv->minor->type == DRM_MINOR_ACCEL; +} + int drm_open(struct inode *inode, struct file *filp); +int accel_open(struct inode *inode, struct file *filp); ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset); int drm_release(struct inode *inode, struct file *filp);