1 /* SPDX-License-Identifier: GPL-2.0-only OR MIT */ 2 /* Copyright (c) 2023 Imagination Technologies Ltd. */ 3 4 #ifndef PVR_FREE_LIST_H 5 #define PVR_FREE_LIST_H 6 7 #include <linux/compiler_attributes.h> 8 #include <linux/kref.h> 9 #include <linux/list.h> 10 #include <linux/mutex.h> 11 #include <linux/types.h> 12 #include <linux/xarray.h> 13 #include <uapi/drm/pvr_drm.h> 14 15 #include "pvr_device.h" 16 17 /* Forward declaration from pvr_gem.h. */ 18 struct pvr_fw_object; 19 20 /* Forward declaration from pvr_gem.h. */ 21 struct pvr_gem_object; 22 23 /* Forward declaration from pvr_hwrt.h. */ 24 struct pvr_hwrt_data; 25 26 /** 27 * struct pvr_free_list_node - structure representing an allocation in the free 28 * list 29 */ 30 struct pvr_free_list_node { 31 /** @node: List node for &pvr_free_list.mem_block_list. */ 32 struct list_head node; 33 34 /** @free_list: Pointer to owning free list. */ 35 struct pvr_free_list *free_list; 36 37 /** @num_pages: Number of pages in this node. */ 38 u32 num_pages; 39 40 /** @mem_obj: GEM object representing the pages in this node. */ 41 struct pvr_gem_object *mem_obj; 42 }; 43 44 /** 45 * struct pvr_free_list - structure representing a free list 46 */ 47 struct pvr_free_list { 48 /** @ref_count: Reference count of object. */ 49 struct kref ref_count; 50 51 /** @pvr_dev: Pointer to device that owns this object. */ 52 struct pvr_device *pvr_dev; 53 54 /** @obj: GEM object representing the free list. */ 55 struct pvr_gem_object *obj; 56 57 /** @fw_obj: FW object representing the FW-side structure. */ 58 struct pvr_fw_object *fw_obj; 59 60 /** @fw_data: Pointer to CPU mapping of the FW-side structure. */ 61 struct rogue_fwif_freelist *fw_data; 62 63 /** 64 * @lock: Mutex protecting modification of the free list. Must be held when accessing any 65 * of the members below. 66 */ 67 struct mutex lock; 68 69 /** @fw_id: Firmware ID for this object. */ 70 u32 fw_id; 71 72 /** @current_pages: Current number of pages in free list. */ 73 u32 current_pages; 74 75 /** @max_pages: Maximum number of pages in free list. */ 76 u32 max_pages; 77 78 /** @grow_pages: Pages to grow free list by per request. */ 79 u32 grow_pages; 80 81 /** 82 * @grow_threshold: Percentage of FL memory used that should trigger a 83 * new grow request. 84 */ 85 u32 grow_threshold; 86 87 /** 88 * @ready_pages: Number of pages reserved for FW to use while a grow 89 * request is being processed. 90 */ 91 u32 ready_pages; 92 93 /** @mem_block_list: List of memory blocks in this free list. */ 94 struct list_head mem_block_list; 95 96 /** @hwrt_list: List of HWRTs using this free list. */ 97 struct list_head hwrt_list; 98 99 /** @initial_num_pages: Initial number of pages in free list. */ 100 u32 initial_num_pages; 101 102 /** @free_list_gpu_addr: Address of free list in GPU address space. */ 103 u64 free_list_gpu_addr; 104 }; 105 106 struct pvr_free_list * 107 pvr_free_list_create(struct pvr_file *pvr_file, 108 struct drm_pvr_ioctl_create_free_list_args *args); 109 110 void 111 pvr_destroy_free_lists_for_file(struct pvr_file *pvr_file); 112 113 u32 114 pvr_get_free_list_min_pages(struct pvr_device *pvr_dev); 115 116 static __always_inline struct pvr_free_list * 117 pvr_free_list_get(struct pvr_free_list *free_list) 118 { 119 if (free_list) 120 kref_get(&free_list->ref_count); 121 122 return free_list; 123 } 124 125 /** 126 * pvr_free_list_lookup() - Lookup free list pointer from handle and file 127 * @pvr_file: Pointer to pvr_file structure. 128 * @handle: Object handle. 129 * 130 * Takes reference on free list object. Call pvr_free_list_put() to release. 131 * 132 * Returns: 133 * * The requested object on success, or 134 * * %NULL on failure (object does not exist in list, is not a free list, or 135 * does not belong to @pvr_file) 136 */ 137 static __always_inline struct pvr_free_list * 138 pvr_free_list_lookup(struct pvr_file *pvr_file, u32 handle) 139 { 140 struct pvr_free_list *free_list; 141 142 xa_lock(&pvr_file->free_list_handles); 143 free_list = pvr_free_list_get(xa_load(&pvr_file->free_list_handles, handle)); 144 xa_unlock(&pvr_file->free_list_handles); 145 146 return free_list; 147 } 148 149 /** 150 * pvr_free_list_lookup_id() - Lookup free list pointer from FW ID 151 * @pvr_dev: Device pointer. 152 * @id: FW object ID. 153 * 154 * Takes reference on free list object. Call pvr_free_list_put() to release. 155 * 156 * Returns: 157 * * The requested object on success, or 158 * * %NULL on failure (object does not exist in list, or is not a free list) 159 */ 160 static __always_inline struct pvr_free_list * 161 pvr_free_list_lookup_id(struct pvr_device *pvr_dev, u32 id) 162 { 163 struct pvr_free_list *free_list; 164 165 xa_lock(&pvr_dev->free_list_ids); 166 167 /* Contexts are removed from the ctx_ids set in the context release path, 168 * meaning the ref_count reached zero before they get removed. We need 169 * to make sure we're not trying to acquire a context that's being 170 * destroyed. 171 */ 172 free_list = xa_load(&pvr_dev->free_list_ids, id); 173 if (free_list && !kref_get_unless_zero(&free_list->ref_count)) 174 free_list = NULL; 175 xa_unlock(&pvr_dev->free_list_ids); 176 177 return free_list; 178 } 179 180 void 181 pvr_free_list_put(struct pvr_free_list *free_list); 182 183 void 184 pvr_free_list_add_hwrt(struct pvr_free_list *free_list, struct pvr_hwrt_data *hwrt_data); 185 void 186 pvr_free_list_remove_hwrt(struct pvr_free_list *free_list, struct pvr_hwrt_data *hwrt_data); 187 188 void pvr_free_list_process_grow_req(struct pvr_device *pvr_dev, 189 struct rogue_fwif_fwccb_cmd_freelist_gs_data *req); 190 191 void 192 pvr_free_list_process_reconstruct_req(struct pvr_device *pvr_dev, 193 struct rogue_fwif_fwccb_cmd_freelists_reconstruction_data *req); 194 195 #endif /* PVR_FREE_LIST_H */ 196