radeon/winsys: increase the IB size for VM
[mesa.git] / src / gallium / winsys / radeon / drm / radeon_drm_cs.c
index 284a404c9975dbc9145c7d29bb93dc13a7a8c553..45eef294369d67d553a9bda56be70bbce971ef35 100644 (file)
@@ -83,17 +83,24 @@ static void radeon_fence_reference(struct pipe_fence_handle **dst,
 static boolean radeon_init_cs_context(struct radeon_cs_context *csc,
                                       struct radeon_drm_winsys *ws)
 {
+    int i;
+
+    csc->buf = MALLOC(ws->ib_max_size);
+    if (!csc->buf)
+        return FALSE;
     csc->fd = ws->fd;
     csc->nrelocs = 512;
     csc->relocs_bo = (struct radeon_bo**)
                      CALLOC(1, csc->nrelocs * sizeof(struct radeon_bo*));
     if (!csc->relocs_bo) {
+        FREE(csc->buf);
         return FALSE;
     }
 
     csc->relocs = (struct drm_radeon_cs_reloc*)
                   CALLOC(1, csc->nrelocs * sizeof(struct drm_radeon_cs_reloc));
     if (!csc->relocs) {
+        FREE(csc->buf);
         FREE(csc->relocs_bo);
         return FALSE;
     }
@@ -113,6 +120,10 @@ static boolean radeon_init_cs_context(struct radeon_cs_context *csc,
     csc->chunk_array[2] = (uint64_t)(uintptr_t)&csc->chunks[2];
 
     csc->cs.chunks = (uint64_t)(uintptr_t)csc->chunk_array;
+
+    for (i = 0; i < Elements(csc->reloc_indices_hashlist); i++) {
+        csc->reloc_indices_hashlist[i] = -1;
+    }
     return TRUE;
 }
 
@@ -131,7 +142,10 @@ static void radeon_cs_context_cleanup(struct radeon_cs_context *csc)
     csc->chunks[1].length_dw = 0;
     csc->used_gart = 0;
     csc->used_vram = 0;
-    memset(csc->is_handle_added, 0, sizeof(csc->is_handle_added));
+
+    for (i = 0; i < Elements(csc->reloc_indices_hashlist); i++) {
+        csc->reloc_indices_hashlist[i] = -1;
+    }
 }
 
 static void radeon_destroy_cs_context(struct radeon_cs_context *csc)
@@ -139,6 +153,7 @@ static void radeon_destroy_cs_context(struct radeon_cs_context *csc)
     radeon_cs_context_cleanup(csc);
     FREE(csc->relocs_bo);
     FREE(csc->relocs);
+    FREE(csc->buf);
 }
 
 
@@ -146,7 +161,7 @@ static struct radeon_winsys_cs *
 radeon_drm_cs_create(struct radeon_winsys *rws,
                      enum ring_type ring_type,
                      void (*flush)(void *ctx, unsigned flags,
-                                  struct pipe_fence_handle **fence),
+                                   struct pipe_fence_handle **fence),
                      void *flush_ctx,
                      struct radeon_winsys_cs_handle *trace_buf)
 {
@@ -179,6 +194,7 @@ radeon_drm_cs_create(struct radeon_winsys *rws,
     cs->cst = &cs->csc2;
     cs->base.buf = cs->csc->buf;
     cs->base.ring_type = ring_type;
+    cs->base.max_dw = ws->ib_max_size / 4;
 
     p_atomic_inc(&ws->num_cs);
     return &cs->base;
@@ -186,11 +202,11 @@ radeon_drm_cs_create(struct radeon_winsys *rws,
 
 #define OUT_CS(cs, value) (cs)->buf[(cs)->cdw++] = (value)
 
-static INLINE void update_reloc(struct drm_radeon_cs_reloc *reloc,
-                               enum radeon_bo_domain rd,
-                               enum radeon_bo_domain wd,
-                               unsigned priority,
-                               enum radeon_bo_domain *added_domains)
+static inline void update_reloc(struct drm_radeon_cs_reloc *reloc,
+                                enum radeon_bo_domain rd,
+                                enum radeon_bo_domain wd,
+                                unsigned priority,
+                                enum radeon_bo_domain *added_domains)
 {
     *added_domains = (rd | wd) & ~(reloc->read_domains | reloc->write_domain);
 
@@ -199,40 +215,32 @@ static INLINE void update_reloc(struct drm_radeon_cs_reloc *reloc,
     reloc->flags = MAX2(reloc->flags, priority);
 }
 
-int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo,
-                     struct drm_radeon_cs_reloc **out_reloc)
+int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo)
 {
-    struct drm_radeon_cs_reloc *reloc = NULL;
-    unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
-    int i = -1;
-
-    if (csc->is_handle_added[hash]) {
-        i = csc->reloc_indices_hashlist[hash];
-        reloc = &csc->relocs[i];
-
-        if (reloc->handle != bo->handle) {
-            /* Hash collision, look for the BO in the list of relocs linearly. */
-            for (i = csc->crelocs - 1; i >= 0; i--) {
-                reloc = &csc->relocs[i];
-                if (reloc->handle == bo->handle) {
-                    /* Put this reloc in the hash list.
-                     * This will prevent additional hash collisions if there are
-                     * several consecutive get_reloc calls for the same buffer.
-                     *
-                     * Example: Assuming buffers A,B,C collide in the hash list,
-                     * the following sequence of relocs:
-                     *         AAAAAAAAAAABBBBBBBBBBBBBBCCCCCCCC
-                     * will collide here: ^ and here:   ^,
-                     * meaning that we should get very few collisions in the end. */
-                    csc->reloc_indices_hashlist[hash] = i;
-                    break;
-                }
-            }
+    unsigned hash = bo->handle & (Elements(csc->reloc_indices_hashlist)-1);
+    int i = csc->reloc_indices_hashlist[hash];
+
+    /* not found or found */
+    if (i == -1 || csc->relocs_bo[i] == bo)
+        return i;
+
+    /* Hash collision, look for the BO in the list of relocs linearly. */
+    for (i = csc->crelocs - 1; i >= 0; i--) {
+        if (csc->relocs_bo[i] == bo) {
+            /* Put this reloc in the hash list.
+             * This will prevent additional hash collisions if there are
+             * several consecutive get_reloc calls for the same buffer.
+             *
+             * Example: Assuming buffers A,B,C collide in the hash list,
+             * the following sequence of relocs:
+             *         AAAAAAAAAAABBBBBBBBBBBBBBCCCCCCCC
+             * will collide here: ^ and here:   ^,
+             * meaning that we should get very few collisions in the end. */
+            csc->reloc_indices_hashlist[hash] = i;
+            return i;
         }
     }
-    if (out_reloc)
-        *out_reloc = reloc;
-    return i;
+    return -1;
 }
 
 static unsigned radeon_add_reloc(struct radeon_drm_cs *cs,
@@ -244,7 +252,7 @@ static unsigned radeon_add_reloc(struct radeon_drm_cs *cs,
 {
     struct radeon_cs_context *csc = cs->csc;
     struct drm_radeon_cs_reloc *reloc;
-    unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
+    unsigned hash = bo->handle & (Elements(csc->reloc_indices_hashlist)-1);
     enum radeon_bo_domain rd = usage & RADEON_USAGE_READ ? domains : 0;
     enum radeon_bo_domain wd = usage & RADEON_USAGE_WRITE ? domains : 0;
     int i = -1;
@@ -252,9 +260,10 @@ static unsigned radeon_add_reloc(struct radeon_drm_cs *cs,
     priority = MIN2(priority, 15);
     *added_domains = 0;
 
-    i = radeon_get_reloc(csc, bo, &reloc);
+    i = radeon_get_reloc(csc, bo);
 
     if (i >= 0) {
+        reloc = &csc->relocs[i];
         update_reloc(reloc, rd, wd, priority, added_domains);
 
         /* For async DMA, every add_reloc call must add a buffer to the list
@@ -296,7 +305,6 @@ static unsigned radeon_add_reloc(struct radeon_drm_cs *cs,
     reloc->write_domain = wd;
     reloc->flags = priority;
 
-    csc->is_handle_added[hash] = TRUE;
     csc->reloc_indices_hashlist[hash] = csc->crelocs;
 
     csc->chunks[1].length_dw += RELOC_DWORDS;
@@ -329,7 +337,7 @@ static int radeon_drm_cs_get_reloc(struct radeon_winsys_cs *rcs,
 {
     struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
 
-    return radeon_get_reloc(cs->csc, (struct radeon_bo*)buf, NULL);
+    return radeon_get_reloc(cs->csc, (struct radeon_bo*)buf);
 }
 
 static boolean radeon_drm_cs_validate(struct radeon_winsys_cs *rcs)
@@ -433,36 +441,40 @@ static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs,
 
     switch (cs->base.ring_type) {
     case RING_DMA:
-           /* pad DMA ring to 8 DWs */
-           if (cs->ws->info.chip_class <= SI) {
-                   while (rcs->cdw & 7)
-                           OUT_CS(&cs->base, 0xf0000000); /* NOP packet */
-           } else {
-                   while (rcs->cdw & 7)
-                           OUT_CS(&cs->base, 0x00000000); /* NOP packet */
-           }
-           break;
+        /* pad DMA ring to 8 DWs */
+        if (cs->ws->info.chip_class <= SI) {
+            while (rcs->cdw & 7)
+                OUT_CS(&cs->base, 0xf0000000); /* NOP packet */
+        } else {
+            while (rcs->cdw & 7)
+                OUT_CS(&cs->base, 0x00000000); /* NOP packet */
+        }
+        break;
     case RING_GFX:
-           /* pad DMA ring to 8 DWs to meet CP fetch alignment requirements
-            * r6xx, requires at least 4 dw alignment to avoid a hw bug.
-            */
-           if (cs->ws->info.chip_class <= SI) {
-                   while (rcs->cdw & 7)
-                           OUT_CS(&cs->base, 0x80000000); /* type2 nop packet */
-           } else {
-                   while (rcs->cdw & 7)
-                           OUT_CS(&cs->base, 0xffff1000); /* type3 nop packet */
-           }
-           break;
+        /* pad DMA ring to 8 DWs to meet CP fetch alignment requirements
+         * r6xx, requires at least 4 dw alignment to avoid a hw bug.
+         * hawaii with old firmware needs type2 nop packet.
+         * accel_working2 with value 3 indicates the new firmware.
+         */
+        if (cs->ws->info.chip_class <= SI ||
+            (cs->ws->info.family == CHIP_HAWAII &&
+             cs->ws->accel_working2 < 3)) {
+            while (rcs->cdw & 7)
+                OUT_CS(&cs->base, 0x80000000); /* type2 nop packet */
+        } else {
+            while (rcs->cdw & 7)
+                OUT_CS(&cs->base, 0xffff1000); /* type3 nop packet */
+        }
+        break;
     case RING_UVD:
-            while (rcs->cdw & 15)
-               OUT_CS(&cs->base, 0x80000000); /* type2 nop packet */
-           break;
+        while (rcs->cdw & 15)
+            OUT_CS(&cs->base, 0x80000000); /* type2 nop packet */
+        break;
     default:
-           break;
+        break;
     }
 
-    if (rcs->cdw > RADEON_MAX_CMDBUF_DWORDS) {
+    if (rcs->cdw > rcs->max_dw) {
        fprintf(stderr, "radeon: command stream overflowed\n");
     }
 
@@ -481,7 +493,7 @@ static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs,
     cs->cst->cs_trace_id = cs_trace_id;
 
     /* If the CS is not empty or overflowed, emit it in a separate thread. */
-    if (cs->base.cdw && cs->base.cdw <= RADEON_MAX_CMDBUF_DWORDS && !debug_get_option_noop()) {
+    if (cs->base.cdw && cs->base.cdw <= cs->base.max_dw && !debug_get_option_noop()) {
         unsigned i, crelocs;
 
         crelocs = cs->cst->crelocs;
@@ -583,7 +595,7 @@ static boolean radeon_bo_is_referenced(struct radeon_winsys_cs *rcs,
     if (!bo->num_cs_references)
         return FALSE;
 
-    index = radeon_get_reloc(cs->csc, bo, NULL);
+    index = radeon_get_reloc(cs->csc, bo);
     if (index == -1)
         return FALSE;
 
@@ -605,7 +617,7 @@ radeon_cs_create_fence(struct radeon_winsys_cs *rcs)
 
     /* Create a fence, which is a dummy BO. */
     fence = cs->ws->base.buffer_create(&cs->ws->base, 1, 1, TRUE,
-                                       RADEON_DOMAIN_GTT);
+                                       RADEON_DOMAIN_GTT, 0);
     /* Add the fence as a dummy relocation. */
     cs->ws->base.cs_add_reloc(rcs, cs->ws->base.buffer_get_cs_handle(fence),
                               RADEON_USAGE_READWRITE, RADEON_DOMAIN_GTT,