From nobody Wed Apr 8 04:55:31 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 19EE2C04A95 for ; Sat, 22 Oct 2022 21:46:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229792AbiJVVqs (ORCPT ); Sat, 22 Oct 2022 17:46:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40366 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229741AbiJVVql (ORCPT ); Sat, 22 Oct 2022 17:46:41 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D66C3EA9FF for ; Sat, 22 Oct 2022 14:46:39 -0700 (PDT) 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 4FC0F60ABB for ; 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 Cc: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Yuji Ishikawa , Jiho Chu , Daniel Stone , Tvrtko Ursulin , Jeffrey Hugo , Christoph Hellwig , Kevin Hilman , Jagan Teki , Jacek Lawrynowicz , Maciej Kwapulinski 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 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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* =20 +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" =20 source "drivers/video/Kconfig" =20 +source "drivers/accel/Kconfig" + source "sound/Kconfig" =20 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) --=20 2.34.1 From nobody Wed Apr 8 04:55:31 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 E5A38C04A95 for ; Sat, 22 Oct 2022 21:46:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229893AbiJVVq6 (ORCPT ); Sat, 22 Oct 2022 17:46:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40646 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229799AbiJVVqt (ORCPT ); Sat, 22 Oct 2022 17:46:49 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F2BD57B7AF for ; Sat, 22 Oct 2022 14:46:47 -0700 (PDT) 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 908B4B80B2E for ; 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 Cc: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Yuji Ishikawa , Jiho Chu , Daniel Stone , Tvrtko Ursulin , Jeffrey Hugo , Christoph Hellwig , Kevin Hilman , Jagan Teki , Jacek Lawrynowicz , Maciej Kwapulinski 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 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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-gu= ide/devices.txt index 9764d6edb189..06c525e01ea5 100644 --- a/Documentation/admin-guide/devices.txt +++ b/Documentation/admin-guide/devices.txt @@ -3080,6 +3080,11 @@ ... 255 =3D /dev/osd255 256th OSD Device =20 + 261 char Compute Acceleration Devices + 0 =3D /dev/accel/accel0 First acceleration device + 1 =3D /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; =20 static struct dentry *drm_debugfs_root; =20 +#ifdef CONFIG_ACCEL +static struct dentry *accel_debugfs_root; +#endif + DEFINE_STATIC_SRCU(drm_unplug_srcu); =20 /* @@ -1031,9 +1035,19 @@ static const struct file_operations drm_stub_fops = =3D { .llseek =3D noop_llseek, }; =20 +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(); } =20 +static int __init accel_core_init(void) +{ +#ifdef CONFIG_ACCEL + int ret; + + ret =3D accel_sysfs_init(); + if (ret < 0) { + DRM_ERROR("Cannot create ACCEL class: %d\n", ret); + goto error; + } + + accel_debugfs_root =3D debugfs_create_dir("accel", NULL); + + ret =3D 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; =20 + ret =3D accel_core_init(); + if (ret < 0) + goto error; + drm_privacy_screen_lookup_init(); =20 drm_core_init_complete =3D 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 *de= v); =20 /* drm_sysfs.c */ extern struct class *drm_class; +extern struct class *accel_class; =20 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 =3D { }; =20 struct class *drm_class; +struct class *accel_class; =20 #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); } =20 +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 =3D class_create(THIS_MODULE, "accel"); + if (IS_ERR(accel_class)) + return PTR_ERR(accel_class); + + err =3D class_create_file(accel_class, &class_attr_accel_version.attr); + if (err) { + class_destroy(accel_class); + accel_class =3D NULL; + return err; + } + + accel_class->devnode =3D 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 =3D 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, unsigne= d 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 =20 /** * enum drm_ioctl_flags - DRM ioctl flags --=20 2.34.1 From nobody Wed Apr 8 04:55:31 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 57EEAC04A95 for ; Sat, 22 Oct 2022 21:47:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229767AbiJVVrF (ORCPT ); Sat, 22 Oct 2022 17:47:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40710 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229849AbiJVVq5 (ORCPT ); Sat, 22 Oct 2022 17:46:57 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E108F1025 for ; Sat, 22 Oct 2022 14:46:54 -0700 (PDT) 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 3AE37B80966 for ; 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 Cc: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Yuji Ishikawa , Jiho Chu , Daniel Stone , Tvrtko Ursulin , Jeffrey Hugo , Christoph Hellwig , Kevin Hilman , Jagan Teki , Jacek Lawrynowicz , Maciej Kwapulinski 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 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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; =20 +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_d= evice *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) =20 put_device(minor->kdev); =20 - spin_lock_irqsave(&drm_minor_lock, flags); - idr_remove(&drm_minors_idr, minor->index); - spin_unlock_irqrestore(&drm_minor_lock, flags); + if (minor->type =3D=3D 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); + } } =20 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, un= signed int type) minor->dev =3D dev; =20 idr_preload(GFP_KERNEL); - spin_lock_irqsave(&drm_minor_lock, flags); - r =3D idr_alloc(&drm_minors_idr, - NULL, - 64 * type, - 64 * (type + 1), - GFP_NOWAIT); - spin_unlock_irqrestore(&drm_minor_lock, flags); + if (type =3D=3D DRM_MINOR_ACCEL) { + spin_lock_irqsave(&accel_minor_lock, flags); + r =3D 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 =3D idr_alloc(&drm_minors_idr, + NULL, + 64 * type, + 64 * (type + 1), + GFP_NOWAIT); + spin_unlock_irqrestore(&drm_minor_lock, flags); + } idr_preload_end(); =20 if (r < 0) @@ -167,7 +188,11 @@ static int drm_minor_register(struct drm_device *dev, = unsigned int type) =20 ret =3D 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 =3D=3D 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; } =20 @@ -176,9 +201,15 @@ static int drm_minor_register(struct drm_device *dev, = unsigned int type) goto err_debugfs; =20 /* 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 =3D=3D 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); + } =20 DRM_DEBUG("new minor registered %d\n", minor->index); return 0; @@ -198,9 +229,15 @@ static void drm_minor_unregister(struct drm_device *de= v, unsigned int type) return; =20 /* 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 =3D=3D 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); + } =20 device_del(minor->kdev); dev_set_drvdata(minor->kdev, NULL); /* safety belt */ @@ -216,16 +253,24 @@ static void drm_minor_unregister(struct drm_device *d= ev, unsigned int type) * minor->dev pointer will stay valid! However, the device may get unplugg= ed 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_m= inor) { struct drm_minor *minor; unsigned long flags; =20 - spin_lock_irqsave(&drm_minor_lock, flags); - minor =3D 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 =3D 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 =3D idr_find(&drm_minors_idr, minor_id); + if (minor) + drm_dev_get(minor->dev); + spin_unlock_irqrestore(&drm_minor_lock, flags); + } =20 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 =3D ~0u; =20 + 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, =20 dev->anon_inode =3D inode; =20 - if (drm_core_check_feature(dev, DRIVER_RENDER)) { - ret =3D drm_minor_alloc(dev, DRM_MINOR_RENDER); + if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL)) { + ret =3D drm_minor_alloc(dev, DRM_MINOR_ACCEL); if (ret) goto err; - } + } else { + if (drm_core_check_feature(dev, DRIVER_RENDER)) { + ret =3D drm_minor_alloc(dev, DRM_MINOR_RENDER); + if (ret) + goto err; + } =20 - ret =3D drm_minor_alloc(dev, DRM_MINOR_PRIMARY); - if (ret) - goto err; + ret =3D drm_minor_alloc(dev, DRM_MINOR_PRIMARY); + if (ret) + goto err; + } =20 ret =3D 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; =20 + ret =3D drm_minor_register(dev, DRM_MINOR_ACCEL); + if (ret) + goto err_minors; + ret =3D 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); =20 goto out_unlock; =20 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); =20 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. */ =20 -static int drm_stub_open(struct inode *inode, struct file *filp) +static int stub_open(struct inode *inode, struct file *filp, struct drm_mi= nor *minor) { const struct file_operations *new_fops; - struct drm_minor *minor; int err; =20 - DRM_DEBUG("\n"); - - minor =3D drm_minor_acquire(iminor(inode)); - if (IS_ERR(minor)) - return PTR_ERR(minor); - new_fops =3D fops_get(minor->dev->driver->fops); if (!new_fops) { err =3D -ENODEV; @@ -1029,18 +1087,51 @@ static int drm_stub_open(struct inode *inode, struc= t file *filp) return err; } =20 +static int drm_stub_open(struct inode *inode, struct file *filp) +{ + struct drm_minor *minor; + + DRM_DEBUG("\n"); + + minor =3D 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 =3D 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 =3D { .owner =3D THIS_MODULE, .open =3D drm_stub_open, .llseek =3D noop_llseek, }; =20 +static const struct file_operations accel_stub_fops =3D { + .owner =3D THIS_MODULE, + .open =3D accel_stub_open, + .llseek =3D 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 } =20 @@ -1060,6 +1151,8 @@ static int __init accel_core_init(void) #ifdef CONFIG_ACCEL int ret; =20 + idr_init(&accel_minors_idr); + ret =3D 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) =20 accel_debugfs_root =3D debugfs_create_dir("accel", NULL); =20 - ret =3D register_chrdev(ACCEL_MAJOR, "accel", &drm_stub_fops); + ret =3D register_chrdev(ACCEL_MAJOR, "accel", &accel_stub_fops); if (ret < 0) goto error; =20 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; } =20 -/** - * 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 me= thod. - * 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_m= inor *minor) { struct drm_device *dev; - struct drm_minor *minor; int retcode; int need_setup =3D 0; =20 - minor =3D drm_minor_acquire(iminor(inode)); - if (IS_ERR(minor)) - return PTR_ERR(minor); - dev =3D 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 me= thod. + * 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 =3D drm_minor_acquire(iminor(inode), false); + if (IS_ERR(minor)) + return PTR_ERR(minor); + + return __drm_open(inode, filp, minor); +} EXPORT_SYMBOL(drm_open); =20 +/** + * 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 me= thod. + * 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 =3D 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_pr= ivate *prime_fpriv, uint32_t handle); =20 /* 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_m= inor); void drm_minor_release(struct drm_minor *minor); =20 /* 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 =3D { .name =3D "drm_minor" }; =20 +static struct device_type accel_sysfs_device_minor =3D { + .name =3D "accel_minor" +}; + static struct device_type drm_sysfs_device_connector =3D { .name =3D "drm_connector", }; @@ -523,19 +527,28 @@ struct device *drm_sysfs_minor_alloc(struct drm_minor= *minor) struct device *kdev; int r; =20 - if (minor->type =3D=3D DRM_MINOR_RENDER) - minor_str =3D "renderD%d"; - else - minor_str =3D "card%d"; - kdev =3D kzalloc(sizeof(*kdev), GFP_KERNEL); if (!kdev) return ERR_PTR(-ENOMEM); =20 device_initialize(kdev); - kdev->devt =3D MKDEV(DRM_MAJOR, minor->index); - kdev->class =3D drm_class; - kdev->type =3D &drm_sysfs_device_minor; + + if (minor->type =3D=3D DRM_MINOR_ACCEL) { + minor_str =3D "accel%d"; + kdev->devt =3D MKDEV(ACCEL_MAJOR, minor->index); + kdev->class =3D accel_class; + kdev->type =3D &accel_sysfs_device_minor; + } else { + if (minor->type =3D=3D DRM_MINOR_RENDER) + minor_str =3D "renderD%d"; + else + minor_str =3D "card%d"; + + kdev->devt =3D MKDEV(DRM_MAJOR, minor->index); + kdev->class =3D drm_class; + kdev->type =3D &drm_sysfs_device_minor; + } + kdev->parent =3D minor->dev->dev; kdev->release =3D 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; =20 + /** @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 =3D BIT(6), + /** + * @DRIVER_COMPUTE_ACCEL: + * + * Driver supports compute acceleration devices. This flag is mutually ex= clusive 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 =3D BIT(7), =20 /* IMPORTANT: Below are all the legacy flags, add new ones above. */ =20 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; =20 /* 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 =3D 32, }; =20 /** @@ -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; =20 @@ -397,7 +401,22 @@ static inline bool drm_is_render_client(const struct d= rm_file *file_priv) return file_priv->minor->type =3D=3D DRM_MINOR_RENDER; } =20 +/** + * 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 =3D=3D 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); --=20 2.34.1