/* SPDX-License-Identifier: GPL-2.0 */12#ifndef __DRM_GEM_SHMEM_HELPER_H__3#define __DRM_GEM_SHMEM_HELPER_H__45#include <linux/fs.h>6#include <linux/mm.h>7#include <linux/mutex.h>89#include <drm/drm_file.h>10#include <drm/drm_gem.h>11#include <drm/drm_ioctl.h>12#include <drm/drm_prime.h>1314struct dma_buf_attachment;15struct drm_mode_create_dumb;16struct drm_printer;17struct sg_table;1819/**20* struct drm_gem_shmem_object - GEM object backed by shmem21*/22struct drm_gem_shmem_object {23/**24* @base: Base GEM object25*/26struct drm_gem_object base;2728/**29* @pages: Page table30*/31struct page **pages;3233/**34* @pages_use_count:35*36* Reference count on the pages table.37* The pages are put when the count reaches zero.38*/39refcount_t pages_use_count;4041/**42* @pages_pin_count:43*44* Reference count on the pinned pages table.45*46* Pages are hard-pinned and reside in memory if count47* greater than zero. Otherwise, when count is zero, the pages are48* allowed to be evicted and purged by memory shrinker.49*/50refcount_t pages_pin_count;5152/**53* @madv: State for madvise54*55* 0 is active/inuse.56* A negative value is the object is purged.57* Positive values are driver specific and not used by the helpers.58*/59int madv;6061/**62* @madv_list: List entry for madvise tracking63*64* Typically used by drivers to track purgeable objects65*/66struct list_head madv_list;6768/**69* @sgt: Scatter/gather table for imported PRIME buffers70*/71struct sg_table *sgt;7273/**74* @vaddr: Kernel virtual address of the backing memory75*/76void *vaddr;7778/**79* @vmap_use_count:80*81* Reference count on the virtual address.82* The address are un-mapped when the count reaches zero.83*/84refcount_t vmap_use_count;8586/**87* @pages_mark_dirty_on_put:88*89* Mark pages as dirty when they are put.90*/91bool pages_mark_dirty_on_put : 1;9293/**94* @pages_mark_accessed_on_put:95*96* Mark pages as accessed when they are put.97*/98bool pages_mark_accessed_on_put : 1;99100/**101* @map_wc: map object write-combined (instead of using shmem defaults).102*/103bool map_wc : 1;104};105106#define to_drm_gem_shmem_obj(obj) \107container_of(obj, struct drm_gem_shmem_object, base)108109int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size);110struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size);111struct drm_gem_shmem_object *drm_gem_shmem_create_with_mnt(struct drm_device *dev,112size_t size,113struct vfsmount *gemfs);114void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem);115void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem);116117void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem);118int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem);119void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem);120int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem,121struct iosys_map *map);122void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,123struct iosys_map *map);124int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct *vma);125126int drm_gem_shmem_pin_locked(struct drm_gem_shmem_object *shmem);127void drm_gem_shmem_unpin_locked(struct drm_gem_shmem_object *shmem);128129int drm_gem_shmem_madvise_locked(struct drm_gem_shmem_object *shmem, int madv);130131static inline bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object *shmem)132{133return (shmem->madv > 0) &&134!refcount_read(&shmem->pages_pin_count) && shmem->sgt &&135!shmem->base.dma_buf && !drm_gem_is_imported(&shmem->base);136}137138void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem);139140struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem);141struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem);142143void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem,144struct drm_printer *p, unsigned int indent);145146extern const struct vm_operations_struct drm_gem_shmem_vm_ops;147148/*149* GEM object functions150*/151152/**153* drm_gem_shmem_object_free - GEM object function for drm_gem_shmem_free()154* @obj: GEM object to free155*156* This function wraps drm_gem_shmem_free(). Drivers that employ the shmem helpers157* should use it as their &drm_gem_object_funcs.free handler.158*/159static inline void drm_gem_shmem_object_free(struct drm_gem_object *obj)160{161struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);162163drm_gem_shmem_free(shmem);164}165166/**167* drm_gem_shmem_object_print_info() - Print &drm_gem_shmem_object info for debugfs168* @p: DRM printer169* @indent: Tab indentation level170* @obj: GEM object171*172* This function wraps drm_gem_shmem_print_info(). Drivers that employ the shmem helpers should173* use this function as their &drm_gem_object_funcs.print_info handler.174*/175static inline void drm_gem_shmem_object_print_info(struct drm_printer *p, unsigned int indent,176const struct drm_gem_object *obj)177{178const struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);179180drm_gem_shmem_print_info(shmem, p, indent);181}182183/**184* drm_gem_shmem_object_pin - GEM object function for drm_gem_shmem_pin()185* @obj: GEM object186*187* This function wraps drm_gem_shmem_pin(). Drivers that employ the shmem helpers should188* use it as their &drm_gem_object_funcs.pin handler.189*/190static inline int drm_gem_shmem_object_pin(struct drm_gem_object *obj)191{192struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);193194return drm_gem_shmem_pin_locked(shmem);195}196197/**198* drm_gem_shmem_object_unpin - GEM object function for drm_gem_shmem_unpin()199* @obj: GEM object200*201* This function wraps drm_gem_shmem_unpin(). Drivers that employ the shmem helpers should202* use it as their &drm_gem_object_funcs.unpin handler.203*/204static inline void drm_gem_shmem_object_unpin(struct drm_gem_object *obj)205{206struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);207208drm_gem_shmem_unpin_locked(shmem);209}210211/**212* drm_gem_shmem_object_get_sg_table - GEM object function for drm_gem_shmem_get_sg_table()213* @obj: GEM object214*215* This function wraps drm_gem_shmem_get_sg_table(). Drivers that employ the shmem helpers should216* use it as their &drm_gem_object_funcs.get_sg_table handler.217*218* Returns:219* A pointer to the scatter/gather table of pinned pages or error pointer on failure.220*/221static inline struct sg_table *drm_gem_shmem_object_get_sg_table(struct drm_gem_object *obj)222{223struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);224225return drm_gem_shmem_get_sg_table(shmem);226}227228/*229* drm_gem_shmem_object_vmap - GEM object function for drm_gem_shmem_vmap_locked()230* @obj: GEM object231* @map: Returns the kernel virtual address of the SHMEM GEM object's backing store.232*233* This function wraps drm_gem_shmem_vmap_locked(). Drivers that employ the shmem234* helpers should use it as their &drm_gem_object_funcs.vmap handler.235*236* Returns:237* 0 on success or a negative error code on failure.238*/239static inline int drm_gem_shmem_object_vmap(struct drm_gem_object *obj,240struct iosys_map *map)241{242struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);243244return drm_gem_shmem_vmap_locked(shmem, map);245}246247/*248* drm_gem_shmem_object_vunmap - GEM object function for drm_gem_shmem_vunmap()249* @obj: GEM object250* @map: Kernel virtual address where the SHMEM GEM object was mapped251*252* This function wraps drm_gem_shmem_vunmap_locked(). Drivers that employ the shmem253* helpers should use it as their &drm_gem_object_funcs.vunmap handler.254*/255static inline void drm_gem_shmem_object_vunmap(struct drm_gem_object *obj,256struct iosys_map *map)257{258struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);259260drm_gem_shmem_vunmap_locked(shmem, map);261}262263/**264* drm_gem_shmem_object_mmap - GEM object function for drm_gem_shmem_mmap()265* @obj: GEM object266* @vma: VMA for the area to be mapped267*268* This function wraps drm_gem_shmem_mmap(). Drivers that employ the shmem helpers should269* use it as their &drm_gem_object_funcs.mmap handler.270*271* Returns:272* 0 on success or a negative error code on failure.273*/274static inline int drm_gem_shmem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)275{276struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);277278return drm_gem_shmem_mmap(shmem, vma);279}280281/*282* Driver ops283*/284285struct drm_gem_object *286drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,287struct dma_buf_attachment *attach,288struct sg_table *sgt);289int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,290struct drm_mode_create_dumb *args);291struct drm_gem_object *drm_gem_shmem_prime_import_no_map(struct drm_device *dev,292struct dma_buf *buf);293294/**295* DRM_GEM_SHMEM_DRIVER_OPS - Default shmem GEM operations296*297* This macro provides a shortcut for setting the shmem GEM operations298* in the &drm_driver structure. Drivers that do not require an s/g table299* for imported buffers should use this.300*/301#define DRM_GEM_SHMEM_DRIVER_OPS \302.gem_prime_import = drm_gem_shmem_prime_import_no_map, \303.dumb_create = drm_gem_shmem_dumb_create304305#endif /* __DRM_GEM_SHMEM_HELPER_H__ */306307308