Commit 565477db authored by Thomas Hellström's avatar Thomas Hellström
Browse files

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: default avatarThomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: default avatarMatthew 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
parent a599b986
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -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;