Skip to content

Commit 17acb9f

Browse files
committed
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 <[email protected]> Cc: Maarten Lankhorst <[email protected]> Cc: Maxime Ripard <[email protected]> Cc: Sean Paul <[email protected]> Cc: David Airlie <[email protected]> Cc: Daniel Vetter <[email protected]> Cc: Eric Anholt <[email protected]> Acked-by: Acked-by: Alyssa Rosenzweig <[email protected]> Signed-off-by: Rob Herring <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 3551a9f commit 17acb9f

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

drivers/gpu/drm/drm_gem_shmem_helper.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t
7575
shmem = to_drm_gem_shmem_obj(obj);
7676
mutex_init(&shmem->pages_lock);
7777
mutex_init(&shmem->vmap_lock);
78+
INIT_LIST_HEAD(&shmem->madv_list);
7879

7980
/*
8081
* Our buffers are kept pinned, so allocating them
@@ -362,6 +363,62 @@ drm_gem_shmem_create_with_handle(struct drm_file *file_priv,
362363
}
363364
EXPORT_SYMBOL(drm_gem_shmem_create_with_handle);
364365

366+
/* Update madvise status, returns true if not purged, else
367+
* false or -errno.
368+
*/
369+
int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv)
370+
{
371+
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
372+
373+
mutex_lock(&shmem->pages_lock);
374+
375+
if (shmem->madv >= 0)
376+
shmem->madv = madv;
377+
378+
madv = shmem->madv;
379+
380+
mutex_unlock(&shmem->pages_lock);
381+
382+
return (madv >= 0);
383+
}
384+
EXPORT_SYMBOL(drm_gem_shmem_madvise);
385+
386+
void drm_gem_shmem_purge_locked(struct drm_gem_object *obj)
387+
{
388+
struct drm_device *dev = obj->dev;
389+
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
390+
391+
WARN_ON(!drm_gem_shmem_is_purgeable(shmem));
392+
393+
drm_gem_shmem_put_pages_locked(shmem);
394+
395+
shmem->madv = -1;
396+
397+
drm_vma_node_unmap(&obj->vma_node, dev->anon_inode->i_mapping);
398+
drm_gem_free_mmap_offset(obj);
399+
400+
/* Our goal here is to return as much of the memory as
401+
* is possible back to the system as we are called from OOM.
402+
* To do this we must instruct the shmfs to drop all of its
403+
* backing pages, *now*.
404+
*/
405+
shmem_truncate_range(file_inode(obj->filp), 0, (loff_t)-1);
406+
407+
invalidate_mapping_pages(file_inode(obj->filp)->i_mapping,
408+
0, (loff_t)-1);
409+
}
410+
EXPORT_SYMBOL(drm_gem_shmem_purge_locked);
411+
412+
void drm_gem_shmem_purge(struct drm_gem_object *obj)
413+
{
414+
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
415+
416+
mutex_lock(&shmem->pages_lock);
417+
drm_gem_shmem_purge_locked(obj);
418+
mutex_unlock(&shmem->pages_lock);
419+
}
420+
EXPORT_SYMBOL(drm_gem_shmem_purge);
421+
365422
/**
366423
* drm_gem_shmem_dumb_create - Create a dumb shmem buffer object
367424
* @file: DRM file structure to create the dumb buffer for

include/drm/drm_gem_shmem_helper.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ struct drm_gem_shmem_object {
4444
*/
4545
unsigned int pages_use_count;
4646

47+
int madv;
48+
struct list_head madv_list;
49+
4750
/**
4851
* @pages_mark_dirty_on_put:
4952
*
@@ -121,6 +124,18 @@ void drm_gem_shmem_unpin(struct drm_gem_object *obj);
121124
void *drm_gem_shmem_vmap(struct drm_gem_object *obj);
122125
void drm_gem_shmem_vunmap(struct drm_gem_object *obj, void *vaddr);
123126

127+
int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv);
128+
129+
static inline bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object *shmem)
130+
{
131+
return (shmem->madv > 0) &&
132+
!shmem->vmap_use_count && shmem->sgt &&
133+
!shmem->base.dma_buf && !shmem->base.import_attach;
134+
}
135+
136+
void drm_gem_shmem_purge_locked(struct drm_gem_object *obj);
137+
void drm_gem_shmem_purge(struct drm_gem_object *obj);
138+
124139
struct drm_gem_shmem_object *
125140
drm_gem_shmem_create_with_handle(struct drm_file *file_priv,
126141
struct drm_device *dev, size_t size,

0 commit comments

Comments
 (0)