Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux-2.6-microblaze.git] / drivers / gpu / drm / radeon / radeon_cs.c
1 /*
2  * Copyright 2008 Jerome Glisse.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * 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  * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Jerome Glisse <glisse@freedesktop.org>
26  */
27 #include <linux/list_sort.h>
28 #include <drm/drmP.h>
29 #include <drm/radeon_drm.h>
30 #include "radeon_reg.h"
31 #include "radeon.h"
32 #include "radeon_trace.h"
33
34 #define RADEON_CS_MAX_PRIORITY          32u
35 #define RADEON_CS_NUM_BUCKETS           (RADEON_CS_MAX_PRIORITY + 1)
36
37 /* This is based on the bucket sort with O(n) time complexity.
38  * An item with priority "i" is added to bucket[i]. The lists are then
39  * concatenated in descending order.
40  */
41 struct radeon_cs_buckets {
42         struct list_head bucket[RADEON_CS_NUM_BUCKETS];
43 };
44
45 static void radeon_cs_buckets_init(struct radeon_cs_buckets *b)
46 {
47         unsigned i;
48
49         for (i = 0; i < RADEON_CS_NUM_BUCKETS; i++)
50                 INIT_LIST_HEAD(&b->bucket[i]);
51 }
52
53 static void radeon_cs_buckets_add(struct radeon_cs_buckets *b,
54                                   struct list_head *item, unsigned priority)
55 {
56         /* Since buffers which appear sooner in the relocation list are
57          * likely to be used more often than buffers which appear later
58          * in the list, the sort mustn't change the ordering of buffers
59          * with the same priority, i.e. it must be stable.
60          */
61         list_add_tail(item, &b->bucket[min(priority, RADEON_CS_MAX_PRIORITY)]);
62 }
63
64 static void radeon_cs_buckets_get_list(struct radeon_cs_buckets *b,
65                                        struct list_head *out_list)
66 {
67         unsigned i;
68
69         /* Connect the sorted buckets in the output list. */
70         for (i = 0; i < RADEON_CS_NUM_BUCKETS; i++) {
71                 list_splice(&b->bucket[i], out_list);
72         }
73 }
74
75 static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
76 {
77         struct drm_device *ddev = p->rdev->ddev;
78         struct radeon_cs_chunk *chunk;
79         struct radeon_cs_buckets buckets;
80         unsigned i;
81         bool need_mmap_lock = false;
82         int r;
83
84         if (p->chunk_relocs == NULL) {
85                 return 0;
86         }
87         chunk = p->chunk_relocs;
88         p->dma_reloc_idx = 0;
89         /* FIXME: we assume that each relocs use 4 dwords */
90         p->nrelocs = chunk->length_dw / 4;
91         p->relocs = kcalloc(p->nrelocs, sizeof(struct radeon_bo_list), GFP_KERNEL);
92         if (p->relocs == NULL) {
93                 return -ENOMEM;
94         }
95
96         radeon_cs_buckets_init(&buckets);
97
98         for (i = 0; i < p->nrelocs; i++) {
99                 struct drm_radeon_cs_reloc *r;
100                 struct drm_gem_object *gobj;
101                 unsigned priority;
102
103                 r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4];
104                 gobj = drm_gem_object_lookup(ddev, p->filp, r->handle);
105                 if (gobj == NULL) {
106                         DRM_ERROR("gem object lookup failed 0x%x\n",
107                                   r->handle);
108                         return -ENOENT;
109                 }
110                 p->relocs[i].robj = gem_to_radeon_bo(gobj);
111
112                 /* The userspace buffer priorities are from 0 to 15. A higher
113                  * number means the buffer is more important.
114                  * Also, the buffers used for write have a higher priority than
115                  * the buffers used for read only, which doubles the range
116                  * to 0 to 31. 32 is reserved for the kernel driver.
117                  */
118                 priority = (r->flags & RADEON_RELOC_PRIO_MASK) * 2
119                            + !!r->write_domain;
120
121                 /* the first reloc of an UVD job is the msg and that must be in
122                    VRAM, also but everything into VRAM on AGP cards and older
123                    IGP chips to avoid image corruptions */
124                 if (p->ring == R600_RING_TYPE_UVD_INDEX &&
125                     (i == 0 || drm_pci_device_is_agp(p->rdev->ddev) ||
126                      p->rdev->family == CHIP_RS780 ||
127                      p->rdev->family == CHIP_RS880)) {
128
129                         /* TODO: is this still needed for NI+ ? */
130                         p->relocs[i].prefered_domains =
131                                 RADEON_GEM_DOMAIN_VRAM;
132
133                         p->relocs[i].allowed_domains =
134                                 RADEON_GEM_DOMAIN_VRAM;
135
136                         /* prioritize this over any other relocation */
137                         priority = RADEON_CS_MAX_PRIORITY;
138                 } else {
139                         uint32_t domain = r->write_domain ?
140                                 r->write_domain : r->read_domains;
141
142                         if (domain & RADEON_GEM_DOMAIN_CPU) {
143                                 DRM_ERROR("RADEON_GEM_DOMAIN_CPU is not valid "
144                                           "for command submission\n");
145                                 return -EINVAL;
146                         }
147
148                         p->relocs[i].prefered_domains = domain;
149                         if (domain == RADEON_GEM_DOMAIN_VRAM)
150                                 domain |= RADEON_GEM_DOMAIN_GTT;
151                         p->relocs[i].allowed_domains = domain;
152                 }
153
154                 if (radeon_ttm_tt_has_userptr(p->relocs[i].robj->tbo.ttm)) {
155                         uint32_t domain = p->relocs[i].prefered_domains;
156                         if (!(domain & RADEON_GEM_DOMAIN_GTT)) {
157                                 DRM_ERROR("Only RADEON_GEM_DOMAIN_GTT is "
158                                           "allowed for userptr BOs\n");
159                                 return -EINVAL;
160                         }
161                         need_mmap_lock = true;
162                         domain = RADEON_GEM_DOMAIN_GTT;
163                         p->relocs[i].prefered_domains = domain;
164                         p->relocs[i].allowed_domains = domain;
165                 }
166
167                 p->relocs[i].tv.bo = &p->relocs[i].robj->tbo;
168                 p->relocs[i].tv.shared = !r->write_domain;
169
170                 radeon_cs_buckets_add(&buckets, &p->relocs[i].tv.head,
171                                       priority);
172         }
173
174         radeon_cs_buckets_get_list(&buckets, &p->validated);
175
176         if (p->cs_flags & RADEON_CS_USE_VM)
177                 p->vm_bos = radeon_vm_get_bos(p->rdev, p->ib.vm,
178                                               &p->validated);
179         if (need_mmap_lock)
180                 down_read(&current->mm->mmap_sem);
181
182         r = radeon_bo_list_validate(p->rdev, &p->ticket, &p->validated, p->ring);
183
184         if (need_mmap_lock)
185                 up_read(&current->mm->mmap_sem);
186
187         return r;
188 }
189
190 static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority)
191 {
192         p->priority = priority;
193
194         switch (ring) {
195         default:
196                 DRM_ERROR("unknown ring id: %d\n", ring);
197                 return -EINVAL;
198         case RADEON_CS_RING_GFX:
199                 p->ring = RADEON_RING_TYPE_GFX_INDEX;
200                 break;
201         case RADEON_CS_RING_COMPUTE:
202                 if (p->rdev->family >= CHIP_TAHITI) {
203                         if (p->priority > 0)
204                                 p->ring = CAYMAN_RING_TYPE_CP1_INDEX;
205                         else
206                                 p->ring = CAYMAN_RING_TYPE_CP2_INDEX;
207                 } else
208                         p->ring = RADEON_RING_TYPE_GFX_INDEX;
209                 break;
210         case RADEON_CS_RING_DMA:
211                 if (p->rdev->family >= CHIP_CAYMAN) {
212                         if (p->priority > 0)
213                                 p->ring = R600_RING_TYPE_DMA_INDEX;
214                         else
215                                 p->ring = CAYMAN_RING_TYPE_DMA1_INDEX;
216                 } else if (p->rdev->family >= CHIP_RV770) {
217                         p->ring = R600_RING_TYPE_DMA_INDEX;
218                 } else {
219                         return -EINVAL;
220                 }
221                 break;
222         case RADEON_CS_RING_UVD:
223                 p->ring = R600_RING_TYPE_UVD_INDEX;
224                 break;
225         case RADEON_CS_RING_VCE:
226                 /* TODO: only use the low priority ring for now */
227                 p->ring = TN_RING_TYPE_VCE1_INDEX;
228                 break;
229         }
230         return 0;
231 }
232
233 static int radeon_cs_sync_rings(struct radeon_cs_parser *p)
234 {
235         struct radeon_bo_list *reloc;
236         int r;
237
238         list_for_each_entry(reloc, &p->validated, tv.head) {
239                 struct reservation_object *resv;
240
241                 resv = reloc->robj->tbo.resv;
242                 r = radeon_sync_resv(p->rdev, &p->ib.sync, resv,
243                                      reloc->tv.shared);
244                 if (r)
245                         return r;
246         }
247         return 0;
248 }
249
250 /* XXX: note that this is called from the legacy UMS CS ioctl as well */
251 int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
252 {
253         struct drm_radeon_cs *cs = data;
254         uint64_t *chunk_array_ptr;
255         unsigned size, i;
256         u32 ring = RADEON_CS_RING_GFX;
257         s32 priority = 0;
258
259         INIT_LIST_HEAD(&p->validated);
260
261         if (!cs->num_chunks) {
262                 return 0;
263         }
264
265         /* get chunks */
266         p->idx = 0;
267         p->ib.sa_bo = NULL;
268         p->const_ib.sa_bo = NULL;
269         p->chunk_ib = NULL;
270         p->chunk_relocs = NULL;
271         p->chunk_flags = NULL;
272         p->chunk_const_ib = NULL;
273         p->chunks_array = kcalloc(cs->num_chunks, sizeof(uint64_t), GFP_KERNEL);
274         if (p->chunks_array == NULL) {
275                 return -ENOMEM;
276         }
277         chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks);
278         if (copy_from_user(p->chunks_array, chunk_array_ptr,
279                                sizeof(uint64_t)*cs->num_chunks)) {
280                 return -EFAULT;
281         }
282         p->cs_flags = 0;
283         p->nchunks = cs->num_chunks;
284         p->chunks = kcalloc(p->nchunks, sizeof(struct radeon_cs_chunk), GFP_KERNEL);
285         if (p->chunks == NULL) {
286                 return -ENOMEM;
287         }
288         for (i = 0; i < p->nchunks; i++) {
289                 struct drm_radeon_cs_chunk __user **chunk_ptr = NULL;
290                 struct drm_radeon_cs_chunk user_chunk;
291                 uint32_t __user *cdata;
292
293                 chunk_ptr = (void __user*)(unsigned long)p->chunks_array[i];
294                 if (copy_from_user(&user_chunk, chunk_ptr,
295                                        sizeof(struct drm_radeon_cs_chunk))) {
296                         return -EFAULT;
297                 }
298                 p->chunks[i].length_dw = user_chunk.length_dw;
299                 if (user_chunk.chunk_id == RADEON_CHUNK_ID_RELOCS) {
300                         p->chunk_relocs = &p->chunks[i];
301                 }
302                 if (user_chunk.chunk_id == RADEON_CHUNK_ID_IB) {
303                         p->chunk_ib = &p->chunks[i];
304                         /* zero length IB isn't useful */
305                         if (p->chunks[i].length_dw == 0)
306                                 return -EINVAL;
307                 }
308                 if (user_chunk.chunk_id == RADEON_CHUNK_ID_CONST_IB) {
309                         p->chunk_const_ib = &p->chunks[i];
310                         /* zero length CONST IB isn't useful */
311                         if (p->chunks[i].length_dw == 0)
312                                 return -EINVAL;
313                 }
314                 if (user_chunk.chunk_id == RADEON_CHUNK_ID_FLAGS) {
315                         p->chunk_flags = &p->chunks[i];
316                         /* zero length flags aren't useful */
317                         if (p->chunks[i].length_dw == 0)
318                                 return -EINVAL;
319                 }
320
321                 size = p->chunks[i].length_dw;
322                 cdata = (void __user *)(unsigned long)user_chunk.chunk_data;
323                 p->chunks[i].user_ptr = cdata;
324                 if (user_chunk.chunk_id == RADEON_CHUNK_ID_CONST_IB)
325                         continue;
326
327                 if (user_chunk.chunk_id == RADEON_CHUNK_ID_IB) {
328                         if (!p->rdev || !(p->rdev->flags & RADEON_IS_AGP))
329                                 continue;
330                 }
331
332                 p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t));
333                 size *= sizeof(uint32_t);
334                 if (p->chunks[i].kdata == NULL) {
335                         return -ENOMEM;
336                 }
337                 if (copy_from_user(p->chunks[i].kdata, cdata, size)) {
338                         return -EFAULT;
339                 }
340                 if (user_chunk.chunk_id == RADEON_CHUNK_ID_FLAGS) {
341                         p->cs_flags = p->chunks[i].kdata[0];
342                         if (p->chunks[i].length_dw > 1)
343                                 ring = p->chunks[i].kdata[1];
344                         if (p->chunks[i].length_dw > 2)
345                                 priority = (s32)p->chunks[i].kdata[2];
346                 }
347         }
348
349         /* these are KMS only */
350         if (p->rdev) {
351                 if ((p->cs_flags & RADEON_CS_USE_VM) &&
352                     !p->rdev->vm_manager.enabled) {
353                         DRM_ERROR("VM not active on asic!\n");
354                         return -EINVAL;
355                 }
356
357                 if (radeon_cs_get_ring(p, ring, priority))
358                         return -EINVAL;
359
360                 /* we only support VM on some SI+ rings */
361                 if ((p->cs_flags & RADEON_CS_USE_VM) == 0) {
362                         if (p->rdev->asic->ring[p->ring]->cs_parse == NULL) {
363                                 DRM_ERROR("Ring %d requires VM!\n", p->ring);
364                                 return -EINVAL;
365                         }
366                 } else {
367                         if (p->rdev->asic->ring[p->ring]->ib_parse == NULL) {
368                                 DRM_ERROR("VM not supported on ring %d!\n",
369                                           p->ring);
370                                 return -EINVAL;
371                         }
372                 }
373         }
374
375         return 0;
376 }
377
378 static int cmp_size_smaller_first(void *priv, struct list_head *a,
379                                   struct list_head *b)
380 {
381         struct radeon_bo_list *la = list_entry(a, struct radeon_bo_list, tv.head);
382         struct radeon_bo_list *lb = list_entry(b, struct radeon_bo_list, tv.head);
383
384         /* Sort A before B if A is smaller. */
385         return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages;
386 }
387
388 /**
389  * cs_parser_fini() - clean parser states
390  * @parser:     parser structure holding parsing context.
391  * @error:      error number
392  *
393  * If error is set than unvalidate buffer, otherwise just free memory
394  * used by parsing context.
395  **/
396 static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error, bool backoff)
397 {
398         unsigned i;
399
400         if (!error) {
401                 /* Sort the buffer list from the smallest to largest buffer,
402                  * which affects the order of buffers in the LRU list.
403                  * This assures that the smallest buffers are added first
404                  * to the LRU list, so they are likely to be later evicted
405                  * first, instead of large buffers whose eviction is more
406                  * expensive.
407                  *
408                  * This slightly lowers the number of bytes moved by TTM
409                  * per frame under memory pressure.
410                  */
411                 list_sort(NULL, &parser->validated, cmp_size_smaller_first);
412
413                 ttm_eu_fence_buffer_objects(&parser->ticket,
414                                             &parser->validated,
415                                             &parser->ib.fence->base);
416         } else if (backoff) {
417                 ttm_eu_backoff_reservation(&parser->ticket,
418                                            &parser->validated);
419         }
420
421         if (parser->relocs != NULL) {
422                 for (i = 0; i < parser->nrelocs; i++) {
423                         struct radeon_bo *bo = parser->relocs[i].robj;
424                         if (bo == NULL)
425                                 continue;
426
427                         drm_gem_object_unreference_unlocked(&bo->gem_base);
428                 }
429         }
430         kfree(parser->track);
431         kfree(parser->relocs);
432         drm_free_large(parser->vm_bos);
433         for (i = 0; i < parser->nchunks; i++)
434                 drm_free_large(parser->chunks[i].kdata);
435         kfree(parser->chunks);
436         kfree(parser->chunks_array);
437         radeon_ib_free(parser->rdev, &parser->ib);
438         radeon_ib_free(parser->rdev, &parser->const_ib);
439 }
440
441 static int radeon_cs_ib_chunk(struct radeon_device *rdev,
442                               struct radeon_cs_parser *parser)
443 {
444         int r;
445
446         if (parser->chunk_ib == NULL)
447                 return 0;
448
449         if (parser->cs_flags & RADEON_CS_USE_VM)
450                 return 0;
451
452         r = radeon_cs_parse(rdev, parser->ring, parser);
453         if (r || parser->parser_error) {
454                 DRM_ERROR("Invalid command stream !\n");
455                 return r;
456         }
457
458         r = radeon_cs_sync_rings(parser);
459         if (r) {
460                 if (r != -ERESTARTSYS)
461                         DRM_ERROR("Failed to sync rings: %i\n", r);
462                 return r;
463         }
464
465         if (parser->ring == R600_RING_TYPE_UVD_INDEX)
466                 radeon_uvd_note_usage(rdev);
467         else if ((parser->ring == TN_RING_TYPE_VCE1_INDEX) ||
468                  (parser->ring == TN_RING_TYPE_VCE2_INDEX))
469                 radeon_vce_note_usage(rdev);
470
471         r = radeon_ib_schedule(rdev, &parser->ib, NULL, true);
472         if (r) {
473                 DRM_ERROR("Failed to schedule IB !\n");
474         }
475         return r;
476 }
477
478 static int radeon_bo_vm_update_pte(struct radeon_cs_parser *p,
479                                    struct radeon_vm *vm)
480 {
481         struct radeon_device *rdev = p->rdev;
482         struct radeon_bo_va *bo_va;
483         int i, r;
484
485         r = radeon_vm_update_page_directory(rdev, vm);
486         if (r)
487                 return r;
488
489         r = radeon_vm_clear_freed(rdev, vm);
490         if (r)
491                 return r;
492
493         if (vm->ib_bo_va == NULL) {
494                 DRM_ERROR("Tmp BO not in VM!\n");
495                 return -EINVAL;
496         }
497
498         r = radeon_vm_bo_update(rdev, vm->ib_bo_va,
499                                 &rdev->ring_tmp_bo.bo->tbo.mem);
500         if (r)
501                 return r;
502
503         for (i = 0; i < p->nrelocs; i++) {
504                 struct radeon_bo *bo;
505
506                 bo = p->relocs[i].robj;
507                 bo_va = radeon_vm_bo_find(vm, bo);
508                 if (bo_va == NULL) {
509                         dev_err(rdev->dev, "bo %p not in vm %p\n", bo, vm);
510                         return -EINVAL;
511                 }
512
513                 r = radeon_vm_bo_update(rdev, bo_va, &bo->tbo.mem);
514                 if (r)
515                         return r;
516
517                 radeon_sync_fence(&p->ib.sync, bo_va->last_pt_update);
518         }
519
520         return radeon_vm_clear_invalids(rdev, vm);
521 }
522
523 static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
524                                  struct radeon_cs_parser *parser)
525 {
526         struct radeon_fpriv *fpriv = parser->filp->driver_priv;
527         struct radeon_vm *vm = &fpriv->vm;
528         int r;
529
530         if (parser->chunk_ib == NULL)
531                 return 0;
532         if ((parser->cs_flags & RADEON_CS_USE_VM) == 0)
533                 return 0;
534
535         if (parser->const_ib.length_dw) {
536                 r = radeon_ring_ib_parse(rdev, parser->ring, &parser->const_ib);
537                 if (r) {
538                         return r;
539                 }
540         }
541
542         r = radeon_ring_ib_parse(rdev, parser->ring, &parser->ib);
543         if (r) {
544                 return r;
545         }
546
547         if (parser->ring == R600_RING_TYPE_UVD_INDEX)
548                 radeon_uvd_note_usage(rdev);
549
550         mutex_lock(&vm->mutex);
551         r = radeon_bo_vm_update_pte(parser, vm);
552         if (r) {
553                 goto out;
554         }
555
556         r = radeon_cs_sync_rings(parser);
557         if (r) {
558                 if (r != -ERESTARTSYS)
559                         DRM_ERROR("Failed to sync rings: %i\n", r);
560                 goto out;
561         }
562
563         if ((rdev->family >= CHIP_TAHITI) &&
564             (parser->chunk_const_ib != NULL)) {
565                 r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib, true);
566         } else {
567                 r = radeon_ib_schedule(rdev, &parser->ib, NULL, true);
568         }
569
570 out:
571         mutex_unlock(&vm->mutex);
572         return r;
573 }
574
575 static int radeon_cs_handle_lockup(struct radeon_device *rdev, int r)
576 {
577         if (r == -EDEADLK) {
578                 r = radeon_gpu_reset(rdev);
579                 if (!r)
580                         r = -EAGAIN;
581         }
582         return r;
583 }
584
585 static int radeon_cs_ib_fill(struct radeon_device *rdev, struct radeon_cs_parser *parser)
586 {
587         struct radeon_cs_chunk *ib_chunk;
588         struct radeon_vm *vm = NULL;
589         int r;
590
591         if (parser->chunk_ib == NULL)
592                 return 0;
593
594         if (parser->cs_flags & RADEON_CS_USE_VM) {
595                 struct radeon_fpriv *fpriv = parser->filp->driver_priv;
596                 vm = &fpriv->vm;
597
598                 if ((rdev->family >= CHIP_TAHITI) &&
599                     (parser->chunk_const_ib != NULL)) {
600                         ib_chunk = parser->chunk_const_ib;
601                         if (ib_chunk->length_dw > RADEON_IB_VM_MAX_SIZE) {
602                                 DRM_ERROR("cs IB CONST too big: %d\n", ib_chunk->length_dw);
603                                 return -EINVAL;
604                         }
605                         r =  radeon_ib_get(rdev, parser->ring, &parser->const_ib,
606                                            vm, ib_chunk->length_dw * 4);
607                         if (r) {
608                                 DRM_ERROR("Failed to get const ib !\n");
609                                 return r;
610                         }
611                         parser->const_ib.is_const_ib = true;
612                         parser->const_ib.length_dw = ib_chunk->length_dw;
613                         if (copy_from_user(parser->const_ib.ptr,
614                                                ib_chunk->user_ptr,
615                                                ib_chunk->length_dw * 4))
616                                 return -EFAULT;
617                 }
618
619                 ib_chunk = parser->chunk_ib;
620                 if (ib_chunk->length_dw > RADEON_IB_VM_MAX_SIZE) {
621                         DRM_ERROR("cs IB too big: %d\n", ib_chunk->length_dw);
622                         return -EINVAL;
623                 }
624         }
625         ib_chunk = parser->chunk_ib;
626
627         r =  radeon_ib_get(rdev, parser->ring, &parser->ib,
628                            vm, ib_chunk->length_dw * 4);
629         if (r) {
630                 DRM_ERROR("Failed to get ib !\n");
631                 return r;
632         }
633         parser->ib.length_dw = ib_chunk->length_dw;
634         if (ib_chunk->kdata)
635                 memcpy(parser->ib.ptr, ib_chunk->kdata, ib_chunk->length_dw * 4);
636         else if (copy_from_user(parser->ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4))
637                 return -EFAULT;
638         return 0;
639 }
640
641 int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
642 {
643         struct radeon_device *rdev = dev->dev_private;
644         struct radeon_cs_parser parser;
645         int r;
646
647         down_read(&rdev->exclusive_lock);
648         if (!rdev->accel_working) {
649                 up_read(&rdev->exclusive_lock);
650                 return -EBUSY;
651         }
652         if (rdev->in_reset) {
653                 up_read(&rdev->exclusive_lock);
654                 r = radeon_gpu_reset(rdev);
655                 if (!r)
656                         r = -EAGAIN;
657                 return r;
658         }
659         /* initialize parser */
660         memset(&parser, 0, sizeof(struct radeon_cs_parser));
661         parser.filp = filp;
662         parser.rdev = rdev;
663         parser.dev = rdev->dev;
664         parser.family = rdev->family;
665         r = radeon_cs_parser_init(&parser, data);
666         if (r) {
667                 DRM_ERROR("Failed to initialize parser !\n");
668                 radeon_cs_parser_fini(&parser, r, false);
669                 up_read(&rdev->exclusive_lock);
670                 r = radeon_cs_handle_lockup(rdev, r);
671                 return r;
672         }
673
674         r = radeon_cs_ib_fill(rdev, &parser);
675         if (!r) {
676                 r = radeon_cs_parser_relocs(&parser);
677                 if (r && r != -ERESTARTSYS)
678                         DRM_ERROR("Failed to parse relocation %d!\n", r);
679         }
680
681         if (r) {
682                 radeon_cs_parser_fini(&parser, r, false);
683                 up_read(&rdev->exclusive_lock);
684                 r = radeon_cs_handle_lockup(rdev, r);
685                 return r;
686         }
687
688         trace_radeon_cs(&parser);
689
690         r = radeon_cs_ib_chunk(rdev, &parser);
691         if (r) {
692                 goto out;
693         }
694         r = radeon_cs_ib_vm_chunk(rdev, &parser);
695         if (r) {
696                 goto out;
697         }
698 out:
699         radeon_cs_parser_fini(&parser, r, true);
700         up_read(&rdev->exclusive_lock);
701         r = radeon_cs_handle_lockup(rdev, r);
702         return r;
703 }
704
705 /**
706  * radeon_cs_packet_parse() - parse cp packet and point ib index to next packet
707  * @parser:     parser structure holding parsing context.
708  * @pkt:        where to store packet information
709  *
710  * Assume that chunk_ib_index is properly set. Will return -EINVAL
711  * if packet is bigger than remaining ib size. or if packets is unknown.
712  **/
713 int radeon_cs_packet_parse(struct radeon_cs_parser *p,
714                            struct radeon_cs_packet *pkt,
715                            unsigned idx)
716 {
717         struct radeon_cs_chunk *ib_chunk = p->chunk_ib;
718         struct radeon_device *rdev = p->rdev;
719         uint32_t header;
720         int ret = 0, i;
721
722         if (idx >= ib_chunk->length_dw) {
723                 DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
724                           idx, ib_chunk->length_dw);
725                 return -EINVAL;
726         }
727         header = radeon_get_ib_value(p, idx);
728         pkt->idx = idx;
729         pkt->type = RADEON_CP_PACKET_GET_TYPE(header);
730         pkt->count = RADEON_CP_PACKET_GET_COUNT(header);
731         pkt->one_reg_wr = 0;
732         switch (pkt->type) {
733         case RADEON_PACKET_TYPE0:
734                 if (rdev->family < CHIP_R600) {
735                         pkt->reg = R100_CP_PACKET0_GET_REG(header);
736                         pkt->one_reg_wr =
737                                 RADEON_CP_PACKET0_GET_ONE_REG_WR(header);
738                 } else
739                         pkt->reg = R600_CP_PACKET0_GET_REG(header);
740                 break;
741         case RADEON_PACKET_TYPE3:
742                 pkt->opcode = RADEON_CP_PACKET3_GET_OPCODE(header);
743                 break;
744         case RADEON_PACKET_TYPE2:
745                 pkt->count = -1;
746                 break;
747         default:
748                 DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
749                 ret = -EINVAL;
750                 goto dump_ib;
751         }
752         if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
753                 DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
754                           pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
755                 ret = -EINVAL;
756                 goto dump_ib;
757         }
758         return 0;
759
760 dump_ib:
761         for (i = 0; i < ib_chunk->length_dw; i++) {
762                 if (i == idx)
763                         printk("\t0x%08x <---\n", radeon_get_ib_value(p, i));
764                 else
765                         printk("\t0x%08x\n", radeon_get_ib_value(p, i));
766         }
767         return ret;
768 }
769
770 /**
771  * radeon_cs_packet_next_is_pkt3_nop() - test if the next packet is P3 NOP
772  * @p:          structure holding the parser context.
773  *
774  * Check if the next packet is NOP relocation packet3.
775  **/
776 bool radeon_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
777 {
778         struct radeon_cs_packet p3reloc;
779         int r;
780
781         r = radeon_cs_packet_parse(p, &p3reloc, p->idx);
782         if (r)
783                 return false;
784         if (p3reloc.type != RADEON_PACKET_TYPE3)
785                 return false;
786         if (p3reloc.opcode != RADEON_PACKET3_NOP)
787                 return false;
788         return true;
789 }
790
791 /**
792  * radeon_cs_dump_packet() - dump raw packet context
793  * @p:          structure holding the parser context.
794  * @pkt:        structure holding the packet.
795  *
796  * Used mostly for debugging and error reporting.
797  **/
798 void radeon_cs_dump_packet(struct radeon_cs_parser *p,
799                            struct radeon_cs_packet *pkt)
800 {
801         volatile uint32_t *ib;
802         unsigned i;
803         unsigned idx;
804
805         ib = p->ib.ptr;
806         idx = pkt->idx;
807         for (i = 0; i <= (pkt->count + 1); i++, idx++)
808                 DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]);
809 }
810
811 /**
812  * radeon_cs_packet_next_reloc() - parse next (should be reloc) packet
813  * @parser:             parser structure holding parsing context.
814  * @data:               pointer to relocation data
815  * @offset_start:       starting offset
816  * @offset_mask:        offset mask (to align start offset on)
817  * @reloc:              reloc informations
818  *
819  * Check if next packet is relocation packet3, do bo validation and compute
820  * GPU offset using the provided start.
821  **/
822 int radeon_cs_packet_next_reloc(struct radeon_cs_parser *p,
823                                 struct radeon_bo_list **cs_reloc,
824                                 int nomm)
825 {
826         struct radeon_cs_chunk *relocs_chunk;
827         struct radeon_cs_packet p3reloc;
828         unsigned idx;
829         int r;
830
831         if (p->chunk_relocs == NULL) {
832                 DRM_ERROR("No relocation chunk !\n");
833                 return -EINVAL;
834         }
835         *cs_reloc = NULL;
836         relocs_chunk = p->chunk_relocs;
837         r = radeon_cs_packet_parse(p, &p3reloc, p->idx);
838         if (r)
839                 return r;
840         p->idx += p3reloc.count + 2;
841         if (p3reloc.type != RADEON_PACKET_TYPE3 ||
842             p3reloc.opcode != RADEON_PACKET3_NOP) {
843                 DRM_ERROR("No packet3 for relocation for packet at %d.\n",
844                           p3reloc.idx);
845                 radeon_cs_dump_packet(p, &p3reloc);
846                 return -EINVAL;
847         }
848         idx = radeon_get_ib_value(p, p3reloc.idx + 1);
849         if (idx >= relocs_chunk->length_dw) {
850                 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
851                           idx, relocs_chunk->length_dw);
852                 radeon_cs_dump_packet(p, &p3reloc);
853                 return -EINVAL;
854         }
855         /* FIXME: we assume reloc size is 4 dwords */
856         if (nomm) {
857                 *cs_reloc = p->relocs;
858                 (*cs_reloc)->gpu_offset =
859                         (u64)relocs_chunk->kdata[idx + 3] << 32;
860                 (*cs_reloc)->gpu_offset |= relocs_chunk->kdata[idx + 0];
861         } else
862                 *cs_reloc = &p->relocs[(idx / 4)];
863         return 0;
864 }