mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	drm/shmem: Add madvise state and purge helpers
Add support to the shmem GEM helpers for tracking madvise state and purging pages. This is based on the msm implementation. The BO provides a list_head, but the list management is handled outside of the shmem helpers as there are different locking requirements. Cc: Tomeu Vizoso <tomeu.vizoso@collabora.com> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Maxime Ripard <maxime.ripard@bootlin.com> Cc: Sean Paul <sean@poorly.run> Cc: David Airlie <airlied@linux.ie> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Eric Anholt <eric@anholt.net> Acked-by: Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20190805143358.21245-1-robh@kernel.org
This commit is contained in:
		
							parent
							
								
									3551a9fa2c
								
							
						
					
					
						commit
						17acb9f35e
					
				
					 2 changed files with 72 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -75,6 +75,7 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t
 | 
			
		|||
	shmem = to_drm_gem_shmem_obj(obj);
 | 
			
		||||
	mutex_init(&shmem->pages_lock);
 | 
			
		||||
	mutex_init(&shmem->vmap_lock);
 | 
			
		||||
	INIT_LIST_HEAD(&shmem->madv_list);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Our buffers are kept pinned, so allocating them
 | 
			
		||||
| 
						 | 
				
			
			@ -362,6 +363,62 @@ drm_gem_shmem_create_with_handle(struct drm_file *file_priv,
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(drm_gem_shmem_create_with_handle);
 | 
			
		||||
 | 
			
		||||
/* Update madvise status, returns true if not purged, else
 | 
			
		||||
 * false or -errno.
 | 
			
		||||
 */
 | 
			
		||||
int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&shmem->pages_lock);
 | 
			
		||||
 | 
			
		||||
	if (shmem->madv >= 0)
 | 
			
		||||
		shmem->madv = madv;
 | 
			
		||||
 | 
			
		||||
	madv = shmem->madv;
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&shmem->pages_lock);
 | 
			
		||||
 | 
			
		||||
	return (madv >= 0);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(drm_gem_shmem_madvise);
 | 
			
		||||
 | 
			
		||||
void drm_gem_shmem_purge_locked(struct drm_gem_object *obj)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = obj->dev;
 | 
			
		||||
	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
 | 
			
		||||
 | 
			
		||||
	WARN_ON(!drm_gem_shmem_is_purgeable(shmem));
 | 
			
		||||
 | 
			
		||||
	drm_gem_shmem_put_pages_locked(shmem);
 | 
			
		||||
 | 
			
		||||
	shmem->madv = -1;
 | 
			
		||||
 | 
			
		||||
	drm_vma_node_unmap(&obj->vma_node, dev->anon_inode->i_mapping);
 | 
			
		||||
	drm_gem_free_mmap_offset(obj);
 | 
			
		||||
 | 
			
		||||
	/* Our goal here is to return as much of the memory as
 | 
			
		||||
	 * is possible back to the system as we are called from OOM.
 | 
			
		||||
	 * To do this we must instruct the shmfs to drop all of its
 | 
			
		||||
	 * backing pages, *now*.
 | 
			
		||||
	 */
 | 
			
		||||
	shmem_truncate_range(file_inode(obj->filp), 0, (loff_t)-1);
 | 
			
		||||
 | 
			
		||||
	invalidate_mapping_pages(file_inode(obj->filp)->i_mapping,
 | 
			
		||||
			0, (loff_t)-1);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(drm_gem_shmem_purge_locked);
 | 
			
		||||
 | 
			
		||||
void drm_gem_shmem_purge(struct drm_gem_object *obj)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&shmem->pages_lock);
 | 
			
		||||
	drm_gem_shmem_purge_locked(obj);
 | 
			
		||||
	mutex_unlock(&shmem->pages_lock);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(drm_gem_shmem_purge);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * drm_gem_shmem_dumb_create - Create a dumb shmem buffer object
 | 
			
		||||
 * @file: DRM file structure to create the dumb buffer for
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,9 @@ struct drm_gem_shmem_object {
 | 
			
		|||
	 */
 | 
			
		||||
	unsigned int pages_use_count;
 | 
			
		||||
 | 
			
		||||
	int madv;
 | 
			
		||||
	struct list_head madv_list;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @pages_mark_dirty_on_put:
 | 
			
		||||
	 *
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +124,18 @@ void drm_gem_shmem_unpin(struct drm_gem_object *obj);
 | 
			
		|||
void *drm_gem_shmem_vmap(struct drm_gem_object *obj);
 | 
			
		||||
void drm_gem_shmem_vunmap(struct drm_gem_object *obj, void *vaddr);
 | 
			
		||||
 | 
			
		||||
int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv);
 | 
			
		||||
 | 
			
		||||
static inline bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object *shmem)
 | 
			
		||||
{
 | 
			
		||||
	return (shmem->madv > 0) &&
 | 
			
		||||
		!shmem->vmap_use_count && shmem->sgt &&
 | 
			
		||||
		!shmem->base.dma_buf && !shmem->base.import_attach;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drm_gem_shmem_purge_locked(struct drm_gem_object *obj);
 | 
			
		||||
void drm_gem_shmem_purge(struct drm_gem_object *obj);
 | 
			
		||||
 | 
			
		||||
struct drm_gem_shmem_object *
 | 
			
		||||
drm_gem_shmem_create_with_handle(struct drm_file *file_priv,
 | 
			
		||||
				 struct drm_device *dev, size_t size,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue