On 14/04/2025 21:41, Adrián Larumbe wrote:
> On 14.04.2025 11:01, Steven Price wrote:
>> On 11/04/2025 16:03, Adrián Larumbe wrote:
>>> Allow UM to label a BO for which it possesses a DRM handle.
>>>
>>> Signed-off-by: Adrián Larumbe <adrian.larumbe(a)collabora.com>
>>> Reviewed-by: Liviu Dudau <liviu.dudau(a)arm.com>
>>> Reviewed-by: Boris Brezillon <boris.brezillon(a)collabora.com>
>>
>> Reviewed-by: Steven Price <steven.price(a)arm.com>
>>
>> Although very minor NITs below which you can consider.
>>
>>> ---
>>> drivers/gpu/drm/panthor/panthor_drv.c | 42 ++++++++++++++++++++++++++-
>>> drivers/gpu/drm/panthor/panthor_gem.h | 2 ++
>>> include/uapi/drm/panthor_drm.h | 23 +++++++++++++++
>>> 3 files changed, 66 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
>>> index 06fe46e32073..983b24f1236c 100644
>>> --- a/drivers/gpu/drm/panthor/panthor_drv.c
>>> +++ b/drivers/gpu/drm/panthor/panthor_drv.c
>>> @@ -1331,6 +1331,44 @@ static int panthor_ioctl_vm_get_state(struct drm_device *ddev, void *data,
>>> return 0;
>>> }
>>>
>>> +static int panthor_ioctl_bo_set_label(struct drm_device *ddev, void *data,
>>> + struct drm_file *file)
>>> +{
>>> + struct drm_panthor_bo_set_label *args = data;
>>> + struct drm_gem_object *obj;
>>> + const char *label;
>>> + int ret = 0;
>>> +
>>> + obj = drm_gem_object_lookup(file, args->handle);
>>> + if (!obj)
>>> + return -ENOENT;
>>> +
>>> + if (args->size && args->label) {
>>> + if (args->size > PANTHOR_BO_LABEL_MAXLEN) {
>>> + ret = -E2BIG;
>>> + goto err_label;
>>> + }
>>> +
>>> + label = strndup_user(u64_to_user_ptr(args->label), args->size);
>>> + if (IS_ERR(label)) {
>>> + ret = PTR_ERR(label);
>>> + goto err_label;
>>> + }
>>> + } else if (args->size && !args->label) {
>>> + ret = -EINVAL;
>>> + goto err_label;
>>> + } else {
>>> + label = NULL;
>>> + }
>>> +
>>> + panthor_gem_bo_set_label(obj, label);
>>> +
>>> +err_label:
>>> + drm_gem_object_put(obj);
>>> +
>>> + return ret;
>>> +}
>>> +
>>> static int
>>> panthor_open(struct drm_device *ddev, struct drm_file *file)
>>> {
>>> @@ -1400,6 +1438,7 @@ static const struct drm_ioctl_desc panthor_drm_driver_ioctls[] = {
>>> PANTHOR_IOCTL(TILER_HEAP_CREATE, tiler_heap_create, DRM_RENDER_ALLOW),
>>> PANTHOR_IOCTL(TILER_HEAP_DESTROY, tiler_heap_destroy, DRM_RENDER_ALLOW),
>>> PANTHOR_IOCTL(GROUP_SUBMIT, group_submit, DRM_RENDER_ALLOW),
>>> + PANTHOR_IOCTL(BO_SET_LABEL, bo_set_label, DRM_RENDER_ALLOW),
>>> };
>>>
>>> static int panthor_mmap(struct file *filp, struct vm_area_struct *vma)
>>> @@ -1509,6 +1548,7 @@ static void panthor_debugfs_init(struct drm_minor *minor)
>>> * - 1.2 - adds DEV_QUERY_GROUP_PRIORITIES_INFO query
>>> * - adds PANTHOR_GROUP_PRIORITY_REALTIME priority
>>> * - 1.3 - adds DRM_PANTHOR_GROUP_STATE_INNOCENT flag
>>> + * - 1.4 - adds DRM_IOCTL_PANTHOR_BO_SET_LABEL ioctl
>>> */
>>> static const struct drm_driver panthor_drm_driver = {
>>> .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |
>>> @@ -1522,7 +1562,7 @@ static const struct drm_driver panthor_drm_driver = {
>>> .name = "panthor",
>>> .desc = "Panthor DRM driver",
>>> .major = 1,
>>> - .minor = 3,
>>> + .minor = 4,
>>>
>>> .gem_create_object = panthor_gem_create_object,
>>> .gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,
>>> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
>>> index af0d77338860..beba066b4974 100644
>>> --- a/drivers/gpu/drm/panthor/panthor_gem.h
>>> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
>>> @@ -13,6 +13,8 @@
>>>
>>> struct panthor_vm;
>>>
>>> +#define PANTHOR_BO_LABEL_MAXLEN PAGE_SIZE
>>> +
>>> /**
>>> * struct panthor_gem_object - Driver specific GEM object.
>>> */
>>> diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h
>>> index 97e2c4510e69..12b1994499a9 100644
>>> --- a/include/uapi/drm/panthor_drm.h
>>> +++ b/include/uapi/drm/panthor_drm.h
>>> @@ -127,6 +127,9 @@ enum drm_panthor_ioctl_id {
>>>
>>> /** @DRM_PANTHOR_TILER_HEAP_DESTROY: Destroy a tiler heap. */
>>> DRM_PANTHOR_TILER_HEAP_DESTROY,
>>> +
>>> + /** @DRM_PANTHOR_BO_SET_LABEL: Label a BO. */
>>> + DRM_PANTHOR_BO_SET_LABEL,
>>> };
>>>
>>> /**
>>> @@ -977,6 +980,24 @@ struct drm_panthor_tiler_heap_destroy {
>>> __u32 pad;
>>> };
>>>
>>> +/**
>>> + * struct drm_panthor_bo_set_label - Arguments passed to DRM_IOCTL_PANTHOR_BO_SET_LABEL
>>> + */
>>> +struct drm_panthor_bo_set_label {
>>> + /** @handle: Handle of the buffer object to label. */
>>> + __u32 handle;
>>> +
>>> + /**
>>> + * @size: Length of the label, including the NULL terminator.
>>> + *
>>> + * Cannot be greater than the OS page size.
>>> + */
>>> + __u32 size;
>>> +
>>> + /** @label: User pointer to a NULL-terminated string */
>>> + __u64 label;
>>> +};
>>
>> First very minor NIT:
>> * NULL is a pointer, i.e. (void*)0
>> * NUL is the ASCII code point '\0'.
>> So it's a NUL-terminated string.
>
> Fixed
>
>> Second NIT: We don't actually need 'size' - since the string is
>> NUL-terminated we can just strndup_user(__user_pointer__, PAGE_SIZE).
>> As things stand we validate that strlen(label) < size <= PAGE_SIZE -
>> which is a little odd (user space might as well just pass PAGE_SIZE
>> rather than calculate the actual length).
>
> The snag I see in this approach is that the only way to make sure
> strlen(label) + 1 <= PAGE_SIZE would be doing something like
>
> label = strndup_user(u64_to_user_ptr(args->label), args->size);
> if (strlen(label) + 1 <= PAGE_SIZE) {
> kfree(label)
> return -E2BIG;
> }
You can just do
strndup_user(u64_to_user_ptr(args->label), PAGE_SIZE)
If you look at the kernel's implementation it handles an overly long
string by returning an error:
> length = strnlen_user(s, n);
>
> if (!length)
> return ERR_PTR(-EFAULT);
>
> if (length > n)
> return ERR_PTR(-EINVAL);
>
> p = memdup_user(s, length);
So there's no need to call strlen() on the result.
> In the meantime, we've duplicated the string and traversed a whole page
> of bytes, all to be discarded at once.
>
> In this case, I think it's alright to expect some cooperation from UM
> in supplying the actual size, although I'm really not an expert in
> designing elegant uAPIs, so if you think this looks very odd I'd be
> glad to replace it with.
>
> Actually, as I was writing this, I realised that strndup_user() calls
> strnlen_user(), which is publicly available for other drivers, so
> I might check the length first, and if it falls within bounds, do
> the actual user stringdup.
Again, no need (and strnlen_user() has a comment basically saying "don't
call this"). strndup_user() has all the magic we need here.
As I say this is just a 'nit' - so no big deal. But I don't really see
the point of the size in the uAPI.
Take a look at dma_buf_set_name() for an example which sets the name on
a dma_buf (and doesn't take a size argument) - although that wasn't an
example of good uAPI design as the type in the ioctl was botched ;(
Thanks,
Steve
> I shall also mention the size bound on the uAPI for the 'label' pointer.
>
>> Thanks,
>> Steve
>>
>> +
>> /**
>> * DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number
>> * @__access: Access type. Must be R, W or RW.
>> @@ -1019,6 +1040,8 @@ enum {
>> DRM_IOCTL_PANTHOR(WR, TILER_HEAP_CREATE, tiler_heap_create),
>> DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY =
>> DRM_IOCTL_PANTHOR(WR, TILER_HEAP_DESTROY, tiler_heap_destroy),
>> + DRM_IOCTL_PANTHOR_BO_SET_LABEL =
>> + DRM_IOCTL_PANTHOR(WR, BO_SET_LABEL, bo_set_label),
>> };
>>
>> #if defined(__cplusplus)
>
>
> Adrian Larumbe
On 14/04/2025 20:43, Adrián Larumbe wrote:
> Hi Steven,
>
> On 14.04.2025 10:50, Steven Price wrote:
>> Hi Adrián,
>>
>> On 11/04/2025 16:03, Adrián Larumbe wrote:
>>> Add a new character string Panthor BO field, and a function that allows
>>> setting it from within the driver.
>>>
>>> Driver takes care of freeing the string when it's replaced or no longer
>>> needed at object destruction time, but allocating it is the responsibility
>>> of callers.
>>>
>>> Signed-off-by: Adrián Larumbe <adrian.larumbe(a)collabora.com>
>>> Reviewed-by: Boris Brezillon <boris.brezillon(a)collabora.com>
>>> ---
>>> drivers/gpu/drm/panthor/panthor_gem.c | 39 +++++++++++++++++++++++++++
>>> drivers/gpu/drm/panthor/panthor_gem.h | 17 ++++++++++++
>>> 2 files changed, 56 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
>>> index 8244a4e6c2a2..af0ac17f357f 100644
>>> --- a/drivers/gpu/drm/panthor/panthor_gem.c
>>> +++ b/drivers/gpu/drm/panthor/panthor_gem.c
>>> @@ -2,6 +2,7 @@
>>> /* Copyright 2019 Linaro, Ltd, Rob Herring <robh(a)kernel.org> */
>>> /* Copyright 2023 Collabora ltd. */
>>>
>>> +#include <linux/cleanup.h>
>>> #include <linux/dma-buf.h>
>>> #include <linux/dma-mapping.h>
>>> #include <linux/err.h>
>>> @@ -18,6 +19,14 @@ static void panthor_gem_free_object(struct drm_gem_object *obj)
>>> struct panthor_gem_object *bo = to_panthor_bo(obj);
>>> struct drm_gem_object *vm_root_gem = bo->exclusive_vm_root_gem;
>>>
>>> + /*
>>> + * Label might have been allocated with kstrdup_const(),
>>> + * we need to take that into account when freeing the memory
>>> + */
>>> + kfree_const(bo->label.str);
>>> +
>>> + mutex_destroy(&bo->label.lock);
>>> +
>>> drm_gem_free_mmap_offset(&bo->base.base);
>>> mutex_destroy(&bo->gpuva_list_lock);
>>> drm_gem_shmem_free(&bo->base);
>>> @@ -196,6 +205,7 @@ struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t
>>> obj->base.map_wc = !ptdev->coherent;
>>> mutex_init(&obj->gpuva_list_lock);
>>> drm_gem_gpuva_set_lock(&obj->base.base, &obj->gpuva_list_lock);
>>> + mutex_init(&obj->label.lock);
>>>
>>> return &obj->base.base;
>>> }
>>> @@ -247,3 +257,32 @@ panthor_gem_create_with_handle(struct drm_file *file,
>>>
>>> return ret;
>>> }
>>> +
>>> +void
>>> +panthor_gem_bo_set_label(struct drm_gem_object *obj, const char *label)
>>> +{
>>> + struct panthor_gem_object *bo = to_panthor_bo(obj);
>>> + const char *old_label;
>>> +
>>> + scoped_guard(mutex, &bo->label.lock) {
>>> + old_label = bo->label.str;
>>> + bo->label.str = label;
>>> + }
>>> +
>>> + kfree(old_label);
>>
>> Shouldn't this be kfree_const()? I suspect as things stand we can't
>> trigger this bug but it's inconsistent.
>
> This could only be called either from the set_label() ioctl, in which case
> old_label could be NULL or a pointer to a string obtained from strdup(); or from
> panthor_gem_kernel_bo_set_label(). In the latter case, it could only ever be
> NULL, since we don't reassign kernel BO labels, so it'd be safe too.
Yeah I thought it probably doesn't cause problems now, but it's a foot
gun for the future.
> However I do agree that it's not consistent, and then in the future perhaps
> relabelling kernel BO's might be justified, so I'll change it to kfree_const().
Thanks!
>>> +}
>>> +
>>> +void
>>> +panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label)
>>> +{
>>> + const char *str;
>>> +
>>> + str = kstrdup_const(label, GFP_KERNEL);
>>> + if (!str) {
>>
>> In the next patch you permit user space to clear the label
>> (args->size==0) which means label==NULL and AFAICT kstrdup_const() will
>> return NULL in this case triggering this warning.
>
> Kernel and UM-exposed BO's should never experience cross-labelling, so in theory
> this scenario ought to be impossible. The only way panthor_gem_kernel_bo_set_label()
> might take NULL in the 'label' argument is that someone called panthor_kernel_bo_create()
> with NULL for its name 'argument'.
You're absolutely correct - I somehow got confused between the kernel
and user paths. It's the user path above which needs to handle NULL (and
does).
> I think as a defensive check, I could do something as follows
>
> void
> panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label)
> {
> const char *str;
>
> /* We should never attempt labelling a UM-exposed GEM object */
> if (drm_WARN_ON(bo->obj->dev, &bo->obj->handle_count > 0))
> return;
>
> if (!label)
> return;
>
> [...]
> }
I'm happy for you to do nothing here - that was my mistake getting the
two functions muddled. Sorry for the noise. I'm equally happy for the
defensive checks above.
Steve
>> Thanks,
>> Steve
>>
>>> + /* Failing to allocate memory for a label isn't a fatal condition */
>>> + drm_warn(bo->obj->dev, "Not enough memory to allocate BO label");
>>> + return;
>>> + }
>>> +
>>> + panthor_gem_bo_set_label(bo->obj, str);
>>> +}
>>> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
>>> index 1a363bb814f4..af0d77338860 100644
>>> --- a/drivers/gpu/drm/panthor/panthor_gem.h
>>> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
>>> @@ -46,6 +46,20 @@ struct panthor_gem_object {
>>>
>>> /** @flags: Combination of drm_panthor_bo_flags flags. */
>>> u32 flags;
>>> +
>>> + /**
>>> + * @label: BO tagging fields. The label can be assigned within the
>>> + * driver itself or through a specific IOCTL.
>>> + */
>>> + struct {
>>> + /**
>>> + * @label.str: Pointer to NULL-terminated string,
>>> + */
>>> + const char *str;
>>> +
>>> + /** @lock.str: Protects access to the @label.str field. */
>>> + struct mutex lock;
>>> + } label;
>>> };
>>>
>>> /**
>>> @@ -91,6 +105,9 @@ panthor_gem_create_with_handle(struct drm_file *file,
>>> struct panthor_vm *exclusive_vm,
>>> u64 *size, u32 flags, uint32_t *handle);
>>>
>>> +void panthor_gem_bo_set_label(struct drm_gem_object *obj, const char *label);
>>> +void panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label);
>>> +
>>> static inline u64
>>> panthor_kernel_bo_gpuva(struct panthor_kernel_bo *bo)
>>> {
>
> Adrian Larumbe
Test struct drm_gem_object.import_attach to detect imported objects.
During object clenanup, the dma_buf field might be NULL. Testing it in
an object's free callback then incorrectly does a cleanup as for native
objects. Happens for calls to drm_mode_destroy_dumb_ioctl() that
clears the dma_buf field in drm_gem_object_exported_dma_buf_free().
v3:
- only test for import_attach (Boris)
v2:
- use import_attach.dmabuf instead of dma_buf (Christian)
Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
Fixes: b57aa47d39e9 ("drm/gem: Test for imported GEM buffers with helper")
Reported-by: Andy Yan <andyshrk(a)163.com>
Closes: https://lore.kernel.org/dri-devel/38d09d34.4354.196379aa560.Coremail.andysh…
Tested-by: Andy Yan <andyshrk(a)163.com>
Cc: Thomas Zimmermann <tzimmermann(a)suse.de>
Cc: Anusha Srivatsa <asrivats(a)redhat.com>
Cc: Christian König <christian.koenig(a)amd.com>
Cc: Maarten Lankhorst <maarten.lankhorst(a)linux.intel.com>
Cc: Maxime Ripard <mripard(a)kernel.org>
Cc: David Airlie <airlied(a)gmail.com>
Cc: Simona Vetter <simona(a)ffwll.ch>
Cc: Sumit Semwal <sumit.semwal(a)linaro.org>
Cc: "Christian König" <christian.koenig(a)amd.com>
Cc: dri-devel(a)lists.freedesktop.org
Cc: linux-media(a)vger.kernel.org
Cc: linaro-mm-sig(a)lists.linaro.org
---
include/drm/drm_gem.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 9b71f7a9f3f8..a3133a08267c 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -588,8 +588,7 @@ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_obje
*/
static inline bool drm_gem_is_imported(const struct drm_gem_object *obj)
{
- /* The dma-buf's priv field points to the original GEM object. */
- return obj->dma_buf && (obj->dma_buf->priv != obj);
+ return !!obj->import_attach;
}
#ifdef CONFIG_LOCKDEP
--
2.49.0
On Tue, Apr 15, 2025 at 10:20 AM Juan Yescas <jyescas(a)google.com> wrote:
>
> This change sets the allocation orders for the different page sizes
> (4k, 16k, 64k) based on PAGE_SHIFT. Before this change, the orders
> for large page sizes were calculated incorrectly, this caused system
> heap to allocate from 2% to 4% more memory on 16KiB page size kernels.
>
> This change was tested on 4k/16k page size kernels.
>
> Signed-off-by: Juan Yescas <jyescas(a)google.com>
I think "dma-buf: system_heap:" would be better for the subject since
this is specific to the system heap.
Would you mind cleaning up the extra space on line 321 too?
@@ -318,7 +318,7 @@ static struct page
*alloc_largest_available(unsigned long size,
int i;
for (i = 0; i < NUM_ORDERS; i++) {
- if (size < (PAGE_SIZE << orders[i]))
+ if (size < (PAGE_SIZE << orders[i]))
With that,
Reviewed-by: T.J. Mercier <tjmercier(a)google.com>
Fixes: d963ab0f15fb ("dma-buf: system_heap: Allocate higher order
pages if available") is also probably a good idea.
> ---
> drivers/dma-buf/heaps/system_heap.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
> index 26d5dc89ea16..54674c02dcb4 100644
> --- a/drivers/dma-buf/heaps/system_heap.c
> +++ b/drivers/dma-buf/heaps/system_heap.c
> @@ -50,8 +50,15 @@ static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP};
> * to match with the sizes often found in IOMMUs. Using order 4 pages instead
> * of order 0 pages can significantly improve the performance of many IOMMUs
> * by reducing TLB pressure and time spent updating page tables.
> + *
> + * Note: When the order is 0, the minimum allocation is PAGE_SIZE. The possible
> + * page sizes for ARM devices could be 4K, 16K and 64K.
> */
> -static const unsigned int orders[] = {8, 4, 0};
> +#define ORDER_1M (20 - PAGE_SHIFT)
> +#define ORDER_64K (16 - PAGE_SHIFT)
> +#define ORDER_FOR_PAGE_SIZE (0)
> +static const unsigned int orders[] = {ORDER_1M, ORDER_64K, ORDER_FOR_PAGE_SIZE};
> +
> #define NUM_ORDERS ARRAY_SIZE(orders)
>
> static struct sg_table *dup_sg_table(struct sg_table *table)
> --
> 2.49.0.604.gff1f9ca942-goog
>
On Tue, Apr 15, 2025 at 10:20 AM Juan Yescas <jyescas(a)google.com> wrote:
>
> This change sets the allocation orders for the different page sizes
> (4k, 16k, 64k) based on PAGE_SHIFT. Before this change, the orders
> for large page sizes were calculated incorrectly, this caused system
> heap to allocate from 2% to 4% more memory on 16KiB page size kernels.
>
> This change was tested on 4k/16k page size kernels.
>
> Signed-off-by: Juan Yescas <jyescas(a)google.com>
Seems reasonable to me.
Acked-by: John Stultz <jstultz(a)google.com>
thanks
-john
Hi
Am 15.04.25 um 16:19 schrieb Boris Brezillon:
> On Tue, 15 Apr 2025 16:02:20 +0200
> Thomas Zimmermann <tzimmermann(a)suse.de> wrote:
>
>> Test struct drm_gem_object.import_attach.dmabuf to detect imported
>> objects. Warn if the stored state is inconsistent.
>>
>> During object clenaup, the dma_buf field might be NULL. Testing it in
>> an object's free callback then incorrectly does a cleanup as for native
>> objects. Happens for calls to drm_mode_destroy_dumb_ioctl() that
>> clears the dma_buf field in drm_gem_object_exported_dma_buf_free().
>>
>> v2:
>> - use import_attach.dmabuf instead of dma_buf (Christian)
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
>> Fixes: b57aa47d39e9 ("drm/gem: Test for imported GEM buffers with helper")
>> Reported-by: Andy Yan <andyshrk(a)163.com>
>> Closes: https://lore.kernel.org/dri-devel/38d09d34.4354.196379aa560.Coremail.andysh…
>> Tested-by: Andy Yan <andyshrk(a)163.com>
>> Cc: Thomas Zimmermann <tzimmermann(a)suse.de>
>> Cc: Anusha Srivatsa <asrivats(a)redhat.com>
>> Cc: Christian König <christian.koenig(a)amd.com>
>> Cc: Maarten Lankhorst <maarten.lankhorst(a)linux.intel.com>
>> Cc: Maxime Ripard <mripard(a)kernel.org>
>> Cc: David Airlie <airlied(a)gmail.com>
>> Cc: Simona Vetter <simona(a)ffwll.ch>
>> Cc: Sumit Semwal <sumit.semwal(a)linaro.org>
>> Cc: "Christian König" <christian.koenig(a)amd.com>
>> Cc: dri-devel(a)lists.freedesktop.org
>> Cc: linux-media(a)vger.kernel.org
>> Cc: linaro-mm-sig(a)lists.linaro.org
>> ---
>> include/drm/drm_gem.h | 26 ++++++++++++++++++++++++--
>> 1 file changed, 24 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
>> index 9b71f7a9f3f8..464b9c7feec0 100644
>> --- a/include/drm/drm_gem.h
>> +++ b/include/drm/drm_gem.h
>> @@ -579,6 +579,21 @@ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_obje
>> return (obj->handle_count > 1) || obj->dma_buf;
>> }
>>
>> +/**
>> + * drm_gem_owns_dma_buf() - Tests if GEM object backs a DMA-buffer object
>> + * @obj: the GEM object
>> + * @obj: the DMA buffer
>> + *
>> + * Returns:
>> + * True if the DMA buffer refers to the GEM object's buffer.
>> + */
>> +static inline bool drm_gem_owns_dma_buf(const struct drm_gem_object *obj,
>> + const struct dma_buf *dma_buf)
>> +{
>> + /* The dma-buf's priv field points to the original GEM object. */
>> + return dma_buf->priv == obj;
>> +}
>> +
>> /**
>> * drm_gem_is_imported() - Tests if GEM object's buffer has been imported
>> * @obj: the GEM object
>> @@ -588,8 +603,15 @@ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_obje
>> */
>> static inline bool drm_gem_is_imported(const struct drm_gem_object *obj)
>> {
>> - /* The dma-buf's priv field points to the original GEM object. */
>> - return obj->dma_buf && (obj->dma_buf->priv != obj);
>> + const struct dma_buf *dma_buf = NULL;
>> +
>> + if (!obj->import_attach)
>> + return false;
>> +
>> + dma_buf = obj->import_attach->dmabuf;
>> +
>> + /* Warn if we somehow reimported our own buffer. */
>> + return !drm_WARN_ON_ONCE(obj->dev, !dma_buf || drm_gem_owns_dma_buf(obj, dma_buf));
> I'm honestly not sure I see the point of checking
> obj->import_attach->dmabuf. If obj->import_attach != NULL, we're sure
> it's a foreign buffer already, otherwise we would get the original GEM
> object which has ->import_attach=NULL. So why not go for a simple
>
> return obj->import_attach != NULL;
>
> check, and extend the check when you get to implement imports without
> import attachments (not sure what those would look like BTW).
I have no strong opinion. I just found it confusing to rely on
import_attach when the dma_buf is what we originally imported.
Best regards
Thomas
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)
Test struct drm_gem_object.import_attach to detect imported objects
during cleanup. At that point, the imported DMA buffer might have
already been released and the dma_buf field is NULL. The object's
free callback then does a cleanup as for native objects.
Happens for calls to drm_mode_destroy_dumb_ioctl() that eventually
clear the dma_buf field in drm_gem_object_exported_dma_buf_free().
Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
Fixes: b57aa47d39e9 ("drm/gem: Test for imported GEM buffers with helper")
Reported-by: Andy Yan <andyshrk(a)163.com>
Closes: https://lore.kernel.org/dri-devel/38d09d34.4354.196379aa560.Coremail.andysh…
Tested-by: Andy Yan <andyshrk(a)163.com>
Cc: Thomas Zimmermann <tzimmermann(a)suse.de>
Cc: Anusha Srivatsa <asrivats(a)redhat.com>
Cc: Christian König <christian.koenig(a)amd.com>
Cc: Maarten Lankhorst <maarten.lankhorst(a)linux.intel.com>
Cc: Maxime Ripard <mripard(a)kernel.org>
Cc: David Airlie <airlied(a)gmail.com>
Cc: Simona Vetter <simona(a)ffwll.ch>
Cc: Sumit Semwal <sumit.semwal(a)linaro.org>
Cc: "Christian König" <christian.koenig(a)amd.com>
Cc: dri-devel(a)lists.freedesktop.org
Cc: linux-media(a)vger.kernel.org
Cc: linaro-mm-sig(a)lists.linaro.org
---
include/drm/drm_gem.h | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 9b71f7a9f3f8..f09b8afcf86d 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -589,7 +589,13 @@ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_obje
static inline bool drm_gem_is_imported(const struct drm_gem_object *obj)
{
/* The dma-buf's priv field points to the original GEM object. */
- return obj->dma_buf && (obj->dma_buf->priv != obj);
+ return (obj->dma_buf && (obj->dma_buf->priv != obj)) ||
+ /*
+ * TODO: During object release, the dma-buf might already
+ * be gone. For now keep testing import_attach, but
+ * this should be removed at some point.
+ */
+ obj->import_attach;
}
#ifdef CONFIG_LOCKDEP
--
2.49.0
Am 15.04.25 um 15:10 schrieb Simona Vetter:
>> This is for devices who only want to do a vmap of the buffer, isn't it?
> ... it's for the vmap only case, where you might not even have a struct
> device. Or definitely not a reasonable one, like maybe a faux_bus device
> or some device on a bus that really doesn't do dma (e.g. spi or i2c), and
> where hence dma_buf_map_attachment is just something you never ever want
> to do.
Even in that case I would still suggest to at least create an attachment to let the exporter know that somebody is doing something with it's buffer.
That is also important for move notification since you can't do those without an attachment.
BTW: What is keeping a vmap alive after dropping the reservation lock? There is no pinning whatsoever as far as I can see.
> I think we might want to transform obj->import_attach into a union or
> tagged pointer or something like that, which can cover both cases. And
> maybe a drm_gem_bo_imported_dma_buf() helper that gives you the dma_buf no
> matter what if it's imported, or NULL if it's allocated on that
> drm_device?
Yeah, I had the same idea before as well. Just didn't know if that was something worth looking into.
Regards,
Christian.
>
> Cheers, Sima