]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/pagemap: Add a refcounted drm_pagemap backpointer to struct drm_pagemap_zdd
authorThomas Hellström <thomas.hellstrom@linux.intel.com>
Fri, 19 Dec 2025 11:33:01 +0000 (12:33 +0100)
committerThomas Hellström <thomas.hellstrom@linux.intel.com>
Tue, 23 Dec 2025 08:36:29 +0000 (09:36 +0100)
To be able to keep track of drm_pagemap usage, add a refcounted
backpointer to struct drm_pagemap_zdd. This will keep the drm_pagemap
reference count from dropping to zero as long as there are drm_pagemap
pages present in a CPU address space.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Acked-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> # For merging through drm-xe.
Link: https://patch.msgid.link/20251219113320.183860-6-thomas.hellstrom@linux.intel.com
drivers/gpu/drm/drm_pagemap.c

index 87648a498a31d9e86da24d9fc75e7d9acbe33563..4cc57ced4993aa22d621bd84dc12558c7cfec506 100644 (file)
@@ -63,6 +63,7 @@
  *
  * @refcount: Reference count for the zdd
  * @devmem_allocation: device memory allocation
+ * @dpagemap: Refcounted pointer to the underlying struct drm_pagemap.
  * @device_private_page_owner: Device private pages owner
  *
  * This structure serves as a generic wrapper installed in
 struct drm_pagemap_zdd {
        struct kref refcount;
        struct drm_pagemap_devmem *devmem_allocation;
+       struct drm_pagemap *dpagemap;
        void *device_private_page_owner;
 };
 
 /**
  * drm_pagemap_zdd_alloc() - Allocate a zdd structure.
+ * @dpagemap: Pointer to the underlying struct drm_pagemap.
  * @device_private_page_owner: Device private pages owner
  *
  * This function allocates and initializes a new zdd structure. It sets up the
@@ -88,7 +91,7 @@ struct drm_pagemap_zdd {
  * Return: Pointer to the allocated zdd on success, ERR_PTR() on failure.
  */
 static struct drm_pagemap_zdd *
-drm_pagemap_zdd_alloc(void *device_private_page_owner)
+drm_pagemap_zdd_alloc(struct drm_pagemap *dpagemap, void *device_private_page_owner)
 {
        struct drm_pagemap_zdd *zdd;
 
@@ -99,6 +102,7 @@ drm_pagemap_zdd_alloc(void *device_private_page_owner)
        kref_init(&zdd->refcount);
        zdd->devmem_allocation = NULL;
        zdd->device_private_page_owner = device_private_page_owner;
+       zdd->dpagemap = drm_pagemap_get(dpagemap);
 
        return zdd;
 }
@@ -128,6 +132,7 @@ static void drm_pagemap_zdd_destroy(struct kref *ref)
        struct drm_pagemap_zdd *zdd =
                container_of(ref, struct drm_pagemap_zdd, refcount);
        struct drm_pagemap_devmem *devmem = zdd->devmem_allocation;
+       struct drm_pagemap *dpagemap = zdd->dpagemap;
 
        if (devmem) {
                complete_all(&devmem->detached);
@@ -135,6 +140,7 @@ static void drm_pagemap_zdd_destroy(struct kref *ref)
                        devmem->ops->devmem_release(devmem);
        }
        kfree(zdd);
+       drm_pagemap_put(dpagemap);
 }
 
 /**
@@ -367,7 +373,7 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
        pagemap_addr = buf + (2 * sizeof(*migrate.src) * npages);
        pages = buf + (2 * sizeof(*migrate.src) + sizeof(*pagemap_addr)) * npages;
 
-       zdd = drm_pagemap_zdd_alloc(pgmap_owner);
+       zdd = drm_pagemap_zdd_alloc(devmem_allocation->dpagemap, pgmap_owner);
        if (!zdd) {
                err = -ENOMEM;
                goto err_free;