1 /* SPDX-License-Identifier: GPL-2.0 OR MIT */ 2 /************************************************************************** 3 * 4 * Copyright (c) 2023-2024 Broadcom. All Rights Reserved. The term 5 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25 * USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29 #ifndef VMWGFX_BO_H 30 #define VMWGFX_BO_H 31 32 #include "device_include/svga_reg.h" 33 34 #include <drm/ttm/ttm_bo.h> 35 #include <drm/ttm/ttm_placement.h> 36 37 #include <linux/rbtree_types.h> 38 #include <linux/types.h> 39 #include <linux/xarray.h> 40 41 struct vmw_bo_dirty; 42 struct vmw_fence_obj; 43 struct vmw_private; 44 struct vmw_resource; 45 struct vmw_surface; 46 47 enum vmw_bo_domain { 48 VMW_BO_DOMAIN_SYS = BIT(0), 49 VMW_BO_DOMAIN_WAITABLE_SYS = BIT(1), 50 VMW_BO_DOMAIN_VRAM = BIT(2), 51 VMW_BO_DOMAIN_GMR = BIT(3), 52 VMW_BO_DOMAIN_MOB = BIT(4), 53 }; 54 55 struct vmw_bo_params { 56 u32 domain; 57 u32 busy_domain; 58 enum ttm_bo_type bo_type; 59 size_t size; 60 bool pin; 61 struct dma_resv *resv; 62 struct sg_table *sg; 63 }; 64 65 /** 66 * struct vmw_bo - TTM buffer object with vmwgfx additions 67 * @tbo: The TTM buffer object 68 * @placement: The preferred placement for this buffer object 69 * @places: The chosen places for the preferred placement. 70 * @busy_places: Chosen busy places for the preferred placement 71 * @map: Kmap object for semi-persistent mappings 72 * @res_tree: RB tree of resources using this buffer object as a backing MOB 73 * @res_prios: Eviction priority counts for attached resources 74 * @cpu_writers: Number of synccpu write grabs. Protected by reservation when 75 * increased. May be decreased without reservation. 76 * @dx_query_ctx: DX context if this buffer object is used as a DX query MOB 77 * @dirty: structure for user-space dirty-tracking 78 */ 79 struct vmw_bo { 80 struct ttm_buffer_object tbo; 81 82 struct ttm_placement placement; 83 struct ttm_place places[5]; 84 struct ttm_place busy_places[5]; 85 86 /* Protected by reservation */ 87 struct ttm_bo_kmap_obj map; 88 89 struct rb_root res_tree; 90 u32 res_prios[TTM_MAX_BO_PRIORITY]; 91 struct xarray detached_resources; 92 93 atomic_t cpu_writers; 94 /* Not ref-counted. Protected by binding_mutex */ 95 struct vmw_resource *dx_query_ctx; 96 struct vmw_bo_dirty *dirty; 97 98 bool is_dumb; 99 struct vmw_surface *dumb_surface; 100 }; 101 102 void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain); 103 void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo); 104 105 int vmw_bo_create(struct vmw_private *dev_priv, 106 struct vmw_bo_params *params, 107 struct vmw_bo **p_bo); 108 109 int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, 110 struct drm_file *file_priv); 111 112 int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, 113 struct vmw_bo *buf, 114 bool interruptible); 115 int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, 116 struct vmw_bo *buf, 117 bool interruptible); 118 int vmw_bo_pin_in_start_of_vram(struct vmw_private *vmw_priv, 119 struct vmw_bo *bo, 120 bool interruptible); 121 void vmw_bo_pin_reserved(struct vmw_bo *bo, bool pin); 122 int vmw_bo_unpin(struct vmw_private *vmw_priv, 123 struct vmw_bo *bo, 124 bool interruptible); 125 126 void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf, 127 SVGAGuestPtr *ptr); 128 int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, 129 struct drm_file *file_priv); 130 void vmw_bo_fence_single(struct ttm_buffer_object *bo, 131 struct vmw_fence_obj *fence); 132 133 void *vmw_bo_map_and_cache(struct vmw_bo *vbo); 134 void *vmw_bo_map_and_cache_size(struct vmw_bo *vbo, size_t size); 135 void vmw_bo_unmap(struct vmw_bo *vbo); 136 137 void vmw_bo_move_notify(struct ttm_buffer_object *bo, 138 struct ttm_resource *mem); 139 void vmw_bo_swap_notify(struct ttm_buffer_object *bo); 140 141 void vmw_bo_add_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res); 142 void vmw_bo_del_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res); 143 struct vmw_surface *vmw_bo_surface(struct vmw_bo *vbo); 144 145 int vmw_user_bo_lookup(struct drm_file *filp, 146 u32 handle, 147 struct vmw_bo **out); 148 149 /** 150 * vmw_bo_adjust_prio - Adjust the buffer object eviction priority 151 * according to attached resources 152 * @vbo: The struct vmw_bo 153 */ 154 static inline void vmw_bo_prio_adjust(struct vmw_bo *vbo) 155 { 156 int i = ARRAY_SIZE(vbo->res_prios); 157 158 while (i--) { 159 if (vbo->res_prios[i]) { 160 vbo->tbo.priority = i; 161 return; 162 } 163 } 164 165 vbo->tbo.priority = 3; 166 } 167 168 /** 169 * vmw_bo_prio_add - Notify a buffer object of a newly attached resource 170 * eviction priority 171 * @vbo: The struct vmw_bo 172 * @prio: The resource priority 173 * 174 * After being notified, the code assigns the highest resource eviction priority 175 * to the backing buffer object (mob). 176 */ 177 static inline void vmw_bo_prio_add(struct vmw_bo *vbo, int prio) 178 { 179 if (vbo->res_prios[prio]++ == 0) 180 vmw_bo_prio_adjust(vbo); 181 } 182 183 /** 184 * vmw_bo_used_prio_del - Notify a buffer object of a resource with a certain 185 * priority being removed 186 * @vbo: The struct vmw_bo 187 * @prio: The resource priority 188 * 189 * After being notified, the code assigns the highest resource eviction priority 190 * to the backing buffer object (mob). 191 */ 192 static inline void vmw_bo_prio_del(struct vmw_bo *vbo, int prio) 193 { 194 if (--vbo->res_prios[prio] == 0) 195 vmw_bo_prio_adjust(vbo); 196 } 197 198 static inline void vmw_bo_unreference(struct vmw_bo **buf) 199 { 200 struct vmw_bo *tmp_buf = *buf; 201 202 *buf = NULL; 203 if (tmp_buf) 204 ttm_bo_put(&tmp_buf->tbo); 205 } 206 207 static inline struct vmw_bo *vmw_bo_reference(struct vmw_bo *buf) 208 { 209 ttm_bo_get(&buf->tbo); 210 return buf; 211 } 212 213 static inline struct vmw_bo *vmw_user_bo_ref(struct vmw_bo *vbo) 214 { 215 drm_gem_object_get(&vbo->tbo.base); 216 return vbo; 217 } 218 219 static inline void vmw_user_bo_unref(struct vmw_bo **buf) 220 { 221 struct vmw_bo *tmp_buf = *buf; 222 223 *buf = NULL; 224 if (tmp_buf) 225 drm_gem_object_put(&tmp_buf->tbo.base); 226 } 227 228 static inline struct vmw_bo *to_vmw_bo(struct drm_gem_object *gobj) 229 { 230 return container_of((gobj), struct vmw_bo, tbo.base); 231 } 232 233 #endif // VMWGFX_BO_H 234