summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellström <thomas.hellstrom@linux.intel.com>2025-12-19 12:33:01 +0100
committerThomas Hellström <thomas.hellstrom@linux.intel.com>2025-12-23 09:36:29 +0100
commit565477dbca6eca0cfa3f6fefede3f6eb1e6e09b3 (patch)
tree0cf59b071909969cd04012f56c8ec94396c8fdb1
parenta599b98607decdc899630fc99a3a2847f6b72965 (diff)
drm/pagemap: Add a refcounted drm_pagemap backpointer to struct drm_pagemap_zdd
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
-rw-r--r--drivers/gpu/drm/drm_pagemap.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c
index 87648a498a31..4cc57ced4993 100644
--- a/drivers/gpu/drm/drm_pagemap.c
+++ b/drivers/gpu/drm/drm_pagemap.c
@@ -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
@@ -75,11 +76,13 @@
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;