diff options
| author | Thomas Hellström <thomas.hellstrom@linux.intel.com> | 2025-12-19 14:33:02 +0300 |
|---|---|---|
| committer | Thomas Hellström <thomas.hellstrom@linux.intel.com> | 2025-12-23 11:36:55 +0300 |
| commit | a26084328ac40c12096ef01482a7520346379453 (patch) | |
| tree | 788470775e49aa6ddfffb6792a0151f23875adf8 /include | |
| parent | 565477dbca6eca0cfa3f6fefede3f6eb1e6e09b3 (diff) | |
| download | linux-a26084328ac40c12096ef01482a7520346379453.tar.xz | |
drm/pagemap, drm/xe: Manage drm_pagemap provider lifetimes
If a device holds a reference on a foregin device's drm_pagemap,
and a device unbind is executed on the foreign device,
Typically that foreign device would evict its device-private
pages and then continue its device-managed cleanup eventually
releasing its drm device and possibly allow for module unload.
However, since we're still holding a reference on a drm_pagemap,
when that reference is released and the provider module is
unloaded we'd execute out of undefined memory.
Therefore keep a reference on the provider device and module until
the last drm_pagemap reference is gone.
Note that in theory, the drm_gpusvm_helper module may be unloaded
as soon as the final module_put() of the provider driver module is
executed, so we need to add a module_exit() function that waits
for the work item executing the module_put() has completed.
v2:
- Better commit message (Matt Brost)
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-7-thomas.hellstrom@linux.intel.com
Diffstat (limited to 'include')
| -rw-r--r-- | include/drm/drm_pagemap.h | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/include/drm/drm_pagemap.h b/include/drm/drm_pagemap.h index 093e7199c44b..b3edcdde4454 100644 --- a/include/drm/drm_pagemap.h +++ b/include/drm/drm_pagemap.h @@ -10,6 +10,7 @@ struct dma_fence; struct drm_pagemap; +struct drm_pagemap_dev_hold; struct drm_pagemap_zdd; struct device; @@ -131,14 +132,17 @@ struct drm_pagemap_ops { * used for device p2p handshaking. * @ops: The struct drm_pagemap_ops. * @ref: Reference count. - * @dev: The struct drevice owning the device-private memory. + * @drm: The struct drm device owning the device-private memory. * @pagemap: Pointer to the underlying dev_pagemap. + * @dev_hold: Pointer to a struct drm_pagemap_dev_hold for + * device referencing. */ struct drm_pagemap { const struct drm_pagemap_ops *ops; struct kref ref; - struct device *dev; + struct drm_device *drm; struct dev_pagemap *pagemap; + struct drm_pagemap_dev_hold *dev_hold; }; struct drm_pagemap_devmem; @@ -213,7 +217,7 @@ struct drm_pagemap_devmem_ops { struct dma_fence *pre_migrate_fence); }; -struct drm_pagemap *drm_pagemap_create(struct device *dev, +struct drm_pagemap *drm_pagemap_create(struct drm_device *drm, struct dev_pagemap *pagemap, const struct drm_pagemap_ops *ops); |
