From 0a0e79a2d9ed846fc3c3f5ef92b691e81bc9721a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Oct 2025 19:33:27 +0300 Subject: drm/atomic: WARN about invalid drm_foo_get_state() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_{crtc,plane,connector,private_obj}_get_state() must not be called after the atomic check phase. At that point the commit has been carved in stone and no new objects must be introduced into it. WARN if anyone attempts to violate this rule. Cc: Maxime Ripard Cc: Dan Carpenter Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20251017163327.9074-2-ville.syrjala@linux.intel.com Reviewed-by: Maxime Ripard --- include/drm/drm_atomic.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 155e82f87e4d..2e433d44658d 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -523,6 +523,14 @@ struct drm_atomic_state { */ bool duplicated : 1; + /** + * @checked: + * + * Indicates the state has been checked and thus must no longer + * be mutated. For internal use only, do not consult from drivers. + */ + bool checked : 1; + /** * @planes: * -- cgit v1.2.3 From 57557964b582238d5ee4b8538d1c4694f91c2186 Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Wed, 29 Oct 2025 10:17:52 +0100 Subject: accel/ivpu: Add support for userptr buffer objects Introduce a new ioctl `drm_ivpu_bo_create_from_userptr` that allows users to create GEM buffer objects from user pointers to memory regions. The user pointer must be page-aligned and the memory region must remain valid for the buffer object's lifetime. Userptr buffers enable direct use of mmapped files (e.g. inference weights) in NPU workloads without copying data to NPU buffer objects. This reduces memory usage and provides better flexibility for NPU applications. Signed-off-by: Jacek Lawrynowicz Reviewed-by: Jeff Hugo Signed-off-by: Karol Wachowski Link: https://patch.msgid.link/20251029091752.203198-1-karol.wachowski@linux.intel.com --- drivers/accel/ivpu/Makefile | 1 + drivers/accel/ivpu/ivpu_drv.c | 3 + drivers/accel/ivpu/ivpu_gem.c | 2 +- drivers/accel/ivpu/ivpu_gem.h | 7 ++ drivers/accel/ivpu/ivpu_gem_userptr.c | 202 ++++++++++++++++++++++++++++++++++ drivers/accel/ivpu/ivpu_mmu_context.c | 4 +- drivers/accel/ivpu/ivpu_mmu_context.h | 2 +- include/uapi/drm/ivpu_accel.h | 52 +++++++++ 8 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 drivers/accel/ivpu/ivpu_gem_userptr.c (limited to 'include') diff --git a/drivers/accel/ivpu/Makefile b/drivers/accel/ivpu/Makefile index 1029e0bab061..dbf76b8a5b4c 100644 --- a/drivers/accel/ivpu/Makefile +++ b/drivers/accel/ivpu/Makefile @@ -6,6 +6,7 @@ intel_vpu-y := \ ivpu_fw.o \ ivpu_fw_log.o \ ivpu_gem.o \ + ivpu_gem_userptr.o \ ivpu_hw.o \ ivpu_hw_btrs.o \ ivpu_hw_ip.o \ diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index c6fe7a408912..ca68730dee88 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -134,6 +134,8 @@ bool ivpu_is_capable(struct ivpu_device *vdev, u32 capability) return true; case DRM_IVPU_CAP_DMA_MEMORY_RANGE: return true; + case DRM_IVPU_CAP_BO_CREATE_FROM_USERPTR: + return true; case DRM_IVPU_CAP_MANAGE_CMDQ: return vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW; default: @@ -313,6 +315,7 @@ static const struct drm_ioctl_desc ivpu_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(IVPU_CMDQ_CREATE, ivpu_cmdq_create_ioctl, 0), DRM_IOCTL_DEF_DRV(IVPU_CMDQ_DESTROY, ivpu_cmdq_destroy_ioctl, 0), DRM_IOCTL_DEF_DRV(IVPU_CMDQ_SUBMIT, ivpu_cmdq_submit_ioctl, 0), + DRM_IOCTL_DEF_DRV(IVPU_BO_CREATE_FROM_USERPTR, ivpu_bo_create_from_userptr_ioctl, 0), }; static int ivpu_wait_for_ready(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c index 7353cfb73bcb..03d39615ad37 100644 --- a/drivers/accel/ivpu/ivpu_gem.c +++ b/drivers/accel/ivpu/ivpu_gem.c @@ -96,7 +96,7 @@ int __must_check ivpu_bo_bind(struct ivpu_bo *bo) if (!bo->mmu_mapped) { drm_WARN_ON(&vdev->drm, !bo->ctx); ret = ivpu_mmu_context_map_sgt(vdev, bo->ctx, bo->vpu_addr, sgt, - ivpu_bo_is_snooped(bo)); + ivpu_bo_is_snooped(bo), ivpu_bo_is_read_only(bo)); if (ret) { ivpu_err(vdev, "Failed to map BO in MMU: %d\n", ret); goto unlock; diff --git a/drivers/accel/ivpu/ivpu_gem.h b/drivers/accel/ivpu/ivpu_gem.h index 54452eb8a41f..2dcd7eba9cb7 100644 --- a/drivers/accel/ivpu/ivpu_gem.h +++ b/drivers/accel/ivpu/ivpu_gem.h @@ -38,6 +38,8 @@ void ivpu_bo_free(struct ivpu_bo *bo); int ivpu_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file); int ivpu_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file); int ivpu_bo_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int ivpu_bo_create_from_userptr_ioctl(struct drm_device *dev, void *data, + struct drm_file *file); void ivpu_bo_list(struct drm_device *dev, struct drm_printer *p); void ivpu_bo_list_print(struct drm_device *dev); @@ -75,6 +77,11 @@ static inline bool ivpu_bo_is_snooped(struct ivpu_bo *bo) return ivpu_bo_cache_mode(bo) == DRM_IVPU_BO_CACHED; } +static inline bool ivpu_bo_is_read_only(struct ivpu_bo *bo) +{ + return bo->flags & DRM_IVPU_BO_READ_ONLY; +} + static inline void *ivpu_to_cpu_addr(struct ivpu_bo *bo, u32 vpu_addr) { if (vpu_addr < bo->vpu_addr) diff --git a/drivers/accel/ivpu/ivpu_gem_userptr.c b/drivers/accel/ivpu/ivpu_gem_userptr.c new file mode 100644 index 000000000000..235c67959453 --- /dev/null +++ b/drivers/accel/ivpu/ivpu_gem_userptr.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020-2025 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ivpu_drv.h" +#include "ivpu_gem.h" + +static struct sg_table * +ivpu_gem_userptr_dmabuf_map(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) +{ + struct sg_table *sgt = attachment->dmabuf->priv; + int ret; + + ret = dma_map_sgtable(attachment->dev, sgt, direction, DMA_ATTR_SKIP_CPU_SYNC); + if (ret) + return ERR_PTR(ret); + + return sgt; +} + +static void ivpu_gem_userptr_dmabuf_unmap(struct dma_buf_attachment *attachment, + struct sg_table *sgt, + enum dma_data_direction direction) +{ + dma_unmap_sgtable(attachment->dev, sgt, direction, DMA_ATTR_SKIP_CPU_SYNC); +} + +static void ivpu_gem_userptr_dmabuf_release(struct dma_buf *dma_buf) +{ + struct sg_table *sgt = dma_buf->priv; + struct sg_page_iter page_iter; + struct page *page; + + for_each_sgtable_page(sgt, &page_iter, 0) { + page = sg_page_iter_page(&page_iter); + unpin_user_page(page); + } + + sg_free_table(sgt); + kfree(sgt); +} + +static const struct dma_buf_ops ivpu_gem_userptr_dmabuf_ops = { + .map_dma_buf = ivpu_gem_userptr_dmabuf_map, + .unmap_dma_buf = ivpu_gem_userptr_dmabuf_unmap, + .release = ivpu_gem_userptr_dmabuf_release, +}; + +static struct dma_buf * +ivpu_create_userptr_dmabuf(struct ivpu_device *vdev, void __user *user_ptr, + size_t size, uint32_t flags) +{ + struct dma_buf_export_info exp_info = {}; + struct dma_buf *dma_buf; + struct sg_table *sgt; + struct page **pages; + unsigned long nr_pages = size >> PAGE_SHIFT; + unsigned int gup_flags = FOLL_LONGTERM; + int ret, i, pinned; + + /* Add FOLL_WRITE only if the BO is not read-only */ + if (!(flags & DRM_IVPU_BO_READ_ONLY)) + gup_flags |= FOLL_WRITE; + + pages = kvmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL); + if (!pages) + return ERR_PTR(-ENOMEM); + + pinned = pin_user_pages_fast((unsigned long)user_ptr, nr_pages, gup_flags, pages); + if (pinned < 0) { + ret = pinned; + ivpu_warn(vdev, "Failed to pin user pages: %d\n", ret); + goto free_pages_array; + } + + if (pinned != nr_pages) { + ivpu_warn(vdev, "Pinned %d pages, expected %lu\n", pinned, nr_pages); + ret = -EFAULT; + goto unpin_pages; + } + + sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) { + ret = -ENOMEM; + goto unpin_pages; + } + + ret = sg_alloc_table_from_pages(sgt, pages, nr_pages, 0, size, GFP_KERNEL); + if (ret) { + ivpu_warn(vdev, "Failed to create sg table: %d\n", ret); + goto free_sgt; + } + + exp_info.exp_name = "ivpu_userptr_dmabuf"; + exp_info.owner = THIS_MODULE; + exp_info.ops = &ivpu_gem_userptr_dmabuf_ops; + exp_info.size = size; + exp_info.flags = O_RDWR | O_CLOEXEC; + exp_info.priv = sgt; + + dma_buf = dma_buf_export(&exp_info); + if (IS_ERR(dma_buf)) { + ret = PTR_ERR(dma_buf); + ivpu_warn(vdev, "Failed to export userptr dma-buf: %d\n", ret); + goto free_sg_table; + } + + kvfree(pages); + return dma_buf; + +free_sg_table: + sg_free_table(sgt); +free_sgt: + kfree(sgt); +unpin_pages: + for (i = 0; i < pinned; i++) + unpin_user_page(pages[i]); +free_pages_array: + kvfree(pages); + return ERR_PTR(ret); +} + +static struct ivpu_bo * +ivpu_bo_create_from_userptr(struct ivpu_device *vdev, void __user *user_ptr, + size_t size, uint32_t flags) +{ + struct dma_buf *dma_buf; + struct drm_gem_object *obj; + struct ivpu_bo *bo; + + dma_buf = ivpu_create_userptr_dmabuf(vdev, user_ptr, size, flags); + if (IS_ERR(dma_buf)) + return ERR_CAST(dma_buf); + + obj = ivpu_gem_prime_import(&vdev->drm, dma_buf); + if (IS_ERR(obj)) { + dma_buf_put(dma_buf); + return ERR_CAST(obj); + } + + dma_buf_put(dma_buf); + + bo = to_ivpu_bo(obj); + bo->flags = flags; + + return bo; +} + +int ivpu_bo_create_from_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct drm_ivpu_bo_create_from_userptr *args = data; + struct ivpu_file_priv *file_priv = file->driver_priv; + struct ivpu_device *vdev = to_ivpu_device(dev); + void __user *user_ptr = u64_to_user_ptr(args->user_ptr); + struct ivpu_bo *bo; + int ret; + + if (args->flags & ~(DRM_IVPU_BO_HIGH_MEM | DRM_IVPU_BO_DMA_MEM | DRM_IVPU_BO_READ_ONLY)) + return -EINVAL; + + if (!args->user_ptr || !args->size) + return -EINVAL; + + if (!PAGE_ALIGNED(args->user_ptr) || !PAGE_ALIGNED(args->size)) + return -EINVAL; + + if (!access_ok(user_ptr, args->size)) + return -EFAULT; + + bo = ivpu_bo_create_from_userptr(vdev, user_ptr, args->size, args->flags); + if (IS_ERR(bo)) + return PTR_ERR(bo); + + ret = drm_gem_handle_create(file, &bo->base.base, &args->handle); + if (ret) { + ivpu_err(vdev, "Failed to create handle for BO: %pe (ctx %u size %llu flags 0x%x)", + bo, file_priv->ctx.id, args->size, args->flags); + } else { + ivpu_dbg(vdev, BO, "Created userptr BO: handle=%u vpu_addr=0x%llx size=%llu flags=0x%x\n", + args->handle, bo->vpu_addr, args->size, bo->flags); + args->vpu_addr = bo->vpu_addr; + } + + drm_gem_object_put(&bo->base.base); + + return ret; +} diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c index 4ffc783426be..d128e8961688 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.c +++ b/drivers/accel/ivpu/ivpu_mmu_context.c @@ -430,7 +430,7 @@ static void ivpu_mmu_context_unmap_pages(struct ivpu_mmu_context *ctx, u64 vpu_a int ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, - u64 vpu_addr, struct sg_table *sgt, bool llc_coherent) + u64 vpu_addr, struct sg_table *sgt, bool llc_coherent, bool read_only) { size_t start_vpu_addr = vpu_addr; struct scatterlist *sg; @@ -450,6 +450,8 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, prot = IVPU_MMU_ENTRY_MAPPED; if (llc_coherent) prot |= IVPU_MMU_ENTRY_FLAG_LLC_COHERENT; + if (read_only) + prot |= IVPU_MMU_ENTRY_FLAG_RO; mutex_lock(&ctx->lock); diff --git a/drivers/accel/ivpu/ivpu_mmu_context.h b/drivers/accel/ivpu/ivpu_mmu_context.h index f255310968cf..663a11a9db11 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.h +++ b/drivers/accel/ivpu/ivpu_mmu_context.h @@ -42,7 +42,7 @@ int ivpu_mmu_context_insert_node(struct ivpu_mmu_context *ctx, const struct ivpu void ivpu_mmu_context_remove_node(struct ivpu_mmu_context *ctx, struct drm_mm_node *node); int ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, - u64 vpu_addr, struct sg_table *sgt, bool llc_coherent); + u64 vpu_addr, struct sg_table *sgt, bool llc_coherent, bool read_only); void ivpu_mmu_context_unmap_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u64 vpu_addr, struct sg_table *sgt); int ivpu_mmu_context_set_pages_ro(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, diff --git a/include/uapi/drm/ivpu_accel.h b/include/uapi/drm/ivpu_accel.h index e470b0221e02..264505d54f93 100644 --- a/include/uapi/drm/ivpu_accel.h +++ b/include/uapi/drm/ivpu_accel.h @@ -25,6 +25,7 @@ extern "C" { #define DRM_IVPU_CMDQ_CREATE 0x0b #define DRM_IVPU_CMDQ_DESTROY 0x0c #define DRM_IVPU_CMDQ_SUBMIT 0x0d +#define DRM_IVPU_BO_CREATE_FROM_USERPTR 0x0e #define DRM_IOCTL_IVPU_GET_PARAM \ DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_GET_PARAM, struct drm_ivpu_param) @@ -69,6 +70,10 @@ extern "C" { #define DRM_IOCTL_IVPU_CMDQ_SUBMIT \ DRM_IOW(DRM_COMMAND_BASE + DRM_IVPU_CMDQ_SUBMIT, struct drm_ivpu_cmdq_submit) +#define DRM_IOCTL_IVPU_BO_CREATE_FROM_USERPTR \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_BO_CREATE_FROM_USERPTR, \ + struct drm_ivpu_bo_create_from_userptr) + /** * DOC: contexts * @@ -127,6 +132,13 @@ extern "C" { * command queue destroy and submit job on specific command queue. */ #define DRM_IVPU_CAP_MANAGE_CMDQ 3 +/** + * DRM_IVPU_CAP_BO_CREATE_FROM_USERPTR + * + * Driver supports creating buffer objects from user space memory pointers. + * This allows creating GEM buffers from existing user memory regions. + */ +#define DRM_IVPU_CAP_BO_CREATE_FROM_USERPTR 4 /** * struct drm_ivpu_param - Get/Set VPU parameters @@ -194,6 +206,7 @@ struct drm_ivpu_param { #define DRM_IVPU_BO_HIGH_MEM DRM_IVPU_BO_SHAVE_MEM #define DRM_IVPU_BO_MAPPABLE 0x00000002 #define DRM_IVPU_BO_DMA_MEM 0x00000004 +#define DRM_IVPU_BO_READ_ONLY 0x00000008 #define DRM_IVPU_BO_CACHED 0x00000000 #define DRM_IVPU_BO_UNCACHED 0x00010000 @@ -204,6 +217,7 @@ struct drm_ivpu_param { (DRM_IVPU_BO_HIGH_MEM | \ DRM_IVPU_BO_MAPPABLE | \ DRM_IVPU_BO_DMA_MEM | \ + DRM_IVPU_BO_READ_ONLY | \ DRM_IVPU_BO_CACHE_MASK) /** @@ -255,6 +269,44 @@ struct drm_ivpu_bo_create { __u64 vpu_addr; }; +/** + * struct drm_ivpu_bo_create_from_userptr - Create dma-buf from user pointer + * + * Create a GEM buffer object from a user pointer to a memory region. + */ +struct drm_ivpu_bo_create_from_userptr { + /** @user_ptr: User pointer to memory region (must be page aligned) */ + __u64 user_ptr; + + /** @size: Size of the memory region in bytes (must be page aligned) */ + __u64 size; + + /** + * @flags: + * + * Supported flags: + * + * %DRM_IVPU_BO_HIGH_MEM: + * + * Allocate VPU address from >4GB range. + * + * %DRM_IVPU_BO_DMA_MEM: + * + * Allocate from DMA memory range accessible by hardware DMA. + * + * %DRM_IVPU_BO_READ_ONLY: + * + * Allocate as a read-only buffer object. + */ + __u32 flags; + + /** @handle: Returned GEM object handle */ + __u32 handle; + + /** @vpu_addr: Returned VPU virtual address */ + __u64 vpu_addr; +}; + /** * struct drm_ivpu_bo_info - Query buffer object info */ -- cgit v1.2.3 From dce4657ff526b65007fe8d5c92968a933cc7c9da Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 27 Oct 2025 13:09:12 +0100 Subject: drm/client: Remove pitch from struct drm_client_buffer Only the client-buffer setup uses the pitch field from struct drm_client_buffer. Remove the field and pass the value among setup helpers. Clients that need the pitch should rather look at the framebuffer's pitches[0] directly. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Tested-by: Francesco Valla Link: https://patch.msgid.link/20251027121042.143588-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_client.c | 14 +++++++------- include/drm/drm_client.h | 5 ----- 2 files changed, 7 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index fe9c6d7083ea..82b871d62313 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -188,7 +188,7 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer) static struct drm_client_buffer * drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, - u32 format, u32 *handle) + u32 format, u32 *handle, u32 *pitch) { const struct drm_format_info *info = drm_format_info(format); struct drm_mode_create_dumb dumb_args = { }; @@ -216,9 +216,9 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, goto err_delete; } - buffer->pitch = dumb_args.pitch; buffer->gem = obj; *handle = dumb_args.handle; + *pitch = dumb_args.pitch; return buffer; @@ -353,7 +353,7 @@ static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer) static int drm_client_buffer_addfb(struct drm_client_buffer *buffer, u32 width, u32 height, u32 format, - u32 handle) + u32 handle, u32 pitch) { struct drm_client_dev *client = buffer->client; struct drm_mode_fb_cmd2 fb_req = { }; @@ -363,7 +363,7 @@ static int drm_client_buffer_addfb(struct drm_client_buffer *buffer, fb_req.height = height; fb_req.pixel_format = format; fb_req.handles[0] = handle; - fb_req.pitches[0] = buffer->pitch; + fb_req.pitches[0] = pitch; ret = drm_mode_addfb2(client->dev, &fb_req, client->file); if (ret) @@ -399,15 +399,15 @@ struct drm_client_buffer * drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format) { struct drm_client_buffer *buffer; - u32 handle; + u32 handle, pitch; int ret; buffer = drm_client_buffer_create(client, width, height, format, - &handle); + &handle, &pitch); if (IS_ERR(buffer)) return buffer; - ret = drm_client_buffer_addfb(buffer, width, height, format, handle); + ret = drm_client_buffer_addfb(buffer, width, height, format, handle, pitch); /* * The handle is only needed for creating the framebuffer, destroy it diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 715b422952ee..c674464f7e74 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -173,11 +173,6 @@ struct drm_client_buffer { */ struct drm_client_dev *client; - /** - * @pitch: Buffer pitch - */ - u32 pitch; - /** * @gem: GEM object backing this buffer * -- cgit v1.2.3 From ea39f2e66e61035e203530977a3df428345d03e2 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 27 Oct 2025 13:09:15 +0100 Subject: drm/client: Deprecate struct drm_client_buffer.gem The client buffer's framebuffer holds a reference and pointer on each of its GEM buffer objects. Thus the field gem in the client- buffer struct is not necessary. Deprecated the field and convert the client-buffer helpers to use the framebuffer's objects. In drm_client_buffer_delete(), do a possible vunmap before releasing the framebuffer. Otherwise we'd eventually release the framebuffer before unmaping its buffer objects. v2: - avoid dependency on CONFIG_DRM_KMS_HELPER Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Tested-by: Francesco Valla Link: https://patch.msgid.link/20251027121042.143588-5-tzimmermann@suse.de --- drivers/gpu/drm/drm_client.c | 20 ++++++++++++-------- include/drm/drm_client.h | 9 +++------ 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index c4db4fc7ba69..0aa56c4b912b 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -178,17 +179,17 @@ EXPORT_SYMBOL(drm_client_release); static void drm_client_buffer_delete(struct drm_client_buffer *buffer) { + struct drm_gem_object *gem = buffer->fb->obj[0]; int ret; + drm_gem_vunmap(gem, &buffer->map); + ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file); if (ret) drm_err(buffer->client->dev, "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret); - if (buffer->gem) { - drm_gem_vunmap(buffer->gem, &buffer->map); - drm_gem_object_put(buffer->gem); - } + drm_gem_object_put(buffer->gem); kfree(buffer); } @@ -278,7 +279,7 @@ err_delete: int drm_client_buffer_vmap_local(struct drm_client_buffer *buffer, struct iosys_map *map_copy) { - struct drm_gem_object *gem = buffer->gem; + struct drm_gem_object *gem = buffer->fb->obj[0]; struct iosys_map *map = &buffer->map; int ret; @@ -307,7 +308,7 @@ EXPORT_SYMBOL(drm_client_buffer_vmap_local); */ void drm_client_buffer_vunmap_local(struct drm_client_buffer *buffer) { - struct drm_gem_object *gem = buffer->gem; + struct drm_gem_object *gem = buffer->fb->obj[0]; struct iosys_map *map = &buffer->map; drm_gem_vunmap_locked(gem, map); @@ -338,9 +339,10 @@ EXPORT_SYMBOL(drm_client_buffer_vunmap_local); int drm_client_buffer_vmap(struct drm_client_buffer *buffer, struct iosys_map *map_copy) { + struct drm_gem_object *gem = buffer->fb->obj[0]; int ret; - ret = drm_gem_vmap(buffer->gem, &buffer->map); + ret = drm_gem_vmap(gem, &buffer->map); if (ret) return ret; *map_copy = buffer->map; @@ -359,7 +361,9 @@ EXPORT_SYMBOL(drm_client_buffer_vmap); */ void drm_client_buffer_vunmap(struct drm_client_buffer *buffer) { - drm_gem_vunmap(buffer->gem, &buffer->map); + struct drm_gem_object *gem = buffer->fb->obj[0]; + + drm_gem_vunmap(gem, &buffer->map); } EXPORT_SYMBOL(drm_client_buffer_vunmap); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index c674464f7e74..b01fc2a21f09 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -176,12 +176,9 @@ struct drm_client_buffer { /** * @gem: GEM object backing this buffer * - * FIXME: The dependency on GEM here isn't required, we could - * convert the driver handle to a dma-buf instead and use the - * backend-agnostic dma-buf vmap support instead. This would - * require that the handle2fd prime ioctl is reworked to pull the - * fd_install step out of the driver backend hooks, to make that - * final step optional for internal users. + * FIXME: The DRM framebuffer holds a reference on its GEM + * buffer objects. Do not use this field in new code and + * update existing users. */ struct drm_gem_object *gem; -- cgit v1.2.3 From 3e3153325fd3693d0f9fe235c4afbcd68ef102e1 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 27 Oct 2025 13:09:16 +0100 Subject: drm/client: Remove drm_client_framebuffer_delete() Release client buffers with drm_client_buffer_delete() instead of drm_client_framebuffer_delete(). The latter is just a tiny wrapper around the former. Move the test for !buffer into drm_client_buffer_delete(), although all callers appear to always have a valid pointer. v2: - test for !buffer before deref-ing pointer (Jocelyn, Dan) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Tested-by: Francesco Valla Link: https://patch.msgid.link/20251027121042.143588-6-tzimmermann@suse.de --- drivers/gpu/drm/clients/drm_log.c | 4 ++-- drivers/gpu/drm/drm_client.c | 28 ++++++++++++---------------- drivers/gpu/drm/drm_fbdev_dma.c | 6 +++--- drivers/gpu/drm/drm_fbdev_shmem.c | 4 ++-- drivers/gpu/drm/drm_fbdev_ttm.c | 8 ++++---- include/drm/drm_client.h | 2 +- 6 files changed, 24 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/clients/drm_log.c b/drivers/gpu/drm/clients/drm_log.c index 24b08fdcb57a..c2ddc57b538e 100644 --- a/drivers/gpu/drm/clients/drm_log.c +++ b/drivers/gpu/drm/clients/drm_log.c @@ -272,7 +272,7 @@ static void drm_log_init_client(struct drm_log *dlog) err_failed_commit: for (i = 0; i < n_modeset; i++) - drm_client_framebuffer_delete(dlog->scanout[i].buffer); + drm_client_buffer_delete(dlog->scanout[i].buffer); err_nomodeset: kfree(dlog->scanout); @@ -286,7 +286,7 @@ static void drm_log_free_scanout(struct drm_client_dev *client) if (dlog->n_scanout) { for (i = 0; i < dlog->n_scanout; i++) - drm_client_framebuffer_delete(dlog->scanout[i].buffer); + drm_client_buffer_delete(dlog->scanout[i].buffer); dlog->n_scanout = 0; kfree(dlog->scanout); dlog->scanout = NULL; diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 0aa56c4b912b..b4e37bb2041b 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -177,11 +177,19 @@ void drm_client_release(struct drm_client_dev *client) } EXPORT_SYMBOL(drm_client_release); -static void drm_client_buffer_delete(struct drm_client_buffer *buffer) +/** + * drm_client_buffer_delete - Delete a client buffer + * @buffer: DRM client buffer + */ +void drm_client_buffer_delete(struct drm_client_buffer *buffer) { - struct drm_gem_object *gem = buffer->fb->obj[0]; + struct drm_gem_object *gem; int ret; + if (!buffer) + return; + + gem = buffer->fb->obj[0]; drm_gem_vunmap(gem, &buffer->map); ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file); @@ -193,6 +201,7 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer) kfree(buffer); } +EXPORT_SYMBOL(drm_client_buffer_delete); static struct drm_client_buffer * drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, @@ -376,7 +385,7 @@ EXPORT_SYMBOL(drm_client_buffer_vunmap); * * This function creates a &drm_client_buffer which consists of a * &drm_framebuffer backed by a dumb buffer. - * Call drm_client_framebuffer_delete() to free the buffer. + * Call drm_client_buffer_delete() to free the buffer. * * Returns: * Pointer to a client buffer or an error pointer on failure. @@ -420,19 +429,6 @@ err_drm_mode_destroy_dumb: } EXPORT_SYMBOL(drm_client_framebuffer_create); -/** - * drm_client_framebuffer_delete - Delete a client framebuffer - * @buffer: DRM client buffer (can be NULL) - */ -void drm_client_framebuffer_delete(struct drm_client_buffer *buffer) -{ - if (!buffer) - return; - - drm_client_buffer_delete(buffer); -} -EXPORT_SYMBOL(drm_client_framebuffer_delete); - /** * drm_client_framebuffer_flush - Manually flush client framebuffer * @buffer: DRM client buffer (can be NULL) diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c index c6196293e424..6216de1446c1 100644 --- a/drivers/gpu/drm/drm_fbdev_dma.c +++ b/drivers/gpu/drm/drm_fbdev_dma.c @@ -55,7 +55,7 @@ static void drm_fbdev_dma_fb_destroy(struct fb_info *info) drm_fb_helper_fini(fb_helper); drm_client_buffer_vunmap(fb_helper->buffer); - drm_client_framebuffer_delete(fb_helper->buffer); + drm_client_buffer_delete(fb_helper->buffer); drm_client_release(&fb_helper->client); } @@ -88,7 +88,7 @@ static void drm_fbdev_dma_shadowed_fb_destroy(struct fb_info *info) vfree(shadow); drm_client_buffer_vunmap(fb_helper->buffer); - drm_client_framebuffer_delete(fb_helper->buffer); + drm_client_buffer_delete(fb_helper->buffer); drm_client_release(&fb_helper->client); } @@ -324,7 +324,7 @@ err_drm_client_buffer_vunmap: fb_helper->buffer = NULL; drm_client_buffer_vunmap(buffer); err_drm_client_buffer_delete: - drm_client_framebuffer_delete(buffer); + drm_client_buffer_delete(buffer); return ret; } EXPORT_SYMBOL(drm_fbdev_dma_driver_fbdev_probe); diff --git a/drivers/gpu/drm/drm_fbdev_shmem.c b/drivers/gpu/drm/drm_fbdev_shmem.c index 51573058df6f..520c2218e5dc 100644 --- a/drivers/gpu/drm/drm_fbdev_shmem.c +++ b/drivers/gpu/drm/drm_fbdev_shmem.c @@ -63,7 +63,7 @@ static void drm_fbdev_shmem_fb_destroy(struct fb_info *info) drm_fb_helper_fini(fb_helper); drm_client_buffer_vunmap(fb_helper->buffer); - drm_client_framebuffer_delete(fb_helper->buffer); + drm_client_buffer_delete(fb_helper->buffer); drm_client_release(&fb_helper->client); } @@ -204,7 +204,7 @@ err_drm_client_buffer_vunmap: fb_helper->buffer = NULL; drm_client_buffer_vunmap(buffer); err_drm_client_buffer_delete: - drm_client_framebuffer_delete(buffer); + drm_client_buffer_delete(buffer); return ret; } EXPORT_SYMBOL(drm_fbdev_shmem_driver_fbdev_probe); diff --git a/drivers/gpu/drm/drm_fbdev_ttm.c b/drivers/gpu/drm/drm_fbdev_ttm.c index ccf460fbc1f0..7f7c88461228 100644 --- a/drivers/gpu/drm/drm_fbdev_ttm.c +++ b/drivers/gpu/drm/drm_fbdev_ttm.c @@ -50,7 +50,7 @@ static void drm_fbdev_ttm_fb_destroy(struct fb_info *info) fb_deferred_io_cleanup(info); drm_fb_helper_fini(fb_helper); vfree(shadow); - drm_client_framebuffer_delete(fb_helper->buffer); + drm_client_buffer_delete(fb_helper->buffer); drm_client_release(&fb_helper->client); } @@ -200,7 +200,7 @@ int drm_fbdev_ttm_driver_fbdev_probe(struct drm_fb_helper *fb_helper, screen_buffer = vzalloc(screen_size); if (!screen_buffer) { ret = -ENOMEM; - goto err_drm_client_framebuffer_delete; + goto err_drm_client_buffer_delete; } info = drm_fb_helper_alloc_info(fb_helper); @@ -233,10 +233,10 @@ err_drm_fb_helper_release_info: drm_fb_helper_release_info(fb_helper); err_vfree: vfree(screen_buffer); -err_drm_client_framebuffer_delete: +err_drm_client_buffer_delete: fb_helper->fb = NULL; fb_helper->buffer = NULL; - drm_client_framebuffer_delete(buffer); + drm_client_buffer_delete(buffer); return ret; } EXPORT_SYMBOL(drm_fbdev_ttm_driver_fbdev_probe); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index b01fc2a21f09..ffc4013b2e18 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -195,7 +195,7 @@ struct drm_client_buffer { struct drm_client_buffer * drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format); -void drm_client_framebuffer_delete(struct drm_client_buffer *buffer); +void drm_client_buffer_delete(struct drm_client_buffer *buffer); int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect); int drm_client_buffer_vmap_local(struct drm_client_buffer *buffer, struct iosys_map *map_copy); -- cgit v1.2.3 From c2707e0f8322607b65e5eb8362ba94a2aeb299b9 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 27 Oct 2025 13:09:17 +0100 Subject: drm/client: Create client buffers with drm_client_buffer_create_dumb() Rename drm_client_framebuffer_create() to drm_client_buffer_create_dump() and adapt callers. The new name reflects the function's purpose. Using dumb buffers is the easiest way for creating a GEM buffer in a drivers- independent way. There's also drm_client_buffer_create(), which creates the client buffer from a preexisting buffer object. This helper can be exported for drivers that create their own GEM buffer object. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Tested-by: Francesco Valla Link: https://patch.msgid.link/20251027121042.143588-7-tzimmermann@suse.de --- drivers/gpu/drm/clients/drm_log.c | 2 +- drivers/gpu/drm/drm_client.c | 6 +++--- drivers/gpu/drm/drm_fbdev_dma.c | 2 +- drivers/gpu/drm/drm_fbdev_shmem.c | 2 +- drivers/gpu/drm/drm_fbdev_ttm.c | 2 +- include/drm/drm_client.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/clients/drm_log.c b/drivers/gpu/drm/clients/drm_log.c index c2ddc57b538e..48636bb1a21e 100644 --- a/drivers/gpu/drm/clients/drm_log.c +++ b/drivers/gpu/drm/clients/drm_log.c @@ -204,7 +204,7 @@ static int drm_log_setup_modeset(struct drm_client_dev *client, if (format == DRM_FORMAT_INVALID) return -EINVAL; - scanout->buffer = drm_client_framebuffer_create(client, width, height, format); + scanout->buffer = drm_client_buffer_create_dumb(client, width, height, format); if (IS_ERR(scanout->buffer)) { drm_warn(client->dev, "drm_log can't create framebuffer %d %d %p4cc\n", width, height, &format); diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index b4e37bb2041b..e7dfbdeca45a 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -377,7 +377,7 @@ void drm_client_buffer_vunmap(struct drm_client_buffer *buffer) EXPORT_SYMBOL(drm_client_buffer_vunmap); /** - * drm_client_framebuffer_create - Create a client framebuffer + * drm_client_buffer_create_dumb - Create a client buffer backed by a dumb buffer * @client: DRM client * @width: Framebuffer width * @height: Framebuffer height @@ -391,7 +391,7 @@ EXPORT_SYMBOL(drm_client_buffer_vunmap); * Pointer to a client buffer or an error pointer on failure. */ struct drm_client_buffer * -drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format) +drm_client_buffer_create_dumb(struct drm_client_dev *client, u32 width, u32 height, u32 format) { const struct drm_format_info *info = drm_format_info(format); struct drm_device *dev = client->dev; @@ -427,7 +427,7 @@ err_drm_mode_destroy_dumb: drm_mode_destroy_dumb(client->dev, dumb_args.handle, client->file); return ERR_PTR(ret); } -EXPORT_SYMBOL(drm_client_framebuffer_create); +EXPORT_SYMBOL(drm_client_buffer_create_dumb); /** * drm_client_framebuffer_flush - Manually flush client framebuffer diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c index 6216de1446c1..876bd8cfc5ea 100644 --- a/drivers/gpu/drm/drm_fbdev_dma.c +++ b/drivers/gpu/drm/drm_fbdev_dma.c @@ -281,7 +281,7 @@ int drm_fbdev_dma_driver_fbdev_probe(struct drm_fb_helper *fb_helper, format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp, sizes->surface_depth); - buffer = drm_client_framebuffer_create(client, sizes->surface_width, + buffer = drm_client_buffer_create_dumb(client, sizes->surface_width, sizes->surface_height, format); if (IS_ERR(buffer)) return PTR_ERR(buffer); diff --git a/drivers/gpu/drm/drm_fbdev_shmem.c b/drivers/gpu/drm/drm_fbdev_shmem.c index 520c2218e5dc..46e43b60b3f9 100644 --- a/drivers/gpu/drm/drm_fbdev_shmem.c +++ b/drivers/gpu/drm/drm_fbdev_shmem.c @@ -147,7 +147,7 @@ int drm_fbdev_shmem_driver_fbdev_probe(struct drm_fb_helper *fb_helper, sizes->surface_bpp); format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp, sizes->surface_depth); - buffer = drm_client_framebuffer_create(client, sizes->surface_width, + buffer = drm_client_buffer_create_dumb(client, sizes->surface_width, sizes->surface_height, format); if (IS_ERR(buffer)) return PTR_ERR(buffer); diff --git a/drivers/gpu/drm/drm_fbdev_ttm.c b/drivers/gpu/drm/drm_fbdev_ttm.c index 7f7c88461228..c7ad779ba590 100644 --- a/drivers/gpu/drm/drm_fbdev_ttm.c +++ b/drivers/gpu/drm/drm_fbdev_ttm.c @@ -187,7 +187,7 @@ int drm_fbdev_ttm_driver_fbdev_probe(struct drm_fb_helper *fb_helper, format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp, sizes->surface_depth); - buffer = drm_client_framebuffer_create(client, sizes->surface_width, + buffer = drm_client_buffer_create_dumb(client, sizes->surface_width, sizes->surface_height, format); if (IS_ERR(buffer)) return PTR_ERR(buffer); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index ffc4013b2e18..690ef04fccce 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -194,7 +194,7 @@ struct drm_client_buffer { }; struct drm_client_buffer * -drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format); +drm_client_buffer_create_dumb(struct drm_client_dev *client, u32 width, u32 height, u32 format); void drm_client_buffer_delete(struct drm_client_buffer *buffer); int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect); int drm_client_buffer_vmap_local(struct drm_client_buffer *buffer, -- cgit v1.2.3 From 231668043d4ffebda28630b120cddcba384a3318 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 27 Oct 2025 13:09:18 +0100 Subject: drm/client: Flush client buffers with drm_client_buffer_sync() Rename drm_client_framebuffer_flush() to drm_cient_buffer_flush() and adapt its callers. The old name was left over from previous naming conventions. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe > Tested-by: Francesco Valla Link: https://patch.msgid.link/20251027121042.143588-8-tzimmermann@suse.de --- drivers/gpu/drm/clients/drm_log.c | 4 ++-- drivers/gpu/drm/drm_client.c | 8 ++++---- include/drm/drm_client.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/clients/drm_log.c b/drivers/gpu/drm/clients/drm_log.c index 48636bb1a21e..19e55aa0ed74 100644 --- a/drivers/gpu/drm/clients/drm_log.c +++ b/drivers/gpu/drm/clients/drm_log.c @@ -100,7 +100,7 @@ static void drm_log_clear_line(struct drm_log_scanout *scanout, u32 line) return; iosys_map_memset(&map, r.y1 * fb->pitches[0], 0, height * fb->pitches[0]); drm_client_buffer_vunmap_local(scanout->buffer); - drm_client_framebuffer_flush(scanout->buffer, &r); + drm_client_buffer_flush(scanout->buffer, &r); } static void drm_log_draw_line(struct drm_log_scanout *scanout, const char *s, @@ -133,7 +133,7 @@ static void drm_log_draw_line(struct drm_log_scanout *scanout, const char *s, if (scanout->line >= scanout->rows) scanout->line = 0; drm_client_buffer_vunmap_local(scanout->buffer); - drm_client_framebuffer_flush(scanout->buffer, &r); + drm_client_buffer_flush(scanout->buffer, &r); } static void drm_log_draw_new_line(struct drm_log_scanout *scanout, diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index e7dfbdeca45a..504ec5bdfa2c 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -430,8 +430,8 @@ err_drm_mode_destroy_dumb: EXPORT_SYMBOL(drm_client_buffer_create_dumb); /** - * drm_client_framebuffer_flush - Manually flush client framebuffer - * @buffer: DRM client buffer (can be NULL) + * drm_client_buffer_flush - Manually flush client buffer + * @buffer: DRM client buffer * @rect: Damage rectangle (if NULL flushes all) * * This calls &drm_framebuffer_funcs->dirty (if present) to flush buffer changes @@ -440,7 +440,7 @@ EXPORT_SYMBOL(drm_client_buffer_create_dumb); * Returns: * Zero on success or negative error code on failure. */ -int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect) +int drm_client_buffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect) { if (!buffer || !buffer->fb || !buffer->fb->funcs->dirty) return 0; @@ -460,4 +460,4 @@ int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_re return buffer->fb->funcs->dirty(buffer->fb, buffer->client->file, 0, 0, NULL, 0); } -EXPORT_SYMBOL(drm_client_framebuffer_flush); +EXPORT_SYMBOL(drm_client_buffer_flush); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 690ef04fccce..5ecde0f6f591 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -196,7 +196,7 @@ struct drm_client_buffer { struct drm_client_buffer * drm_client_buffer_create_dumb(struct drm_client_dev *client, u32 width, u32 height, u32 format); void drm_client_buffer_delete(struct drm_client_buffer *buffer); -int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect); +int drm_client_buffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect); int drm_client_buffer_vmap_local(struct drm_client_buffer *buffer, struct iosys_map *map_copy); void drm_client_buffer_vunmap_local(struct drm_client_buffer *buffer); -- cgit v1.2.3 From 9695c143b72a7faa2dbbb2a5881269f82e6f9783 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Oct 2025 12:39:46 +0200 Subject: drm/buddy: replace drm_print.h include with a forward declaration The drm_buddy.h header does not really need anything from drm_print.h. A simple forward declaration for struct drm_printer is sufficient. An explicit drm_print.h include has previously been added to all the files that indirectly depended on this include. v3: Only remove the include here (Thomas) Cc: Thomas Zimmermann Reviewed-by: Thomas Zimmermann Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/b303996b407fcbe2c7357bea036f79c45d6dae49.1761734313.git.jani.nikula@intel.com --- include/drm/drm_buddy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h index c2e05a281252..b909fa8f810a 100644 --- a/include/drm/drm_buddy.h +++ b/include/drm/drm_buddy.h @@ -12,7 +12,7 @@ #include #include -#include +struct drm_printer; #define DRM_BUDDY_RANGE_ALLOCATION BIT(0) #define DRM_BUDDY_TOPDOWN_ALLOCATION BIT(1) -- cgit v1.2.3 From ea722522d505fa8fb3533a386adeb400607e5072 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Oct 2025 12:39:47 +0200 Subject: drm/mm: replace drm_print.h include with a forward declaration The drm_mm.h header does not really need anything from drm_print.h. A simple forward declaration for struct drm_printer is sufficient. An explicit drm_print.h include has previously been added to all the files that indirectly depended on this include. v3: Only remove the include here (Thomas) Cc: Thomas Zimmermann Reviewed-by: Thomas Zimmermann Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/7d570ed1f0f0f14cac346bea50bce9ef02ddd166.1761734313.git.jani.nikula@intel.com --- include/drm/drm_mm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index f654874c4ce6..16ce0e8f36a6 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -48,7 +48,7 @@ #endif #include -#include +struct drm_printer; #ifdef CONFIG_DRM_DEBUG_MM #define DRM_MM_BUG_ON(expr) BUG_ON(expr) -- cgit v1.2.3 From d7a849d126d0a75b2c5101f82d0c9693e04a43fd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Oct 2025 12:39:48 +0200 Subject: drm/ttm: replace drm_print.h include with a forward declaration The ttm/ttm_resource.h header does not really need anything from drm_print.h. A simple forward declaration for struct drm_printer is sufficient. An explicit drm_print.h include has previously been added to all the files that indirectly depended on this include. v3: Only remove the include here (Thomas) Cc: Thomas Zimmermann Reviewed-by: Thomas Zimmermann Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/cfdb1095033112c2a7e58767481c98929984a33c.1761734313.git.jani.nikula@intel.com --- include/drm/ttm/ttm_resource.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index f49daa504c36..68bf010d8b40 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -31,14 +31,15 @@ #include #include -#include #include #include #define TTM_MAX_BO_PRIORITY 4U #define TTM_NUM_MEM_TYPES 9 +struct dentry; struct dmem_cgroup_device; +struct drm_printer; struct ttm_device; struct ttm_resource_manager; struct ttm_resource; -- cgit v1.2.3 From 0af5b6a8f8dd41fd801bb0f2af3295d69ba8b7fe Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 20 Oct 2025 12:54:07 +0100 Subject: drm/ttm: Replace multiple booleans with flags in pool init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multiple consecutive boolean function arguments are usually not very readable. Replace the ones in ttm_pool_init() with flags with the additional benefit of soon being able to pass in more data with just this one code base churning cost. Signed-off-by: Tvrtko Ursulin Cc: Alex Deucher Cc: Christian König Cc: Thomas Hellström Reviewed-by: Christian König Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20251020115411.36818-3-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/ttm/tests/ttm_device_test.c | 25 ++++++++++--------------- drivers/gpu/drm/ttm/tests/ttm_pool_test.c | 24 +++++++++++------------- drivers/gpu/drm/ttm/ttm_device.c | 5 ++++- drivers/gpu/drm/ttm/ttm_pool.c | 8 +++----- drivers/gpu/drm/ttm/ttm_pool_internal.h | 5 +++-- include/drm/ttm/ttm_allocation.h | 10 ++++++++++ include/drm/ttm/ttm_pool.h | 8 +++----- 8 files changed, 45 insertions(+), 42 deletions(-) create mode 100644 include/drm/ttm/ttm_allocation.h (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index aa9ee5dffa45..8f6d331e1ea2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1837,7 +1837,7 @@ static int amdgpu_ttm_pools_init(struct amdgpu_device *adev) for (i = 0; i < adev->gmc.num_mem_partitions; i++) { ttm_pool_init(&adev->mman.ttm_pools[i], adev->dev, adev->gmc.mem_partitions[i].numa.node, - false, false); + 0); } return 0; } diff --git a/drivers/gpu/drm/ttm/tests/ttm_device_test.c b/drivers/gpu/drm/ttm/tests/ttm_device_test.c index 1621903818e5..98648d5f20e7 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_device_test.c +++ b/drivers/gpu/drm/ttm/tests/ttm_device_test.c @@ -7,11 +7,11 @@ #include #include "ttm_kunit_helpers.h" +#include "../ttm_pool_internal.h" struct ttm_device_test_case { const char *description; - bool use_dma_alloc; - bool use_dma32; + unsigned int alloc_flags; bool pools_init_expected; }; @@ -119,26 +119,22 @@ static void ttm_device_init_no_vma_man(struct kunit *test) static const struct ttm_device_test_case ttm_device_cases[] = { { .description = "No DMA allocations, no DMA32 required", - .use_dma_alloc = false, - .use_dma32 = false, .pools_init_expected = false, }, { .description = "DMA allocations, DMA32 required", - .use_dma_alloc = true, - .use_dma32 = true, + .alloc_flags = TTM_ALLOCATION_POOL_USE_DMA_ALLOC | + TTM_ALLOCATION_POOL_USE_DMA32, .pools_init_expected = true, }, { .description = "No DMA allocations, DMA32 required", - .use_dma_alloc = false, - .use_dma32 = true, + .alloc_flags = TTM_ALLOCATION_POOL_USE_DMA32, .pools_init_expected = false, }, { .description = "DMA allocations, no DMA32 required", - .use_dma_alloc = true, - .use_dma32 = false, + .alloc_flags = TTM_ALLOCATION_POOL_USE_DMA_ALLOC, .pools_init_expected = true, }, }; @@ -163,15 +159,14 @@ static void ttm_device_init_pools(struct kunit *test) KUNIT_ASSERT_NOT_NULL(test, ttm_dev); err = ttm_device_kunit_init(priv, ttm_dev, - params->use_dma_alloc, - params->use_dma32); + params->alloc_flags & TTM_ALLOCATION_POOL_USE_DMA_ALLOC, + params->alloc_flags & TTM_ALLOCATION_POOL_USE_DMA32); KUNIT_ASSERT_EQ(test, err, 0); pool = &ttm_dev->pool; KUNIT_ASSERT_NOT_NULL(test, pool); KUNIT_EXPECT_PTR_EQ(test, pool->dev, priv->dev); - KUNIT_EXPECT_EQ(test, pool->use_dma_alloc, params->use_dma_alloc); - KUNIT_EXPECT_EQ(test, pool->use_dma32, params->use_dma32); + KUNIT_EXPECT_EQ(test, pool->alloc_flags, params->alloc_flags); if (params->pools_init_expected) { for (int i = 0; i < TTM_NUM_CACHING_TYPES; ++i) { @@ -181,7 +176,7 @@ static void ttm_device_init_pools(struct kunit *test) KUNIT_EXPECT_EQ(test, pt.caching, i); KUNIT_EXPECT_EQ(test, pt.order, j); - if (params->use_dma_alloc) + if (ttm_pool_uses_dma_alloc(pool)) KUNIT_ASSERT_FALSE(test, list_empty(&pt.pages)); } diff --git a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c index 17ebb9fbd688..11c92bd75779 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c +++ b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c @@ -13,7 +13,7 @@ struct ttm_pool_test_case { const char *description; unsigned int order; - bool use_dma_alloc; + unsigned int alloc_flags; }; struct ttm_pool_test_priv { @@ -87,7 +87,7 @@ static struct ttm_pool *ttm_pool_pre_populated(struct kunit *test, pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, pool); - ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, true, false); + ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, TTM_ALLOCATION_POOL_USE_DMA_ALLOC); err = ttm_pool_alloc(pool, tt, &simple_ctx); KUNIT_ASSERT_EQ(test, err, 0); @@ -114,12 +114,12 @@ static const struct ttm_pool_test_case ttm_pool_basic_cases[] = { { .description = "One page, with coherent DMA mappings enabled", .order = 0, - .use_dma_alloc = true, + .alloc_flags = TTM_ALLOCATION_POOL_USE_DMA_ALLOC, }, { .description = "Above the allocation limit, with coherent DMA mappings enabled", .order = MAX_PAGE_ORDER + 1, - .use_dma_alloc = true, + .alloc_flags = TTM_ALLOCATION_POOL_USE_DMA_ALLOC, }, }; @@ -151,13 +151,11 @@ static void ttm_pool_alloc_basic(struct kunit *test) pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, pool); - ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, params->use_dma_alloc, - false); + ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, params->alloc_flags); KUNIT_ASSERT_PTR_EQ(test, pool->dev, devs->dev); KUNIT_ASSERT_EQ(test, pool->nid, NUMA_NO_NODE); - KUNIT_ASSERT_EQ(test, ttm_pool_uses_dma_alloc(pool), - params->use_dma_alloc); + KUNIT_ASSERT_EQ(test, pool->alloc_flags, params->alloc_flags); err = ttm_pool_alloc(pool, tt, &simple_ctx); KUNIT_ASSERT_EQ(test, err, 0); @@ -167,14 +165,14 @@ static void ttm_pool_alloc_basic(struct kunit *test) last_page = tt->pages[tt->num_pages - 1]; if (params->order <= MAX_PAGE_ORDER) { - if (params->use_dma_alloc) { + if (ttm_pool_uses_dma_alloc(pool)) { KUNIT_ASSERT_NOT_NULL(test, (void *)fst_page->private); KUNIT_ASSERT_NOT_NULL(test, (void *)last_page->private); } else { KUNIT_ASSERT_EQ(test, fst_page->private, params->order); } } else { - if (params->use_dma_alloc) { + if (ttm_pool_uses_dma_alloc(pool)) { KUNIT_ASSERT_NOT_NULL(test, (void *)fst_page->private); KUNIT_ASSERT_NULL(test, (void *)last_page->private); } else { @@ -220,7 +218,7 @@ static void ttm_pool_alloc_basic_dma_addr(struct kunit *test) pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, pool); - ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, true, false); + ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, TTM_ALLOCATION_POOL_USE_DMA_ALLOC); err = ttm_pool_alloc(pool, tt, &simple_ctx); KUNIT_ASSERT_EQ(test, err, 0); @@ -350,7 +348,7 @@ static void ttm_pool_free_dma_alloc(struct kunit *test) pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, pool); - ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, true, false); + ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, TTM_ALLOCATION_POOL_USE_DMA_ALLOC); ttm_pool_alloc(pool, tt, &simple_ctx); pt = &pool->caching[caching].orders[order]; @@ -381,7 +379,7 @@ static void ttm_pool_free_no_dma_alloc(struct kunit *test) pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, pool); - ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, false, false); + ttm_pool_init(pool, devs->dev, NUMA_NO_NODE, 0); ttm_pool_alloc(pool, tt, &simple_ctx); pt = &pool->caching[caching].orders[order]; diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index c3e2fcbdd2cc..a97b1444536c 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -236,7 +237,9 @@ int ttm_device_init(struct ttm_device *bdev, const struct ttm_device_funcs *func else nid = NUMA_NO_NODE; - ttm_pool_init(&bdev->pool, dev, nid, use_dma_alloc, use_dma32); + ttm_pool_init(&bdev->pool, dev, nid, + (use_dma_alloc ? TTM_ALLOCATION_POOL_USE_DMA_ALLOC : 0) | + (use_dma32 ? TTM_ALLOCATION_POOL_USE_DMA32 : 0)); bdev->vma_manager = vma_manager; spin_lock_init(&bdev->lru_lock); diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index ff6fab4122bb..4fc69447060c 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -1059,13 +1059,12 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt, * @pool: the pool to initialize * @dev: device for DMA allocations and mappings * @nid: NUMA node to use for allocations - * @use_dma_alloc: true if coherent DMA alloc should be used - * @use_dma32: true if GFP_DMA32 should be used + * @alloc_flags: TTM_ALLOCATION_POOL_ flags * * Initialize the pool and its pool types. */ void ttm_pool_init(struct ttm_pool *pool, struct device *dev, - int nid, bool use_dma_alloc, bool use_dma32) + int nid, unsigned int alloc_flags) { unsigned int i, j; @@ -1073,8 +1072,7 @@ void ttm_pool_init(struct ttm_pool *pool, struct device *dev, pool->dev = dev; pool->nid = nid; - pool->use_dma_alloc = use_dma_alloc; - pool->use_dma32 = use_dma32; + pool->alloc_flags = alloc_flags; for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) { for (j = 0; j < NR_PAGE_ORDERS; ++j) { diff --git a/drivers/gpu/drm/ttm/ttm_pool_internal.h b/drivers/gpu/drm/ttm/ttm_pool_internal.h index 3e50d30bd95a..96b7f21514fb 100644 --- a/drivers/gpu/drm/ttm/ttm_pool_internal.h +++ b/drivers/gpu/drm/ttm/ttm_pool_internal.h @@ -4,16 +4,17 @@ #ifndef _TTM_POOL_INTERNAL_H_ #define _TTM_POOL_INTERNAL_H_ +#include #include static inline bool ttm_pool_uses_dma_alloc(struct ttm_pool *pool) { - return pool->use_dma_alloc; + return pool->alloc_flags & TTM_ALLOCATION_POOL_USE_DMA_ALLOC; } static inline bool ttm_pool_uses_dma32(struct ttm_pool *pool) { - return pool->use_dma32; + return pool->alloc_flags & TTM_ALLOCATION_POOL_USE_DMA32; } #endif diff --git a/include/drm/ttm/ttm_allocation.h b/include/drm/ttm/ttm_allocation.h new file mode 100644 index 000000000000..7869dc32bd91 --- /dev/null +++ b/include/drm/ttm/ttm_allocation.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* Copyright (c) 2025 Valve Corporation */ + +#ifndef _TTM_ALLOCATION_H_ +#define _TTM_ALLOCATION_H_ + +#define TTM_ALLOCATION_POOL_USE_DMA_ALLOC BIT(0) /* Use coherent DMA allocations. */ +#define TTM_ALLOCATION_POOL_USE_DMA32 BIT(1) /* Use GFP_DMA32 allocations. */ + +#endif diff --git a/include/drm/ttm/ttm_pool.h b/include/drm/ttm/ttm_pool.h index 54cd34a6e4c0..67c72de913bb 100644 --- a/include/drm/ttm/ttm_pool.h +++ b/include/drm/ttm/ttm_pool.h @@ -64,16 +64,14 @@ struct ttm_pool_type { * * @dev: the device we allocate pages for * @nid: which numa node to use - * @use_dma_alloc: if coherent DMA allocations should be used - * @use_dma32: if GFP_DMA32 should be used + * @alloc_flags: TTM_ALLOCATION_POOL_ flags * @caching: pools for each caching/order */ struct ttm_pool { struct device *dev; int nid; - bool use_dma_alloc; - bool use_dma32; + unsigned int alloc_flags; struct { struct ttm_pool_type orders[NR_PAGE_ORDERS]; @@ -85,7 +83,7 @@ int ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt, void ttm_pool_free(struct ttm_pool *pool, struct ttm_tt *tt); void ttm_pool_init(struct ttm_pool *pool, struct device *dev, - int nid, bool use_dma_alloc, bool use_dma32); + int nid, unsigned int alloc_flags); void ttm_pool_fini(struct ttm_pool *pool); int ttm_pool_debugfs(struct ttm_pool *pool, struct seq_file *m); -- cgit v1.2.3 From 77e19f8d32979f00b7c2cbcb35dbbf6f2116518e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 20 Oct 2025 12:54:08 +0100 Subject: drm/ttm: Replace multiple booleans with flags in device init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multiple consecutive boolean function arguments are usually not very readable. Replace the ones in ttm_device_init() with flags with the additional benefit of soon being able to pass in more data with just a one off code base churning cost. Signed-off-by: Tvrtko Ursulin Cc: Alex Deucher Cc: Christian König Cc: Danilo Krummrich Cc: Dave Airlie Cc: Gerd Hoffmann Cc: Joonas Lahtinen Cc: Lucas De Marchi Cc: Lyude Paul Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Rodrigo Vivi Cc: Sui Jingfeng Cc: Thomas Hellström Cc: Thomas Zimmermann Cc: Zack Rusin Acked-by: Christian König Acked-by: Zack Rusin Acked-by: Thomas Hellström # For xe Reviewed-by: Christian König Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20251020115411.36818-4-tvrtko.ursulin@igalia.com [tursulin: fixup checkpatch while applying] --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 ++++-- drivers/gpu/drm/drm_gem_vram_helper.c | 2 +- drivers/gpu/drm/i915/intel_region_ttm.c | 2 +- drivers/gpu/drm/loongson/lsdc_ttm.c | 3 ++- drivers/gpu/drm/nouveau/nouveau_ttm.c | 6 ++++-- drivers/gpu/drm/qxl/qxl_ttm.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 6 ++++-- drivers/gpu/drm/ttm/tests/ttm_bo_test.c | 16 ++++++++-------- drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c | 2 +- drivers/gpu/drm/ttm/tests/ttm_device_test.c | 12 +++++------- drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c | 22 +++++++++------------- drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h | 7 ++----- drivers/gpu/drm/ttm/ttm_device.c | 9 +++------ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 4 ++-- drivers/gpu/drm/xe/xe_device.c | 2 +- include/drm/ttm/ttm_device.h | 3 ++- 16 files changed, 50 insertions(+), 54 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8f6d331e1ea2..7b144ddea268 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1930,8 +1930,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) r = ttm_device_init(&adev->mman.bdev, &amdgpu_bo_driver, adev->dev, adev_to_drm(adev)->anon_inode->i_mapping, adev_to_drm(adev)->vma_offset_manager, - adev->need_swiotlb, - dma_addressing_limited(adev->dev)); + (adev->need_swiotlb ? + TTM_ALLOCATION_POOL_USE_DMA_ALLOC : 0) | + (dma_addressing_limited(adev->dev) ? + TTM_ALLOCATION_POOL_USE_DMA32 : 0)); if (r) { dev_err(adev->dev, "failed initializing buffer object driver(%d).\n", r); diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 9996d42ddc97..5e5b70518dbe 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -860,7 +860,7 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, ret = ttm_device_init(&vmm->bdev, &bo_driver, dev->dev, dev->anon_inode->i_mapping, dev->vma_offset_manager, - false, true); + TTM_ALLOCATION_POOL_USE_DMA32); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c index 04525d92bec5..47a69aad5c3f 100644 --- a/drivers/gpu/drm/i915/intel_region_ttm.c +++ b/drivers/gpu/drm/i915/intel_region_ttm.c @@ -34,7 +34,7 @@ int intel_region_ttm_device_init(struct drm_i915_private *dev_priv) return ttm_device_init(&dev_priv->bdev, i915_ttm_driver(), drm->dev, drm->anon_inode->i_mapping, - drm->vma_offset_manager, false, false); + drm->vma_offset_manager, 0); } /** diff --git a/drivers/gpu/drm/loongson/lsdc_ttm.c b/drivers/gpu/drm/loongson/lsdc_ttm.c index 383a758bbd7e..5d9075634bf8 100644 --- a/drivers/gpu/drm/loongson/lsdc_ttm.c +++ b/drivers/gpu/drm/loongson/lsdc_ttm.c @@ -545,7 +545,8 @@ int lsdc_ttm_init(struct lsdc_device *ldev) ret = ttm_device_init(&ldev->bdev, &lsdc_bo_driver, ddev->dev, ddev->anon_inode->i_mapping, - ddev->vma_offset_manager, false, true); + ddev->vma_offset_manager, + TTM_ALLOCATION_POOL_USE_DMA32); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 7d2436e5d50d..0a55babdf667 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -302,8 +302,10 @@ nouveau_ttm_init(struct nouveau_drm *drm) ret = ttm_device_init(&drm->ttm.bdev, &nouveau_bo_driver, drm->dev->dev, dev->anon_inode->i_mapping, dev->vma_offset_manager, - drm_need_swiotlb(drm->client.mmu.dmabits), - drm->client.mmu.dmabits <= 32); + (drm_need_swiotlb(drm->client.mmu.dmabits) ? + TTM_ALLOCATION_POOL_USE_DMA_ALLOC : 0) | + (drm->client.mmu.dmabits <= 32 ? + TTM_ALLOCATION_POOL_USE_DMA32 : 0)); if (ret) { NV_ERROR(drm, "error initialising bo driver, %d\n", ret); return ret; diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index a6dd2d1f1004..1a40590077dd 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -197,7 +197,7 @@ int qxl_ttm_init(struct qxl_device *qdev) r = ttm_device_init(&qdev->mman.bdev, &qxl_bo_driver, NULL, qdev->ddev.anon_inode->i_mapping, qdev->ddev.vma_offset_manager, - false, false); + 0); if (r) { DRM_ERROR("failed initializing buffer object driver(%d).\n", r); return r; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 616d25c8c2de..695ac32f7535 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -683,8 +683,10 @@ int radeon_ttm_init(struct radeon_device *rdev) r = ttm_device_init(&rdev->mman.bdev, &radeon_bo_driver, rdev->dev, rdev_to_drm(rdev)->anon_inode->i_mapping, rdev_to_drm(rdev)->vma_offset_manager, - rdev->need_swiotlb, - dma_addressing_limited(&rdev->pdev->dev)); + (rdev->need_swiotlb ? + TTM_ALLOCATION_POOL_USE_DMA_ALLOC : 0) | + (dma_addressing_limited(&rdev->pdev->dev) ? + TTM_ALLOCATION_POOL_USE_DMA32 : 0)); if (r) { DRM_ERROR("failed initializing buffer object driver(%d).\n", r); return r; diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c index 5426b435f702..d468f8322072 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c +++ b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c @@ -251,7 +251,7 @@ static void ttm_bo_unreserve_basic(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); priv->ttm_dev = ttm_dev; @@ -290,7 +290,7 @@ static void ttm_bo_unreserve_pinned(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); priv->ttm_dev = ttm_dev; @@ -342,7 +342,7 @@ static void ttm_bo_unreserve_bulk(struct kunit *test) resv = kunit_kzalloc(test, sizeof(*resv), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, resv); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); priv->ttm_dev = ttm_dev; @@ -394,7 +394,7 @@ static void ttm_bo_fini_basic(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); priv->ttm_dev = ttm_dev; @@ -437,7 +437,7 @@ static void ttm_bo_fini_shared_resv(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); priv->ttm_dev = ttm_dev; @@ -477,7 +477,7 @@ static void ttm_bo_pin_basic(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); priv->ttm_dev = ttm_dev; @@ -512,7 +512,7 @@ static void ttm_bo_pin_unpin_resource(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); priv->ttm_dev = ttm_dev; @@ -563,7 +563,7 @@ static void ttm_bo_multiple_pin_one_unpin(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); priv->ttm_dev = ttm_dev; diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c index 3a1eef83190c..17a570af296c 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c +++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c @@ -995,7 +995,7 @@ static void ttm_bo_validate_busy_domain_evict(struct kunit *test) */ ttm_device_fini(priv->ttm_dev); - err = ttm_device_kunit_init_bad_evict(test->priv, priv->ttm_dev, false, false); + err = ttm_device_kunit_init_bad_evict(test->priv, priv->ttm_dev); KUNIT_ASSERT_EQ(test, err, 0); ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); diff --git a/drivers/gpu/drm/ttm/tests/ttm_device_test.c b/drivers/gpu/drm/ttm/tests/ttm_device_test.c index 98648d5f20e7..2d55ad34fe48 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_device_test.c +++ b/drivers/gpu/drm/ttm/tests/ttm_device_test.c @@ -25,7 +25,7 @@ static void ttm_device_init_basic(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); KUNIT_EXPECT_PTR_EQ(test, ttm_dev->funcs, &ttm_dev_funcs); @@ -55,7 +55,7 @@ static void ttm_device_init_multiple(struct kunit *test) KUNIT_ASSERT_NOT_NULL(test, ttm_devs); for (i = 0; i < num_dev; i++) { - err = ttm_device_kunit_init(priv, &ttm_devs[i], false, false); + err = ttm_device_kunit_init(priv, &ttm_devs[i], 0); KUNIT_ASSERT_EQ(test, err, 0); KUNIT_EXPECT_PTR_EQ(test, ttm_devs[i].dev_mapping, @@ -81,7 +81,7 @@ static void ttm_device_fini_basic(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); man = ttm_manager_type(ttm_dev, TTM_PL_SYSTEM); @@ -109,7 +109,7 @@ static void ttm_device_init_no_vma_man(struct kunit *test) vma_man = drm->vma_offset_manager; drm->vma_offset_manager = NULL; - err = ttm_device_kunit_init(priv, ttm_dev, false, false); + err = ttm_device_kunit_init(priv, ttm_dev, 0); KUNIT_EXPECT_EQ(test, err, -EINVAL); /* Bring the manager back for a graceful cleanup */ @@ -158,9 +158,7 @@ static void ttm_device_init_pools(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(priv, ttm_dev, - params->alloc_flags & TTM_ALLOCATION_POOL_USE_DMA_ALLOC, - params->alloc_flags & TTM_ALLOCATION_POOL_USE_DMA32); + err = ttm_device_kunit_init(priv, ttm_dev, params->alloc_flags); KUNIT_ASSERT_EQ(test, err, 0); pool = &ttm_dev->pool; diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c index 7aaf0d1395ff..7b533e4e1e04 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c +++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c @@ -117,8 +117,7 @@ static void bad_evict_flags(struct ttm_buffer_object *bo, static int ttm_device_kunit_init_with_funcs(struct ttm_test_devices *priv, struct ttm_device *ttm, - bool use_dma_alloc, - bool use_dma32, + unsigned int alloc_flags, struct ttm_device_funcs *funcs) { struct drm_device *drm = priv->drm; @@ -127,7 +126,7 @@ static int ttm_device_kunit_init_with_funcs(struct ttm_test_devices *priv, err = ttm_device_init(ttm, funcs, drm->dev, drm->anon_inode->i_mapping, drm->vma_offset_manager, - use_dma_alloc, use_dma32); + alloc_flags); return err; } @@ -143,11 +142,10 @@ EXPORT_SYMBOL_GPL(ttm_dev_funcs); int ttm_device_kunit_init(struct ttm_test_devices *priv, struct ttm_device *ttm, - bool use_dma_alloc, - bool use_dma32) + unsigned int alloc_flags) { - return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc, - use_dma32, &ttm_dev_funcs); + return ttm_device_kunit_init_with_funcs(priv, ttm, alloc_flags, + &ttm_dev_funcs); } EXPORT_SYMBOL_GPL(ttm_device_kunit_init); @@ -161,12 +159,10 @@ struct ttm_device_funcs ttm_dev_funcs_bad_evict = { EXPORT_SYMBOL_GPL(ttm_dev_funcs_bad_evict); int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv, - struct ttm_device *ttm, - bool use_dma_alloc, - bool use_dma32) + struct ttm_device *ttm) { - return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc, - use_dma32, &ttm_dev_funcs_bad_evict); + return ttm_device_kunit_init_with_funcs(priv, ttm, 0, + &ttm_dev_funcs_bad_evict); } EXPORT_SYMBOL_GPL(ttm_device_kunit_init_bad_evict); @@ -252,7 +248,7 @@ struct ttm_test_devices *ttm_test_devices_all(struct kunit *test) ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ttm_dev); - err = ttm_device_kunit_init(devs, ttm_dev, false, false); + err = ttm_device_kunit_init(devs, ttm_dev, 0); KUNIT_ASSERT_EQ(test, err, 0); devs->ttm_dev = ttm_dev; diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h index c7da23232ffa..f8402b979d05 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h +++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h @@ -28,12 +28,9 @@ struct ttm_test_devices { /* Building blocks for test-specific init functions */ int ttm_device_kunit_init(struct ttm_test_devices *priv, struct ttm_device *ttm, - bool use_dma_alloc, - bool use_dma32); + unsigned int alloc_flags); int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv, - struct ttm_device *ttm, - bool use_dma_alloc, - bool use_dma32); + struct ttm_device *ttm); struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test, struct ttm_test_devices *devs, size_t size, diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index a97b1444536c..87c85ccb21ac 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -199,8 +199,7 @@ EXPORT_SYMBOL(ttm_device_swapout); * @dev: The core kernel device pointer for DMA mappings and allocations. * @mapping: The address space to use for this bo. * @vma_manager: A pointer to a vma manager. - * @use_dma_alloc: If coherent DMA allocation API should be used. - * @use_dma32: If we should use GFP_DMA32 for device memory allocations. + * @alloc_flags: TTM_ALLOCATION_ flags. * * Initializes a struct ttm_device: * Returns: @@ -209,7 +208,7 @@ EXPORT_SYMBOL(ttm_device_swapout); int ttm_device_init(struct ttm_device *bdev, const struct ttm_device_funcs *funcs, struct device *dev, struct address_space *mapping, struct drm_vma_offset_manager *vma_manager, - bool use_dma_alloc, bool use_dma32) + unsigned int alloc_flags) { struct ttm_global *glob = &ttm_glob; int ret, nid; @@ -237,9 +236,7 @@ int ttm_device_init(struct ttm_device *bdev, const struct ttm_device_funcs *func else nid = NUMA_NO_NODE; - ttm_pool_init(&bdev->pool, dev, nid, - (use_dma_alloc ? TTM_ALLOCATION_POOL_USE_DMA_ALLOC : 0) | - (use_dma32 ? TTM_ALLOCATION_POOL_USE_DMA32 : 0)); + ttm_pool_init(&bdev->pool, dev, nid, alloc_flags); bdev->vma_manager = vma_manager; spin_lock_init(&bdev->lru_lock); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 8ff958d119be..599052d07ae8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1023,8 +1023,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) dev_priv->drm.dev, dev_priv->drm.anon_inode->i_mapping, dev_priv->drm.vma_offset_manager, - dev_priv->map_mode == vmw_dma_alloc_coherent, - false); + (dev_priv->map_mode == vmw_dma_alloc_coherent) ? + TTM_ALLOCATION_POOL_USE_DMA_ALLOC : 0); if (unlikely(ret != 0)) { drm_err(&dev_priv->drm, "Failed initializing TTM buffer object driver.\n"); diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 5f6a412b571c..58e7996160a0 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -437,7 +437,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, err = ttm_device_init(&xe->ttm, &xe_ttm_funcs, xe->drm.dev, xe->drm.anon_inode->i_mapping, - xe->drm.vma_offset_manager, false, false); + xe->drm.vma_offset_manager, 0); if (WARN_ON(err)) goto err; diff --git a/include/drm/ttm/ttm_device.h b/include/drm/ttm/ttm_device.h index 592b5f802859..074b98572275 100644 --- a/include/drm/ttm/ttm_device.h +++ b/include/drm/ttm/ttm_device.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -292,7 +293,7 @@ static inline void ttm_set_driver_manager(struct ttm_device *bdev, int type, int ttm_device_init(struct ttm_device *bdev, const struct ttm_device_funcs *funcs, struct device *dev, struct address_space *mapping, struct drm_vma_offset_manager *vma_manager, - bool use_dma_alloc, bool use_dma32); + unsigned int alloc_flags); void ttm_device_fini(struct ttm_device *bdev); void ttm_device_clear_dma_mappings(struct ttm_device *bdev); -- cgit v1.2.3 From 7e9c548d3709c76601c953834bed9c888f3e17b2 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 20 Oct 2025 12:54:09 +0100 Subject: drm/ttm: Allow drivers to specify maximum beneficial TTM pool size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GPUs typically benefit from contiguous memory via reduced TLB pressure and improved caching performance, where the maximum size of contiguous block which adds a performance benefit is related to hardware design. TTM pool allocator by default tries (hard) to allocate up to the system MAX_PAGE_ORDER blocks. This varies by the CPU platform and can also be configured via Kconfig. If that limit was set to be higher than the GPU can make an extra use of, lets allow the individual drivers to let TTM know over which allocation order can the pool allocator afford to make a little bit less effort with. We implement this by disabling direct reclaim for those allocations, which reduces the allocation latency and lowers the demands on the page allocator, in cases where expending this effort is not critical for the GPU in question. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Thadeu Lima de Souza Cascardo Reviewed-by: Christian König Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20251020115411.36818-5-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/ttm/ttm_pool.c | 8 ++++++++ drivers/gpu/drm/ttm/ttm_pool_internal.h | 5 +++++ include/drm/ttm/ttm_allocation.h | 5 +++-- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index 4fc69447060c..97e9ce505cf6 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -136,6 +136,7 @@ static DECLARE_RWSEM(pool_shrink_rwsem); static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags, unsigned int order) { + const unsigned int beneficial_order = ttm_pool_beneficial_order(pool); unsigned long attr = DMA_ATTR_FORCE_CONTIGUOUS; struct ttm_pool_dma *dma; struct page *p; @@ -149,6 +150,13 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags, gfp_flags |= __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | __GFP_THISNODE; + /* + * Do not add latency to the allocation path for allocations orders + * device tolds us do not bring them additional performance gains. + */ + if (beneficial_order && order > beneficial_order) + gfp_flags &= ~__GFP_DIRECT_RECLAIM; + if (!ttm_pool_uses_dma_alloc(pool)) { p = alloc_pages_node(pool->nid, gfp_flags, order); if (p) diff --git a/drivers/gpu/drm/ttm/ttm_pool_internal.h b/drivers/gpu/drm/ttm/ttm_pool_internal.h index 96b7f21514fb..82c4b7e56a99 100644 --- a/drivers/gpu/drm/ttm/ttm_pool_internal.h +++ b/drivers/gpu/drm/ttm/ttm_pool_internal.h @@ -17,4 +17,9 @@ static inline bool ttm_pool_uses_dma32(struct ttm_pool *pool) return pool->alloc_flags & TTM_ALLOCATION_POOL_USE_DMA32; } +static inline bool ttm_pool_beneficial_order(struct ttm_pool *pool) +{ + return pool->alloc_flags & 0xff; +} + #endif diff --git a/include/drm/ttm/ttm_allocation.h b/include/drm/ttm/ttm_allocation.h index 7869dc32bd91..8f8544760306 100644 --- a/include/drm/ttm/ttm_allocation.h +++ b/include/drm/ttm/ttm_allocation.h @@ -4,7 +4,8 @@ #ifndef _TTM_ALLOCATION_H_ #define _TTM_ALLOCATION_H_ -#define TTM_ALLOCATION_POOL_USE_DMA_ALLOC BIT(0) /* Use coherent DMA allocations. */ -#define TTM_ALLOCATION_POOL_USE_DMA32 BIT(1) /* Use GFP_DMA32 allocations. */ +#define TTM_ALLOCATION_POOL_BENEFICIAL_ORDER(n) ((n) & 0xff) /* Max order which caller can benefit from */ +#define TTM_ALLOCATION_POOL_USE_DMA_ALLOC BIT(8) /* Use coherent DMA allocations. */ +#define TTM_ALLOCATION_POOL_USE_DMA32 BIT(9) /* Use GFP_DMA32 allocations. */ #endif -- cgit v1.2.3 From 402b3a865090578f9245115e17ee230e01daf60e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 20 Oct 2025 12:54:11 +0100 Subject: drm/ttm: Add an allocation flag to propagate -ENOSPC on OOM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some graphics APIs differentiate between out-of-graphics-memory and out-of-host-memory (system memory). Add a device init flag to have -ENOSPC propagated from the resource managers instead of being converted to -ENOMEM, to aid driver stacks in determining what error code to return or whether corrective action can be taken at the driver level. Co-developed-by: Thomas Hellström Cc: Christian König Cc: Matthew Brost Signed-off-by: Tvrtko Ursulin Reviewed-by: Thomas Hellström Reviewed-by: Christian König Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20251020115411.36818-7-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/ttm/ttm_bo.c | 4 +++- drivers/gpu/drm/ttm/ttm_device.c | 1 + include/drm/ttm/ttm_allocation.h | 1 + include/drm/ttm/ttm_device.h | 5 +++++ 4 files changed, 10 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 44559dbf62f9..c4e669686fd6 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -32,6 +32,7 @@ #define pr_fmt(fmt) "[TTM] " fmt #include +#include #include #include #include @@ -878,7 +879,8 @@ bounce: /* For backward compatibility with userspace */ if (ret == -ENOSPC) - return -ENOMEM; + return bo->bdev->alloc_flags & TTM_ALLOCATION_PROPAGATE_ENOSPC ? + ret : -ENOMEM; /* * We might need to add a TTM. diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index 87c85ccb21ac..5c10e5fbf43b 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -227,6 +227,7 @@ int ttm_device_init(struct ttm_device *bdev, const struct ttm_device_funcs *func return -ENOMEM; } + bdev->alloc_flags = alloc_flags; bdev->funcs = funcs; ttm_sys_man_init(bdev); diff --git a/include/drm/ttm/ttm_allocation.h b/include/drm/ttm/ttm_allocation.h index 8f8544760306..655d1e44aba7 100644 --- a/include/drm/ttm/ttm_allocation.h +++ b/include/drm/ttm/ttm_allocation.h @@ -7,5 +7,6 @@ #define TTM_ALLOCATION_POOL_BENEFICIAL_ORDER(n) ((n) & 0xff) /* Max order which caller can benefit from */ #define TTM_ALLOCATION_POOL_USE_DMA_ALLOC BIT(8) /* Use coherent DMA allocations. */ #define TTM_ALLOCATION_POOL_USE_DMA32 BIT(9) /* Use GFP_DMA32 allocations. */ +#define TTM_ALLOCATION_PROPAGATE_ENOSPC BIT(10) /* Do not convert ENOSPC from resource managers to ENOMEM. */ #endif diff --git a/include/drm/ttm/ttm_device.h b/include/drm/ttm/ttm_device.h index 074b98572275..d016360e5ceb 100644 --- a/include/drm/ttm/ttm_device.h +++ b/include/drm/ttm/ttm_device.h @@ -220,6 +220,11 @@ struct ttm_device { */ struct list_head device_list; + /** + * @alloc_flags: TTM_ALLOCATION_ flags. + */ + unsigned int alloc_flags; + /** * @funcs: Function table for the device. * Constant after bo device init -- cgit v1.2.3 From 8b61583f993589a64c061aa91b44f5bd350d90a5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 28 Oct 2025 22:07:26 +0200 Subject: drm/edid: add DRM_EDID_IDENT_INIT() to initialize struct drm_edid_ident MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a convenience helper for initializing struct drm_edid_ident. Cc: Tiago Martins Araújo Acked-by: Alex Deucher Tested-by: Tiago Martins Araújo Cc: stable@vger.kernel.org Link: https://patch.msgid.link/710b2ac6a211606ec1f90afa57b79e8c7375a27e.1761681968.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- include/drm/drm_edid.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 3d1aecfec9b2..04f7a7f1f108 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -340,6 +340,12 @@ struct drm_edid_ident { const char *name; }; +#define DRM_EDID_IDENT_INIT(_vend_chr_0, _vend_chr_1, _vend_chr_2, _product_id, _name) \ +{ \ + .panel_id = drm_edid_encode_panel_id(_vend_chr_0, _vend_chr_1, _vend_chr_2, _product_id), \ + .name = _name, \ +} + #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8)) /* Short Audio Descriptor */ -- cgit v1.2.3 From 1556c170d2f78344a9eee567fbfcee4651689813 Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Mon, 3 Nov 2025 22:25:44 -0800 Subject: accel/amdxdna: Add IOCTL parameter for resource data Extend DRM_IOCTL_AMDXDNA_GET_INFO to include additional parameters that allow collection of resource data. Reviewed-by: Mario Limonciello (AMD) Signed-off-by: Lizhi Hou Link: https://patch.msgid.link/20251104062546.833771-2-lizhi.hou@amd.com --- drivers/accel/amdxdna/aie2_ctx.c | 6 ------ drivers/accel/amdxdna/aie2_message.c | 2 ++ drivers/accel/amdxdna/aie2_pci.c | 27 +++++++++++++++++++++++++++ drivers/accel/amdxdna/amdxdna_pci_drv.c | 3 ++- include/uapi/drm/amdxdna_accel.h | 17 +++++++++++++++++ 5 files changed, 48 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index 289a2aaf4cae..b78c47ed0d34 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -556,7 +556,6 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) struct drm_gpu_scheduler *sched; struct amdxdna_hwctx_priv *priv; struct amdxdna_gem_obj *heap; - struct amdxdna_dev_hdl *ndev; int i, ret; priv = kzalloc(sizeof(*hwctx->priv), GFP_KERNEL); @@ -654,8 +653,6 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) amdxdna_pm_suspend_put(xdna); hwctx->status = HWCTX_STAT_INIT; - ndev = xdna->dev_handle; - ndev->hwctx_num++; init_waitqueue_head(&priv->job_free_wq); XDNA_DBG(xdna, "hwctx %s init completed", hwctx->name); @@ -688,13 +685,10 @@ free_priv: void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx) { - struct amdxdna_dev_hdl *ndev; struct amdxdna_dev *xdna; int idx; xdna = hwctx->client->xdna; - ndev = xdna->dev_handle; - ndev->hwctx_num--; XDNA_DBG(xdna, "%s sequence number %lld", hwctx->name, hwctx->priv->seq); drm_sched_entity_destroy(&hwctx->priv->entity); diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c index 339dec998247..39214253d804 100644 --- a/drivers/accel/amdxdna/aie2_message.c +++ b/drivers/accel/amdxdna/aie2_message.c @@ -235,6 +235,7 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct ret = -EINVAL; goto out_destroy_context; } + ndev->hwctx_num++; XDNA_DBG(xdna, "%s mailbox channel irq: %d, msix_id: %d", hwctx->name, ret, resp.msix_id); @@ -269,6 +270,7 @@ int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwc hwctx->fw_ctx_id); hwctx->priv->mbox_chann = NULL; hwctx->fw_ctx_id = -1; + ndev->hwctx_num--; return ret; } diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c index ce57b915004e..396dc6e06007 100644 --- a/drivers/accel/amdxdna/aie2_pci.c +++ b/drivers/accel/amdxdna/aie2_pci.c @@ -838,6 +838,30 @@ static int aie2_get_hwctx_status(struct amdxdna_client *client, return 0; } +static int aie2_query_resource_info(struct amdxdna_client *client, + struct amdxdna_drm_get_info *args) +{ + struct amdxdna_drm_get_resource_info res_info; + const struct amdxdna_dev_priv *priv; + struct amdxdna_dev_hdl *ndev; + struct amdxdna_dev *xdna; + + xdna = client->xdna; + ndev = xdna->dev_handle; + priv = ndev->priv; + + res_info.npu_clk_max = priv->dpm_clk_tbl[ndev->max_dpm_level].hclk; + res_info.npu_tops_max = ndev->max_tops; + res_info.npu_task_max = priv->hwctx_limit; + res_info.npu_tops_curr = ndev->curr_tops; + res_info.npu_task_curr = ndev->hwctx_num; + + if (copy_to_user(u64_to_user_ptr(args->buffer), &res_info, sizeof(res_info))) + return -EFAULT; + + return 0; +} + static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_info *args) { struct amdxdna_dev *xdna = client->xdna; @@ -872,6 +896,9 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i case DRM_AMDXDNA_GET_POWER_MODE: ret = aie2_get_power_mode(client, args); break; + case DRM_AMDXDNA_QUERY_RESOURCE_INFO: + ret = aie2_query_resource_info(client, args); + break; default: XDNA_ERR(xdna, "Not supported request parameter %u", args->param); ret = -EOPNOTSUPP; diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c index 3599e713bfcb..af943a603ad1 100644 --- a/drivers/accel/amdxdna/amdxdna_pci_drv.c +++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c @@ -29,9 +29,10 @@ MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin"); * 0.1: Support getting all hardware contexts by DRM_IOCTL_AMDXDNA_GET_ARRAY * 0.2: Support getting last error hardware error * 0.3: Support firmware debug buffer + * 0.4: Support getting resource information */ #define AMDXDNA_DRIVER_MAJOR 0 -#define AMDXDNA_DRIVER_MINOR 3 +#define AMDXDNA_DRIVER_MINOR 4 /* * Bind the driver base on (vendor_id, device_id) pair and later use the diff --git a/include/uapi/drm/amdxdna_accel.h b/include/uapi/drm/amdxdna_accel.h index c7eec9ceb2ae..8b679c38d308 100644 --- a/include/uapi/drm/amdxdna_accel.h +++ b/include/uapi/drm/amdxdna_accel.h @@ -442,6 +442,23 @@ enum amdxdna_drm_get_param { DRM_AMDXDNA_QUERY_HW_CONTEXTS, DRM_AMDXDNA_QUERY_FIRMWARE_VERSION = 8, DRM_AMDXDNA_GET_POWER_MODE, + DRM_AMDXDNA_QUERY_RESOURCE_INFO = 12, +}; + +/** + * struct amdxdna_drm_get_resource_info - Get resource information + */ +struct amdxdna_drm_get_resource_info { + /** @npu_clk_max: max H-Clocks */ + __u64 npu_clk_max; + /** @npu_tops_max: max TOPs */ + __u64 npu_tops_max; + /** @npu_task_max: max number of tasks */ + __u64 npu_task_max; + /** @npu_tops_curr: current TOPs */ + __u64 npu_tops_curr; + /** @npu_task_curr: current number of tasks */ + __u64 npu_task_curr; }; /** -- cgit v1.2.3 From e568dc3e625d818f199bd085005213cce3271453 Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Mon, 3 Nov 2025 22:25:45 -0800 Subject: accel/amdxdna: Add IOCTL parameter for telemetry data Extend DRM_IOCTL_AMDXDNA_GET_INFO to include additional parameters that allow collection of telemetry data. Reviewed-by: Mario Limonciello (AMD) Signed-off-by: Lizhi Hou Link: https://patch.msgid.link/20251104062546.833771-3-lizhi.hou@amd.com --- drivers/accel/amdxdna/aie2_message.c | 56 +++++++++++++++++--- drivers/accel/amdxdna/aie2_msg_priv.h | 25 ++++++++- drivers/accel/amdxdna/aie2_pci.c | 73 ++++++++++++++++++++++++++ drivers/accel/amdxdna/aie2_pci.h | 3 ++ drivers/accel/amdxdna/amdxdna_mailbox_helper.h | 6 ++- drivers/accel/amdxdna/amdxdna_pci_drv.c | 3 +- include/uapi/drm/amdxdna_accel.h | 17 ++++++ 7 files changed, 173 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c index 39214253d804..69cdce9ff208 100644 --- a/drivers/accel/amdxdna/aie2_message.c +++ b/drivers/accel/amdxdna/aie2_message.c @@ -47,7 +47,7 @@ static int aie2_send_mgmt_msg_wait(struct amdxdna_dev_hdl *ndev, ndev->mgmt_chann = NULL; } - if (!ret && *hdl->data != AIE2_STATUS_SUCCESS) { + if (!ret && *hdl->status != AIE2_STATUS_SUCCESS) { XDNA_ERR(xdna, "command opcode 0x%x failed, status 0x%x", msg->opcode, *hdl->data); ret = -EINVAL; @@ -336,11 +336,6 @@ int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf, goto fail; } - if (resp.status != AIE2_STATUS_SUCCESS) { - XDNA_ERR(xdna, "Query NPU status failed, status 0x%x", resp.status); - ret = -EINVAL; - goto fail; - } XDNA_DBG(xdna, "Query NPU status completed"); if (size < resp.size) { @@ -362,6 +357,55 @@ fail: return ret; } +int aie2_query_telemetry(struct amdxdna_dev_hdl *ndev, + char __user *buf, u32 size, + struct amdxdna_drm_query_telemetry_header *header) +{ + DECLARE_AIE2_MSG(get_telemetry, MSG_OP_GET_TELEMETRY); + struct amdxdna_dev *xdna = ndev->xdna; + dma_addr_t dma_addr; + u8 *addr; + int ret; + + if (header->type >= MAX_TELEMETRY_TYPE) + return -EINVAL; + + addr = dma_alloc_noncoherent(xdna->ddev.dev, size, &dma_addr, + DMA_FROM_DEVICE, GFP_KERNEL); + if (!addr) + return -ENOMEM; + + req.buf_addr = dma_addr; + req.buf_size = size; + req.type = header->type; + + drm_clflush_virt_range(addr, size); /* device can access */ + ret = aie2_send_mgmt_msg_wait(ndev, &msg); + if (ret) { + XDNA_ERR(xdna, "Query telemetry failed, status %d", ret); + goto free_buf; + } + + if (size < resp.size) { + ret = -EINVAL; + XDNA_ERR(xdna, "Bad buffer size. Available: %u. Needs: %u", size, resp.size); + goto free_buf; + } + + if (copy_to_user(buf, addr, resp.size)) { + ret = -EFAULT; + XDNA_ERR(xdna, "Failed to copy telemetry to user space"); + goto free_buf; + } + + header->major = resp.major; + header->minor = resp.minor; + +free_buf: + dma_free_noncoherent(xdna->ddev.dev, size, addr, dma_addr, DMA_FROM_DEVICE); + return ret; +} + int aie2_register_asyn_event_msg(struct amdxdna_dev_hdl *ndev, dma_addr_t addr, u32 size, void *handle, int (*cb)(void*, void __iomem *, size_t)) { diff --git a/drivers/accel/amdxdna/aie2_msg_priv.h b/drivers/accel/amdxdna/aie2_msg_priv.h index 945140011763..947daa63f064 100644 --- a/drivers/accel/amdxdna/aie2_msg_priv.h +++ b/drivers/accel/amdxdna/aie2_msg_priv.h @@ -9,7 +9,8 @@ enum aie2_msg_opcode { MSG_OP_CREATE_CONTEXT = 0x2, MSG_OP_DESTROY_CONTEXT = 0x3, - MSG_OP_SYNC_BO = 0x7, + MSG_OP_GET_TELEMETRY = 0x4, + MSG_OP_SYNC_BO = 0x7, MSG_OP_EXECUTE_BUFFER_CF = 0xC, MSG_OP_QUERY_COL_STATUS = 0xD, MSG_OP_QUERY_AIE_TILE_INFO = 0xE, @@ -137,6 +138,28 @@ struct destroy_ctx_resp { enum aie2_msg_status status; } __packed; +enum telemetry_type { + TELEMETRY_TYPE_DISABLED, + TELEMETRY_TYPE_HEALTH, + TELEMETRY_TYPE_ERROR_INFO, + TELEMETRY_TYPE_PROFILING, + TELEMETRY_TYPE_DEBUG, + MAX_TELEMETRY_TYPE +}; + +struct get_telemetry_req { + enum telemetry_type type; + __u64 buf_addr; + __u32 buf_size; +} __packed; + +struct get_telemetry_resp { + __u32 major; + __u32 minor; + __u32 size; + enum aie2_msg_status status; +} __packed; + struct execute_buffer_req { __u32 cu_idx; __u32 payload[19]; diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c index 396dc6e06007..d7ccbdaf47f5 100644 --- a/drivers/accel/amdxdna/aie2_pci.c +++ b/drivers/accel/amdxdna/aie2_pci.c @@ -862,6 +862,76 @@ static int aie2_query_resource_info(struct amdxdna_client *client, return 0; } +static int aie2_fill_hwctx_map(struct amdxdna_hwctx *hwctx, void *arg) +{ + struct amdxdna_dev *xdna = hwctx->client->xdna; + u32 *map = arg; + + if (hwctx->fw_ctx_id >= xdna->dev_handle->priv->hwctx_limit) { + XDNA_ERR(xdna, "Invalid fw ctx id %d/%d ", hwctx->fw_ctx_id, + xdna->dev_handle->priv->hwctx_limit); + return -EINVAL; + } + + map[hwctx->fw_ctx_id] = hwctx->id; + return 0; +} + +static int aie2_get_telemetry(struct amdxdna_client *client, + struct amdxdna_drm_get_info *args) +{ + struct amdxdna_drm_query_telemetry_header *header __free(kfree) = NULL; + u32 telemetry_data_sz, header_sz, elem_num; + struct amdxdna_dev *xdna = client->xdna; + struct amdxdna_client *tmp_client; + int ret; + + elem_num = xdna->dev_handle->priv->hwctx_limit; + header_sz = struct_size(header, map, elem_num); + if (args->buffer_size <= header_sz) { + XDNA_ERR(xdna, "Invalid buffer size"); + return -EINVAL; + } + + telemetry_data_sz = args->buffer_size - header_sz; + if (telemetry_data_sz > SZ_4M) { + XDNA_ERR(xdna, "Buffer size is too big, %d", telemetry_data_sz); + return -EINVAL; + } + + header = kzalloc(header_sz, GFP_KERNEL); + if (!header) + return -ENOMEM; + + if (copy_from_user(header, u64_to_user_ptr(args->buffer), sizeof(*header))) { + XDNA_ERR(xdna, "Failed to copy telemetry header from user"); + return -EFAULT; + } + + header->map_num_elements = elem_num; + list_for_each_entry(tmp_client, &xdna->client_list, node) { + ret = amdxdna_hwctx_walk(tmp_client, &header->map, + aie2_fill_hwctx_map); + if (ret) + return ret; + } + + ret = aie2_query_telemetry(xdna->dev_handle, + u64_to_user_ptr(args->buffer + header_sz), + telemetry_data_sz, header); + if (ret) { + XDNA_ERR(xdna, "Query telemetry failed ret %d", ret); + return ret; + } + + if (copy_to_user(u64_to_user_ptr(args->buffer), header, header_sz)) { + XDNA_ERR(xdna, "Copy header failed"); + return -EFAULT; + } + + return 0; +} + static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_info *args) { struct amdxdna_dev *xdna = client->xdna; @@ -896,6 +966,9 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i case DRM_AMDXDNA_GET_POWER_MODE: ret = aie2_get_power_mode(client, args); break; + case DRM_AMDXDNA_QUERY_TELEMETRY: + ret = aie2_get_telemetry(client, args); + break; case DRM_AMDXDNA_QUERY_RESOURCE_INFO: ret = aie2_query_resource_info(client, args); break; diff --git a/drivers/accel/amdxdna/aie2_pci.h b/drivers/accel/amdxdna/aie2_pci.h index a79f4f71ff6b..9793cd1e0c55 100644 --- a/drivers/accel/amdxdna/aie2_pci.h +++ b/drivers/accel/amdxdna/aie2_pci.h @@ -305,6 +305,9 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwctx); int aie2_map_host_buf(struct amdxdna_dev_hdl *ndev, u32 context_id, u64 addr, u64 size); int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf, u32 size, u32 *cols_filled); +int aie2_query_telemetry(struct amdxdna_dev_hdl *ndev, + char __user *buf, u32 size, + struct amdxdna_drm_query_telemetry_header *header); int aie2_register_asyn_event_msg(struct amdxdna_dev_hdl *ndev, dma_addr_t addr, u32 size, void *handle, int (*cb)(void*, void __iomem *, size_t)); int aie2_config_cu(struct amdxdna_hwctx *hwctx, diff --git a/drivers/accel/amdxdna/amdxdna_mailbox_helper.h b/drivers/accel/amdxdna/amdxdna_mailbox_helper.h index 710ff8873d61..556c712cad0a 100644 --- a/drivers/accel/amdxdna/amdxdna_mailbox_helper.h +++ b/drivers/accel/amdxdna/amdxdna_mailbox_helper.h @@ -16,16 +16,18 @@ struct xdna_notify { u32 *data; size_t size; int error; + u32 *status; }; -#define DECLARE_XDNA_MSG_COMMON(name, op, status) \ +#define DECLARE_XDNA_MSG_COMMON(name, op, s) \ struct name##_req req = { 0 }; \ - struct name##_resp resp = { status }; \ + struct name##_resp resp = { .status = s }; \ struct xdna_notify hdl = { \ .error = 0, \ .data = (u32 *)&resp, \ .size = sizeof(resp), \ .comp = COMPLETION_INITIALIZER_ONSTACK(hdl.comp), \ + .status = (u32 *)&resp.status, \ }; \ struct xdna_mailbox_msg msg = { \ .send_data = (u8 *)&req, \ diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c index af943a603ad1..7590265d4485 100644 --- a/drivers/accel/amdxdna/amdxdna_pci_drv.c +++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c @@ -30,9 +30,10 @@ MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin"); * 0.2: Support getting last error hardware error * 0.3: Support firmware debug buffer * 0.4: Support getting resource information + * 0.5: Support getting telemetry data */ #define AMDXDNA_DRIVER_MAJOR 0 -#define AMDXDNA_DRIVER_MINOR 4 +#define AMDXDNA_DRIVER_MINOR 5 /* * Bind the driver base on (vendor_id, device_id) pair and later use the diff --git a/include/uapi/drm/amdxdna_accel.h b/include/uapi/drm/amdxdna_accel.h index 8b679c38d308..8ad254bc35a5 100644 --- a/include/uapi/drm/amdxdna_accel.h +++ b/include/uapi/drm/amdxdna_accel.h @@ -442,6 +442,7 @@ enum amdxdna_drm_get_param { DRM_AMDXDNA_QUERY_HW_CONTEXTS, DRM_AMDXDNA_QUERY_FIRMWARE_VERSION = 8, DRM_AMDXDNA_GET_POWER_MODE, + DRM_AMDXDNA_QUERY_TELEMETRY, DRM_AMDXDNA_QUERY_RESOURCE_INFO = 12, }; @@ -461,6 +462,22 @@ struct amdxdna_drm_get_resource_info { __u64 npu_task_curr; }; +/** + * struct amdxdna_drm_query_telemetry_header - Telemetry data header + */ +struct amdxdna_drm_query_telemetry_header { + /** @major: Firmware telemetry interface major version number */ + __u32 major; + /** @minor: Firmware telemetry interface minor version number */ + __u32 minor; + /** @type: Telemetry query type */ + __u32 type; + /** @map_num_elements: Total number of elements in the map table */ + __u32 map_num_elements; + /** @map: Element map */ + __u32 map[]; +}; + /** * struct amdxdna_drm_get_info - Get some information from the AIE hardware. * @param: Value in enum amdxdna_drm_get_param. Specifies the structure passed in the buffer. -- cgit v1.2.3