Add an IOCTL to get a file descriptor referencing a memory region for SVM. Signed-off-by: Thomas Hellström <thomas.hellst...@linux.intel.com> --- drivers/gpu/drm/xe/xe_device.c | 1 + drivers/gpu/drm/xe/xe_svm.c | 50 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_svm.h | 8 ++++++ include/uapi/drm/xe_drm.h | 29 ++++++++++++++++++++ 4 files changed, 88 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 68de09db9ad5..160b3c189de0 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -195,6 +195,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = { DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE, xe_wait_user_fence_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(XE_DEVMEM_OPEN, xe_devmem_open_ioctl, DRM_RENDER_ALLOW), }; static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 660fae255a09..ebdd27b02be7 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -6,6 +6,7 @@ #include <drm/drm_drv.h> #include <drm/drm_managed.h> #include <drm/drm_pagemap.h> +#include <drm/drm_pagemap_util.h> #include "xe_bo.h" #include "xe_gt_tlb_invalidation.h" @@ -1272,6 +1273,55 @@ xe_pagemap_find_or_create(struct xe_device *xe, struct xe_pagemap_cache *cache, return xpagemap; } +/** + * xe_devmem_open_ioctl() - IOCTL callback implementing the devmem_open functionality + * @dev: The struct drm_device. + * @data: The ioctl argurment. + * @file: The drm file. + * + * For the given xe device and memory region, open a pagemap and return a + * file descriptor that can be used to reference the pagemap. First, + * attempt to look up an already used or cached pagemap. If that fails, + * create a new one. + * + * Return: %0 on success. Negative error code on failure. + */ +int xe_devmem_open_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct xe_device *xe = to_xe_device(dev); + struct drm_xe_devmem_open *args = data; + struct drm_pagemap *dpagemap; + struct xe_pagemap *xpagemap; + struct xe_vram_region *vr; + u32 tile_id; + int fd; + + if (XE_IOCTL_DBG(xe, args->extensions) || + XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1])) + return -EINVAL; + + tile_id = (u32)args->region_instance - 1; + if (XE_IOCTL_DBG(xe, tile_id >= xe->info.tile_count)) + return -ENOENT; + + if (XE_IOCTL_DBG(xe, !((BIT(tile_id) << 1) & xe->info.mem_region_mask))) + return -ENOENT; + + vr = &xe->tiles[tile_id].mem.vram; + xpagemap = xe_pagemap_find_or_create(xe, &vr->pagemap_cache, vr); + if (XE_IOCTL_DBG(xe, IS_ERR(xpagemap))) + return -ENOENT; + + dpagemap = &xpagemap->dpagemap; + fd = drm_pagemap_fd(dpagemap); + xe_pagemap_put(xpagemap); + if (XE_IOCTL_DBG(xe, fd < 0)) + return fd; + + args->pagemap_fd = fd; + + return 0; +} #endif /** diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index c5d542567cfc..4f1a9e410dad 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -149,6 +149,8 @@ static inline void xe_svm_vma_assign_dpagemap(struct xe_svm_vma *svma, #else #include <linux/interval_tree.h> +struct drm_device; +struct drm_file; struct drm_pagemap_device_addr; struct xe_bo; struct xe_device; @@ -243,6 +245,8 @@ int xe_pagemap_cache_init(struct drm_device *drm, struct xe_pagemap_cache *cache void xe_pagemaps_remove(struct xe_device *xe); +int xe_devmem_open_ioctl(struct drm_device *dev, void *data, struct drm_file *file); + #else #define xe_pagemap_cache_init(...) 0 @@ -251,6 +255,10 @@ static inline void xe_pagemaps_remove(struct xe_device *xe) { } +static inline int xe_devmem_open_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + return -EOPNOTSUPP; +} #endif #endif diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 616916985e3f..bb22413713f0 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -102,6 +102,7 @@ extern "C" { #define DRM_XE_EXEC 0x09 #define DRM_XE_WAIT_USER_FENCE 0x0a #define DRM_XE_OBSERVATION 0x0b +#define DRM_XE_DEVMEM_OPEN 0x0c /* Must be kept compact -- no holes */ @@ -117,6 +118,7 @@ extern "C" { #define DRM_IOCTL_XE_EXEC DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec) #define DRM_IOCTL_XE_WAIT_USER_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence) #define DRM_IOCTL_XE_OBSERVATION DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param) +#define DRM_IOCTL_XE_DEVMEM_OPEN DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVMEM_OPEN, struct drm_xe_devmem_open) /** * DOC: Xe IOCTL Extensions @@ -1961,6 +1963,33 @@ struct drm_xe_query_eu_stall { __u64 sampling_rates[]; }; +/** + * struct drm_xe_devmem_open - Get a file-descriptor representing + * device memory on a specific tile on a specific device. + */ +struct drm_xe_devmem_open { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** @region_instance: The memory region describing the device memory to open. */ + __u16 region_instance; + + /** @pad: MBZ */ + __u16 pad; + + /** + * @pagemap_fd: On successful return, a file descriptor + * representing the device memory to open. + * Should be close()d when no longer in use. The file + * descriptor can be used to represent the device memory in + * gpu madvise ioctl and the devmem_allow ioctl. + */ + __u32 pagemap_fd; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + #if defined(__cplusplus) } #endif -- 2.48.1