Commit 97d9a4e9 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2020-02-20' of...

Merge tag 'drm-intel-fixes-2020-02-20' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes

drm/i915 fixes for v5.6-rc3:
- Workaround missing Display Stream Compression (DSC) state readout by
  forcing modeset when its enabled at probe
- Fix EHL port clock voltage level requirements
- Fix queuing retire workers on the virtual engine
- Fix use of partially initialized waiters
- Stop using drm_pci_alloc/drm_pci/free
- Fix rewind of RING_TAIL by forcing a context reload
- Fix locking on resetting ring->head
- Propagate our bug filing URL change to stable kernels
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87y2sxtsrd.fsf@intel.com
parents c1368b34 15de9cb5
...@@ -8392,7 +8392,7 @@ M: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> ...@@ -8392,7 +8392,7 @@ M: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
M: Rodrigo Vivi <rodrigo.vivi@intel.com> M: Rodrigo Vivi <rodrigo.vivi@intel.com>
L: intel-gfx@lists.freedesktop.org L: intel-gfx@lists.freedesktop.org
W: https://01.org/linuxgraphics/ W: https://01.org/linuxgraphics/
B: https://01.org/linuxgraphics/documentation/how-report-bugs B: https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
C: irc://chat.freenode.net/intel-gfx C: irc://chat.freenode.net/intel-gfx
Q: http://patchwork.freedesktop.org/project/intel-gfx/ Q: http://patchwork.freedesktop.org/project/intel-gfx/
T: git git://anongit.freedesktop.org/drm-intel T: git git://anongit.freedesktop.org/drm-intel
......
...@@ -75,9 +75,8 @@ config DRM_I915_CAPTURE_ERROR ...@@ -75,9 +75,8 @@ config DRM_I915_CAPTURE_ERROR
help help
This option enables capturing the GPU state when a hang is detected. This option enables capturing the GPU state when a hang is detected.
This information is vital for triaging hangs and assists in debugging. This information is vital for triaging hangs and assists in debugging.
Please report any hang to Please report any hang for triaging according to:
https://bugs.freedesktop.org/enter_bug.cgi?product=DRI https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
for triaging.
If in doubt, say "Y". If in doubt, say "Y".
......
...@@ -4251,7 +4251,9 @@ static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, ...@@ -4251,7 +4251,9 @@ static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
struct intel_crtc_state *crtc_state) struct intel_crtc_state *crtc_state)
{ {
if (INTEL_GEN(dev_priv) >= 11 && crtc_state->port_clock > 594000) if (IS_ELKHARTLAKE(dev_priv) && crtc_state->port_clock > 594000)
crtc_state->min_voltage_level = 3;
else if (INTEL_GEN(dev_priv) >= 11 && crtc_state->port_clock > 594000)
crtc_state->min_voltage_level = 1; crtc_state->min_voltage_level = 1;
else if (IS_CANNONLAKE(dev_priv) && crtc_state->port_clock > 594000) else if (IS_CANNONLAKE(dev_priv) && crtc_state->port_clock > 594000)
crtc_state->min_voltage_level = 2; crtc_state->min_voltage_level = 2;
......
...@@ -11087,7 +11087,7 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state) ...@@ -11087,7 +11087,7 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
u32 base; u32 base;
if (INTEL_INFO(dev_priv)->display.cursor_needs_physical) if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
base = obj->phys_handle->busaddr; base = sg_dma_address(obj->mm.pages->sgl);
else else
base = intel_plane_ggtt_offset(plane_state); base = intel_plane_ggtt_offset(plane_state);
...@@ -17433,6 +17433,24 @@ static int intel_initial_commit(struct drm_device *dev) ...@@ -17433,6 +17433,24 @@ static int intel_initial_commit(struct drm_device *dev)
* have readout for pipe gamma enable. * have readout for pipe gamma enable.
*/ */
crtc_state->uapi.color_mgmt_changed = true; crtc_state->uapi.color_mgmt_changed = true;
/*
* FIXME hack to force full modeset when DSC is being
* used.
*
* As long as we do not have full state readout and
* config comparison of crtc_state->dsc, we have no way
* to ensure reliable fastset. Remove once we have
* readout for DSC.
*/
if (crtc_state->dsc.compression_enable) {
ret = drm_atomic_add_affected_connectors(state,
&crtc->base);
if (ret)
goto out;
crtc_state->uapi.mode_changed = true;
drm_dbg_kms(dev, "Force full modeset for DSC\n");
}
} }
} }
......
...@@ -565,6 +565,22 @@ static int __context_set_persistence(struct i915_gem_context *ctx, bool state) ...@@ -565,6 +565,22 @@ static int __context_set_persistence(struct i915_gem_context *ctx, bool state)
if (!(ctx->i915->caps.scheduler & I915_SCHEDULER_CAP_PREEMPTION)) if (!(ctx->i915->caps.scheduler & I915_SCHEDULER_CAP_PREEMPTION))
return -ENODEV; return -ENODEV;
/*
* If the cancel fails, we then need to reset, cleanly!
*
* If the per-engine reset fails, all hope is lost! We resort
* to a full GPU reset in that unlikely case, but realistically
* if the engine could not reset, the full reset does not fare
* much better. The damage has been done.
*
* However, if we cannot reset an engine by itself, we cannot
* cleanup a hanging persistent context without causing
* colateral damage, and we should not pretend we can by
* exposing the interface.
*/
if (!intel_has_reset_engine(&ctx->i915->gt))
return -ENODEV;
i915_gem_context_clear_persistence(ctx); i915_gem_context_clear_persistence(ctx);
} }
......
...@@ -285,9 +285,6 @@ struct drm_i915_gem_object { ...@@ -285,9 +285,6 @@ struct drm_i915_gem_object {
void *gvt_info; void *gvt_info;
}; };
/** for phys allocated objects */
struct drm_dma_handle *phys_handle;
}; };
static inline struct drm_i915_gem_object * static inline struct drm_i915_gem_object *
......
...@@ -22,88 +22,87 @@ ...@@ -22,88 +22,87 @@
static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
{ {
struct address_space *mapping = obj->base.filp->f_mapping; struct address_space *mapping = obj->base.filp->f_mapping;
struct drm_dma_handle *phys;
struct sg_table *st;
struct scatterlist *sg; struct scatterlist *sg;
char *vaddr; struct sg_table *st;
dma_addr_t dma;
void *vaddr;
void *dst;
int i; int i;
int err;
if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj))) if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
return -EINVAL; return -EINVAL;
/* Always aligning to the object size, allows a single allocation /*
* Always aligning to the object size, allows a single allocation
* to handle all possible callers, and given typical object sizes, * to handle all possible callers, and given typical object sizes,
* the alignment of the buddy allocation will naturally match. * the alignment of the buddy allocation will naturally match.
*/ */
phys = drm_pci_alloc(obj->base.dev, vaddr = dma_alloc_coherent(&obj->base.dev->pdev->dev,
roundup_pow_of_two(obj->base.size), roundup_pow_of_two(obj->base.size),
roundup_pow_of_two(obj->base.size)); &dma, GFP_KERNEL);
if (!phys) if (!vaddr)
return -ENOMEM; return -ENOMEM;
vaddr = phys->vaddr; st = kmalloc(sizeof(*st), GFP_KERNEL);
if (!st)
goto err_pci;
if (sg_alloc_table(st, 1, GFP_KERNEL))
goto err_st;
sg = st->sgl;
sg->offset = 0;
sg->length = obj->base.size;
sg_assign_page(sg, (struct page *)vaddr);
sg_dma_address(sg) = dma;
sg_dma_len(sg) = obj->base.size;
dst = vaddr;
for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
struct page *page; struct page *page;
char *src; void *src;
page = shmem_read_mapping_page(mapping, i); page = shmem_read_mapping_page(mapping, i);
if (IS_ERR(page)) { if (IS_ERR(page))
err = PTR_ERR(page); goto err_st;
goto err_phys;
}
src = kmap_atomic(page); src = kmap_atomic(page);
memcpy(vaddr, src, PAGE_SIZE); memcpy(dst, src, PAGE_SIZE);
drm_clflush_virt_range(vaddr, PAGE_SIZE); drm_clflush_virt_range(dst, PAGE_SIZE);
kunmap_atomic(src); kunmap_atomic(src);
put_page(page); put_page(page);
vaddr += PAGE_SIZE; dst += PAGE_SIZE;
} }
intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt); intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
st = kmalloc(sizeof(*st), GFP_KERNEL);
if (!st) {
err = -ENOMEM;
goto err_phys;
}
if (sg_alloc_table(st, 1, GFP_KERNEL)) {
kfree(st);
err = -ENOMEM;
goto err_phys;
}
sg = st->sgl;
sg->offset = 0;
sg->length = obj->base.size;
sg_dma_address(sg) = phys->busaddr;
sg_dma_len(sg) = obj->base.size;
obj->phys_handle = phys;
__i915_gem_object_set_pages(obj, st, sg->length); __i915_gem_object_set_pages(obj, st, sg->length);
return 0; return 0;
err_phys: err_st:
drm_pci_free(obj->base.dev, phys); kfree(st);
err_pci:
return err; dma_free_coherent(&obj->base.dev->pdev->dev,
roundup_pow_of_two(obj->base.size),
vaddr, dma);
return -ENOMEM;
} }
static void static void
i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj, i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
struct sg_table *pages) struct sg_table *pages)
{ {
dma_addr_t dma = sg_dma_address(pages->sgl);
void *vaddr = sg_page(pages->sgl);
__i915_gem_object_release_shmem(obj, pages, false); __i915_gem_object_release_shmem(obj, pages, false);
if (obj->mm.dirty) { if (obj->mm.dirty) {
struct address_space *mapping = obj->base.filp->f_mapping; struct address_space *mapping = obj->base.filp->f_mapping;
char *vaddr = obj->phys_handle->vaddr; void *src = vaddr;
int i; int i;
for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
...@@ -115,15 +114,16 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj, ...@@ -115,15 +114,16 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
continue; continue;
dst = kmap_atomic(page); dst = kmap_atomic(page);
drm_clflush_virt_range(vaddr, PAGE_SIZE); drm_clflush_virt_range(src, PAGE_SIZE);
memcpy(dst, vaddr, PAGE_SIZE); memcpy(dst, src, PAGE_SIZE);
kunmap_atomic(dst); kunmap_atomic(dst);
set_page_dirty(page); set_page_dirty(page);
if (obj->mm.madv == I915_MADV_WILLNEED) if (obj->mm.madv == I915_MADV_WILLNEED)
mark_page_accessed(page); mark_page_accessed(page);
put_page(page); put_page(page);
vaddr += PAGE_SIZE;
src += PAGE_SIZE;
} }
obj->mm.dirty = false; obj->mm.dirty = false;
} }
...@@ -131,7 +131,9 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj, ...@@ -131,7 +131,9 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
sg_free_table(pages); sg_free_table(pages);
kfree(pages); kfree(pages);
drm_pci_free(obj->base.dev, obj->phys_handle); dma_free_coherent(&obj->base.dev->pdev->dev,
roundup_pow_of_two(obj->base.size),
vaddr, dma);
} }
static void phys_release(struct drm_i915_gem_object *obj) static void phys_release(struct drm_i915_gem_object *obj)
......
...@@ -136,6 +136,9 @@ static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl) ...@@ -136,6 +136,9 @@ static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl)
struct intel_engine_cs *engine = struct intel_engine_cs *engine =
container_of(b, struct intel_engine_cs, breadcrumbs); container_of(b, struct intel_engine_cs, breadcrumbs);
if (unlikely(intel_engine_is_virtual(engine)))
engine = intel_virtual_engine_get_sibling(engine, 0);
intel_engine_add_retire(engine, tl); intel_engine_add_retire(engine, tl);
} }
......
...@@ -99,6 +99,9 @@ static bool add_retire(struct intel_engine_cs *engine, ...@@ -99,6 +99,9 @@ static bool add_retire(struct intel_engine_cs *engine,
void intel_engine_add_retire(struct intel_engine_cs *engine, void intel_engine_add_retire(struct intel_engine_cs *engine,
struct intel_timeline *tl) struct intel_timeline *tl)
{ {
/* We don't deal well with the engine disappearing beneath us */
GEM_BUG_ON(intel_engine_is_virtual(engine));
if (add_retire(engine, tl)) if (add_retire(engine, tl))
schedule_work(&engine->retire_work); schedule_work(&engine->retire_work);
} }
......
...@@ -237,7 +237,8 @@ static void execlists_init_reg_state(u32 *reg_state, ...@@ -237,7 +237,8 @@ static void execlists_init_reg_state(u32 *reg_state,
bool close); bool close);
static void static void
__execlists_update_reg_state(const struct intel_context *ce, __execlists_update_reg_state(const struct intel_context *ce,
const struct intel_engine_cs *engine); const struct intel_engine_cs *engine,
u32 head);
static void mark_eio(struct i915_request *rq) static void mark_eio(struct i915_request *rq)
{ {
...@@ -1186,12 +1187,11 @@ static void reset_active(struct i915_request *rq, ...@@ -1186,12 +1187,11 @@ static void reset_active(struct i915_request *rq,
head = rq->tail; head = rq->tail;
else else
head = active_request(ce->timeline, rq)->head; head = active_request(ce->timeline, rq)->head;
ce->ring->head = intel_ring_wrap(ce->ring, head); head = intel_ring_wrap(ce->ring, head);
intel_ring_update_space(ce->ring);
/* Scrub the context image to prevent replaying the previous batch */ /* Scrub the context image to prevent replaying the previous batch */
restore_default_state(ce, engine); restore_default_state(ce, engine);
__execlists_update_reg_state(ce, engine); __execlists_update_reg_state(ce, engine, head);
/* We've switched away, so this should be a no-op, but intent matters */ /* We've switched away, so this should be a no-op, but intent matters */
ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
...@@ -1321,7 +1321,7 @@ static u64 execlists_update_context(struct i915_request *rq) ...@@ -1321,7 +1321,7 @@ static u64 execlists_update_context(struct i915_request *rq)
{ {
struct intel_context *ce = rq->context; struct intel_context *ce = rq->context;
u64 desc = ce->lrc_desc; u64 desc = ce->lrc_desc;
u32 tail; u32 tail, prev;
/* /*
* WaIdleLiteRestore:bdw,skl * WaIdleLiteRestore:bdw,skl
...@@ -1334,9 +1334,15 @@ static u64 execlists_update_context(struct i915_request *rq) ...@@ -1334,9 +1334,15 @@ static u64 execlists_update_context(struct i915_request *rq)
* subsequent resubmissions (for lite restore). Should that fail us, * subsequent resubmissions (for lite restore). Should that fail us,
* and we try and submit the same tail again, force the context * and we try and submit the same tail again, force the context
* reload. * reload.
*
* If we need to return to a preempted context, we need to skip the
* lite-restore and force it to reload the RING_TAIL. Otherwise, the
* HW has a tendency to ignore us rewinding the TAIL to the end of
* an earlier request.
*/ */
tail = intel_ring_set_tail(rq->ring, rq->tail); tail = intel_ring_set_tail(rq->ring, rq->tail);
if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL] == tail)) prev = ce->lrc_reg_state[CTX_RING_TAIL];
if (unlikely(intel_ring_direction(rq->ring, tail, prev) <= 0))
desc |= CTX_DESC_FORCE_RESTORE; desc |= CTX_DESC_FORCE_RESTORE;
ce->lrc_reg_state[CTX_RING_TAIL] = tail; ce->lrc_reg_state[CTX_RING_TAIL] = tail;
rq->tail = rq->wa_tail; rq->tail = rq->wa_tail;
...@@ -1605,6 +1611,11 @@ last_active(const struct intel_engine_execlists *execlists) ...@@ -1605,6 +1611,11 @@ last_active(const struct intel_engine_execlists *execlists)
return *last; return *last;
} }
#define for_each_waiter(p__, rq__) \
list_for_each_entry_lockless(p__, \
&(rq__)->sched.waiters_list, \
wait_link)
static void defer_request(struct i915_request *rq, struct list_head * const pl) static void defer_request(struct i915_request *rq, struct list_head * const pl)
{ {
LIST_HEAD(list); LIST_HEAD(list);
...@@ -1622,7 +1633,7 @@ static void defer_request(struct i915_request *rq, struct list_head * const pl) ...@@ -1622,7 +1633,7 @@ static void defer_request(struct i915_request *rq, struct list_head * const pl)
GEM_BUG_ON(i915_request_is_active(rq)); GEM_BUG_ON(i915_request_is_active(rq));
list_move_tail(&rq->sched.link, pl); list_move_tail(&rq->sched.link, pl);
list_for_each_entry(p, &rq->sched.waiters_list, wait_link) { for_each_waiter(p, rq) {
struct i915_request *w = struct i915_request *w =
container_of(p->waiter, typeof(*w), sched); container_of(p->waiter, typeof(*w), sched);
...@@ -1834,14 +1845,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) ...@@ -1834,14 +1845,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
*/ */
__unwind_incomplete_requests(engine); __unwind_incomplete_requests(engine);
/*
* If we need to return to the preempted context, we
* need to skip the lite-restore and force it to
* reload the RING_TAIL. Otherwise, the HW has a
* tendency to ignore us rewinding the TAIL to the
* end of an earlier request.
*/
last->context->lrc_desc |= CTX_DESC_FORCE_RESTORE;
last = NULL; last = NULL;
} else if (need_timeslice(engine, last) && } else if (need_timeslice(engine, last) &&
timer_expired(&engine->execlists.timer)) { timer_expired(&engine->execlists.timer)) {
...@@ -2860,16 +2863,17 @@ static void execlists_context_unpin(struct intel_context *ce) ...@@ -2860,16 +2863,17 @@ static void execlists_context_unpin(struct intel_context *ce)
static void static void
__execlists_update_reg_state(const struct intel_context *ce, __execlists_update_reg_state(const struct intel_context *ce,
const struct intel_engine_cs *engine) const struct intel_engine_cs *engine,
u32 head)
{ {
struct intel_ring *ring = ce->ring; struct intel_ring *ring = ce->ring;
u32 *regs = ce->lrc_reg_state; u32 *regs = ce->lrc_reg_state;
GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->head)); GEM_BUG_ON(!intel_ring_offset_valid(ring, head));
GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->tail)); GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->tail));
regs[CTX_RING_START] = i915_ggtt_offset(ring->vma); regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
regs[CTX_RING_HEAD] = ring->head; regs[CTX_RING_HEAD] = head;
regs[CTX_RING_TAIL] = ring->tail; regs[CTX_RING_TAIL] = ring->tail;
/* RPCS */ /* RPCS */
...@@ -2898,7 +2902,7 @@ __execlists_context_pin(struct intel_context *ce, ...@@ -2898,7 +2902,7 @@ __execlists_context_pin(struct intel_context *ce,
ce->lrc_desc = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE; ce->lrc_desc = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE;
ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
__execlists_update_reg_state(ce, engine); __execlists_update_reg_state(ce, engine, ce->ring->tail);
return 0; return 0;
} }
...@@ -2939,7 +2943,7 @@ static void execlists_context_reset(struct intel_context *ce) ...@@ -2939,7 +2943,7 @@ static void execlists_context_reset(struct intel_context *ce)
/* Scrub away the garbage */ /* Scrub away the garbage */
execlists_init_reg_state(ce->lrc_reg_state, execlists_init_reg_state(ce->lrc_reg_state,
ce, ce->engine, ce->ring, true); ce, ce->engine, ce->ring, true);
__execlists_update_reg_state(ce, ce->engine); __execlists_update_reg_state(ce, ce->engine, ce->ring->tail);
ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
} }
...@@ -3494,6 +3498,7 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled) ...@@ -3494,6 +3498,7 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
struct intel_engine_execlists * const execlists = &engine->execlists; struct intel_engine_execlists * const execlists = &engine->execlists;
struct intel_context *ce; struct intel_context *ce;
struct i915_request *rq; struct i915_request *rq;
u32 head;
mb(); /* paranoia: read the CSB pointers from after the reset */ mb(); /* paranoia: read the CSB pointers from after the reset */
clflush(execlists->csb_write); clflush(execlists->csb_write);
...@@ -3521,15 +3526,15 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled) ...@@ -3521,15 +3526,15 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
if (i915_request_completed(rq)) { if (i915_request_completed(rq)) {
/* Idle context; tidy up the ring so we can restart afresh */ /* Idle context; tidy up the ring so we can restart afresh */
ce->ring->head = intel_ring_wrap(ce->ring, rq->tail); head = intel_ring_wrap(ce->ring, rq->tail);
goto out_replay; goto out_replay;
} }
/* Context has requests still in-flight; it should not be idle! */ /* Context has requests still in-flight; it should not be idle! */
GEM_BUG_ON(i915_active_is_idle(&ce->active)); GEM_BUG_ON(i915_active_is_idle(&ce->active));
rq = active_request(ce->timeline, rq); rq = active_request(ce->timeline, rq);
ce->ring->head = intel_ring_wrap(ce->ring, rq->head); head = intel_ring_wrap(ce->ring, rq->head);
GEM_BUG_ON(ce->ring->head == ce->ring->tail); GEM_BUG_ON(head == ce->ring->tail);
/* /*
* If this request hasn't started yet, e.g. it is waiting on a * If this request hasn't started yet, e.g. it is waiting on a
...@@ -3574,10 +3579,9 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled) ...@@ -3574,10 +3579,9 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
out_replay: out_replay:
ENGINE_TRACE(engine, "replay {head:%04x, tail:%04x}\n", ENGINE_TRACE(engine, "replay {head:%04x, tail:%04x}\n",
ce->ring->head, ce->ring->tail); head, ce->ring->tail);
intel_ring_update_space(ce->ring);
__execlists_reset_reg_state(ce, engine); __execlists_reset_reg_state(ce, engine);
__execlists_update_reg_state(ce, engine); __execlists_update_reg_state(ce, engine, head);
ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; /* paranoid: GPU was reset! */ ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; /* paranoid: GPU was reset! */
unwind: unwind:
...@@ -5220,10 +5224,7 @@ void intel_lr_context_reset(struct intel_engine_cs *engine, ...@@ -5220,10 +5224,7 @@ void intel_lr_context_reset(struct intel_engine_cs *engine,
restore_default_state(ce, engine); restore_default_state(ce, engine);
/* Rerun the request; its payload has been neutered (if guilty). */ /* Rerun the request; its payload has been neutered (if guilty). */
ce->ring->head = head; __execlists_update_reg_state(ce, engine, head);
intel_ring_update_space(ce->ring);
__execlists_update_reg_state(ce, engine);
} }
bool bool
......
...@@ -145,6 +145,7 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size) ...@@ -145,6 +145,7 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size)
kref_init(&ring->ref); kref_init(&ring->ref);
ring->size = size; ring->size = size;
ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(size);
/* /*
* Workaround an erratum on the i830 which causes a hang if * Workaround an erratum on the i830 which causes a hang if
......
...@@ -56,6 +56,14 @@ static inline u32 intel_ring_wrap(const struct intel_ring *ring, u32 pos) ...@@ -56,6 +56,14 @@ static inline u32 intel_ring_wrap(const struct intel_ring *ring, u32 pos)
return pos & (ring->size - 1); return pos & (ring->size - 1);
} }
static inline int intel_ring_direction(const struct intel_ring *ring,
u32 next, u32 prev)
{
typecheck(typeof(ring->size), next);
typecheck(typeof(ring->size), prev);
return (next - prev) << ring->wrap;
}
static inline bool static inline bool
intel_ring_offset_valid(const struct intel_ring *ring, intel_ring_offset_valid(const struct intel_ring *ring,
unsigned int pos) unsigned int pos)
......
...@@ -39,12 +39,13 @@ struct intel_ring { ...@@ -39,12 +39,13 @@ struct intel_ring {
*/ */
atomic_t pin_count; atomic_t pin_count;
u32 head; u32 head; /* updated during retire, loosely tracks RING_HEAD */
u32 tail; u32 tail; /* updated on submission, used for RING_TAIL */
u32 emit; u32 emit; /* updated during request construction */
u32 space; u32 space;
u32 size; u32 size;
u32 wrap;
u32 effective_size; u32 effective_size;
}; };
......
...@@ -186,7 +186,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio) ...@@ -186,7 +186,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
} }
GEM_BUG_ON(!ce[1]->ring->size); GEM_BUG_ON(!ce[1]->ring->size);
intel_ring_reset(ce[1]->ring, ce[1]->ring->size / 2); intel_ring_reset(ce[1]->ring, ce[1]->ring->size / 2);
__execlists_update_reg_state(ce[1], engine); __execlists_update_reg_state(ce[1], engine, ce[1]->ring->head);
rq[0] = igt_spinner_create_request(&spin, ce[0], MI_ARB_CHECK); rq[0] = igt_spinner_create_request(&spin, ce[0], MI_ARB_CHECK);
if (IS_ERR(rq[0])) { if (IS_ERR(rq[0])) {
......
...@@ -180,7 +180,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, ...@@ -180,7 +180,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
struct drm_i915_gem_pwrite *args, struct drm_i915_gem_pwrite *args,
struct drm_file *file) struct drm_file *file)
{ {
void *vaddr = obj->phys_handle->vaddr + args->offset; void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
char __user *user_data = u64_to_user_ptr(args->data_ptr); char __user *user_data = u64_to_user_ptr(args->data_ptr);
/* /*
...@@ -844,10 +844,10 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, ...@@ -844,10 +844,10 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
ret = i915_gem_gtt_pwrite_fast(obj, args); ret = i915_gem_gtt_pwrite_fast(obj, args);
if (ret == -EFAULT || ret == -ENOSPC) { if (ret == -EFAULT || ret == -ENOSPC) {
if (obj->phys_handle) if (i915_gem_object_has_struct_page(obj))
ret = i915_gem_phys_pwrite(obj, args, file);
else
ret = i915_gem_shmem_pwrite(obj, args); ret = i915_gem_shmem_pwrite(obj, args);
else
ret = i915_gem_phys_pwrite(obj, args, file);
} }
i915_gem_object_unpin_pages(obj); i915_gem_object_unpin_pages(obj);
......
...@@ -1852,7 +1852,8 @@ void i915_error_state_store(struct i915_gpu_coredump *error) ...@@ -1852,7 +1852,8 @@ void i915_error_state_store(struct i915_gpu_coredump *error)
if (!xchg(&warned, true) && if (!xchg(&warned, true) &&
ktime_get_real_seconds() - DRIVER_TIMESTAMP < DAY_AS_SECONDS(180)) { ktime_get_real_seconds() - DRIVER_TIMESTAMP < DAY_AS_SECONDS(180)) {
pr_info("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n"); pr_info("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
pr_info("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n"); pr_info("Please file a _new_ bug report at https://gitlab.freedesktop.org/drm/intel/issues/new.\n");
pr_info("Please see https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs for details.\n");
pr_info("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n"); pr_info("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
pr_info("The GPU crash dump is required to analyze GPU hangs, so please always attach it.\n"); pr_info("The GPU crash dump is required to analyze GPU hangs, so please always attach it.\n");
pr_info("GPU crash dump saved to /sys/class/drm/card%d/error\n", pr_info("GPU crash dump saved to /sys/class/drm/card%d/error\n",
......
...@@ -595,6 +595,8 @@ static void __i915_request_ctor(void *arg) ...@@ -595,6 +595,8 @@ static void __i915_request_ctor(void *arg)
i915_sw_fence_init(&rq->submit, submit_notify); i915_sw_fence_init(&rq->submit, submit_notify);
i915_sw_fence_init(&rq->semaphore, semaphore_notify); i915_sw_fence_init(&rq->semaphore, semaphore_notify);
dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock, 0, 0);
rq->file_priv = NULL; rq->file_priv = NULL;
rq->capture_list = NULL; rq->capture_list = NULL;
...@@ -653,25 +655,30 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp) ...@@ -653,25 +655,30 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
} }
} }
ret = intel_timeline_get_seqno(tl, rq, &seqno);
if (ret)
goto err_free;
rq->i915 = ce->engine->i915; rq->i915 = ce->engine->i915;
rq->context = ce; rq->context = ce;
rq->engine = ce->engine; rq->engine = ce->engine;
rq->ring = ce->ring; rq->ring = ce->ring;
rq->execution_mask = ce->engine->mask; rq->execution_mask = ce->engine->mask;
kref_init(&rq->fence.refcount);
rq->fence.flags = 0;
rq->fence.error = 0;
INIT_LIST_HEAD(&rq->fence.cb_list);
ret = intel_timeline_get_seqno(tl, rq, &seqno);
if (ret)
goto err_free;
rq->fence.context = tl->fence_context;
rq->fence.seqno = seqno;
RCU_INIT_POINTER(rq->timeline, tl); RCU_INIT_POINTER(rq->timeline, tl);
RCU_INIT_POINTER(rq->hwsp_cacheline, tl->hwsp_cacheline); RCU_INIT_POINTER(rq->hwsp_cacheline, tl->hwsp_cacheline);
rq->hwsp_seqno = tl->hwsp_seqno; rq->hwsp_seqno = tl->hwsp_seqno;
rq->rcustate = get_state_synchronize_rcu(); /* acts as smp_mb() */ rq->rcustate = get_state_synchronize_rcu(); /* acts as smp_mb() */
dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock,
tl->fence_context, seqno);
/* We bump the ref for the fence chain */ /* We bump the ref for the fence chain */
i915_sw_fence_reinit(&i915_request_get(rq)->submit); i915_sw_fence_reinit(&i915_request_get(rq)->submit);
i915_sw_fence_reinit(&i915_request_get(rq)->semaphore); i915_sw_fence_reinit(&i915_request_get(rq)->semaphore);
......
...@@ -423,8 +423,6 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node, ...@@ -423,8 +423,6 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
if (!node_signaled(signal)) { if (!node_signaled(signal)) {
INIT_LIST_HEAD(&dep->dfs_link); INIT_LIST_HEAD(&dep->dfs_link);
list_add(&dep->wait_link, &signal->waiters_list);
list_add(&dep->signal_link, &node->signalers_list);
dep->signaler = signal; dep->signaler = signal;
dep->waiter = node; dep->waiter = node;
dep->flags = flags; dep->flags = flags;
...@@ -434,6 +432,10 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node, ...@@ -434,6 +432,10 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
!node_started(signal)) !node_started(signal))
node->flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN; node->flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN;
/* All set, now publish. Beware the lockless walkers. */
list_add(&dep->signal_link, &node->signalers_list);
list_add_rcu(&dep->wait_link, &signal->waiters_list);
/* /*
* As we do not allow WAIT to preempt inflight requests, * As we do not allow WAIT to preempt inflight requests,
* once we have executed a request, along with triggering * once we have executed a request, along with triggering
......
...@@ -8,9 +8,8 @@ ...@@ -8,9 +8,8 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_utils.h" #include "i915_utils.h"
#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI" #define FDO_BUG_URL "https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs"
#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \ #define FDO_BUG_MSG "Please file a bug on drm/i915; see " FDO_BUG_URL " for details."
"providing the dmesg log by booting with drm.debug=0xf"
void void
__i915_printk(struct drm_i915_private *dev_priv, const char *level, __i915_printk(struct drm_i915_private *dev_priv, const char *level,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment