1 /* $NetBSD: amdgpu_vector.c,v 1.2 2021/12/18 23:45:00 riastradh Exp $ */ 2 3 /* 4 * Copyright 2012-15 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: AMD 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_vector.c,v 1.2 2021/12/18 23:45:00 riastradh Exp $"); 30 31 #include <linux/slab.h> 32 33 #include "dm_services.h" 34 #include "include/vector.h" 35 36 bool dal_vector_construct( 37 struct vector *vector, 38 struct dc_context *ctx, 39 uint32_t capacity, 40 uint32_t struct_size) 41 { 42 vector->container = NULL; 43 44 if (!struct_size || !capacity) { 45 /* Container must be non-zero size*/ 46 BREAK_TO_DEBUGGER(); 47 return false; 48 } 49 50 vector->container = kcalloc(capacity, struct_size, GFP_KERNEL); 51 if (vector->container == NULL) 52 return false; 53 vector->capacity = capacity; 54 vector->struct_size = struct_size; 55 vector->count = 0; 56 vector->ctx = ctx; 57 return true; 58 } 59 60 bool dal_vector_presized_costruct( 61 struct vector *vector, 62 struct dc_context *ctx, 63 uint32_t count, 64 void *initial_value, 65 uint32_t struct_size) 66 { 67 uint32_t i; 68 69 vector->container = NULL; 70 71 if (!struct_size || !count) { 72 /* Container must be non-zero size*/ 73 BREAK_TO_DEBUGGER(); 74 return false; 75 } 76 77 vector->container = kcalloc(count, struct_size, GFP_KERNEL); 78 79 if (vector->container == NULL) 80 return false; 81 82 /* If caller didn't supply initial value then the default 83 * of all zeros is expected, which is exactly what dal_alloc() 84 * initialises the memory to. */ 85 if (NULL != initial_value) { 86 for (i = 0; i < count; ++i) 87 memmove( 88 vector->container + i * struct_size, 89 initial_value, 90 struct_size); 91 } 92 93 vector->capacity = count; 94 vector->struct_size = struct_size; 95 vector->count = count; 96 return true; 97 } 98 99 struct vector *dal_vector_presized_create( 100 struct dc_context *ctx, 101 uint32_t size, 102 void *initial_value, 103 uint32_t struct_size) 104 { 105 struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); 106 107 if (vector == NULL) 108 return NULL; 109 110 if (dal_vector_presized_costruct( 111 vector, ctx, size, initial_value, struct_size)) 112 return vector; 113 114 BREAK_TO_DEBUGGER(); 115 kfree(vector); 116 return NULL; 117 } 118 119 struct vector *dal_vector_create( 120 struct dc_context *ctx, 121 uint32_t capacity, 122 uint32_t struct_size) 123 { 124 struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); 125 126 if (vector == NULL) 127 return NULL; 128 129 if (dal_vector_construct(vector, ctx, capacity, struct_size)) 130 return vector; 131 132 BREAK_TO_DEBUGGER(); 133 kfree(vector); 134 return NULL; 135 } 136 137 void dal_vector_destruct( 138 struct vector *vector) 139 { 140 kfree(vector->container); 141 vector->count = 0; 142 vector->capacity = 0; 143 } 144 145 void dal_vector_destroy( 146 struct vector **vector) 147 { 148 if (vector == NULL || *vector == NULL) 149 return; 150 dal_vector_destruct(*vector); 151 kfree(*vector); 152 *vector = NULL; 153 } 154 155 uint32_t dal_vector_get_count( 156 const struct vector *vector) 157 { 158 return vector->count; 159 } 160 161 void *dal_vector_at_index( 162 const struct vector *vector, 163 uint32_t index) 164 { 165 if (vector->container == NULL || index >= vector->count) 166 return NULL; 167 return vector->container + (index * vector->struct_size); 168 } 169 170 bool dal_vector_remove_at_index( 171 struct vector *vector, 172 uint32_t index) 173 { 174 if (index >= vector->count) 175 return false; 176 177 if (index != vector->count - 1) 178 memmove( 179 vector->container + (index * vector->struct_size), 180 vector->container + ((index + 1) * vector->struct_size), 181 (vector->count - index - 1) * vector->struct_size); 182 vector->count -= 1; 183 184 return true; 185 } 186 187 void dal_vector_set_at_index( 188 const struct vector *vector, 189 const void *what, 190 uint32_t index) 191 { 192 void *where = dal_vector_at_index(vector, index); 193 194 if (!where) { 195 BREAK_TO_DEBUGGER(); 196 return; 197 } 198 memmove( 199 where, 200 what, 201 vector->struct_size); 202 } 203 204 static inline uint32_t calc_increased_capacity( 205 uint32_t old_capacity) 206 { 207 return old_capacity * 2; 208 } 209 210 bool dal_vector_insert_at( 211 struct vector *vector, 212 const void *what, 213 uint32_t position) 214 { 215 uint8_t *insert_address; 216 217 if (vector->count == vector->capacity) { 218 if (!dal_vector_reserve( 219 vector, 220 calc_increased_capacity(vector->capacity))) 221 return false; 222 } 223 224 insert_address = vector->container + (vector->struct_size * position); 225 226 if (vector->count && position < vector->count) 227 memmove( 228 insert_address + vector->struct_size, 229 insert_address, 230 vector->struct_size * (vector->count - position)); 231 232 memmove( 233 insert_address, 234 what, 235 vector->struct_size); 236 237 vector->count++; 238 239 return true; 240 } 241 242 bool dal_vector_append( 243 struct vector *vector, 244 const void *item) 245 { 246 return dal_vector_insert_at(vector, item, vector->count); 247 } 248 249 struct vector *dal_vector_clone( 250 const struct vector *vector) 251 { 252 struct vector *vec_cloned; 253 uint32_t count; 254 255 /* create new vector */ 256 count = dal_vector_get_count(vector); 257 258 if (count == 0) 259 /* when count is 0 we still want to create clone of the vector 260 */ 261 vec_cloned = dal_vector_create( 262 vector->ctx, 263 vector->capacity, 264 vector->struct_size); 265 else 266 /* Call "presized create" version, independently of how the 267 * original vector was created. 268 * The owner of original vector must know how to treat the new 269 * vector - as "presized" or as "regular". 270 * But from vector point of view it doesn't matter. */ 271 vec_cloned = dal_vector_presized_create(vector->ctx, count, 272 NULL,/* no initial value */ 273 vector->struct_size); 274 275 if (NULL == vec_cloned) { 276 BREAK_TO_DEBUGGER(); 277 return NULL; 278 } 279 280 /* copy vector's data */ 281 memmove(vec_cloned->container, vector->container, 282 vec_cloned->struct_size * vec_cloned->capacity); 283 284 return vec_cloned; 285 } 286 287 uint32_t dal_vector_capacity(const struct vector *vector) 288 { 289 return vector->capacity; 290 } 291 292 bool dal_vector_reserve(struct vector *vector, uint32_t capacity) 293 { 294 void *new_container; 295 296 if (capacity <= vector->capacity) 297 return true; 298 299 new_container = krealloc(vector->container, 300 capacity * vector->struct_size, GFP_KERNEL); 301 302 if (new_container) { 303 vector->container = new_container; 304 vector->capacity = capacity; 305 return true; 306 } 307 308 return false; 309 } 310 311 void dal_vector_clear(struct vector *vector) 312 { 313 vector->count = 0; 314 } 315