196 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only OR MIT */2/* Copyright (c) 2023 Imagination Technologies Ltd. */3 4#ifndef PVR_FREE_LIST_H5#define PVR_FREE_LIST_H6 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. */18struct pvr_fw_object;19 20/* Forward declaration from pvr_gem.h. */21struct pvr_gem_object;22 23/* Forward declaration from pvr_hwrt.h. */24struct pvr_hwrt_data;25 26/**27 * struct pvr_free_list_node - structure representing an allocation in the free28 * list29 */30struct 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 list46 */47struct 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 any65 * 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 a83 * new grow request.84 */85 u32 grow_threshold;86 87 /**88 * @ready_pages: Number of pages reserved for FW to use while a grow89 * 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 106struct pvr_free_list *107pvr_free_list_create(struct pvr_file *pvr_file,108 struct drm_pvr_ioctl_create_free_list_args *args);109 110void111pvr_destroy_free_lists_for_file(struct pvr_file *pvr_file);112 113u32114pvr_get_free_list_min_pages(struct pvr_device *pvr_dev);115 116static __always_inline struct pvr_free_list *117pvr_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 file127 * @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, or134 * * %NULL on failure (object does not exist in list, is not a free list, or135 * does not belong to @pvr_file)136 */137static __always_inline struct pvr_free_list *138pvr_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 ID151 * @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, or158 * * %NULL on failure (object does not exist in list, or is not a free list)159 */160static __always_inline struct pvr_free_list *161pvr_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 need169 * to make sure we're not trying to acquire a context that's being170 * 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 180void181pvr_free_list_put(struct pvr_free_list *free_list);182 183void184pvr_free_list_add_hwrt(struct pvr_free_list *free_list, struct pvr_hwrt_data *hwrt_data);185void186pvr_free_list_remove_hwrt(struct pvr_free_list *free_list, struct pvr_hwrt_data *hwrt_data);187 188void pvr_free_list_process_grow_req(struct pvr_device *pvr_dev,189 struct rogue_fwif_fwccb_cmd_freelist_gs_data *req);190 191void192pvr_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