X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Filo%2Filo_cp.c;h=1f5d4ec7658815d9a429efdbc3548ed6c7bde558;hb=d77fa310ed8fb54aafc017eae844a51407ca907c;hp=55d90266cb509f0a7150b10583492d86845c064c;hpb=90786613e98a4d9e5dbb733c18003c36992aba30;p=mesa.git diff --git a/src/gallium/drivers/ilo/ilo_cp.c b/src/gallium/drivers/ilo/ilo_cp.c index 55d90266cb5..1f5d4ec7658 100644 --- a/src/gallium/drivers/ilo/ilo_cp.c +++ b/src/gallium/drivers/ilo/ilo_cp.c @@ -25,194 +25,113 @@ * Chia-I Wu */ -#include "intel_reg.h" /* for MI_xxx */ -#include "intel_winsys.h" +#include "core/ilo_builder_mi.h" +#include "core/intel_winsys.h" +#include "ilo_shader.h" #include "ilo_cp.h" -/* the size of the private space */ -static const int ilo_cp_private = 2; +static const struct ilo_cp_owner ilo_cp_default_owner; -/** - * Dump the contents of the parser bo. This can only be called in the flush - * callback. - */ -void -ilo_cp_dump(struct ilo_cp *cp) -{ - ilo_printf("dumping %d bytes\n", cp->used * 4); - if (cp->used) - intel_winsys_decode_commands(cp->winsys, cp->bo, cp->used * 4); -} - -/** - * Save the command parser state for rewind. - * - * Note that this cannot rewind a flush, and the caller must make sure - * that does not happend. - */ -void -ilo_cp_setjmp(struct ilo_cp *cp, struct ilo_cp_jmp_buf *jmp) +static void +ilo_cp_release_owner(struct ilo_cp *cp) { - jmp->id = pointer_to_intptr(cp->bo); + if (cp->owner != &ilo_cp_default_owner) { + const struct ilo_cp_owner *owner = cp->owner; - jmp->size = cp->size; - jmp->used = cp->used; - jmp->stolen = cp->stolen; - /* save reloc count to rewind ilo_cp_write_bo() */ - jmp->reloc_count = intel_bo_get_reloc_count(cp->bo); -} + cp->owner = &ilo_cp_default_owner; -/** - * Rewind to the saved state. - */ -void -ilo_cp_longjmp(struct ilo_cp *cp, const struct ilo_cp_jmp_buf *jmp) -{ - if (jmp->id != pointer_to_intptr(cp->bo)) { - assert(!"invalid use of CP longjmp"); - return; + assert(ilo_cp_space(cp) >= owner->reserve); + owner->release(cp, owner->data); } - - cp->size = jmp->size; - cp->used = jmp->used; - cp->stolen = jmp->stolen; - intel_bo_truncate_relocs(cp->bo, jmp->reloc_count); } /** - * Clear the parser buffer. + * Set the parser owner. If this is a new owner or a new ring, the old owner + * is released and the new owner's own() is called. The parser may implicitly + * submit if there is a ring change. + * + * own() is called before \p owner owns the parser. It must make sure there + * is more space than \p owner->reserve when it returns. Calling + * ilo_cp_submit() is allowed. + * + * release() will be called after \p owner loses the parser. That may happen + * just before the parser submits and ilo_cp_submit() is not allowed. */ -static void -ilo_cp_clear_buffer(struct ilo_cp *cp) +void +ilo_cp_set_owner(struct ilo_cp *cp, enum intel_ring_type ring, + const struct ilo_cp_owner *owner) { - cp->cmd_cur = 0; - cp->cmd_end = 0; - - cp->used = 0; - cp->stolen = 0; - - /* - * Recalculate cp->size. This is needed not only because cp->stolen is - * reset above, but also that ilo_cp_private are added to cp->size in - * ilo_cp_end_buffer(). - */ - cp->size = cp->bo_size - ilo_cp_private; -} + if (!owner) + owner = &ilo_cp_default_owner; -/** - * Add MI_BATCH_BUFFER_END to the private space of the parser buffer. - */ -static void -ilo_cp_end_buffer(struct ilo_cp *cp) -{ - /* make the private space available */ - cp->size += ilo_cp_private; + if (cp->ring != ring) { + ilo_cp_submit(cp, "ring change"); + cp->ring = ring; + } - assert(cp->used + 2 <= cp->size); + if (cp->owner != owner) { + ilo_cp_release_owner(cp); - cp->ptr[cp->used++] = MI_BATCH_BUFFER_END; + owner->own(cp, owner->data); - /* - * From the Sandy Bridge PRM, volume 1 part 1, page 107: - * - * "The batch buffer must be QWord aligned and a multiple of QWords in - * length." - */ - if (cp->used & 1) - cp->ptr[cp->used++] = MI_NOOP; + assert(ilo_cp_space(cp) >= owner->reserve); + cp->owner = owner; + } } -/** - * Upload the parser buffer to the bo. - */ -static int -ilo_cp_upload_buffer(struct ilo_cp *cp) +static struct intel_bo * +ilo_cp_end_batch(struct ilo_cp *cp, unsigned *used) { - int err; - - if (!cp->sys) { - intel_bo_unmap(cp->bo); - return 0; - } + struct intel_bo *bo; - err = intel_bo_pwrite(cp->bo, 0, cp->used * 4, cp->ptr); - if (likely(!err && cp->stolen)) { - const int offset = cp->bo_size - cp->stolen; + ilo_cp_release_owner(cp); - err = intel_bo_pwrite(cp->bo, offset * 4, - cp->stolen * 4, &cp->ptr[offset]); + if (!ilo_builder_batch_used(&cp->builder)) { + ilo_builder_batch_discard(&cp->builder); + return NULL; } - return err; -} + /* see ilo_cp_space() */ + assert(ilo_builder_batch_space(&cp->builder) >= 2); + gen6_mi_batch_buffer_end(&cp->builder); -/** - * Reallocate the parser bo. - */ -static void -ilo_cp_realloc_bo(struct ilo_cp *cp) -{ - struct intel_bo *bo; + bo = ilo_builder_end(&cp->builder, used); - /* - * allocate the new bo before unreferencing the old one so that they - * won't point at the same address, which is needed for jmpbuf - */ - bo = intel_winsys_alloc_buffer(cp->winsys, - "batch buffer", cp->bo_size * 4, 0); - if (unlikely(!bo)) { - /* reuse the old one */ - bo = cp->bo; - intel_bo_reference(bo); - } + /* we have to assume that kernel uploads also failed */ + if (!bo) + ilo_shader_cache_invalidate(cp->shader_cache); - if (cp->bo) - intel_bo_unreference(cp->bo); - cp->bo = bo; - - if (!cp->sys) { - intel_bo_map(cp->bo, true); - cp->ptr = intel_bo_get_virtual(cp->bo); - } + return bo; } -/** - * Execute the parser bo. - */ -static int -ilo_cp_exec_bo(struct ilo_cp *cp) +static bool +ilo_cp_detect_hang(struct ilo_cp *cp) { - const bool do_exec = !(ilo_debug & ILO_DEBUG_NOHW); - struct intel_context *ctx; - unsigned long flags; - int err; - - switch (cp->ring) { - case ILO_CP_RING_RENDER: - ctx = cp->render_ctx; - flags = INTEL_EXEC_RENDER; - break; - case ILO_CP_RING_BLT: - ctx = NULL; - flags = INTEL_EXEC_BLT; - break; - default: - ctx = NULL; - flags = 0; - break; + uint32_t active_lost, pending_lost; + bool guilty = false; + + if (likely(!(ilo_debug & ILO_DEBUG_HANG))) + return false; + + /* wait and get reset stats */ + if (intel_bo_wait(cp->last_submitted_bo, -1) || + intel_winsys_get_reset_stats(cp->winsys, cp->render_ctx, + &active_lost, &pending_lost)) + return false; + + if (cp->active_lost != active_lost) { + ilo_err("GPU hang caused by bo %p\n", cp->last_submitted_bo); + cp->active_lost = active_lost; + guilty = true; } - flags |= cp->one_off_flags; - - if (likely(do_exec)) - err = intel_bo_exec(cp->bo, cp->used * 4, ctx, flags); - else - err = 0; - - cp->one_off_flags = 0; + if (cp->pending_lost != pending_lost) { + ilo_err("GPU hang detected\n"); + cp->pending_lost = pending_lost; + } - return err; + return guilty; } /** @@ -220,34 +139,46 @@ ilo_cp_exec_bo(struct ilo_cp *cp) * is empty, the callback is not invoked. */ void -ilo_cp_flush_internal(struct ilo_cp *cp) +ilo_cp_submit_internal(struct ilo_cp *cp) { + const bool do_exec = !(ilo_debug & ILO_DEBUG_NOHW); + struct intel_bo *bo; + unsigned used; int err; - ilo_cp_set_owner(cp, NULL, 0); + bo = ilo_cp_end_batch(cp, &used); + if (!bo) + return; - /* sanity check */ - assert(cp->bo_size == cp->size + cp->stolen + ilo_cp_private); + if (likely(do_exec)) { + err = intel_winsys_submit_bo(cp->winsys, cp->ring, + bo, used, cp->render_ctx, cp->one_off_flags); + } + else { + err = 0; + } - if (!cp->used) { - /* return the space stolen and etc. */ - ilo_cp_clear_buffer(cp); + cp->one_off_flags = 0; - return; - } + if (!err) { + bool guilty; + + intel_bo_unref(cp->last_submitted_bo); + cp->last_submitted_bo = intel_bo_ref(bo); - ilo_cp_end_buffer(cp); + guilty = ilo_cp_detect_hang(cp); - /* upload and execute */ - err = ilo_cp_upload_buffer(cp); - if (likely(!err)) - err = ilo_cp_exec_bo(cp); + if (unlikely((ilo_debug & ILO_DEBUG_BATCH) || guilty)) { + ilo_builder_decode(&cp->builder); + if (guilty) + abort(); + } - if (likely(!err && cp->flush_callback)) - cp->flush_callback(cp, cp->flush_callback_data); + if (cp->submit_callback) + cp->submit_callback(cp, cp->submit_callback_data); + } - ilo_cp_clear_buffer(cp); - ilo_cp_realloc_bo(cp); + ilo_builder_begin(&cp->builder); } /** @@ -256,17 +187,9 @@ ilo_cp_flush_internal(struct ilo_cp *cp) void ilo_cp_destroy(struct ilo_cp *cp) { - if (cp->bo) { - if (!cp->sys) - intel_bo_unmap(cp->bo); - - intel_bo_unreference(cp->bo); - } - - if (cp->render_ctx) - intel_winsys_destroy_context(cp->winsys, cp->render_ctx); + ilo_builder_reset(&cp->builder); - FREE(cp->sys); + intel_winsys_destroy_context(cp->winsys, cp->render_ctx); FREE(cp); } @@ -274,7 +197,9 @@ ilo_cp_destroy(struct ilo_cp *cp) * Create a command parser. */ struct ilo_cp * -ilo_cp_create(struct intel_winsys *winsys, bool direct_map) +ilo_cp_create(const struct ilo_dev *dev, + struct intel_winsys *winsys, + struct ilo_shader_cache *shc) { struct ilo_cp *cp; @@ -283,31 +208,22 @@ ilo_cp_create(struct intel_winsys *winsys, bool direct_map) return NULL; cp->winsys = winsys; + cp->shader_cache = shc; cp->render_ctx = intel_winsys_create_context(winsys); + if (!cp->render_ctx) { + FREE(cp); + return NULL; + } - cp->ring = ILO_CP_RING_RENDER; - cp->no_implicit_flush = false; - - cp->bo_size = 8192; + cp->ring = INTEL_RING_RENDER; + cp->owner = &ilo_cp_default_owner; - if (!direct_map) { - cp->sys = MALLOC(cp->bo_size * 4); - if (!cp->sys) { - FREE(cp); - return NULL; - } + ilo_builder_init(&cp->builder, dev, winsys); - cp->ptr = cp->sys; - } - - ilo_cp_realloc_bo(cp); - if (!cp->bo) { - FREE(cp->sys); - FREE(cp); + if (!ilo_builder_begin(&cp->builder)) { + ilo_cp_destroy(cp); return NULL; } - ilo_cp_clear_buffer(cp); - return cp; }