| File: | radeon/radeon_cs_gem.c |
| Location: | line 342, column 5 |
| Description: | Value stored to 'root' is never read |
| 1 | /* |
| 2 | * Copyright © 2008 Jérôme Glisse |
| 3 | * All Rights Reserved. |
| 4 | * |
| 5 | * Permission is hereby granted, free of charge, to any person obtaining |
| 6 | * a copy of this software and associated documentation files (the |
| 7 | * "Software"), to deal in the Software without restriction, including |
| 8 | * without limitation the rights to use, copy, modify, merge, publish, |
| 9 | * distribute, sub license, and/or sell copies of the Software, and to |
| 10 | * permit persons to whom the Software is furnished to do so, subject to |
| 11 | * the following conditions: |
| 12 | * |
| 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 14 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
| 15 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 16 | * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS |
| 17 | * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| 20 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 21 | * |
| 22 | * The above copyright notice and this permission notice (including the |
| 23 | * next paragraph) shall be included in all copies or substantial portions |
| 24 | * of the Software. |
| 25 | */ |
| 26 | /* |
| 27 | * Authors: |
| 28 | * Aapo Tahkola <aet@rasterburn.org> |
| 29 | * Nicolai Haehnle <prefect_@gmx.net> |
| 30 | * Jérôme Glisse <glisse@freedesktop.org> |
| 31 | */ |
| 32 | #include <assert.h> |
| 33 | #include <errno(*__errno_location ()).h> |
| 34 | #include <stdlib.h> |
| 35 | #include <string.h> |
| 36 | #include <pthread.h> |
| 37 | #include <sys/mman.h> |
| 38 | #include <sys/ioctl.h> |
| 39 | #include "radeon_cs.h" |
| 40 | #include "radeon_cs_int.h" |
| 41 | #include "radeon_bo_int.h" |
| 42 | #include "radeon_cs_gem.h" |
| 43 | #include "radeon_bo_gem.h" |
| 44 | #include "drm.h" |
| 45 | #include "xf86drm.h" |
| 46 | #include "xf86atomic.h" |
| 47 | #include "radeon_drm.h" |
| 48 | #include "bof.h" |
| 49 | |
| 50 | #define CS_BOF_DUMP0 0 |
| 51 | |
| 52 | struct radeon_cs_manager_gem { |
| 53 | struct radeon_cs_manager base; |
| 54 | uint32_t device_id; |
| 55 | unsigned nbof; |
| 56 | }; |
| 57 | |
| 58 | #pragma pack(1) |
| 59 | struct cs_reloc_gem { |
| 60 | uint32_t handle; |
| 61 | uint32_t read_domain; |
| 62 | uint32_t write_domain; |
| 63 | uint32_t flags; |
| 64 | }; |
| 65 | |
| 66 | #pragma pack() |
| 67 | #define RELOC_SIZE(sizeof(struct cs_reloc_gem) / sizeof(uint32_t)) (sizeof(struct cs_reloc_gem) / sizeof(uint32_t)) |
| 68 | |
| 69 | struct cs_gem { |
| 70 | struct radeon_cs_int base; |
| 71 | struct drm_radeon_cs cs; |
| 72 | struct drm_radeon_cs_chunk chunks[2]; |
| 73 | unsigned nrelocs; |
| 74 | uint32_t *relocs; |
| 75 | struct radeon_bo_int **relocs_bo; |
| 76 | }; |
| 77 | |
| 78 | static pthread_mutex_t id_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, { 0, 0 } } }; |
| 79 | static uint32_t cs_id_source = 0; |
| 80 | |
| 81 | /** |
| 82 | * result is undefined if called with ~0 |
| 83 | */ |
| 84 | static uint32_t get_first_zero(const uint32_t n) |
| 85 | { |
| 86 | /* __builtin_ctz returns number of trailing zeros. */ |
| 87 | return 1 << __builtin_ctz(~n); |
| 88 | } |
| 89 | |
| 90 | /** |
| 91 | * Returns a free id for cs. |
| 92 | * If there is no free id we return zero |
| 93 | **/ |
| 94 | static uint32_t generate_id(void) |
| 95 | { |
| 96 | uint32_t r = 0; |
| 97 | pthread_mutex_lock( &id_mutex ); |
| 98 | /* check for free ids */ |
| 99 | if (cs_id_source != ~r) { |
| 100 | /* find first zero bit */ |
| 101 | r = get_first_zero(cs_id_source); |
| 102 | |
| 103 | /* set id as reserved */ |
| 104 | cs_id_source |= r; |
| 105 | } |
| 106 | pthread_mutex_unlock( &id_mutex ); |
| 107 | return r; |
| 108 | } |
| 109 | |
| 110 | /** |
| 111 | * Free the id for later reuse |
| 112 | **/ |
| 113 | static void free_id(uint32_t id) |
| 114 | { |
| 115 | pthread_mutex_lock( &id_mutex ); |
| 116 | |
| 117 | cs_id_source &= ~id; |
| 118 | |
| 119 | pthread_mutex_unlock( &id_mutex ); |
| 120 | } |
| 121 | |
| 122 | static struct radeon_cs_int *cs_gem_create(struct radeon_cs_manager *csm, |
| 123 | uint32_t ndw) |
| 124 | { |
| 125 | struct cs_gem *csg; |
| 126 | |
| 127 | /* max cmd buffer size is 64Kb */ |
| 128 | if (ndw > (64 * 1024 / 4)) { |
| 129 | return NULL((void *)0); |
| 130 | } |
| 131 | csg = (struct cs_gem*)calloc(1, sizeof(struct cs_gem)); |
| 132 | if (csg == NULL((void *)0)) { |
| 133 | return NULL((void *)0); |
| 134 | } |
| 135 | csg->base.csm = csm; |
| 136 | csg->base.ndw = 64 * 1024 / 4; |
| 137 | csg->base.packets = (uint32_t*)calloc(1, 64 * 1024); |
| 138 | if (csg->base.packets == NULL((void *)0)) { |
| 139 | free(csg); |
| 140 | return NULL((void *)0); |
| 141 | } |
| 142 | csg->base.relocs_total_size = 0; |
| 143 | csg->base.crelocs = 0; |
| 144 | csg->base.id = generate_id(); |
| 145 | csg->nrelocs = 4096 / (4 * 4) ; |
| 146 | csg->relocs_bo = (struct radeon_bo_int**)calloc(1, |
| 147 | csg->nrelocs*sizeof(void*)); |
| 148 | if (csg->relocs_bo == NULL((void *)0)) { |
| 149 | free(csg->base.packets); |
| 150 | free(csg); |
| 151 | return NULL((void *)0); |
| 152 | } |
| 153 | csg->base.relocs = csg->relocs = (uint32_t*)calloc(1, 4096); |
| 154 | if (csg->relocs == NULL((void *)0)) { |
| 155 | free(csg->relocs_bo); |
| 156 | free(csg->base.packets); |
| 157 | free(csg); |
| 158 | return NULL((void *)0); |
| 159 | } |
| 160 | csg->chunks[0].chunk_id = RADEON_CHUNK_ID_IB0x02; |
| 161 | csg->chunks[0].length_dw = 0; |
| 162 | csg->chunks[0].chunk_data = (uint64_t)(uintptr_t)csg->base.packets; |
| 163 | csg->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS0x01; |
| 164 | csg->chunks[1].length_dw = 0; |
| 165 | csg->chunks[1].chunk_data = (uint64_t)(uintptr_t)csg->relocs; |
| 166 | return (struct radeon_cs_int*)csg; |
| 167 | } |
| 168 | |
| 169 | static int cs_gem_write_reloc(struct radeon_cs_int *cs, |
| 170 | struct radeon_bo *bo, |
| 171 | uint32_t read_domain, |
| 172 | uint32_t write_domain, |
| 173 | uint32_t flags) |
| 174 | { |
| 175 | struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; |
| 176 | struct cs_gem *csg = (struct cs_gem*)cs; |
| 177 | struct cs_reloc_gem *reloc; |
| 178 | uint32_t idx; |
| 179 | unsigned i; |
| 180 | |
| 181 | assert(boi->space_accounted)((boi->space_accounted) ? (void) (0) : __assert_fail ("boi->space_accounted" , "radeon_cs_gem.c", 181, __PRETTY_FUNCTION__)); |
| 182 | |
| 183 | /* check domains */ |
| 184 | if ((read_domain && write_domain) || (!read_domain && !write_domain)) { |
| 185 | /* in one CS a bo can only be in read or write domain but not |
| 186 | * in read & write domain at the same sime |
| 187 | */ |
| 188 | return -EINVAL22; |
| 189 | } |
| 190 | if (read_domain == RADEON_GEM_DOMAIN_CPU0x1) { |
| 191 | return -EINVAL22; |
| 192 | } |
| 193 | if (write_domain == RADEON_GEM_DOMAIN_CPU0x1) { |
| 194 | return -EINVAL22; |
| 195 | } |
| 196 | /* use bit field hash function to determine |
| 197 | if this bo is for sure not in this cs.*/ |
| 198 | if ((atomic_read((atomic_t *)radeon_gem_get_reloc_in_cs(bo))(((atomic_t *)radeon_gem_get_reloc_in_cs(bo))->atomic) & cs->id)) { |
| 199 | /* check if bo is already referenced. |
| 200 | * Scanning from end to begin reduces cycles with mesa because |
| 201 | * it often relocates same shared dma bo again. */ |
| 202 | for(i = cs->crelocs; i != 0;) { |
| 203 | --i; |
| 204 | idx = i * RELOC_SIZE(sizeof(struct cs_reloc_gem) / sizeof(uint32_t)); |
| 205 | reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; |
| 206 | if (reloc->handle == bo->handle) { |
| 207 | /* Check domains must be in read or write. As we check already |
| 208 | * checked that in argument one of the read or write domain was |
| 209 | * set we only need to check that if previous reloc as the read |
| 210 | * domain set then the read_domain should also be set for this |
| 211 | * new relocation. |
| 212 | */ |
| 213 | /* the DDX expects to read and write from same pixmap */ |
| 214 | if (write_domain && (reloc->read_domain & write_domain)) { |
| 215 | reloc->read_domain = 0; |
| 216 | reloc->write_domain = write_domain; |
| 217 | } else if (read_domain & reloc->write_domain) { |
| 218 | reloc->read_domain = 0; |
| 219 | } else { |
| 220 | if (write_domain != reloc->write_domain) |
| 221 | return -EINVAL22; |
| 222 | if (read_domain != reloc->read_domain) |
| 223 | return -EINVAL22; |
| 224 | } |
| 225 | |
| 226 | reloc->read_domain |= read_domain; |
| 227 | reloc->write_domain |= write_domain; |
| 228 | /* update flags */ |
| 229 | reloc->flags |= (flags & reloc->flags); |
| 230 | /* write relocation packet */ |
| 231 | radeon_cs_write_dword((struct radeon_cs *)cs, 0xc0001000); |
| 232 | radeon_cs_write_dword((struct radeon_cs *)cs, idx); |
| 233 | return 0; |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | /* new relocation */ |
| 238 | if (csg->base.crelocs >= csg->nrelocs) { |
| 239 | /* allocate more memory (TODO: should use a slab allocatore maybe) */ |
| 240 | uint32_t *tmp, size; |
| 241 | size = ((csg->nrelocs + 1) * sizeof(struct radeon_bo*)); |
| 242 | tmp = (uint32_t*)realloc(csg->relocs_bo, size); |
| 243 | if (tmp == NULL((void *)0)) { |
| 244 | return -ENOMEM12; |
| 245 | } |
| 246 | csg->relocs_bo = (struct radeon_bo_int **)tmp; |
| 247 | size = ((csg->nrelocs + 1) * RELOC_SIZE(sizeof(struct cs_reloc_gem) / sizeof(uint32_t)) * 4); |
| 248 | tmp = (uint32_t*)realloc(csg->relocs, size); |
| 249 | if (tmp == NULL((void *)0)) { |
| 250 | return -ENOMEM12; |
| 251 | } |
| 252 | cs->relocs = csg->relocs = tmp; |
| 253 | csg->nrelocs += 1; |
| 254 | csg->chunks[1].chunk_data = (uint64_t)(uintptr_t)csg->relocs; |
| 255 | } |
| 256 | csg->relocs_bo[csg->base.crelocs] = boi; |
| 257 | idx = (csg->base.crelocs++) * RELOC_SIZE(sizeof(struct cs_reloc_gem) / sizeof(uint32_t)); |
| 258 | reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; |
| 259 | reloc->handle = bo->handle; |
| 260 | reloc->read_domain = read_domain; |
| 261 | reloc->write_domain = write_domain; |
| 262 | reloc->flags = flags; |
| 263 | csg->chunks[1].length_dw += RELOC_SIZE(sizeof(struct cs_reloc_gem) / sizeof(uint32_t)); |
| 264 | radeon_bo_ref(bo); |
| 265 | /* bo might be referenced from another context so have to use atomic opertions */ |
| 266 | atomic_add((atomic_t *)radeon_gem_get_reloc_in_cs(bo), cs->id)((void) __sync_add_and_fetch(&((atomic_t *)radeon_gem_get_reloc_in_cs (bo))->atomic, (cs->id))); |
| 267 | cs->relocs_total_size += boi->size; |
| 268 | radeon_cs_write_dword((struct radeon_cs *)cs, 0xc0001000); |
| 269 | radeon_cs_write_dword((struct radeon_cs *)cs, idx); |
| 270 | return 0; |
| 271 | } |
| 272 | |
| 273 | static int cs_gem_begin(struct radeon_cs_int *cs, |
| 274 | uint32_t ndw, |
| 275 | const char *file, |
| 276 | const char *func, |
| 277 | int line) |
| 278 | { |
| 279 | |
| 280 | if (cs->section_ndw) { |
| 281 | fprintf(stderrstderr, "CS already in a section(%s,%s,%d)\n", |
| 282 | cs->section_file, cs->section_func, cs->section_line); |
| 283 | fprintf(stderrstderr, "CS can't start section(%s,%s,%d)\n", |
| 284 | file, func, line); |
| 285 | return -EPIPE32; |
| 286 | } |
| 287 | cs->section_ndw = ndw; |
| 288 | cs->section_cdw = 0; |
| 289 | cs->section_file = file; |
| 290 | cs->section_func = func; |
| 291 | cs->section_line = line; |
| 292 | |
| 293 | if (cs->cdw + ndw > cs->ndw) { |
| 294 | uint32_t tmp, *ptr; |
| 295 | |
| 296 | /* round up the required size to a multiple of 1024 */ |
| 297 | tmp = (cs->cdw + ndw + 0x3FF) & (~0x3FF); |
| 298 | ptr = (uint32_t*)realloc(cs->packets, 4 * tmp); |
| 299 | if (ptr == NULL((void *)0)) { |
| 300 | return -ENOMEM12; |
| 301 | } |
| 302 | cs->packets = ptr; |
| 303 | cs->ndw = tmp; |
| 304 | } |
| 305 | return 0; |
| 306 | } |
| 307 | |
| 308 | static int cs_gem_end(struct radeon_cs_int *cs, |
| 309 | const char *file, |
| 310 | const char *func, |
| 311 | int line) |
| 312 | |
| 313 | { |
| 314 | if (!cs->section_ndw) { |
| 315 | fprintf(stderrstderr, "CS no section to end at (%s,%s,%d)\n", |
| 316 | file, func, line); |
| 317 | return -EPIPE32; |
| 318 | } |
| 319 | if (cs->section_ndw != cs->section_cdw) { |
| 320 | fprintf(stderrstderr, "CS section size missmatch start at (%s,%s,%d) %d vs %d\n", |
| 321 | cs->section_file, cs->section_func, cs->section_line, cs->section_ndw, cs->section_cdw); |
| 322 | fprintf(stderrstderr, "CS section end at (%s,%s,%d)\n", |
| 323 | file, func, line); |
| 324 | |
| 325 | /* We must reset the section even when there is error. */ |
| 326 | cs->section_ndw = 0; |
| 327 | return -EPIPE32; |
| 328 | } |
| 329 | cs->section_ndw = 0; |
| 330 | return 0; |
| 331 | } |
| 332 | |
| 333 | static void cs_gem_dump_bof(struct radeon_cs_int *cs) |
| 334 | { |
| 335 | struct cs_gem *csg = (struct cs_gem*)cs; |
| 336 | struct radeon_cs_manager_gem *csm; |
| 337 | bof_t *bcs, *blob, *array, *bo, *size, *handle, *device_id, *root; |
| 338 | char tmp[256]; |
| 339 | unsigned i; |
| 340 | |
| 341 | csm = (struct radeon_cs_manager_gem *)cs->csm; |
| 342 | root = device_id = bcs = blob = array = bo = size = handle = NULL((void *)0); |
Value stored to 'root' is never read | |
| 343 | root = bof_object(); |
| 344 | if (root == NULL((void *)0)) |
| 345 | goto out_err; |
| 346 | device_id = bof_int32(csm->device_id); |
| 347 | if (device_id == NULL((void *)0)) |
| 348 | return; |
| 349 | if (bof_object_set(root, "device_id", device_id)) |
| 350 | goto out_err; |
| 351 | bof_decref(device_id); |
| 352 | device_id = NULL((void *)0); |
| 353 | /* dump relocs */ |
| 354 | blob = bof_blob(csg->nrelocs * 16, csg->relocs); |
| 355 | if (blob == NULL((void *)0)) |
| 356 | goto out_err; |
| 357 | if (bof_object_set(root, "reloc", blob)) |
| 358 | goto out_err; |
| 359 | bof_decref(blob); |
| 360 | blob = NULL((void *)0); |
| 361 | /* dump cs */ |
| 362 | blob = bof_blob(cs->cdw * 4, cs->packets); |
| 363 | if (blob == NULL((void *)0)) |
| 364 | goto out_err; |
| 365 | if (bof_object_set(root, "pm4", blob)) |
| 366 | goto out_err; |
| 367 | bof_decref(blob); |
| 368 | blob = NULL((void *)0); |
| 369 | /* dump bo */ |
| 370 | array = bof_array(); |
| 371 | if (array == NULL((void *)0)) |
| 372 | goto out_err; |
| 373 | for (i = 0; i < csg->base.crelocs; i++) { |
| 374 | bo = bof_object(); |
| 375 | if (bo == NULL((void *)0)) |
| 376 | goto out_err; |
| 377 | size = bof_int32(csg->relocs_bo[i]->size); |
| 378 | if (size == NULL((void *)0)) |
| 379 | goto out_err; |
| 380 | if (bof_object_set(bo, "size", size)) |
| 381 | goto out_err; |
| 382 | bof_decref(size); |
| 383 | size = NULL((void *)0); |
| 384 | handle = bof_int32(csg->relocs_bo[i]->handle); |
| 385 | if (handle == NULL((void *)0)) |
| 386 | goto out_err; |
| 387 | if (bof_object_set(bo, "handle", handle)) |
| 388 | goto out_err; |
| 389 | bof_decref(handle); |
| 390 | handle = NULL((void *)0); |
| 391 | radeon_bo_map((struct radeon_bo*)csg->relocs_bo[i], 0); |
| 392 | blob = bof_blob(csg->relocs_bo[i]->size, csg->relocs_bo[i]->ptr); |
| 393 | radeon_bo_unmap((struct radeon_bo*)csg->relocs_bo[i]); |
| 394 | if (blob == NULL((void *)0)) |
| 395 | goto out_err; |
| 396 | if (bof_object_set(bo, "data", blob)) |
| 397 | goto out_err; |
| 398 | bof_decref(blob); |
| 399 | blob = NULL((void *)0); |
| 400 | if (bof_array_append(array, bo)) |
| 401 | goto out_err; |
| 402 | bof_decref(bo); |
| 403 | bo = NULL((void *)0); |
| 404 | } |
| 405 | if (bof_object_set(root, "bo", array)) |
| 406 | goto out_err; |
| 407 | sprintf(tmp, "d-0x%04X-%08d.bof", csm->device_id, csm->nbof++); |
| 408 | bof_dump_file(root, tmp); |
| 409 | out_err: |
| 410 | bof_decref(blob); |
| 411 | bof_decref(array); |
| 412 | bof_decref(bo); |
| 413 | bof_decref(size); |
| 414 | bof_decref(handle); |
| 415 | bof_decref(device_id); |
| 416 | bof_decref(root); |
| 417 | } |
| 418 | |
| 419 | static int cs_gem_emit(struct radeon_cs_int *cs) |
| 420 | { |
| 421 | struct cs_gem *csg = (struct cs_gem*)cs; |
| 422 | uint64_t chunk_array[2]; |
| 423 | unsigned i; |
| 424 | int r; |
| 425 | |
| 426 | #if CS_BOF_DUMP0 |
| 427 | cs_gem_dump_bof(cs); |
| 428 | #endif |
| 429 | csg->chunks[0].length_dw = cs->cdw; |
| 430 | |
| 431 | chunk_array[0] = (uint64_t)(uintptr_t)&csg->chunks[0]; |
| 432 | chunk_array[1] = (uint64_t)(uintptr_t)&csg->chunks[1]; |
| 433 | |
| 434 | csg->cs.num_chunks = 2; |
| 435 | csg->cs.chunks = (uint64_t)(uintptr_t)chunk_array; |
| 436 | |
| 437 | r = drmCommandWriteRead(cs->csm->fd, DRM_RADEON_CS0x26, |
| 438 | &csg->cs, sizeof(struct drm_radeon_cs)); |
| 439 | for (i = 0; i < csg->base.crelocs; i++) { |
| 440 | csg->relocs_bo[i]->space_accounted = 0; |
| 441 | /* bo might be referenced from another context so have to use atomic opertions */ |
| 442 | atomic_dec((atomic_t *)radeon_gem_get_reloc_in_cs((struct radeon_bo*)csg->relocs_bo[i]), cs->id)((void) __sync_sub_and_fetch(&((atomic_t *)radeon_gem_get_reloc_in_cs ((struct radeon_bo*)csg->relocs_bo[i]))->atomic, (cs-> id))); |
| 443 | radeon_bo_unref((struct radeon_bo *)csg->relocs_bo[i]); |
| 444 | csg->relocs_bo[i] = NULL((void *)0); |
| 445 | } |
| 446 | |
| 447 | cs->csm->read_used = 0; |
| 448 | cs->csm->vram_write_used = 0; |
| 449 | cs->csm->gart_write_used = 0; |
| 450 | return r; |
| 451 | } |
| 452 | |
| 453 | static int cs_gem_destroy(struct radeon_cs_int *cs) |
| 454 | { |
| 455 | struct cs_gem *csg = (struct cs_gem*)cs; |
| 456 | |
| 457 | free_id(cs->id); |
| 458 | free(csg->relocs_bo); |
| 459 | free(cs->relocs); |
| 460 | free(cs->packets); |
| 461 | free(cs); |
| 462 | return 0; |
| 463 | } |
| 464 | |
| 465 | static int cs_gem_erase(struct radeon_cs_int *cs) |
| 466 | { |
| 467 | struct cs_gem *csg = (struct cs_gem*)cs; |
| 468 | unsigned i; |
| 469 | |
| 470 | if (csg->relocs_bo) { |
| 471 | for (i = 0; i < csg->base.crelocs; i++) { |
| 472 | if (csg->relocs_bo[i]) { |
| 473 | /* bo might be referenced from another context so have to use atomic opertions */ |
| 474 | atomic_dec((atomic_t *)radeon_gem_get_reloc_in_cs((struct radeon_bo*)csg->relocs_bo[i]), cs->id)((void) __sync_sub_and_fetch(&((atomic_t *)radeon_gem_get_reloc_in_cs ((struct radeon_bo*)csg->relocs_bo[i]))->atomic, (cs-> id))); |
| 475 | radeon_bo_unref((struct radeon_bo *)csg->relocs_bo[i]); |
| 476 | csg->relocs_bo[i] = NULL((void *)0); |
| 477 | } |
| 478 | } |
| 479 | } |
| 480 | cs->relocs_total_size = 0; |
| 481 | cs->cdw = 0; |
| 482 | cs->section_ndw = 0; |
| 483 | cs->crelocs = 0; |
| 484 | csg->chunks[0].length_dw = 0; |
| 485 | csg->chunks[1].length_dw = 0; |
| 486 | return 0; |
| 487 | } |
| 488 | |
| 489 | static int cs_gem_need_flush(struct radeon_cs_int *cs) |
| 490 | { |
| 491 | return 0; //(cs->relocs_total_size > (32*1024*1024)); |
| 492 | } |
| 493 | |
| 494 | static void cs_gem_print(struct radeon_cs_int *cs, FILE *file) |
| 495 | { |
| 496 | struct radeon_cs_manager_gem *csm; |
| 497 | unsigned int i; |
| 498 | |
| 499 | csm = (struct radeon_cs_manager_gem *)cs->csm; |
| 500 | fprintf(file, "VENDORID:DEVICEID 0x%04X:0x%04X\n", 0x1002, csm->device_id); |
| 501 | for (i = 0; i < cs->cdw; i++) { |
| 502 | fprintf(file, "0x%08X\n", cs->packets[i]); |
| 503 | } |
| 504 | } |
| 505 | |
| 506 | static struct radeon_cs_funcs radeon_cs_gem_funcs = { |
| 507 | cs_gem_create, |
| 508 | cs_gem_write_reloc, |
| 509 | cs_gem_begin, |
| 510 | cs_gem_end, |
| 511 | cs_gem_emit, |
| 512 | cs_gem_destroy, |
| 513 | cs_gem_erase, |
| 514 | cs_gem_need_flush, |
| 515 | cs_gem_print, |
| 516 | }; |
| 517 | |
| 518 | static int radeon_get_device_id(int fd, uint32_t *device_id) |
| 519 | { |
| 520 | struct drm_radeon_info info = {}; |
| 521 | int r; |
| 522 | |
| 523 | *device_id = 0; |
| 524 | info.request = RADEON_INFO_DEVICE_ID0x00; |
| 525 | info.value = (uintptr_t)device_id; |
| 526 | r = drmCommandWriteRead(fd, DRM_RADEON_INFO0x27, &info, |
| 527 | sizeof(struct drm_radeon_info)); |
| 528 | return r; |
| 529 | } |
| 530 | |
| 531 | struct radeon_cs_manager *radeon_cs_manager_gem_ctor(int fd) |
| 532 | { |
| 533 | struct radeon_cs_manager_gem *csm; |
| 534 | |
| 535 | csm = calloc(1, sizeof(struct radeon_cs_manager_gem)); |
| 536 | if (csm == NULL((void *)0)) { |
| 537 | return NULL((void *)0); |
| 538 | } |
| 539 | csm->base.funcs = &radeon_cs_gem_funcs; |
| 540 | csm->base.fd = fd; |
| 541 | radeon_get_device_id(fd, &csm->device_id); |
| 542 | return &csm->base; |
| 543 | } |
| 544 | |
| 545 | void radeon_cs_manager_gem_dtor(struct radeon_cs_manager *csm) |
| 546 | { |
| 547 | free(csm); |
| 548 | } |