From: Eugeni Dodonov <eugeni.dodonov at intel.com> Allow userspace to discover current cache level for a bo and set a specific cache level if necessary. The patch is mostly based on the original patch from Ben Widawsky. Signed-off-by: Eugeni Dodonov <eugeni.dodonov at intel.com> --- drivers/gpu/drm/i915/i915_dma.c | 2 + drivers/gpu/drm/i915/i915_gem.c | 74 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 5 +++ include/drm/i915_drm.h | 14 +++++++ 4 files changed, 95 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 5ffbd95..adb8bca 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2301,6 +2301,8 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GET_CACHE_TYPE, intel_get_cache_type_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_SET_CACHE_TYPE, intel_set_cache_type_ioctl, DRM_UNLOCKED), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index dccec77..7dc1dc4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4208,3 +4208,77 @@ rescan: mutex_unlock(&dev->struct_mutex); return cnt / 100 * sysctl_vfs_cache_pressure; } + +/** + * Sets the cache mode of an object. + */ +int +intel_set_cache_type_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_gem_get_cache_type *args = data; + struct drm_i915_gem_object *obj; + int ret = 0; + + ret = i915_mutex_lock_interruptible(dev); + if (ret) + return ret; + + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); + if (&obj->base == NULL) { + ret = -ENOENT; + goto unlock; + } + + switch (args->cache_level) { + case I915_CACHE_LLC: + if (!HAS_LLC(dev)) { + ret = -EINVAL; + break; + } + ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); + break; + case I915_CACHE_NONE: + ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE); + break; + default: + ret = -EINVAL; + break; + } + + drm_gem_object_unreference(&obj->base); +unlock: + mutex_unlock(&dev->struct_mutex); + + return ret; +} + +/** + * Returns the cache mode of an object. + */ +int +intel_get_cache_type_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_gem_get_cache_type *args = data; + struct drm_i915_gem_object *obj; + int ret = 0; + + mutex_lock(&dev->struct_mutex); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); + if (&obj->base == NULL) { + ret = -ENOENT; + goto unlock; + } + + /* Assume that kernel always knows what he is doing, so we shouldn't + * have unknown cache level for exporting. If we do, we have bigger + * things to worry about anyway. */ + args->cache_level = obj->cache_level; + + drm_gem_object_unreference(&obj->base); +unlock: + mutex_unlock(&dev->struct_mutex); + + return ret; +} diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bd9a604..2e0841a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -376,6 +376,11 @@ extern int intel_overlay_put_image(struct drm_device *dev, void *data, extern int intel_overlay_attrs(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int intel_get_cache_type_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int intel_set_cache_type_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern void intel_fb_output_poll_changed(struct drm_device *dev); extern void intel_fb_restore_mode(struct drm_device *dev); diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 7f778f5..de6bb61 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -198,6 +198,8 @@ typedef struct _drm_i915_sarea { #define DRM_I915_OVERLAY_PUT_IMAGE 0x27 #define DRM_I915_OVERLAY_ATTRS 0x28 #define DRM_I915_GEM_EXECBUFFER2 0x29 +#define DRM_I915_GET_CACHE_TYPE 0x2a +#define DRM_I915_SET_CACHE_TYPE 0x2b #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -239,6 +241,8 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise) #define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image) #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) +#define DRM_IOCTL_I915_GET_CACHE_TYPE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_CACHE_TYPE, struct drm_i915_gem_get_cache_type) +#define DRM_IOCTL_I915_SET_CACHE_TYPE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_CACHE_TYPE, struct drm_i915_gem_set_cache_type) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -853,4 +857,14 @@ struct drm_intel_overlay_attrs { #define I915_CACHE_LLC 1 #define I915_CACHE_LLC_MLC 2 +struct drm_i915_gem_get_cache_type { + __u32 handle; + __u32 cache_level; +}; + +struct drm_i915_gem_set_cache_type { + __u32 handle; + __u32 cache_level; +}; + #endif /* _I915_DRM_H_ */ -- 1.7.7.4