From patchwork Wed May 17 14:52:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 13245261 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 73465C77B75 for ; Wed, 17 May 2023 16:00:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=53yQ5WAlsgSKbKfPAJNRS0Vf8Mhg/M9EmPqqwDtVX7Y=; b=H7lB5H8MNdbRe2KS+4MQed9JtK BD3y+FhtRmSq/PvXgIrLoTUjmhiU7sPLPpwqST+a5L6fQo+V/y4hjl/tQX/TqihTWDcptaR+RowLc I3WxRGNuNZ0yK0KxCVUqZS7ljbgVklYu4ym64isXrDgrRR0GvXNMlQATIAX8c8hb49Hp0P/dChMqb De2SuKN9s3/oWa3M4m1/dWBEEVNqE/C3g9OTr0NTRD93gs0VzXXDGX7jXeEJE/eIvtiBzGhQBVvyZ BrwMBlEMkWkfSMhG2sfaPzGst66hcZbfXMtBuy9NU2a3cZLO5/XmX2lnFgB12pOwYW8LWGkFs+RFF yoEZpOQQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1pzJZu-00AOMG-1y; Wed, 17 May 2023 16:00:38 +0000 Received: from mail-wr1-x434.google.com ([2a00:1450:4864:20::434]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzIWH-00ACAX-0F for linux-mediatek@lists.infradead.org; Wed, 17 May 2023 14:52:52 +0000 Received: by mail-wr1-x434.google.com with SMTP id ffacd0b85a97d-3093a778089so629949f8f.1 for ; Wed, 17 May 2023 07:52:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20221208.gappssmtp.com; s=20221208; t=1684335165; x=1686927165; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=53yQ5WAlsgSKbKfPAJNRS0Vf8Mhg/M9EmPqqwDtVX7Y=; b=uP94VE8FRaeKi54S5wqD9ZoflKuQ97i4LxQN2rLaTlvpXkjiHzQZvTiILoc945VCvG EkvSyXfYBdYIbxrcK6Er6nXn9Rzhu53yIjnCpySHYihhSORMT2hkYMUNZZ8EBGzUlIsG jbbp5H2bZz2x/PTZpzW7GvEBJEClwCzasxSck2jBqjY8l8rWfMD2OQ7+ddDlM87K0vZZ AmBzb9YNhiP2MlNHEYbVnXbx0ZuTHT0qr+VdBkKYOCk6Z5SyxuvSH10wt7KxFYR9dB0X kyeu8l0gqKeO/If723w61vT9W8TFQvgaohDAscMVAslU/H4PFjpigrFC+5ffLqZI2xm5 465g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684335165; x=1686927165; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=53yQ5WAlsgSKbKfPAJNRS0Vf8Mhg/M9EmPqqwDtVX7Y=; b=UqfqtqfqrySlXh9AD+cDWEbhO5ZHj4hEAl8x2rKEgn7a3ZlxV18gqIGDX5cfQUAl2z rrJ45n4sVcoFkUoDz6LNsW1nytfgLV3lLzTauGvhROwROxyxz4pXuxvv+TQK9NpWUjvw BLCMMH/O/FLgl+/2xop7fAbr2OL6jZXMKxli5lepqAxYJ+52ZJsZAdhX0N06Wf2Oo2sI X5d734VpE6n9gMLa/L6rXZZtVecQGwx0rN0LOI7ha2seumwma7jcuA/z/GgbHxcgV++9 urMd/FRG8L6dvUs8n75e6cYC0lZHc1vqFngEmZjNi+3UK9B+lSU7xQAWhQbUyl1RfaiO KxiQ== X-Gm-Message-State: AC+VfDxMlRxH+C6FnayxvmvSeW5DT1fnmgNM8rM7UmuODGdJQvYVZj2/ WKxIctqdGlEHSdLY7iLUtWgHUQ== X-Google-Smtp-Source: ACHHUZ7m6fs008rRX4GnYew3Bs5IbiZ+LTVWrGeG8VJEU+HTH+tD3errRQp3lrkI3GLvMjQRVqqLFA== X-Received: by 2002:a5d:591a:0:b0:309:3df3:8e0f with SMTP id v26-20020a5d591a000000b003093df38e0fmr997547wrd.51.1684335165200; Wed, 17 May 2023 07:52:45 -0700 (PDT) Received: from blaptop.baylibre (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id v11-20020a5d678b000000b002f7780eee10sm2979098wru.59.2023.05.17.07.52.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 May 2023 07:52:44 -0700 (PDT) From: Alexandre Bailon To: airlied@gmail.com, daniel@ffwll.ch, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, sumit.semwal@linaro.org, christian.koenig@amd.com, jstephan@baylibre.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, nbelin@baylibre.com, bero@baylibre.com, Alexandre Bailon Subject: [PATCH 1/7] drm: Add support of AI Processor Unit (APU) Date: Wed, 17 May 2023 16:52:31 +0200 Message-Id: <20230517145237.295461-2-abailon@baylibre.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230517145237.295461-1-abailon@baylibre.com> References: <20230517145237.295461-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230517_075249_117610_8FEC7034 X-CRM114-Status: GOOD ( 30.55 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Many AI Processur Unit (APU) have a similar architecture. This driver intends helping supporting them. This relies on DRM and provides some abstractions useful for AI accelerators. Currently, this provides the infrastructure to alloc an APU device and register one or many cores. The driver will takes care to register itself to DRM. Signed-off-by: Alexandre Bailon Reviewed-by: Julien Stephan --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/apu/Kconfig | 12 ++ drivers/gpu/drm/apu/Makefile | 5 + drivers/gpu/drm/apu/apu_drv.c | 272 +++++++++++++++++++++++++++++ drivers/gpu/drm/apu/apu_internal.h | 68 ++++++++ include/uapi/drm/apu_drm.h | 28 +++ 7 files changed, 388 insertions(+) create mode 100644 drivers/gpu/drm/apu/Kconfig create mode 100644 drivers/gpu/drm/apu/Makefile create mode 100644 drivers/gpu/drm/apu/apu_drv.c create mode 100644 drivers/gpu/drm/apu/apu_internal.h create mode 100644 include/uapi/drm/apu_drm.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index ba3fb04bb691..32ffa66a8b54 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -371,6 +371,8 @@ source "drivers/gpu/drm/solomon/Kconfig" source "drivers/gpu/drm/sprd/Kconfig" +source "drivers/gpu/drm/apu/Kconfig" + config DRM_HYPERV tristate "DRM Support for Hyper-V synthetic video device" depends on DRM && PCI && MMU && HYPERV diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index a33257d2bc7f..7cd8c0f3936a 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -191,6 +191,7 @@ obj-$(CONFIG_DRM_MCDE) += mcde/ obj-$(CONFIG_DRM_TIDSS) += tidss/ obj-y += xlnx/ obj-y += gud/ +obj-$(CONFIG_DRM_APU) += apu/ obj-$(CONFIG_DRM_HYPERV) += hyperv/ obj-y += solomon/ obj-$(CONFIG_DRM_SPRD) += sprd/ diff --git a/drivers/gpu/drm/apu/Kconfig b/drivers/gpu/drm/apu/Kconfig new file mode 100644 index 000000000000..226dcf072115 --- /dev/null +++ b/drivers/gpu/drm/apu/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# + +config DRM_APU + tristate "APU (AI Processor Unit)" + select DRM_GEM_DMA_HELPER + select DRM_KMS_HELPER + help + This provides a DRM driver that provides some facilities to + communicate with an AI Processor Unit (APU). + The driver intends to provide a common infrastructure that may be + used to support many different APU. diff --git a/drivers/gpu/drm/apu/Makefile b/drivers/gpu/drm/apu/Makefile new file mode 100644 index 000000000000..ad85b88a8b52 --- /dev/null +++ b/drivers/gpu/drm/apu/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_apu-y += apu_drv.o + +obj-$(CONFIG_DRM_APU) += drm_apu.o diff --git a/drivers/gpu/drm/apu/apu_drv.c b/drivers/gpu/drm/apu/apu_drv.c new file mode 100644 index 000000000000..b420b13a9ffd --- /dev/null +++ b/drivers/gpu/drm/apu/apu_drv.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2020 BayLibre SAS + +#include +#include + +#include +#include +#include +#include + +#include "apu_internal.h" + +static LIST_HEAD(apu_devices); + +static int ioctl_apu_state(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +static const struct drm_ioctl_desc ioctls[] = { + DRM_IOCTL_DEF_DRV(APU_STATE, ioctl_apu_state, + DRM_RENDER_ALLOW), +}; + +DEFINE_DRM_GEM_DMA_FOPS(apu_drm_ops); + +static struct drm_driver apu_drm_driver = { + .driver_features = DRIVER_GEM | DRIVER_SYNCOBJ, + .name = "drm_apu", + .desc = "APU DRM driver", + .date = "20210319", + .major = 1, + .minor = 0, + .patchlevel = 0, + .ioctls = ioctls, + .num_ioctls = ARRAY_SIZE(ioctls), + .fops = &apu_drm_ops, + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_gem_dma_dumb_create), +}; + +/** + * apu_dev_alloc() - Allocate a new APU device + * + * @dev: Pointer to the device instance. + + * This allocate an APU device. + * The APU describe a hardware accelerator that may have one or more + * core (or unit). + * + * Returns: A pointer or NULL in case of failure. + */ +struct apu_drm *apu_dev_alloc(struct device *dev) +{ + struct drm_device *drm; + struct apu_drm *apu; + + apu = devm_drm_dev_alloc(dev, &apu_drm_driver, typeof(*apu), base); + if (IS_ERR(apu)) + return NULL; + INIT_LIST_HEAD(&apu->cores); + + apu->dev = dev; + ida_init(&apu->ida); + drm = &apu->base; + drm->dev_private = apu; + + dev_set_drvdata(dev, drm); + + return apu; +} +EXPORT_SYMBOL_GPL(apu_dev_alloc); + +/** + * apu_dev_register() - Register the APU to DRM + * + * @apu: Pointer to APU device + * + * Register an APU device to DRM. + * On success, this creates everything required to use the APU. + * Note that at this step, the cores (or units) have not been + * registered so we can't yet perform any operations. + * + * Returns: Zero on success, non-zero value on failure. + */ +int apu_dev_register(struct apu_drm *apu) +{ + struct drm_device *drm = &apu->base; + int ret; + + ret = drm_dev_register(drm, 0); + if (ret) + return ret; + + list_add(&apu->node, &apu_devices); + + return 0; +} +EXPORT_SYMBOL_GPL(apu_dev_register); + +/** + * apu_dev_unregister() - Unregister the APU + * + * @apu: Pointer to APU device + * + * This undo what has been done by apu_dev_register(); + */ +void apu_dev_unregister(struct apu_drm *apu) +{ + struct drm_device *drm = &apu->base; + + list_del(&apu->node); + drm_dev_unregister(drm); +} +EXPORT_SYMBOL_GPL(apu_dev_unregister); + +/** + * apu_core_alloc() - Allocate an APU core + * + * @apu: Pointer to APU device + * @ops: The operation callbacks to use for this core + * @priv: + * + * Allocate an APU core. This represents a computing unit that could + * execute a job. The APU may be composed of different units that doesn't + * accept same kind of jobs so we may to use differents callbacks for each + * core. + * + * Returns: A pointer or NULL in case of failure. + */ +struct apu_core *apu_core_alloc(struct apu_drm *apu, struct apu_core_ops *ops, + void *priv) +{ + struct apu_core *core; + + if (!ops || !ops->is_ready) + return NULL; + + core = devm_kzalloc(apu->dev, sizeof(*core), GFP_KERNEL); + if (!core) + return NULL; + + core->device_id = ida_alloc(&apu->ida, GFP_KERNEL); + if (core->device_id < 0) + return NULL; + + core->apu = apu; + core->priv = priv; + core->ops = ops; + + list_add(&core->node, &apu->cores); + + return core; +} +EXPORT_SYMBOL_GPL(apu_core_alloc); + +/** + * apu_core_free() - Free an APU core allocated using apu_core_alloc() + * + * @core: The APU core to release + */ +void apu_core_free(struct apu_core *core) +{ + ida_free(&core->apu->ida, core->device_id); + list_del(&core->node); +} +EXPORT_SYMBOL_GPL(apu_core_free); + +/** + * apu_core_register() - Register a core to APU device + * + * @dev: Pointer to APU device + * @core: Pointer to APU core to register + * @priv: Private data attached to this core + * + * Register an APU core and make it available for computing. + * On success, userspace can start using this core. + * + * Returns: Zero on success, non-zero value on failure. + */ +int apu_core_register(struct device *dev, struct apu_core *core, void *priv) +{ + int ret; + + core->dev_priv = priv; + core->dev = dev; + + if (core->ops->register_core) { + ret = core->ops->register_core(core); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(apu_core_register); + +/** + * apu_core_remove() - Remove a core from the APU device + * + * @core: Pointer to APU core to remove + */ +void apu_core_remove(struct apu_core *core) +{ + core->dev_priv = NULL; +} +EXPORT_SYMBOL_GPL(apu_core_remove); + +/** + * apu_find_core_by_priv() - Find a core allocated by apu_core_alloc() + * + * @priv: The pointer used to allocate the core + * + * All core allocated using apu_core_alloc() is registered to a list. + * This goes through the list to find the core using the @priv field. + * + * Returns: A pointer or NULL if no core has been found. + */ +struct apu_core *apu_find_core_by_priv(void *priv) +{ + struct apu_drm *apu; + struct apu_core *core; + + list_for_each_entry(apu, &apu_devices, node) { + list_for_each_entry(core, &apu->cores, node) { + if (core->priv == priv) + return core; + } + } + + return NULL; +} +EXPORT_SYMBOL_GPL(apu_find_core_by_priv); + +static struct apu_core *get_apu_core(struct apu_drm *apu, int device_id) +{ + struct apu_core *core; + + list_for_each_entry(core, &apu->cores, node) { + if (core->device_id == device_id) + return core; + } + + return NULL; +} + +static void apu_core_update_state(struct apu_core *core) +{ + if (!core->ops->is_ready(core)) + core->flags &= ~APU_ONLINE; +} + +static int ioctl_apu_state(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct apu_drm *apu = dev->dev_private; + struct drm_apu_state *args = data; + struct apu_core *core; + + args->flags = 0; + + core = get_apu_core(apu, args->device); + if (!core) + return -ENODEV; + + apu_core_update_state(core); + args->flags |= core->flags; + + return 0; +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexandre Bailon"); diff --git a/drivers/gpu/drm/apu/apu_internal.h b/drivers/gpu/drm/apu/apu_internal.h new file mode 100644 index 000000000000..58d93a16c68f --- /dev/null +++ b/drivers/gpu/drm/apu/apu_internal.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __APU_INTERNAL_H__ +#define __APU_INTERNAL_H__ + +#include + +struct apu_core { + int device_id; + struct device *dev; + struct apu_core_ops *ops; + struct apu_drm *apu; + + struct list_head node; + void *priv; + void *dev_priv; + + u32 flags; +}; + +struct apu_drm { + struct drm_device base; + struct device *dev; + + struct list_head cores; + struct list_head node; + + struct ida ida; +}; + +/** + * @apu_core_ops: Provides platform specific callbacks + */ +struct apu_core_ops { + /** + * @register_core: + * + * Optional. Platform specific APU core registration. + */ + int (*register_core)(struct apu_core *core); + + /** + * @is_ready: + * + * Implements platform specific code to test if APU is ready to receive + * commands. + * Basically, an APU core may be running but not be ready to handle + * commands. This allows checking if APU is ready and start executing + * requests. + * + * Returns: + * + * One if the APU is ready or zero. + */ + int (*is_ready)(struct apu_core *core); +}; + +struct apu_drm *apu_dev_alloc(struct device *dev); +int apu_dev_register(struct apu_drm *apu); +void apu_dev_unregister(struct apu_drm *apu); + +struct apu_core *apu_core_alloc(struct apu_drm *apu, struct apu_core_ops *ops, + void *priv); +void apu_core_free(struct apu_core *core); +int apu_core_register(struct device *dev, struct apu_core *core, void *priv); +void apu_core_remove(struct apu_core *core); +struct apu_core *apu_find_core_by_priv(void *priv); + +#endif /* __APU_INTERNAL_H__ */ diff --git a/include/uapi/drm/apu_drm.h b/include/uapi/drm/apu_drm.h new file mode 100644 index 000000000000..d50c63d1b813 --- /dev/null +++ b/include/uapi/drm/apu_drm.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note*/ + +#ifndef __UAPI_APU_DRM_H__ +#define __UAPI_APU_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define APU_ONLINE BIT(0) + +struct drm_apu_state { + __u32 device; + __u32 flags; +}; + +#define DRM_APU_STATE 0x00 +#define DRM_APU_NUM_IOCTLS 0x01 + +#define DRM_IOCTL_APU_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_STATE, struct drm_apu_state) + +#if defined(__cplusplus) +} +#endif + +#endif /* __UAPI_APU_DRM_H__ */ From patchwork Wed May 17 14:52:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 13245262 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 C68F6C77B7F for ; Wed, 17 May 2023 16:00:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=6JUprTNR2AYUu5r4ykuSp6iVwLiXEOaF7GCdZkfyl4I=; b=XGDPGdI2OLhoPvbNNLaMDD+q73 eWQP2N7OfM+EvtREyHoed582dQmafSCd9z+LD8vJLd05TCGAoDhOb9yk4Vs0nh1c4FN2wF9Dg7Gpn zGJExSWGNwkuNEbw4we394XXeSIjJWMUVDdKmDGRcUVDwPJaTIhRku4gaclhKER2IrtRALq6f1ARm FkogDELzcvxp15ctGX6hDHwq/tExnDWy+0aNZdNm4o0tAP5ElwxpkXQu2bPD/tKvgjcXoh40T5xcP 7FIVZI6JjdQpcDJ4uFjhhL9GRzVEzBgK7GKe1LWCCYklN7heoC0e33MMMqsERsag7jw6uUx975JqT bo4Vwuqg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1pzJZv-00AOMm-06; Wed, 17 May 2023 16:00:39 +0000 Received: from mail-wm1-x32c.google.com ([2a00:1450:4864:20::32c]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzIWH-00ACAk-37 for linux-mediatek@lists.infradead.org; Wed, 17 May 2023 14:52:53 +0000 Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-3f450815d02so6418135e9.0 for ; Wed, 17 May 2023 07:52:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20221208.gappssmtp.com; s=20221208; t=1684335166; x=1686927166; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=6JUprTNR2AYUu5r4ykuSp6iVwLiXEOaF7GCdZkfyl4I=; b=mvPAtFy7apBepnb2BTkYGHlvdW8gzOsxkpjwMwkUvaUINN6vA6MJIgQbwok/QGlH8E hz+s2kr8iExnopHTUw8gL7llJFGaxST1HFeU3DvVO9ESvMAddRIW+HC3j7N42WTeU5kT uZD9jfR/Pe2bewmosqEXRDxYaOYyI6CGXVK8844+SddYPyX67Qpy6g+pAUY4J3rdMsrp NE77iiXnU8al++6TcHl6lxTCA1TFe9oGKXnNiQ/eVddXIdFIHf/md3w1N9dCAbRBrjXS xWnuZut8s3j43s0yWg5jT4VJgQRpIaO+nsd/OF++k3Rp0erxFbNkeiWQgiXorBrbFPE1 nEIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684335166; x=1686927166; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6JUprTNR2AYUu5r4ykuSp6iVwLiXEOaF7GCdZkfyl4I=; b=CDNfqhX57r9IR7+5wqOffZyCxdbpUgi6jHSjoxB0JAc0Cab8BWsyPY0lgTvLGzM3le vJANBJqUJzSWbbS413ly9nZfequ4EA1POyMTEi7COG/xW+snILDyQAvzrB2IDmE+ADRK U8mIBTCxidxZNt9n1dAAfcfVfNFmlYs+iz0Rk18r23lpun88fbOMswfw5/lm/yYP8izv +yqSgzwwGTTt0LcXLQQEeLf9Kpfc6rENPKsk7vuI7OnIAE6GzC5EzWeGrnK+8bYj1hNS MO3FObMMnhNX4Z1+q2QK+N6XhNDiYCslBmmFn8IONM5LXRrMaUcz9i4QvatOg594eVrD opWQ== X-Gm-Message-State: AC+VfDyrkf4nQ//lKAJkkP7xDsLPYggdnL4k3h0LTjNgqs4DtF8QzIx3 7iOBTpJfYwsyMSqBMcTFBsGuRg== X-Google-Smtp-Source: ACHHUZ7uV59fB+OW0baGaDbzIBdg1HfxU+jbrYxN5WEdFry9HrBC7HW5wsz8930CXaIqsQmv/54a7g== X-Received: by 2002:a1c:7c0f:0:b0:3f4:219f:5b7a with SMTP id x15-20020a1c7c0f000000b003f4219f5b7amr23742232wmc.30.1684335166168; Wed, 17 May 2023 07:52:46 -0700 (PDT) Received: from blaptop.baylibre (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id v11-20020a5d678b000000b002f7780eee10sm2979098wru.59.2023.05.17.07.52.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 May 2023 07:52:45 -0700 (PDT) From: Alexandre Bailon To: airlied@gmail.com, daniel@ffwll.ch, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, sumit.semwal@linaro.org, christian.koenig@amd.com, jstephan@baylibre.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, nbelin@baylibre.com, bero@baylibre.com, Alexandre Bailon Subject: [PATCH 2/7] drm/apu: Add memory allocator Date: Wed, 17 May 2023 16:52:32 +0200 Message-Id: <20230517145237.295461-3-abailon@baylibre.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230517145237.295461-1-abailon@baylibre.com> References: <20230517145237.295461-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230517_075250_039882_EEF0F60A X-CRM114-Status: GOOD ( 19.89 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org This adds a new ioctl to allocate GEM object. Signed-off-by: Alexandre Bailon Reviewed-by: Julien Stephan --- drivers/gpu/drm/apu/Makefile | 1 + drivers/gpu/drm/apu/apu_drv.c | 2 ++ drivers/gpu/drm/apu/apu_gem.c | 56 ++++++++++++++++++++++++++++++ drivers/gpu/drm/apu/apu_internal.h | 30 ++++++++++++++++ include/uapi/drm/apu_drm.h | 16 ++++++++- 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/apu/apu_gem.c diff --git a/drivers/gpu/drm/apu/Makefile b/drivers/gpu/drm/apu/Makefile index ad85b88a8b52..91894250d4c1 100644 --- a/drivers/gpu/drm/apu/Makefile +++ b/drivers/gpu/drm/apu/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 drm_apu-y += apu_drv.o +drm_apu-y += apu_gem.o obj-$(CONFIG_DRM_APU) += drm_apu.o diff --git a/drivers/gpu/drm/apu/apu_drv.c b/drivers/gpu/drm/apu/apu_drv.c index b420b13a9ffd..323e267b0f53 100644 --- a/drivers/gpu/drm/apu/apu_drv.c +++ b/drivers/gpu/drm/apu/apu_drv.c @@ -20,6 +20,8 @@ static int ioctl_apu_state(struct drm_device *dev, void *data, static const struct drm_ioctl_desc ioctls[] = { DRM_IOCTL_DEF_DRV(APU_STATE, ioctl_apu_state, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_GEM_NEW, ioctl_gem_new, + DRM_RENDER_ALLOW), }; DEFINE_DRM_GEM_DMA_FOPS(apu_drm_ops); diff --git a/drivers/gpu/drm/apu/apu_gem.c b/drivers/gpu/drm/apu/apu_gem.c new file mode 100644 index 000000000000..0e7b3b27942c --- /dev/null +++ b/drivers/gpu/drm/apu/apu_gem.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2020 BayLibre SAS + +#include + +#include + +#include "apu_internal.h" + +struct drm_gem_object *apu_gem_create_object(struct drm_device *dev, + size_t size) +{ + struct drm_gem_dma_object *dma_obj; + + dma_obj = drm_gem_dma_create(dev, size); + if (!dma_obj) + return NULL; + + return &dma_obj->base; +} + +int ioctl_gem_new(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_apu_gem_new *args = data; + struct drm_gem_dma_object *dma_obj; + struct apu_gem_object *apu_obj; + struct drm_gem_object *gem_obj; + int ret; + + dma_obj = drm_gem_dma_create(dev, args->size); + if (IS_ERR(dma_obj)) + return PTR_ERR(dma_obj); + + gem_obj = &dma_obj->base; + apu_obj = to_apu_bo(gem_obj); + + /* + * Save the size of buffer expected by application instead of the + * aligned one. + */ + apu_obj->size = args->size; + apu_obj->offset = 0; + mutex_init(&apu_obj->mutex); + + ret = drm_gem_handle_create(file_priv, gem_obj, &args->handle); + drm_gem_object_put(gem_obj); + if (ret) { + drm_gem_dma_object_free(gem_obj); + return ret; + } + args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node); + + return 0; +} diff --git a/drivers/gpu/drm/apu/apu_internal.h b/drivers/gpu/drm/apu/apu_internal.h index 58d93a16c68f..203aadc58b72 100644 --- a/drivers/gpu/drm/apu/apu_internal.h +++ b/drivers/gpu/drm/apu/apu_internal.h @@ -3,6 +3,14 @@ #define __APU_INTERNAL_H__ #include +#include + +struct apu_gem_object { + struct drm_gem_dma_object base; + struct mutex mutex; + size_t size; + u32 offset; +}; struct apu_core { int device_id; @@ -54,6 +62,17 @@ struct apu_core_ops { int (*is_ready)(struct apu_core *core); }; +static inline struct apu_gem_object *to_apu_bo(struct drm_gem_object *obj) +{ + return container_of(to_drm_gem_dma_obj(obj), struct apu_gem_object, + base); +} + +static inline void *apu_drm_priv(struct apu_core *apu_core) +{ + return apu_core->dev_priv; +} + struct apu_drm *apu_dev_alloc(struct device *dev); int apu_dev_register(struct apu_drm *apu); void apu_dev_unregister(struct apu_drm *apu); @@ -65,4 +84,15 @@ int apu_core_register(struct device *dev, struct apu_core *core, void *priv); void apu_core_remove(struct apu_core *core); struct apu_core *apu_find_core_by_priv(void *priv); +struct apu_gem_object *to_apu_bo(struct drm_gem_object *obj); +struct drm_gem_object *apu_gem_create_object(struct drm_device *dev, + size_t size); + +int ioctl_gem_new(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_gem_user_new(struct drm_device *dev, void *data, + struct drm_file *file_priv); +struct dma_buf *apu_gem_prime_export(struct drm_gem_object *gem, + int flags); + #endif /* __APU_INTERNAL_H__ */ diff --git a/include/uapi/drm/apu_drm.h b/include/uapi/drm/apu_drm.h index d50c63d1b813..14fc478f45dc 100644 --- a/include/uapi/drm/apu_drm.h +++ b/include/uapi/drm/apu_drm.h @@ -9,6 +9,18 @@ extern "C" { #endif +/* + * Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + */ + +struct drm_apu_gem_new { + __u32 size; /* in */ + __u32 flags; /* in */ + __u32 handle; /* out */ + __u64 offset; /* out */ +}; + #define APU_ONLINE BIT(0) struct drm_apu_state { @@ -17,9 +29,11 @@ struct drm_apu_state { }; #define DRM_APU_STATE 0x00 -#define DRM_APU_NUM_IOCTLS 0x01 +#define DRM_APU_GEM_NEW 0x01 +#define DRM_APU_NUM_IOCTLS 0x02 #define DRM_IOCTL_APU_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_STATE, struct drm_apu_state) +#define DRM_IOCTL_APU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_NEW, struct drm_apu_gem_new) #if defined(__cplusplus) } From patchwork Wed May 17 14:52:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 13245211 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 80A7DC77B7F for ; Wed, 17 May 2023 15:40:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Nr7mrK+6tSYd8YQg8OUgoKT303dzmLPmQg+9F+7XGpw=; b=0Yap2e4xkB5Y4ETMWOFTlXop3t 8IOZS5XfSEgoo7TmRQOOTOflql+9um8gGOD0Q35etM9BixHX+O99Ai7PC4VSfrecCyG5FEXoE5EFQ 6ulW0eUceP/grkYxfz3GBmCs5hJEfQsQHmY68NXGCIDO9Pr2702LnctTk9cQyrJopY6fWHak3gQsh aaVSBx+pblnAzPujzPzhI7WAfP/i4GQAFTHVif+JD9ssnmJn4vIAMwSQBffW3Ko1yp7+auNvVQesA a/c6emJubzYHvbeYNZdF43R4Or53zfrW14bSDs+a30fM3g2qBafHe1SgIA8p9pu05jk602Pze8Xe8 oIEdsNKg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1pzJGR-00AKOd-0D; Wed, 17 May 2023 15:40:31 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzJGK-00AKKx-1r for linux-mediatek@bombadil.infradead.org; Wed, 17 May 2023 15:40:24 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:MIME-Version :References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=Nr7mrK+6tSYd8YQg8OUgoKT303dzmLPmQg+9F+7XGpw=; b=JKZ85+JQph1FFrUjVwZlfGbTAb +YeSY41ddjFJPCQ/prQXSv8/0uaM7laKFnj2bVJKidP+dVOZ3ap9hqbgIdZSaEWsj6jl74eRVpCVP /82n3OcLUpdeznhYYjw7oVUWqQP4UmiRg2Rvg/rUDJTGPwAUoePxAmH0XCJktm3R1uqdOaMHL1KjU JmRNqsU/HHdVjsUTkhorqsU2KWxcr7qbDQlzMZrWGQV5zDs8TwjPhvt5BbWSknsrGJbxPp0NuSeRV QLm5kHhCKkE43kZEIanx9NxlFySG3STHpnpaJ7BrJauSLGgoL4vKbyFK/78iWyyHG2KyvnMmJwEQG 8LSc808w==; Received: from mail-wr1-x436.google.com ([2a00:1450:4864:20::436]) by desiato.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzIWH-00DFhu-1v for linux-mediatek@lists.infradead.org; Wed, 17 May 2023 14:52:52 +0000 Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-309438004a6so451862f8f.2 for ; Wed, 17 May 2023 07:52:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20221208.gappssmtp.com; s=20221208; t=1684335167; x=1686927167; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Nr7mrK+6tSYd8YQg8OUgoKT303dzmLPmQg+9F+7XGpw=; b=LzLDbCdcTBYtSEhd2l/0x+6iblcvk8LvzFbXOer3dStbScQfSb3AuwfX9ADL5SfoVx pNwu/FyIyTdKo5Y/nGSeJ6oIMO5SVb1fwjeTOz7WZH7dpFqcevDNsr7DO9F0ajlqtStV aOiDluo/V3mcJ3O294/tKHQOT4ksz4xkkM/+40IC0+wdldzn4e4TakwirwGaglzuMJiH wMd3cAteZqah/0CaQfSmGjvXbQgTga3WVxjUS4VtghXDsNIJWLb1azMix3Y5R9g/eaFv 2TqANN3iwPyqD7KktB4CknbHn25Gr+kQga/PRZkcemKLIZQJCn1YNt7smLzS4EeDy8IK E9dQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684335167; x=1686927167; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Nr7mrK+6tSYd8YQg8OUgoKT303dzmLPmQg+9F+7XGpw=; b=dA3CsZPvcpgePRaf4qQdEqDle3a2MOFAU1RcH2zhGHJ31/2SfXHb3IPC8hMDfjYUpp nC3WMIJb3rKh6Cs+MtfXDTQ6a1wQRbnZ3EqH4RxhRNtxe81I5emjkLOooIUQj5+7GVz6 QccWiDYbWBvz/tPJvkRRH4coH+SSXbh+TQL0ZNDQvTVGbW7WbNFK2V3yX39M2gc7RjVR DHdWC5EYaaFpxubi3q0dtGiV5TmUg1/rKVvWS07TcUqrfL4GNsuyYXWKYHTNtgNxzhUu fxo5SPsxSBel7Yj+FfiDmCGUL0obKIl1sZRORze/QaRQEaM8mrIDSvjt35PCsOuoYB1K LRVQ== X-Gm-Message-State: AC+VfDwY7PP33dP2bjyf819AlCF/2OWvNN7wGmmOYOaalqoheTqYyh/d 7S6dTSVAHQc1vj07DXILdlWecg== X-Google-Smtp-Source: ACHHUZ6E9PDxwNASjWneyPfqsNbUMzas8Fc4Vnk/HvhbHQcmj7121Shzz9bplamcC/BeRNWcybflUw== X-Received: by 2002:a5d:63c3:0:b0:306:321c:995b with SMTP id c3-20020a5d63c3000000b00306321c995bmr966382wrw.41.1684335167157; Wed, 17 May 2023 07:52:47 -0700 (PDT) Received: from blaptop.baylibre (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id v11-20020a5d678b000000b002f7780eee10sm2979098wru.59.2023.05.17.07.52.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 May 2023 07:52:46 -0700 (PDT) From: Alexandre Bailon To: airlied@gmail.com, daniel@ffwll.ch, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, sumit.semwal@linaro.org, christian.koenig@amd.com, jstephan@baylibre.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, nbelin@baylibre.com, bero@baylibre.com, Alexandre Bailon Subject: [PATCH 3/7] drm/apu: Add support of requests Date: Wed, 17 May 2023 16:52:33 +0200 Message-Id: <20230517145237.295461-4-abailon@baylibre.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230517145237.295461-1-abailon@baylibre.com> References: <20230517145237.295461-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230517_155250_001066_188383CB X-CRM114-Status: GOOD ( 30.11 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org This updates the APU driver to with two new ioctls to queue and dequeue requests. This uses DRM scheduler to manage the requests. The requests allocation and send and receive operations are platform specifics and must be implemented as callback. Signed-off-by: Alexandre Bailon Reviewed-by: Julien Stephan --- drivers/gpu/drm/apu/Kconfig | 1 + drivers/gpu/drm/apu/Makefile | 1 + drivers/gpu/drm/apu/apu_drv.c | 52 +-- drivers/gpu/drm/apu/apu_internal.h | 93 ++++- drivers/gpu/drm/apu/apu_sched.c | 564 +++++++++++++++++++++++++++++ include/uapi/drm/apu_drm.h | 31 +- 6 files changed, 697 insertions(+), 45 deletions(-) create mode 100644 drivers/gpu/drm/apu/apu_sched.c diff --git a/drivers/gpu/drm/apu/Kconfig b/drivers/gpu/drm/apu/Kconfig index 226dcf072115..a769df42091c 100644 --- a/drivers/gpu/drm/apu/Kconfig +++ b/drivers/gpu/drm/apu/Kconfig @@ -5,6 +5,7 @@ config DRM_APU tristate "APU (AI Processor Unit)" select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER + select DRM_SCHED help This provides a DRM driver that provides some facilities to communicate with an AI Processor Unit (APU). diff --git a/drivers/gpu/drm/apu/Makefile b/drivers/gpu/drm/apu/Makefile index 91894250d4c1..fc8d6380fc38 100644 --- a/drivers/gpu/drm/apu/Makefile +++ b/drivers/gpu/drm/apu/Makefile @@ -2,5 +2,6 @@ drm_apu-y += apu_drv.o drm_apu-y += apu_gem.o +drm_apu-y += apu_sched.o obj-$(CONFIG_DRM_APU) += drm_apu.o diff --git a/drivers/gpu/drm/apu/apu_drv.c b/drivers/gpu/drm/apu/apu_drv.c index 323e267b0f53..b6bd340b2bc8 100644 --- a/drivers/gpu/drm/apu/apu_drv.c +++ b/drivers/gpu/drm/apu/apu_drv.c @@ -14,14 +14,15 @@ static LIST_HEAD(apu_devices); -static int ioctl_apu_state(struct drm_device *dev, void *data, - struct drm_file *file_priv); - static const struct drm_ioctl_desc ioctls[] = { DRM_IOCTL_DEF_DRV(APU_STATE, ioctl_apu_state, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(APU_GEM_NEW, ioctl_gem_new, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_GEM_QUEUE, ioctl_gem_queue, + DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_GEM_DEQUEUE, ioctl_gem_dequeue, + DRM_RENDER_ALLOW), }; DEFINE_DRM_GEM_DMA_FOPS(apu_drm_ops); @@ -134,7 +135,8 @@ struct apu_core *apu_core_alloc(struct apu_drm *apu, struct apu_core_ops *ops, { struct apu_core *core; - if (!ops || !ops->is_ready) + if (!ops || !ops->alloc_prepare_request || !ops->send_request + || !ops->handle_request || !ops->is_ready) return NULL; core = devm_kzalloc(apu->dev, sizeof(*core), GFP_KERNEL); @@ -148,6 +150,8 @@ struct apu_core *apu_core_alloc(struct apu_drm *apu, struct apu_core_ops *ops, core->apu = apu; core->priv = priv; core->ops = ops; + spin_lock_init(&core->ctx_lock); + INIT_LIST_HEAD(&core->requests); list_add(&core->node, &apu->cores); @@ -192,7 +196,7 @@ int apu_core_register(struct device *dev, struct apu_core *core, void *priv) return ret; } - return 0; + return apu_drm_job_init(core); } EXPORT_SYMBOL_GPL(apu_core_register); @@ -203,6 +207,7 @@ EXPORT_SYMBOL_GPL(apu_core_register); */ void apu_core_remove(struct apu_core *core) { + apu_sched_fini(core); core->dev_priv = NULL; } EXPORT_SYMBOL_GPL(apu_core_remove); @@ -233,42 +238,5 @@ struct apu_core *apu_find_core_by_priv(void *priv) } EXPORT_SYMBOL_GPL(apu_find_core_by_priv); -static struct apu_core *get_apu_core(struct apu_drm *apu, int device_id) -{ - struct apu_core *core; - - list_for_each_entry(core, &apu->cores, node) { - if (core->device_id == device_id) - return core; - } - - return NULL; -} - -static void apu_core_update_state(struct apu_core *core) -{ - if (!core->ops->is_ready(core)) - core->flags &= ~APU_ONLINE; -} - -static int ioctl_apu_state(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct apu_drm *apu = dev->dev_private; - struct drm_apu_state *args = data; - struct apu_core *core; - - args->flags = 0; - - core = get_apu_core(apu, args->device); - if (!core) - return -ENODEV; - - apu_core_update_state(core); - args->flags |= core->flags; - - return 0; -} - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alexandre Bailon"); diff --git a/drivers/gpu/drm/apu/apu_internal.h b/drivers/gpu/drm/apu/apu_internal.h index 203aadc58b72..021a3efdedf2 100644 --- a/drivers/gpu/drm/apu/apu_internal.h +++ b/drivers/gpu/drm/apu/apu_internal.h @@ -4,6 +4,7 @@ #include #include +#include struct apu_gem_object { struct drm_gem_dma_object base; @@ -12,16 +13,21 @@ struct apu_gem_object { u32 offset; }; +struct apu_sched; struct apu_core { int device_id; struct device *dev; struct apu_core_ops *ops; struct apu_drm *apu; + spinlock_t ctx_lock; + struct list_head requests; + struct list_head node; void *priv; void *dev_priv; + struct apu_sched *sched; u32 flags; }; @@ -35,6 +41,43 @@ struct apu_drm { struct ida ida; }; +struct apu_job { + struct drm_sched_job base; + + struct kref refcount; + + struct apu_core *core; + struct apu_drm *apu; + + /* Fence to be signaled by IRQ handler when the job is complete. */ + struct dma_fence *done_fence; + + __u32 cmd; + + /* Exclusive fences we have taken from the BOs to wait for */ + struct dma_fence **implicit_fences; + struct drm_gem_object **bos; + u32 bo_count; + + /* Fence to be signaled by drm-sched once its done with the job */ + struct dma_fence *render_done_fence; + + void *data_in; + uint16_t size_in; + void *data_out; + uint16_t size_out; + uint16_t result; + uint16_t id; + + struct list_head node; + struct drm_syncobj *sync_out; + + struct apu_event *event; + + void *request_data; + int request_len; +}; + /** * @apu_core_ops: Provides platform specific callbacks */ @@ -46,6 +89,40 @@ struct apu_core_ops { */ int (*register_core)(struct apu_core *core); + /** + * @alloc_prepare_request: + * + * Allocate and initialize the data to be sent to the APU. + * Basically, this must convert the job object to something + * that could be understand by the hardware accelerator. + * + * Returns: + * + * Zero on success, non-zero value on failure. + */ + int (*alloc_prepare_request)(struct apu_job *job); + + /** + * @send_data: + * + * Implements platform specific code to send the data previously + * allocated using @alloc_data. + * + * Returns: + * + * Zero on success, non-zero value on failure. + */ + int (*send_request)(struct apu_job *job); + + /** + * @handle_request: + * + * Implements platform specific code to handle incoming request. + * This must decode the data encoded using platform specific format + * and convert it to generic format. + */ + int (*handle_request)(struct apu_job *job, void *data, int len); + /** * @is_ready: * @@ -68,9 +145,9 @@ static inline struct apu_gem_object *to_apu_bo(struct drm_gem_object *obj) base); } -static inline void *apu_drm_priv(struct apu_core *apu_core) +static inline void *apu_drm_priv(struct apu_core *core) { - return apu_core->dev_priv; + return core->dev_priv; } struct apu_drm *apu_dev_alloc(struct device *dev); @@ -94,5 +171,17 @@ int ioctl_gem_user_new(struct drm_device *dev, void *data, struct drm_file *file_priv); struct dma_buf *apu_gem_prime_export(struct drm_gem_object *gem, int flags); +int ioctl_gem_queue(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_gem_dequeue(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_apu_state(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int apu_drm_callback(struct apu_core *core, uint16_t job_id, void *data, int len); + +struct apu_job; + +int apu_drm_job_init(struct apu_core *core); +void apu_sched_fini(struct apu_core *core); #endif /* __APU_INTERNAL_H__ */ diff --git a/drivers/gpu/drm/apu/apu_sched.c b/drivers/gpu/drm/apu/apu_sched.c new file mode 100644 index 000000000000..13b6fbd00bd8 --- /dev/null +++ b/drivers/gpu/drm/apu/apu_sched.c @@ -0,0 +1,564 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2020 BayLibre SAS + +#include +#include +#include + +#include "apu_internal.h" + +struct apu_queue_state { + struct drm_gpu_scheduler sched; + u64 fence_context; + u64 seqno; +}; + +struct apu_request { + struct list_head node; + struct apu_job *job; +}; + +struct apu_sched { + struct apu_queue_state apu_queue; + spinlock_t job_lock; + struct drm_sched_entity sched_entity; +}; + +struct apu_event { + struct drm_pending_event pending_event; + union { + struct drm_event base; + struct apu_job_event job_event; + }; +}; + +static DEFINE_IDA(req_ida); +static LIST_HEAD(complete_node); + +static void apu_core_update_state(struct apu_core *core) +{ + if (!core->ops->is_ready(core)) + core->flags &= ~APU_ONLINE; +} + +static int apu_core_is_running(struct apu_core *core) +{ + apu_core_update_state(core); + + return core->flags & APU_ONLINE; +} + +static void apu_set_online(struct apu_core *core) +{ + core->flags |= APU_ONLINE; +} + +static void apu_set_offline(struct apu_core *core) +{ + core->flags &= ~APU_ONLINE; +} + +/* + * apu_drm_callback() - Handle the data coming from accelerator + * + * @core: The pointer to the APU core + * @job_id: The job id + * @data: The data coming from the accelerator + * @len: The size of the data + * + * Returns: Zero on success, non-zero value on failure. + */ +int apu_drm_callback(struct apu_core *core, uint16_t job_id, void *data, int len) +{ + struct apu_request *apu_req, *tmp; + unsigned long flags; + int ret = -EINVAL; + + spin_lock_irqsave(&core->ctx_lock, flags); + list_for_each_entry_safe(apu_req, tmp, &core->requests, node) { + struct apu_job *job = apu_req->job; + + if (job && job_id == job->id) { + kref_get(&job->refcount); + ret = core->ops->handle_request(job, data, len); + list_add(&job->node, &complete_node); + list_del(&apu_req->node); + ida_simple_remove(&req_ida, job->id); + kfree(apu_req); + drm_send_event(&job->apu->base, + &job->event->pending_event); + dma_fence_signal_locked(job->done_fence); + break; + } + } + spin_unlock_irqrestore(&core->ctx_lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(apu_drm_callback); + +static void apu_job_cleanup(struct kref *ref) +{ + struct apu_job *job = container_of(ref, struct apu_job, + refcount); + unsigned int i; + + if (job->implicit_fences) { + for (i = 0; i < job->bo_count; i++) + dma_fence_put(job->implicit_fences[i]); + kvfree(job->implicit_fences); + } + dma_fence_put(job->done_fence); + dma_fence_put(job->render_done_fence); + + if (job->bos) { + for (i = 0; i < job->bo_count; i++) { + struct apu_gem_object *apu_obj; + + apu_obj = to_apu_bo(job->bos[i]); + drm_gem_object_put(job->bos[i]); + } + + kvfree(job->bos); + } + + kfree(job->data_out); + kfree(job->data_in); + kfree(job); +} + +static void apu_job_put(struct apu_job *job) +{ + kref_put(&job->refcount, apu_job_cleanup); +} + +static void apu_acquire_object_fences(struct drm_gem_object **bos, + int bo_count, + struct dma_fence **implicit_fences) +{ + int i; + + for (i = 0; i < bo_count; i++) + dma_resv_get_singleton(bos[i]->resv, DMA_RESV_USAGE_KERNEL, + &implicit_fences[i]); +} + +static void apu_attach_object_fences(struct drm_gem_object **bos, + int bo_count, struct dma_fence *fence) +{ + int i; + + for (i = 0; i < bo_count; i++) { + dma_resv_reserve_fences(bos[i]->resv, 1); + dma_resv_add_fence(bos[i]->resv, fence, DMA_RESV_USAGE_KERNEL); + } +} + +static int apu_job_push(struct apu_job *job) +{ + struct drm_sched_entity *entity = &job->core->sched->sched_entity; + struct ww_acquire_ctx acquire_ctx; + int ret = 0; + int i; + + ret = drm_gem_lock_reservations(job->bos, job->bo_count, &acquire_ctx); + if (ret) + return ret; + + ret = drm_sched_job_init(&job->base, entity, NULL); + if (ret) + goto unlock; + + drm_sched_job_arm(&job->base); + job->render_done_fence = dma_fence_get(&job->base.s_fence->finished); + + kref_get(&job->refcount); /* put by scheduler job completion */ + apu_acquire_object_fences(job->bos, job->bo_count, + job->implicit_fences); + + drm_sched_entity_push_job(&job->base); + + apu_attach_object_fences(job->bos, job->bo_count, + job->render_done_fence); + + for (i = 0; i < job->bo_count; i++) + ret = drm_sched_job_add_implicit_dependencies(&job->base, job->bos[i], + true); +unlock: + drm_gem_unlock_reservations(job->bos, job->bo_count, &acquire_ctx); + + return ret; +} + +static const char *apu_fence_get_driver_name(struct dma_fence *fence) +{ + return "apu"; +} + +static const char *apu_fence_get_timeline_name(struct dma_fence *fence) +{ + return "apu-0"; +} + +static void apu_fence_release(struct dma_fence *f) +{ + kfree(f); +} + +static const struct dma_fence_ops apu_fence_ops = { + .get_driver_name = apu_fence_get_driver_name, + .get_timeline_name = apu_fence_get_timeline_name, + .release = apu_fence_release, +}; + +static struct dma_fence *apu_fence_create(struct apu_sched *sched) +{ + struct dma_fence *fence; + struct apu_queue_state *apu_queue = &sched->apu_queue; + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) + return ERR_PTR(-ENOMEM); + + dma_fence_init(fence, &apu_fence_ops, &sched->job_lock, + apu_queue->fence_context, apu_queue->seqno++); + + return fence; +} + +static struct apu_job *to_apu_job(struct drm_sched_job *sched_job) +{ + return container_of(sched_job, struct apu_job, base); +} + +static int apu_job_hw_submit(struct apu_job *job) +{ + int ret; + struct apu_core *core = job->core; + struct apu_request *apu_req; + unsigned long flags; + + ret = ida_simple_get(&req_ida, 0, 0xffff, GFP_KERNEL); + if (ret < 0) + return ret; + job->id = ret; + + ret = core->ops->alloc_prepare_request(job); + if (ret || !job->request_data || !job->request_len) { + ret = -ENOMEM; + goto err_ida_remove; + } + + apu_req = kzalloc(sizeof(*apu_req), GFP_KERNEL); + if (!apu_req) { + ret = -ENOMEM; + goto err_free_data; + } + + apu_req->job = job; + spin_lock_irqsave(&core->ctx_lock, flags); + list_add(&apu_req->node, &core->requests); + spin_unlock_irqrestore(&core->ctx_lock, flags); + ret = core->ops->send_request(job); + if (ret < 0) + goto err; + kfree(job->request_data); + + return 0; + +err: + list_del(&apu_req->node); + kfree(apu_req); +err_free_data: + kfree(job->request_data); +err_ida_remove: + ida_simple_remove(&req_ida, job->id); + + return ret; +} + +static struct dma_fence *apu_job_run(struct drm_sched_job *sched_job) +{ + struct apu_job *job = to_apu_job(sched_job); + struct dma_fence *fence = NULL; + + if (unlikely(job->base.s_fence->finished.error)) + return NULL; + + fence = apu_fence_create(job->core->sched); + if (IS_ERR(fence)) + return NULL; + + job->done_fence = dma_fence_get(fence); + + apu_job_hw_submit(job); + + return fence; +} + +static enum drm_gpu_sched_stat apu_job_timedout(struct drm_sched_job *sched_job) +{ + struct apu_request *apu_req, *tmp; + struct apu_job *job = to_apu_job(sched_job); + + if (dma_fence_is_signaled(job->done_fence)) + return DRM_GPU_SCHED_STAT_NOMINAL; + + list_for_each_entry_safe(apu_req, tmp, &job->core->requests, node) { + /* Remove the request and notify user about timeout */ + if (apu_req->job == job) { + kref_get(&job->refcount); + job->result = ETIMEDOUT; + list_add(&job->node, &complete_node); + list_del(&apu_req->node); + ida_simple_remove(&req_ida, job->id); + kfree(apu_req); + drm_send_event(&job->apu->base, + &job->event->pending_event); + dma_fence_signal_locked(job->done_fence); + } + } + + return DRM_GPU_SCHED_STAT_NOMINAL; +} + +static void apu_job_free(struct drm_sched_job *sched_job) +{ + struct apu_job *job = to_apu_job(sched_job); + + drm_sched_job_cleanup(sched_job); + + apu_job_put(job); +} + +static const struct drm_sched_backend_ops apu_sched_ops = { + .run_job = apu_job_run, + .timedout_job = apu_job_timedout, + .free_job = apu_job_free +}; + +int apu_drm_job_init(struct apu_core *core) +{ + int ret; + struct apu_sched *apu_sched; + struct drm_gpu_scheduler *sched; + + apu_sched = devm_kzalloc(core->dev, sizeof(*apu_sched), GFP_KERNEL); + if (!apu_sched) + return -ENOMEM; + + sched = &apu_sched->apu_queue.sched; + apu_sched->apu_queue.fence_context = dma_fence_context_alloc(1); + ret = drm_sched_init(sched, &apu_sched_ops, + 1, 0, msecs_to_jiffies(500), + NULL, NULL, "apu_js", core->dev); + if (ret) { + dev_err(core->dev, "Failed to create scheduler"); + return ret; + } + + ret = drm_sched_entity_init(&apu_sched->sched_entity, + DRM_SCHED_PRIORITY_NORMAL, + &sched, 1, NULL); + if (ret) { + dev_err(core->dev, "Failed to initialize scheduler entity"); + drm_sched_fini(&core->sched->apu_queue.sched); + return ret; + } + + core->sched = apu_sched; + apu_set_online(core); + + return 0; +} + +void apu_sched_fini(struct apu_core *core) +{ + apu_set_offline(core); + drm_sched_fini(&core->sched->apu_queue.sched); + devm_kfree(core->dev, core->sched); + core->sched = NULL; +} + +static struct apu_core *get_apu_core(struct apu_drm *apu, int device_id) +{ + struct apu_core *core; + + list_for_each_entry(core, &apu->cores, node) { + if (core->device_id == device_id) + return core; + } + + return NULL; +} + +static int apu_lookup_bos(struct drm_device *dev, struct drm_file *file_priv, + struct drm_apu_gem_queue *args, struct apu_job *job) +{ + void __user *bo_handles; + int ret; + + job->bo_count = args->bo_handle_count; + + if (!job->bo_count) + return 0; + + job->implicit_fences = kvmalloc_array(job->bo_count, + sizeof(struct dma_fence *), + GFP_KERNEL | __GFP_ZERO); + if (!job->implicit_fences) + return -ENOMEM; + + bo_handles = (void __user *)(uintptr_t) args->bo_handles; + ret = drm_gem_objects_lookup(file_priv, bo_handles, + job->bo_count, &job->bos); + + return ret; +} + +int ioctl_gem_queue(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct apu_drm *apu = dev->dev_private; + struct drm_apu_gem_queue *args = data; + struct apu_event *event; + struct apu_core *core; + struct drm_syncobj *sync_out = NULL; + struct apu_job *job; + int ret = 0; + + core = get_apu_core(apu, args->device); + if (!apu_core_is_running(core)) + return -ENODEV; + + if (args->out_sync > 0) { + sync_out = drm_syncobj_find(file_priv, args->out_sync); + if (!sync_out) + return -ENODEV; + } + + job = kzalloc(sizeof(*job), GFP_KERNEL); + if (!job) { + ret = -ENOMEM; + goto fail_out_sync; + } + + kref_init(&job->refcount); + + job->apu = apu; + job->core = core; + job->cmd = args->cmd; + job->size_in = args->size_in; + job->size_out = args->size_out; + job->sync_out = sync_out; + if (job->size_in) { + job->data_in = kmalloc(job->size_in, GFP_KERNEL); + if (!job->data_in) { + ret = -ENOMEM; + goto fail_job; + } + + ret = + copy_from_user(job->data_in, + (void __user *)(uintptr_t) args->data, + job->size_in); + if (ret) + goto fail_job; + } + + if (job->size_out) { + job->data_out = kmalloc(job->size_out, GFP_KERNEL); + if (!job->data_out) { + ret = -ENOMEM; + goto fail_job; + } + } + + ret = apu_lookup_bos(dev, file_priv, args, job); + if (ret) + goto fail_job; + + event = kzalloc(sizeof(*event), GFP_KERNEL); + event->base.length = sizeof(struct apu_job_event); + event->base.type = APU_JOB_COMPLETED; + event->job_event.out_sync = args->out_sync; + job->event = event; + ret = drm_event_reserve_init(dev, file_priv, &job->event->pending_event, + &job->event->base); + if (ret) + goto fail_job; + + ret = apu_job_push(job); + if (ret) { + drm_event_cancel_free(dev, &job->event->pending_event); + goto fail_job; + } + + if (sync_out) + drm_syncobj_replace_fence(sync_out, job->render_done_fence); + +fail_job: + apu_job_put(job); +fail_out_sync: + if (sync_out) + drm_syncobj_put(sync_out); + + return ret; +} + +int ioctl_gem_dequeue(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_apu_gem_dequeue *args = data; + struct drm_syncobj *sync_out = NULL; + struct apu_job *job; + int ret = 0; + + if (args->out_sync > 0) { + sync_out = drm_syncobj_find(file_priv, args->out_sync); + if (!sync_out) + return -ENODEV; + } + + list_for_each_entry(job, &complete_node, node) { + if (job->sync_out == sync_out) { + if (job->data_out) { + ret = copy_to_user((void __user *)(uintptr_t) + args->data, job->data_out, + job->size_out); + args->size = job->size_out; + } + args->result = job->result; + list_del(&job->node); + apu_job_put(job); + drm_syncobj_put(sync_out); + + return ret; + } + } + + if (sync_out) + drm_syncobj_put(sync_out); + + return 0; +} + +int ioctl_apu_state(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct apu_drm *apu = dev->dev_private; + struct drm_apu_state *args = data; + struct apu_core *core; + + args->flags = 0; + + core = get_apu_core(apu, args->device); + if (!core) + return -ENODEV; + + apu_core_update_state(core); + args->flags |= core->flags; + + return 0; +} diff --git a/include/uapi/drm/apu_drm.h b/include/uapi/drm/apu_drm.h index 14fc478f45dc..c47000097040 100644 --- a/include/uapi/drm/apu_drm.h +++ b/include/uapi/drm/apu_drm.h @@ -9,6 +9,8 @@ extern "C" { #endif +#define APU_JOB_COMPLETED 0x80000000 + /* * Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints. @@ -21,6 +23,29 @@ struct drm_apu_gem_new { __u64 offset; /* out */ }; +struct drm_apu_gem_queue { + __u32 device; + __u32 cmd; + __u32 out_sync; + __u64 bo_handles; + __u32 bo_handle_count; + __u16 size_in; + __u16 size_out; + __u64 data; +}; + +struct drm_apu_gem_dequeue { + __u32 out_sync; + __u16 result; + __u16 size; + __u64 data; +}; + +struct apu_job_event { + struct drm_event base; + __u32 out_sync; +}; + #define APU_ONLINE BIT(0) struct drm_apu_state { @@ -30,10 +55,14 @@ struct drm_apu_state { #define DRM_APU_STATE 0x00 #define DRM_APU_GEM_NEW 0x01 -#define DRM_APU_NUM_IOCTLS 0x02 +#define DRM_APU_GEM_QUEUE 0x02 +#define DRM_APU_GEM_DEQUEUE 0x03 +#define DRM_APU_NUM_IOCTLS 0x04 #define DRM_IOCTL_APU_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_STATE, struct drm_apu_state) #define DRM_IOCTL_APU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_NEW, struct drm_apu_gem_new) +#define DRM_IOCTL_APU_GEM_QUEUE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_QUEUE, struct drm_apu_gem_queue) +#define DRM_IOCTL_APU_GEM_DEQUEUE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_DEQUEUE, struct drm_apu_gem_dequeue) #if defined(__cplusplus) } From patchwork Wed May 17 14:52:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 13245263 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 B8EEAC7EE23 for ; Wed, 17 May 2023 16:00:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=UI38mzNCyvFGBkMAaNja4Azr5yleuYJIUin5avWU87w=; b=iZpEIRHG+diw2i9Ks74tVqH70u FQ7oUZY6vyyAv48r3jp+AaZ3kJs5D4xv0p5nq7o7vdsxhePZiPuA/LvjBnGQthQlMyD5/62v7YOPX crHokaVEH5qt86kf+ciW57fwIZYKJeGIp2Ob5WhjN3Sg1h4dz/k9UHc/Gmz8/3TZriyB1mMDCkcaZ mm/xz60Djs1uJA1q/PzHtkH91tBolcqglxZ717yCuUdTbo+ewOGgwu3tda4B+sDTamcH1IWauI1Hx cZXD/aNpSqx3WTBsBIycWTu+RBc1IR6zD04RNxgIB/ncmli3N25RdYhZbKXXx8PpLnq9ssHCNy/X+ KkNRSayw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1pzJZv-00AONU-31; Wed, 17 May 2023 16:00:39 +0000 Received: from mail-wr1-f42.google.com ([209.85.221.42]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzIWK-00ACCE-06 for linux-mediatek@lists.infradead.org; Wed, 17 May 2023 14:52:54 +0000 Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-3075e802738so862144f8f.1 for ; Wed, 17 May 2023 07:52:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20221208.gappssmtp.com; s=20221208; t=1684335168; x=1686927168; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UI38mzNCyvFGBkMAaNja4Azr5yleuYJIUin5avWU87w=; b=e74ivfotYAEvNLXSoqnCbQRc9OZxuaMFcKWG98sXJkM1UYMEbrDC+fZ+yf/fBn7rWm 7ZYq7pQyTY46To9Zy5Gvb3oSYZgv43cFQK23EdYNBEGiu0IwRUA/KSJ5ZxzOuJhpJq6L dTfLgSxLneb3v3GTWEqwfHYNIayKYpbczq4o9fhjIOCxCPWTd1A60a8PV5jCEn9IwF7w +nIpOmYu0OqA2D2yHnf96kTARb3U30oW1njUkybx3o7uPyGk5bB6XbSTklwWpKCZsw14 1hoU/E7mUYlbHWHjFFg94PJWraslcL1xCGN0eriq/kUM0mbzrRfeGpr3EwnQgd98LUXG xW5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684335168; x=1686927168; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UI38mzNCyvFGBkMAaNja4Azr5yleuYJIUin5avWU87w=; b=RJ/E32/vWEgGObLwWFu2dPur9pNrnD1b0Kd5yZ3Dxf+9ADE56XgkuEc4UbDI4hxBJ3 FQq1sAcWz0QEctjnFOv7lnOvsQqlcJx1z86ouwjunjYSe4TPS6QWTnQjhQTfyXVj0e7D 1APYg8MMxxYEmrUhmq0qzByAEDbJGy2NCZCE4BM+kzJRFdTrY2ts0fvqzGWFCBrWA6iP c6SyA+c5FZL8jJVL/QSQVglTW0KUfYWjtjVz2CxzasyqdoID6OvKRR90vu1Zyxqm41WK oi0DJ2v02AN3p8zOtBUqzKn2XsB44Ku/p99GoYMYRzyk2rtcUztE+WkwYzbkO2weY9hQ QorA== X-Gm-Message-State: AC+VfDzdNELO5iCXm8Fz0Kssv8ypOe2KT03CBa67v/Aj3qFZ+okxF1yC Ysap6tIUvBzbrCvMZsEZuF0DXg== X-Google-Smtp-Source: ACHHUZ56bam5aYUqhbaIruRepK3WLO/dsctJUOsMK7UcXWOFFicMDzFlyXEYrjPGZ6kWWPArtbYqIQ== X-Received: by 2002:adf:f4d0:0:b0:307:873d:2ea with SMTP id h16-20020adff4d0000000b00307873d02eamr929458wrp.47.1684335168300; Wed, 17 May 2023 07:52:48 -0700 (PDT) Received: from blaptop.baylibre (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id v11-20020a5d678b000000b002f7780eee10sm2979098wru.59.2023.05.17.07.52.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 May 2023 07:52:48 -0700 (PDT) From: Alexandre Bailon To: airlied@gmail.com, daniel@ffwll.ch, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, sumit.semwal@linaro.org, christian.koenig@amd.com, jstephan@baylibre.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, nbelin@baylibre.com, bero@baylibre.com, Alexandre Bailon Subject: [PATCH 4/7] drm/apu: Add support of IOMMU Date: Wed, 17 May 2023 16:52:34 +0200 Message-Id: <20230517145237.295461-5-abailon@baylibre.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230517145237.295461-1-abailon@baylibre.com> References: <20230517145237.295461-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230517_075252_127300_BEEC3B1D X-CRM114-Status: GOOD ( 22.02 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Some APU devices are behind an IOMMU. For some of these devices, we can't use DMA API because they use static addresses so we have to manually use IOMMU API to correctly map the buffers. This adds support of IOMMU. Signed-off-by: Alexandre Bailon Reviewed-by: Julien Stephan --- drivers/gpu/drm/apu/apu_drv.c | 4 + drivers/gpu/drm/apu/apu_gem.c | 174 +++++++++++++++++++++++++++++ drivers/gpu/drm/apu/apu_internal.h | 16 +++ drivers/gpu/drm/apu/apu_sched.c | 28 +++++ include/uapi/drm/apu_drm.h | 12 +- 5 files changed, 233 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/apu/apu_drv.c b/drivers/gpu/drm/apu/apu_drv.c index b6bd340b2bc8..a0dce785a02a 100644 --- a/drivers/gpu/drm/apu/apu_drv.c +++ b/drivers/gpu/drm/apu/apu_drv.c @@ -23,6 +23,10 @@ static const struct drm_ioctl_desc ioctls[] = { DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(APU_GEM_DEQUEUE, ioctl_gem_dequeue, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_GEM_IOMMU_MAP, ioctl_gem_iommu_map, + DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_GEM_IOMMU_UNMAP, ioctl_gem_iommu_unmap, + DRM_RENDER_ALLOW), }; DEFINE_DRM_GEM_DMA_FOPS(apu_drm_ops); diff --git a/drivers/gpu/drm/apu/apu_gem.c b/drivers/gpu/drm/apu/apu_gem.c index 0e7b3b27942c..0a91363754c5 100644 --- a/drivers/gpu/drm/apu/apu_gem.c +++ b/drivers/gpu/drm/apu/apu_gem.c @@ -2,6 +2,9 @@ // // Copyright 2020 BayLibre SAS +#include +#include + #include #include @@ -42,6 +45,7 @@ int ioctl_gem_new(struct drm_device *dev, void *data, */ apu_obj->size = args->size; apu_obj->offset = 0; + apu_obj->iommu_refcount = 0; mutex_init(&apu_obj->mutex); ret = drm_gem_handle_create(file_priv, gem_obj, &args->handle); @@ -54,3 +58,173 @@ int ioctl_gem_new(struct drm_device *dev, void *data, return 0; } + +void apu_bo_iommu_unmap(struct apu_drm *apu_drm, struct apu_gem_object *obj) +{ + int iova_pfn; + int i; + + if (!obj->iommu_sgt) + return; + + mutex_lock(&obj->mutex); + obj->iommu_refcount--; + if (obj->iommu_refcount) { + mutex_unlock(&obj->mutex); + return; + } + + iova_pfn = PHYS_PFN(obj->iova); + for (i = 0; i < obj->iommu_sgt->nents; i++) { + iommu_unmap(apu_drm->domain, PFN_PHYS(iova_pfn), + PAGE_ALIGN(obj->iommu_sgt->sgl[i].length)); + iova_pfn += PHYS_PFN(PAGE_ALIGN(obj->iommu_sgt->sgl[i].length)); + } + + sg_free_table(obj->iommu_sgt); + kfree(obj->iommu_sgt); + + free_iova(&apu_drm->iovad, PHYS_PFN(obj->iova)); + mutex_unlock(&obj->mutex); +} + +static struct sg_table *apu_get_sg_table(struct drm_gem_object *obj) +{ + if (obj->funcs) + return obj->funcs->get_sg_table(obj); + return NULL; +} + +int apu_bo_iommu_map(struct apu_drm *apu_drm, struct drm_gem_object *obj) +{ + struct apu_gem_object *apu_obj = to_apu_bo(obj); + struct scatterlist *sgl; + phys_addr_t phys; + int total_buf_space; + int iova_pfn; + int iova; + int ret; + int i; + + mutex_lock(&apu_obj->mutex); + apu_obj->iommu_refcount++; + if (apu_obj->iommu_refcount != 1) { + mutex_unlock(&apu_obj->mutex); + return 0; + } + + apu_obj->iommu_sgt = apu_get_sg_table(obj); + if (IS_ERR(apu_obj->iommu_sgt)) { + mutex_unlock(&apu_obj->mutex); + return PTR_ERR(apu_obj->iommu_sgt); + } + + total_buf_space = obj->size; + iova_pfn = alloc_iova_fast(&apu_drm->iovad, + total_buf_space >> PAGE_SHIFT, + apu_drm->iova_limit_pfn, true); + apu_obj->iova = PFN_PHYS(iova_pfn); + + if (!iova_pfn) { + dev_err(apu_drm->dev, "Failed to allocate iova address\n"); + mutex_unlock(&apu_obj->mutex); + return -ENOMEM; + } + + iova = apu_obj->iova; + sgl = apu_obj->iommu_sgt->sgl; + for (i = 0; i < apu_obj->iommu_sgt->nents; i++) { + phys = page_to_phys(sg_page(&sgl[i])); + ret = + iommu_map(apu_drm->domain, PFN_PHYS(iova_pfn), phys, + PAGE_ALIGN(sgl[i].length), IOMMU_READ | IOMMU_WRITE, + GFP_KERNEL); + if (ret) { + dev_err(apu_drm->dev, "Failed to iommu map\n"); + free_iova(&apu_drm->iovad, iova_pfn); + mutex_unlock(&apu_obj->mutex); + return ret; + } + iova += sgl[i].offset + sgl[i].length; + iova_pfn += PHYS_PFN(PAGE_ALIGN(sgl[i].length)); + } + mutex_unlock(&apu_obj->mutex); + + return 0; +} + +int ioctl_gem_iommu_map(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct apu_drm *apu_drm = dev->dev_private; + struct drm_apu_gem_iommu_map *args = data; + struct drm_gem_object **bos; + void __user *bo_handles; + u64 *das; + int ret; + int i; + + if (!apu_drm->domain) + return -ENODEV; + + das = kvmalloc_array(args->bo_handle_count, sizeof(*das), GFP_KERNEL); + if (!das) + return -ENOMEM; + + bo_handles = (void __user *)(uintptr_t) args->bo_handles; + ret = drm_gem_objects_lookup(file_priv, bo_handles, + args->bo_handle_count, &bos); + if (ret) { + kvfree(das); + return ret; + } + + for (i = 0; i < args->bo_handle_count; i++) { + ret = apu_bo_iommu_map(apu_drm, bos[i]); + if (ret) { + /* TODO: handle error */ + break; + } + das[i] = to_apu_bo(bos[i])->iova + to_apu_bo(bos[i])->offset; + } + + if (copy_to_user((void *)args->bo_device_addresses, das, + args->bo_handle_count * sizeof(u64))) { + ret = -EFAULT; + DRM_DEBUG("Failed to copy device addresses\n"); + goto out; + } + +out: + kvfree(das); + kvfree(bos); + + return 0; +} + +int ioctl_gem_iommu_unmap(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct apu_drm *apu_drm = dev->dev_private; + struct drm_apu_gem_iommu_map *args = data; + struct drm_gem_object **bos; + void __user *bo_handles; + int ret; + int i; + + if (!apu_drm->domain) + return -ENODEV; + + bo_handles = (void __user *)(uintptr_t) args->bo_handles; + ret = drm_gem_objects_lookup(file_priv, bo_handles, + args->bo_handle_count, &bos); + if (ret) + return ret; + + for (i = 0; i < args->bo_handle_count; i++) + apu_bo_iommu_unmap(apu_drm, to_apu_bo(bos[i])); + + kvfree(bos); + + return 0; +} diff --git a/drivers/gpu/drm/apu/apu_internal.h b/drivers/gpu/drm/apu/apu_internal.h index 021a3efdedf2..ea4183f3fb15 100644 --- a/drivers/gpu/drm/apu/apu_internal.h +++ b/drivers/gpu/drm/apu/apu_internal.h @@ -2,6 +2,9 @@ #ifndef __APU_INTERNAL_H__ #define __APU_INTERNAL_H__ +#include +#include + #include #include #include @@ -9,7 +12,10 @@ struct apu_gem_object { struct drm_gem_dma_object base; struct mutex mutex; + struct sg_table *iommu_sgt; + int iommu_refcount; size_t size; + u32 iova; u32 offset; }; @@ -35,6 +41,10 @@ struct apu_drm { struct drm_device base; struct device *dev; + struct iommu_domain *domain; + struct iova_domain iovad; + int iova_limit_pfn; + struct list_head cores; struct list_head node; @@ -165,12 +175,18 @@ struct apu_gem_object *to_apu_bo(struct drm_gem_object *obj); struct drm_gem_object *apu_gem_create_object(struct drm_device *dev, size_t size); +int apu_bo_iommu_map(struct apu_drm *apu_drm, struct drm_gem_object *obj); +void apu_bo_iommu_unmap(struct apu_drm *apu_drm, struct apu_gem_object *obj); int ioctl_gem_new(struct drm_device *dev, void *data, struct drm_file *file_priv); int ioctl_gem_user_new(struct drm_device *dev, void *data, struct drm_file *file_priv); struct dma_buf *apu_gem_prime_export(struct drm_gem_object *gem, int flags); +int ioctl_gem_iommu_map(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_gem_iommu_unmap(struct drm_device *dev, void *data, + struct drm_file *file_priv); int ioctl_gem_queue(struct drm_device *dev, void *data, struct drm_file *file_priv); int ioctl_gem_dequeue(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/apu/apu_sched.c b/drivers/gpu/drm/apu/apu_sched.c index 13b6fbd00bd8..716d4b7f2d55 100644 --- a/drivers/gpu/drm/apu/apu_sched.c +++ b/drivers/gpu/drm/apu/apu_sched.c @@ -117,6 +117,8 @@ static void apu_job_cleanup(struct kref *ref) struct apu_gem_object *apu_obj; apu_obj = to_apu_bo(job->bos[i]); + if (job->apu->domain) + apu_bo_iommu_unmap(job->apu, apu_obj); drm_gem_object_put(job->bos[i]); } @@ -397,6 +399,7 @@ static int apu_lookup_bos(struct drm_device *dev, struct drm_file *file_priv, struct drm_apu_gem_queue *args, struct apu_job *job) { void __user *bo_handles; + unsigned int i; int ret; job->bo_count = args->bo_handle_count; @@ -413,6 +416,31 @@ static int apu_lookup_bos(struct drm_device *dev, struct drm_file *file_priv, bo_handles = (void __user *)(uintptr_t) args->bo_handles; ret = drm_gem_objects_lookup(file_priv, bo_handles, job->bo_count, &job->bos); + if (ret) + return ret; + + if (!job->apu->domain) + return 0; + + for (i = 0; i < job->bo_count; i++) { + ret = apu_bo_iommu_map(job->apu, job->bos[i]); + if (ret) + goto err_iommu_map; + } + + return ret; + +err_iommu_map: + kvfree(job->implicit_fences); + for (i = 0; i < job->bo_count; i++) { + struct apu_gem_object *apu_obj; + + apu_obj = to_apu_bo(job->bos[i]); + if (job->apu->domain) + apu_bo_iommu_unmap(job->apu, apu_obj); + drm_gem_object_put(job->bos[i]); + } + kvfree(job->bos); return ret; } diff --git a/include/uapi/drm/apu_drm.h b/include/uapi/drm/apu_drm.h index c47000097040..0ecc739d8aed 100644 --- a/include/uapi/drm/apu_drm.h +++ b/include/uapi/drm/apu_drm.h @@ -41,6 +41,12 @@ struct drm_apu_gem_dequeue { __u64 data; }; +struct drm_apu_gem_iommu_map { + __u64 bo_handles; + __u32 bo_handle_count; + __u64 bo_device_addresses; +}; + struct apu_job_event { struct drm_event base; __u32 out_sync; @@ -57,12 +63,16 @@ struct drm_apu_state { #define DRM_APU_GEM_NEW 0x01 #define DRM_APU_GEM_QUEUE 0x02 #define DRM_APU_GEM_DEQUEUE 0x03 -#define DRM_APU_NUM_IOCTLS 0x04 +#define DRM_APU_GEM_IOMMU_MAP 0x04 +#define DRM_APU_GEM_IOMMU_UNMAP 0x05 +#define DRM_APU_NUM_IOCTLS 0x06 #define DRM_IOCTL_APU_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_STATE, struct drm_apu_state) #define DRM_IOCTL_APU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_NEW, struct drm_apu_gem_new) #define DRM_IOCTL_APU_GEM_QUEUE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_QUEUE, struct drm_apu_gem_queue) #define DRM_IOCTL_APU_GEM_DEQUEUE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_DEQUEUE, struct drm_apu_gem_dequeue) +#define DRM_IOCTL_APU_GEM_IOMMU_MAP DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_IOMMU_MAP, struct drm_apu_gem_iommu_map) +#define DRM_IOCTL_APU_GEM_IOMMU_UNMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_IOMMU_UNMAP, struct drm_apu_gem_iommu_map) #if defined(__cplusplus) } From patchwork Wed May 17 14:52:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 13245210 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 2A09CC77B75 for ; Wed, 17 May 2023 15:40:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=ChL28icQVyizqOaIAH3gAMzq5UZ5InLkC1WcC+s6530=; b=t5/VSiriNsRMSdA0O8k7e1URq7 z8VfgAnuwbKzF372Y6YaQOAtEpP6HNR9mmD29SMCy4aEV1zMeNO7Wj5EnDbMEoN2J0kTSiKQAY1TX CZUpdPgWVMtJubn9a4JTO87mUZzgNAP1EH7LjZ/nocSTx6Ma3Byv+BBHbOXOulfxnA5KA4btpmmkw WQmaoakXbTKGiLKxJq3nHmt2WREuW71mAUkqlVp5iI+5ABP+GCxgFb9xlvk1jHMxuLBqCdZ2AB61B JB5VUm3DgD9iN+C2WPsqEEKBjNDULiOXnU5ZGifTu/uMAawPmwbYKK4eXt5cs2ymuaeTdrlgGdhNY 3M2sv/PQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1pzJG7-00AKGT-2m; Wed, 17 May 2023 15:40:11 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzJG6-00AKGF-2w for linux-mediatek@bombadil.infradead.org; Wed, 17 May 2023 15:40:11 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:MIME-Version :References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=ChL28icQVyizqOaIAH3gAMzq5UZ5InLkC1WcC+s6530=; b=EHuMy4ZnEKrGkT5kc8urJnCV+F 9p7b6Rs+UtI/m2S2uEMelPvok4g05zHu752dx8lAQX8Ejcd092SXLGagQPUuFggT3t8wxxRytOQXu wsNYtTK939S5fxyOo7bIrGLA+s2MkDwUJ1Kfg88GiHE39UJ8+TtDabbtnkfkv/98d3YtfOS8YM+C3 vH8y0QTDkvx9WLV6q1YPWZ/CfBfe3qbaBLciYAavJJw1SqV55jCwdYGsEX67RiRvECDJh/vfNt/CB i0W6XlEMtc/vJjSglftS7qSn9+L08ZERfmXCaeTDEpEFasOCw/oLzB8b8aKAnLRKGGH3AId1oVHxl CkSkfs1g==; Received: from mail-wr1-x435.google.com ([2a00:1450:4864:20::435]) by desiato.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzIWI-00DFic-1G for linux-mediatek@lists.infradead.org; Wed, 17 May 2023 14:52:55 +0000 Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-307c040797bso595411f8f.3 for ; Wed, 17 May 2023 07:52:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20221208.gappssmtp.com; s=20221208; t=1684335169; x=1686927169; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ChL28icQVyizqOaIAH3gAMzq5UZ5InLkC1WcC+s6530=; b=iG7od/evTKtot/nJm1gK/1OL6Lc2v1Bmw9HJrvZNepXY3d+ijpP+DWiwPAyVpH4pE1 whGLUhjKSF4oMqvwtGaC3U7qu0JGLJf2iHcaZHG/KUWeDATqb+7kMGgK4oAbo+BiDQwI jpxA3KkT4mge9b6qQfuW6PavzHMyngFUeL5rUs8wtlXokzk0Gl/ytdd5BZqb0/1Z5e/Y cIV4AMhkBECqg1zNTCLE/3Y42tLbWIq2Tz99acBQU/rwUfG6htIKFOBvud87i13WKEpC cNz6RrsgVyoegDNgLU4Dj6l4jtXBZeukG92pSorCCUG0L5/O72DQRlJqUtdW4XruFu5P MPxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684335169; x=1686927169; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ChL28icQVyizqOaIAH3gAMzq5UZ5InLkC1WcC+s6530=; b=XIy6XPv6ukTCEN6Y0pUj/0LuJOnAaGwgYwENa4NJcDQ5R3xPknLzfmyL1PswuMlqI2 iZ8mzwzy/uMiDFiOdPmM77SlPu70AwfKq8DBU6WWeaZaPxKXTNgVyD8lTa8wMcYdp47e FrAcHCjUGlJRSDg5YqJTMJYeowSrUp0DsT6+23glmeAtzRlvuldK3gFnfpkWMWhGuNc/ JNKLkeMmDVcgaEHzSdlT3NrjdG9ueS0Xn/bAStH8MvAwmW4OmurgMqfy8C6ngFXKzGza J5K1zEyy4952uHPBIlcUUjK9ToeiDu4PY6+Y3ZQcQF8e14VyPYGp4AxdJhatxlqRUXDy XrfA== X-Gm-Message-State: AC+VfDwgTuCmq7Ua014+DMSrmKTcErd42CXYTZS+IF29mBPvsb+94+Lg vnem1n/xeRZdNu5oQgmVxR2MQQ== X-Google-Smtp-Source: ACHHUZ5uCAqHjUKdV/6t3weODX6sjiburDexUUIvFFfFHhqo6Yq6iD6TS/qXA3nyRGAEZJG5rutnCQ== X-Received: by 2002:a5d:4cc9:0:b0:2fb:7099:6070 with SMTP id c9-20020a5d4cc9000000b002fb70996070mr839383wrt.47.1684335169252; Wed, 17 May 2023 07:52:49 -0700 (PDT) Received: from blaptop.baylibre (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id v11-20020a5d678b000000b002f7780eee10sm2979098wru.59.2023.05.17.07.52.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 May 2023 07:52:48 -0700 (PDT) From: Alexandre Bailon To: airlied@gmail.com, daniel@ffwll.ch, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, sumit.semwal@linaro.org, christian.koenig@amd.com, jstephan@baylibre.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, nbelin@baylibre.com, bero@baylibre.com Subject: [PATCH 5/7] drm/apu: allow platform driver to implement their own mmap function Date: Wed, 17 May 2023 16:52:35 +0200 Message-Id: <20230517145237.295461-6-abailon@baylibre.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230517145237.295461-1-abailon@baylibre.com> References: <20230517145237.295461-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230517_155250_496303_931F4FC9 X-CRM114-Status: GOOD ( 13.45 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: Julien Stephan By default we will call drm_gem_mmap() unless the apu driver has declared it's own mmap handler. Signed-off-by: Julien Stephan Reviewed-by: Julien Stephan --- drivers/gpu/drm/apu/apu_drv.c | 38 +++++++++++++++++++++++++++++- drivers/gpu/drm/apu/apu_internal.h | 2 ++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/apu/apu_drv.c b/drivers/gpu/drm/apu/apu_drv.c index a0dce785a02a..703d4515f075 100644 --- a/drivers/gpu/drm/apu/apu_drv.c +++ b/drivers/gpu/drm/apu/apu_drv.c @@ -29,7 +29,20 @@ static const struct drm_ioctl_desc ioctls[] = { DRM_RENDER_ALLOW), }; -DEFINE_DRM_GEM_DMA_FOPS(apu_drm_ops); +static int apu_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); + +static const struct file_operations apu_drm_ops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .compat_ioctl = drm_compat_ioctl, + .poll = drm_poll, + .read = drm_read, + .llseek = noop_llseek, + .mmap = apu_drm_gem_mmap, + DRM_GEM_DMA_UNMAPPED_AREA_FOPS +}; static struct drm_driver apu_drm_driver = { .driver_features = DRIVER_GEM | DRIVER_SYNCOBJ, @@ -45,6 +58,29 @@ static struct drm_driver apu_drm_driver = { DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_gem_dma_dumb_create), }; +/** + * apu_drm_gem_mmap() + * + * @filp: DRM file pointer + * @vma: VMA for the area to be mapped + * + * by default will call drm_gem_mmap() unless the apu driver has declared it's + * own mmap handler + * + */ +static int apu_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->minor->dev; + struct apu_drm *apu = dev->dev_private; + + if (apu->mmap) + return apu->mmap(filp, vma); + else + return drm_gem_mmap(filp, vma); +} + + /** * apu_dev_alloc() - Allocate a new APU device * diff --git a/drivers/gpu/drm/apu/apu_internal.h b/drivers/gpu/drm/apu/apu_internal.h index ea4183f3fb15..46e0b2be7821 100644 --- a/drivers/gpu/drm/apu/apu_internal.h +++ b/drivers/gpu/drm/apu/apu_internal.h @@ -45,6 +45,8 @@ struct apu_drm { struct iova_domain iovad; int iova_limit_pfn; + int (*mmap)(struct file *filp, struct vm_area_struct *vma); + struct list_head cores; struct list_head node; From patchwork Wed May 17 14:52:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 13245212 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 829C6C7EE23 for ; Wed, 17 May 2023 15:40:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=gDAViNn0OrgwOgKdIFqM87DFD/WIAZjGkg0w/gGFC28=; b=TqGuct8h2HN4dsgPZVfKCiizMz c7+e2DkrN146e392yBk2YT/5PrI3dBBuatQEKiyaaZyMkjze7NhHsqCBCZz4sqI5AJHnsI7mBKP0A AA/PVwEF28VAYcWd5FgpC4ssT4cLvjb4kKnD9gi4eA1sx8nOAzKMdUuM7Mr0tn0h0gmZTh4WFSom6 b33p2xPmqLs9fzRT4OPGitwk4jzoZ29mI33BPOVwC99z3+5g0ufm7/H5d2Bm5MNyiJtamCV5ruSZV ylwbEUHoKn5v/lfXF/vc8szyUeV+Q8XFR3e77wDy+EdmlYigbTNljOF6c6fwgn7NnNeHBnJ1Bv6dg ZB1qwt0A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1pzJGP-00AKNE-0k; Wed, 17 May 2023 15:40:29 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzJGH-00AKJq-1Z for linux-mediatek@bombadil.infradead.org; Wed, 17 May 2023 15:40:21 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:MIME-Version :References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=gDAViNn0OrgwOgKdIFqM87DFD/WIAZjGkg0w/gGFC28=; b=EmOxRZPosPzodWOrrO2ZCQBCRN kz8v3B3CM/v4GrQlUcZHPQjvlBD7rA4RSMNuqqhb9O8CJ8qAidZ53WfDV56io6VzJZJ1ij0VAXrGQ d3u563aEeBGhKtDpZPUBjhTEiL/SPfkFUDQSxYB+G/g5bgv2G5MaegiMBXOzzG2HYZJ3sG+q2gon1 uHq+3DwPfzfmf4UV05VOKf4kueXvDVFVvApfZNTj65Bqvhj54Rn3tzbxexc4EkU8RDR2SUYYY8qe9 9qBbdrwuE0MQ9ybYyOqOAVcdRG0YJNp59uBUMRwVa4olvgL14W2yCOaY3AOYKLgzGqcV/8v7HaZt8 sMKcAezA==; Received: from mail-wr1-x42b.google.com ([2a00:1450:4864:20::42b]) by desiato.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzIWJ-00DFiq-1y for linux-mediatek@lists.infradead.org; Wed, 17 May 2023 14:52:55 +0000 Received: by mail-wr1-x42b.google.com with SMTP id ffacd0b85a97d-30935d343f7so828437f8f.1 for ; Wed, 17 May 2023 07:52:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20221208.gappssmtp.com; s=20221208; t=1684335170; x=1686927170; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gDAViNn0OrgwOgKdIFqM87DFD/WIAZjGkg0w/gGFC28=; b=b495HJazHg0Ng27LlsAm3lPCnV9VhpPRLWdZE53fQIFVlD4GU+RbhZ1cJxnPFSwNdA HcaYLSCPi8KOFmOurLVZGHGjMdxvn88lPghdx5er/Cbi80/umddsZ7zO7m2tfEKWAhHc Rqe1i2VZkgTZsDe+1kw0bFvr6vSS0qmPSkat6oGaCBi2YGGwpbLADvUKY5s+nOHaRvu1 +EOiiQJVgnUepfVjzu0RsyNAp0X31Wa1aYGegDiRLMw1IcY0tpQwpSvMMS9BhqIuQHi/ NhnXfgb2H6jxdQcJSlExIsKcli4wUAZtwv/AwuTZ9eaOWwnCkE7hpmg7NpPu/uYhFXMz nqew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684335170; x=1686927170; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gDAViNn0OrgwOgKdIFqM87DFD/WIAZjGkg0w/gGFC28=; b=k+a4+k2S3+hyRYh/wXerTh9g5HF4dOPiDkL0icrCZEkVRFHqcPSoy+IfWlkUCMaU8v Y+oz7z/8wf1+J/NP7JoGvli8eI5ouyj8u5kd5fRDnc1vpPik9b5OuwkylEIuujP2fRjn srbGp81NeJmEWSFFPx0nbuq64JD9tO/iXTVJti8fr0nXuZ6QCTEqCMvSkaKtZRPU2gOE EbLHaOu5W0jyVwBVCqs4pkXBC4XJcEvll8ITVJV3SmAA6Js6Tte4VnQhYB4cZJqhkVCY C6thYZCo3LDsLxfimfQl8xmPyUC8y7aCv4IVe5b+DsrV+HH0DEO7Gpc/PQH2hDOubUZN 5SUw== X-Gm-Message-State: AC+VfDzI6mLBOXvvKMrERgZPsgbERTAUSBJlwgKK9mvW2rTacP0ZZ1mT 20XAHk2Cv2gRBmK7ao7LGtM7rg== X-Google-Smtp-Source: ACHHUZ6w4HWznKUY4Y6qU6rnRMXtzFEUnhSSv/0/k9+B8KB7LLKW0IPbU1ofdiJQhKloHX5gMjZa9w== X-Received: by 2002:a5d:5445:0:b0:306:2bb6:c7c3 with SMTP id w5-20020a5d5445000000b003062bb6c7c3mr921325wrv.6.1684335170471; Wed, 17 May 2023 07:52:50 -0700 (PDT) Received: from blaptop.baylibre (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id v11-20020a5d678b000000b002f7780eee10sm2979098wru.59.2023.05.17.07.52.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 May 2023 07:52:49 -0700 (PDT) From: Alexandre Bailon To: airlied@gmail.com, daniel@ffwll.ch, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, sumit.semwal@linaro.org, christian.koenig@amd.com, jstephan@baylibre.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, nbelin@baylibre.com, bero@baylibre.com Subject: [PATCH 6/7] drm/apu: Add support for a simulated APU Date: Wed, 17 May 2023 16:52:36 +0200 Message-Id: <20230517145237.295461-7-abailon@baylibre.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230517145237.295461-1-abailon@baylibre.com> References: <20230517145237.295461-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230517_155251_802079_4ED5B03A X-CRM114-Status: GOOD ( 34.17 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: Julien Stephan This implements a driver to use with a simulation APU. This is useful for testing purpose and can be used as a basis to implement real platform driver. Communication between the simulated APU and the driver is done using netlink socket. Signed-off-by: Julien Stephan --- drivers/gpu/drm/apu/Kconfig | 9 + drivers/gpu/drm/apu/Makefile | 3 + drivers/gpu/drm/apu/simu_apu.c | 313 +++++++++++++++++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 drivers/gpu/drm/apu/simu_apu.c diff --git a/drivers/gpu/drm/apu/Kconfig b/drivers/gpu/drm/apu/Kconfig index a769df42091c..e0ffc166497c 100644 --- a/drivers/gpu/drm/apu/Kconfig +++ b/drivers/gpu/drm/apu/Kconfig @@ -11,3 +11,12 @@ config DRM_APU communicate with an AI Processor Unit (APU). The driver intends to provide a common infrastructure that may be used to support many different APU. + +config DRM_SIMU_APU + tristate "SIMULATION APU DRM driver" + depends on DRM_APU + default n + help + This provides a driver using netlink socket to communicate + with a simu APU. + This is useful for simulation and testing of libAPU stack. diff --git a/drivers/gpu/drm/apu/Makefile b/drivers/gpu/drm/apu/Makefile index fc8d6380fc38..0b007854a07f 100644 --- a/drivers/gpu/drm/apu/Makefile +++ b/drivers/gpu/drm/apu/Makefile @@ -4,4 +4,7 @@ drm_apu-y += apu_drv.o drm_apu-y += apu_gem.o drm_apu-y += apu_sched.o +drm_simu_apu-y += simu_apu.o + obj-$(CONFIG_DRM_APU) += drm_apu.o +obj-$(CONFIG_DRM_SIMU_APU) += drm_simu_apu.o diff --git a/drivers/gpu/drm/apu/simu_apu.c b/drivers/gpu/drm/apu/simu_apu.c new file mode 100644 index 000000000000..5557f8b78a83 --- /dev/null +++ b/drivers/gpu/drm/apu/simu_apu.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2023 BayLibre SAS + +#include +#include +#include +#include + +#include + +#include + +#include "apu_internal.h" + + +#define MYPROTO 17 +#define MYGRP 17 + +#define DRIVER_NAME "SIMU APU DRIVER" + +/* + * Firmware request, must be aligned with the one defined in firmware. + * @id: Request id, used in the case of reply, to find the pending request + * @cmd: The command id to execute in the firmware + * @result: The result of the command executed on the firmware + * @size: The size of the data available in this request + * @count: The number of shared buffer + * @data: Contains the data attached with the request if size is greater than + * zero, and the addresses of shared buffers if count is greater than + * zero. Both the data and the shared buffer could be read and write + * by the APU. + */ +struct apu_dev_request { + u16 id; + u16 cmd; + u16 result; + u16 size_in; + u16 size_out; + u16 count; + u8 data[0]; +} __packed; + +struct platform_device *platform; +struct apu_core *apu_core; +static int pid = -1; +struct sock *nl_sock; + +static int apu_netlink_read(struct sk_buff *skb, struct apu_dev_request **msg_ptr, int *pid) +{ + struct nlmsghdr *nlh; + + nlh = (struct nlmsghdr *)skb->data; + *pid = nlh->nlmsg_pid; /* pid of sending process */ + *msg_ptr = nlmsg_data(nlh); + + return nlh->nlmsg_len - NLMSG_HDRLEN; +} + +static int apu_netlink_write(void *msg_ptr, int msg_size, int pid) +{ + struct sk_buff *skb_out; + struct nlmsghdr *nlh; + int res; + + skb_out = nlmsg_new(msg_size, 0); + if (!skb_out) + return -ENOMEM; + + nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0); + NETLINK_CB(skb_out).dst_group = 0; /* not in multicast group */ + memcpy(nlmsg_data(nlh), msg_ptr, msg_size); + + res = nlmsg_unicast(nl_sock, skb_out, pid); + + if (res < 0) + return res; + else + return nlh->nlmsg_len - NLMSG_HDRLEN; +} + +static void netlink_recv_msg(struct sk_buff *skb) +{ + int msg_size; + struct apu_dev_request *hdr; + int nlmsg_pid; + + msg_size = apu_netlink_read(skb, &hdr, &nlmsg_pid); + + if (pid == -1) { + // No device registered yet, the first message should be + // "READY" + if (!strncmp((char *)hdr, "READY", strlen("READY"))) { + + pid = nlmsg_pid; + if (apu_core_register(&platform->dev, apu_core, apu_core->apu)) + pr_err("cannot register SIMU APU\n"); + } + } else if (pid == nlmsg_pid) { + if (!strncmp((char *)hdr, "STOP", strlen("STOP"))) { + pid = -1; + apu_core_remove(apu_core); + } else + apu_drm_callback(apu_core, hdr->id, hdr, msg_size); + } else { + pr_err("%s: Only one core is supported for now\n", DRIVER_NAME); + } +} + +static int netlink_setup(void) +{ + int ret = 0; + struct netlink_kernel_cfg cfg = { + .input = netlink_recv_msg, + }; + + nl_sock = netlink_kernel_create(&init_net, MYPROTO, &cfg); + if (!nl_sock) + ret = -ENOMEM; + + return ret; +} + +static int simu_apu_send(struct apu_job *job) +{ + return apu_netlink_write((void *)(job->request_data), job->request_len, pid); +} + +static int simu_apu_handle_request(struct apu_job *job, void *data, int len) +{ + struct apu_dev_request *hdr = data; + + job->result = hdr->result; + if (job->size_out) + memcpy(job->data_out, hdr->data + job->size_in, + min(job->size_out, hdr->size_out)); + job->size_out = hdr->size_out; + return 0; +} + +static int simu_apu_alloc_request(struct apu_job *job) +{ + struct apu_dev_request *dev_req; + + int size; + u64 *dev_req_da; + u32 *dev_req_buffer_size; + int i; + + size = sizeof(*dev_req) + (sizeof(u64) + sizeof(u32)) * job->bo_count * 2 + + job->size_in + job->size_out; + dev_req = kmalloc(size, GFP_KERNEL); + if (!dev_req) + return -ENOMEM; + + dev_req->cmd = job->cmd; + dev_req->size_in = job->size_in; + dev_req->size_out = job->size_out; + dev_req->count = job->bo_count; + dev_req_da = + (u64 *) (dev_req->data + dev_req->size_in + dev_req->size_out); + dev_req_buffer_size = (u32 *) (dev_req_da + dev_req->count); + memcpy(dev_req->data, job->data_in, job->size_in); + + for (i = 0; i < job->bo_count; i++) { + struct apu_gem_object *obj = to_apu_bo(job->bos[i]); + + dev_req_da[i] = drm_vma_node_offset_addr(&obj->base.base.vma_node); + dev_req_buffer_size[i] = obj->size; + } + + dev_req->id = job->id; + + job->request_data = dev_req; + job->request_len = size; + return 0; +} + +static int simu_apu_ready(struct apu_core *core) +{ + if (pid == -1) + return 0; + + return 1; +} + +/** + * simu_apu_gem_mmap + * + * this is directly based on drm_gem_mmap() function but removing the permission + * check before mapping a buffer. This is useful here to be able to easily + * share buffers between libapu host application and libapu device application + * (simulation use case) + * + */ +static int simu_apu_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->minor->dev; + struct drm_gem_object *obj = NULL; + struct drm_vma_offset_node *node; + int ret; + + if (drm_dev_is_unplugged(dev)) + return -ENODEV; + + drm_vma_offset_lock_lookup(dev->vma_offset_manager); + node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager, + vma->vm_pgoff, + vma_pages(vma)); + if (likely(node)) { + obj = container_of(node, struct drm_gem_object, vma_node); + /* + * When the object is being freed, after it hits 0-refcnt it + * proceeds to tear down the object. In the process it will + * attempt to remove the VMA offset and so acquire this + * mgr->vm_lock. Therefore if we find an object with a 0-refcnt + * that matches our range, we know it is in the process of being + * destroyed and will be freed as soon as we release the lock - + * so we have to check for the 0-refcnted object and treat it as + * invalid. + */ + if (!kref_get_unless_zero(&obj->refcount)) { + obj = NULL; + pr_err("DTC: %s: %d\n", __func__, __LINE__); + } + } + drm_vma_offset_unlock_lookup(dev->vma_offset_manager); + + if (!obj) + return -EINVAL; + + ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT, + vma); + + drm_gem_object_put(obj); + + return ret; +} + +static struct apu_core_ops simu_apu_ops = { + .alloc_prepare_request = simu_apu_alloc_request, + .send_request = simu_apu_send, + .handle_request = simu_apu_handle_request, + .is_ready = simu_apu_ready, +}; + +static int __init apu_platform_init(void) +{ + int ret; + struct apu_drm *apu; + + platform = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + if (IS_ERR(platform)) + return PTR_ERR(platform); + + if (!devres_open_group(&platform->dev, NULL, GFP_KERNEL)) { + ret = -ENOMEM; + goto out_unregister; + } + + apu = apu_dev_alloc(&platform->dev); + if (!apu) { + ret = -ENOMEM; + goto out_devres; + } + + apu_core = apu_core_alloc(apu, &simu_apu_ops, apu); + if (!apu_core) { + ret = -ENOMEM; + goto out_devres; + } + + ret = apu_dev_register(apu); + if (ret) + goto out_apu_core_free; + + apu->mmap = simu_apu_gem_mmap; + + ret = netlink_setup(); + if (ret) + goto out_apu_dev_unregister; + + return 0; + +out_apu_dev_unregister: + apu_dev_unregister(apu); +out_apu_core_free: + apu_core_free(apu_core); +out_devres: + devres_release_group(&platform->dev, NULL); +out_unregister: + platform_device_unregister(platform); + return ret; +} + +static void __exit apu_platform_exit(void) +{ + netlink_kernel_release(nl_sock); + apu_core_remove(apu_core); + apu_core_free(apu_core); + apu_dev_unregister((struct apu_drm *)apu_core->apu); + devres_release_group(&platform->dev, NULL); + platform_device_unregister(platform); +} + + +module_init(apu_platform_init); +module_exit(apu_platform_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Julien Stephan"); +MODULE_DESCRIPTION(DRIVER_NAME); From patchwork Wed May 17 14:52:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 13245264 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 334D4C7EE2A for ; Wed, 17 May 2023 16:00:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=9mr1L/m4ima+2h/NhXtcjqbHddpi6u41EWoGArxh1iQ=; b=v8BnVhbSoZa5BvUO/sTCFA5njJ FLCygm46fyVxDVLCOcKOFG9RSwaYu1D7qA9kGkdWo7a0LQVgwPQpQHRzV1zxZqwa4ES2DJmV8PQ2L 2MwcUNXKERN+NeGven2w8D3l1uxzYU2i6WCfRVG3A6bbD1xXnaIflx+S8VdIw9uI3SAG0fIpgDJkq H70VqEecz1MXQ/nlVCitUmvI55XbyOS++SQG/fCCZ+PJV7R7nvyKVzwFkOcz6JX9pY/5yMQgZqIw2 L0cvCVaXh3h9slWaitK1rjoIt0eJF4feODEN3nwx4YwJbxxmdrV5mHWkUGposgPj/eZ/ARYbH3+IU qaDuaBLA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1pzJZw-00AONp-16; Wed, 17 May 2023 16:00:40 +0000 Received: from mail-wm1-x344.google.com ([2a00:1450:4864:20::344]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pzIWM-00ACET-0i for linux-mediatek@lists.infradead.org; Wed, 17 May 2023 14:52:55 +0000 Received: by mail-wm1-x344.google.com with SMTP id 5b1f17b1804b1-3f41dceb9d1so8864105e9.1 for ; Wed, 17 May 2023 07:52:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20221208.gappssmtp.com; s=20221208; t=1684335171; x=1686927171; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9mr1L/m4ima+2h/NhXtcjqbHddpi6u41EWoGArxh1iQ=; b=pdG2+3ODw0cGuNg/LORzvNsUqX1IiweDfrWioVGocQZDWZOWLRqkDaX4MTzyiQe1c7 pkyEeUQ7xqMrhFPqgtTXbdZp3T0rwW0l0BIMsILSnzXcX/Sd7NVDoMo/aiSxsYvHmvbE 9CFhqMy1vU2U8NqgvLhl8WgFol9WpTF6r6EFUqq/RKyHw1v7dAJHBpN4C35EGlhKFu2m bv8X2zua8yim+q2TU1Nwjf+yYUMToKg1IrzAFE9ZZPxUgS9V2JJXJY3xZezoYKEGwVXh 5JUMdyDg8DXWWvuNp3X07uEX8GvfXlSZm2H1ourLwVfh0bfHuRQHtAUbRtnalP8rK24w 5aJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684335171; x=1686927171; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9mr1L/m4ima+2h/NhXtcjqbHddpi6u41EWoGArxh1iQ=; b=jBVnZ2R6Zo++w77iudWT48t3XHS4MbSw+PGshss+d4uaWIPWDZEzq5CMOSuqH8CtrD kcomr7JcnpSxUg3qwf5EwMQi6UkvN5SsZ/Fzsl3Yx7dhX8LVETMMagwQX9hyP4WlVkNK vCuKNRmyO/nUKGu8NNxpwxE53dsUOYMv6hJsyKQ47RsQ0o3rzAhjXL7GAZGla1YDE4LF sDtFnS22CSY9CJgsPCGNpVl2iokhMlm4YBfr/fqaJG+7hhIL5rtLD2gg1n7lqtn6+WeH l/ZOa1HYakSZkuyf48eu+GzLTIs2Zl08ErKVZL/5HDn1p37qz9rgFXi5HcXn6rnCgU8f pMIQ== X-Gm-Message-State: AC+VfDwtGKssl6bL26FeiY7hv9Dj3N5tWwc53dk6OjtFLQbIcUhTXrJQ xYJ7BeUgrp3TONluD+DaDYzKTg== X-Google-Smtp-Source: ACHHUZ7D+XIYOY7fwEt1VA+EKenIzVfyhPoXQPx4ACohe42JP1CZtzERdmroTv625PctD16NHx1kmg== X-Received: by 2002:adf:e450:0:b0:307:97dd:1de2 with SMTP id t16-20020adfe450000000b0030797dd1de2mr930581wrm.25.1684335171626; Wed, 17 May 2023 07:52:51 -0700 (PDT) Received: from blaptop.baylibre (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id v11-20020a5d678b000000b002f7780eee10sm2979098wru.59.2023.05.17.07.52.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 May 2023 07:52:51 -0700 (PDT) From: Alexandre Bailon To: airlied@gmail.com, daniel@ffwll.ch, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com, sumit.semwal@linaro.org, christian.koenig@amd.com, jstephan@baylibre.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, nbelin@baylibre.com, bero@baylibre.com, Alexandre Bailon Subject: [PATCH 7/7] dt-bindings: Add bidings for mtk,apu-drm Date: Wed, 17 May 2023 16:52:37 +0200 Message-Id: <20230517145237.295461-8-abailon@baylibre.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230517145237.295461-1-abailon@baylibre.com> References: <20230517145237.295461-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230517_075254_259536_81907039 X-CRM114-Status: GOOD ( 12.24 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org This adds the device tree bindings for the APU DRM driver. Signed-off-by: Alexandre Bailon Reviewed-by: Julien Stephan --- .../devicetree/bindings/gpu/mtk,apu-drm.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpu/mtk,apu-drm.yaml diff --git a/Documentation/devicetree/bindings/gpu/mtk,apu-drm.yaml b/Documentation/devicetree/bindings/gpu/mtk,apu-drm.yaml new file mode 100644 index 000000000000..6f432d3ea478 --- /dev/null +++ b/Documentation/devicetree/bindings/gpu/mtk,apu-drm.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpu/mediatek,apu-drm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AI Processor Unit DRM + +properties: + compatible: + const: mediatek,apu-drm + + remoteproc: + maxItems: 2 + description: + Handle to remoteproc devices controlling the APU + + iova: + maxItems: 1 + description: + Address and size of virtual memory that could used by the APU + +required: + - compatible + - remoteproc + - iova + +additionalProperties: false + +examples: + - | + apu@0 { + compatible = "mediatek,apu-drm"; + remoteproc = <&vpu0>, <&vpu1>; + iova = <0 0x60000000 0 0x10000000>; + }; + +...