Merge tag 'drm-intel-next-fixes-2020-10-22' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
Merge commit. Changes below are compared with the first parent: 3f31dedb.
Changes
15 files changed · +334 −53
| File | Status | Add | Del | Content |
|---|---|---|---|---|
| drivers/gpu/drm/i915/Kconfig.debug | modified | +1 | −0 | View file |
| drivers/gpu/drm/i915/display/intel_display.c | modified | +8 | −0 | View file |
| drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | modified | +20 | −11 | View file |
| drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | modified | +8 | −2 | View file |
| drivers/gpu/drm/i915/gem/i915_gem_stolen.c | modified | +4 | −2 | View file |
| drivers/gpu/drm/i915/gem/i915_gem_stolen.h | modified | +2 | −0 | View file |
| drivers/gpu/drm/i915/gt/gen6_ppgtt.c | modified | +12 | −6 | View file |
| drivers/gpu/drm/i915/gt/gen8_ppgtt.c | modified | +2 | −1 | View file |
| drivers/gpu/drm/i915/gt/intel_engine_types.h | modified | +1 | −1 | View file |
| drivers/gpu/drm/i915/gt/intel_lrc.c | modified | +37 | −21 | View file |
| drivers/gpu/drm/i915/gt/intel_mocs.c | modified | +11 | −5 | View file |
| drivers/gpu/drm/i915/gt/selftest_reset.c | modified | +196 | −0 | View file |
| drivers/gpu/drm/i915/i915_drv.h | modified | +5 | −1 | View file |
| drivers/gpu/drm/i915/i915_gpu_error.c | modified | +1 | −2 | View file |
| drivers/gpu/drm/i915/intel_uncore.c | modified | +26 | −1 | View file |
Only the first 600 diff lines are shown. Download the complete patch.
drivers/gpu/drm/i915/Kconfig.debug
View filediff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
index 1cb28c2..25cd978 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -153,6 +153,7 @@ config DRM_I915_SELFTEST
select DRM_EXPORT_FOR_TESTS if m
select FAULT_INJECTION
select PRIME_NUMBERS
+ select CRC32
help
Choose this option to allow the driver to perform selftests upon
loading; also requires the i915.selftest=1 module parameter. To
drivers/gpu/drm/i915/display/intel_display.c
View filediff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index a1fba7e..829b2a4 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3434,6 +3434,14 @@ initial_plane_vma(struct drm_i915_private *i915,
if (IS_ERR(obj))
return NULL;
+ /*
+ * Mark it WT ahead of time to avoid changing the
+ * cache_level during fbdev initialization. The
+ * unbind there would get stuck waiting for rcu.
+ */
+ i915_gem_object_set_cache_coherency(obj, HAS_WT(i915) ?
+ I915_CACHE_WT : I915_CACHE_NONE);
+
switch (plane_config->tiling) {
case I915_TILING_NONE:
break;
drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
View filediff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
index acbd7eb..036f504 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -52,17 +52,11 @@ static void set_aux_backlight_enable(struct intel_dp *intel_dp, bool enable)
}
}
-/*
- * Read the current backlight value from DPCD register(s) based
- * on if 8-bit(MSB) or 16-bit(MSB and LSB) values are supported
- */
-static u32 intel_dp_aux_get_backlight(struct intel_connector *connector)
+static bool intel_dp_aux_backlight_dpcd_mode(struct intel_connector *connector)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- u8 read_val[2] = { 0x0 };
u8 mode_reg;
- u16 level = 0;
if (drm_dp_dpcd_readb(&intel_dp->aux,
DP_EDP_BACKLIGHT_MODE_SET_REGISTER,
@@ -70,15 +64,29 @@ static u32 intel_dp_aux_get_backlight(struct intel_connector *connector)
drm_dbg_kms(&i915->drm,
"Failed to read the DPCD register 0x%x\n",
DP_EDP_BACKLIGHT_MODE_SET_REGISTER);
- return 0;
+ return false;
}
+ return (mode_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) ==
+ DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD;
+}
+
+/*
+ * Read the current backlight value from DPCD register(s) based
+ * on if 8-bit(MSB) or 16-bit(MSB and LSB) values are supported
+ */
+static u32 intel_dp_aux_get_backlight(struct intel_connector *connector)
+{
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ u8 read_val[2] = { 0x0 };
+ u16 level = 0;
+
/*
* If we're not in DPCD control mode yet, the programmed brightness
* value is meaningless and we should assume max brightness
*/
- if ((mode_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) !=
- DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD)
+ if (!intel_dp_aux_backlight_dpcd_mode(connector))
return connector->panel.backlight.max;
if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
@@ -319,7 +327,8 @@ static int intel_dp_aux_setup_backlight(struct intel_connector *connector,
panel->backlight.min = 0;
panel->backlight.level = intel_dp_aux_get_backlight(connector);
- panel->backlight.enabled = panel->backlight.level != 0;
+ panel->backlight.enabled = intel_dp_aux_backlight_dpcd_mode(connector) &&
+ panel->backlight.level != 0;
return 0;
}
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
View filediff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 4b09bcd..1904e6e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -287,8 +287,8 @@ struct i915_execbuffer {
u64 invalid_flags; /** Set of execobj.flags that are invalid */
u32 context_flags; /** Set of execobj.flags to insert from the ctx */
+ u64 batch_len; /** Length of batch within object */
u32 batch_start_offset; /** Location within object of batch */
- u32 batch_len; /** Length of batch within object */
u32 batch_flags; /** Flags composed for emit_bb_start() */
struct intel_gt_buffer_pool_node *batch_pool; /** pool node for batch buffer */
@@ -871,6 +871,10 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
if (eb->batch_len == 0)
eb->batch_len = eb->batch->vma->size - eb->batch_start_offset;
+ if (unlikely(eb->batch_len == 0)) { /* impossible! */
+ drm_dbg(&i915->drm, "Invalid batch length\n");
+ return -EINVAL;
+ }
return 0;
@@ -2424,7 +2428,7 @@ static int eb_parse(struct i915_execbuffer *eb)
struct drm_i915_private *i915 = eb->i915;
struct intel_gt_buffer_pool_node *pool = eb->batch_pool;
struct i915_vma *shadow, *trampoline, *batch;
- unsigned int len;
+ unsigned long len;
int err;
if (!eb_use_cmdparser(eb)) {
@@ -2449,6 +2453,8 @@ static int eb_parse(struct i915_execbuffer *eb)
} else {
len += I915_CMD_PARSER_TRAMPOLINE_SIZE;
}
+ if (unlikely(len < eb->batch_len)) /* last paranoid check of overflow */
+ return -EINVAL;
if (!pool) {
pool = intel_gt_get_buffer_pool(eb->engine->gt, len);
drivers/gpu/drm/i915/gem/i915_gem_stolen.c
View filediff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index 0be5e86..84b2707 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -53,8 +53,10 @@ int i915_gem_stolen_insert_node(struct drm_i915_private *i915,
struct drm_mm_node *node, u64 size,
unsigned alignment)
{
- return i915_gem_stolen_insert_node_in_range(i915, node, size,
- alignment, 0, U64_MAX);
+ return i915_gem_stolen_insert_node_in_range(i915, node,
+ size, alignment,
+ I915_GEM_STOLEN_BIAS,
+ U64_MAX);
}
void i915_gem_stolen_remove_node(struct drm_i915_private *i915,
drivers/gpu/drm/i915/gem/i915_gem_stolen.h
View filediff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
index e15c0ad..61e0280 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
@@ -30,4 +30,6 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv
resource_size_t stolen_offset,
resource_size_t size);
+#define I915_GEM_STOLEN_BIAS SZ_128K
+
#endif /* __I915_GEM_STOLEN_H__ */
drivers/gpu/drm/i915/gt/gen6_ppgtt.c
View filediff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c
index fd0d24d..c30adc0 100644
--- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c
+++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c
@@ -239,18 +239,24 @@ static int gen6_ppgtt_init_scratch(struct gen6_ppgtt *ppgtt)
I915_CACHE_NONE, PTE_READ_ONLY);
vm->scratch[1] = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K);
- if (IS_ERR(vm->scratch[1]))
- return PTR_ERR(vm->scratch[1]);
+ if (IS_ERR(vm->scratch[1])) {
+ ret = PTR_ERR(vm->scratch[1]);
+ goto err_scratch0;
+ }
ret = pin_pt_dma(vm, vm->scratch[1]);
- if (ret) {
- i915_gem_object_put(vm->scratch[1]);
- return ret;
- }
+ if (ret)
+ goto err_scratch1;
fill32_px(vm->scratch[1], vm->scratch[0]->encode);
return 0;
+
+err_scratch1:
+ i915_gem_object_put(vm->scratch[1]);
+err_scratch0:
+ i915_gem_object_put(vm->scratch[0]);
+ return ret;
}
static void gen6_ppgtt_free_pd(struct gen6_ppgtt *ppgtt)
drivers/gpu/drm/i915/gt/gen8_ppgtt.c
View filediff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
index eb64f47..38c7069 100644
--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
@@ -604,7 +604,8 @@ static int gen8_init_scratch(struct i915_address_space *vm)
return 0;
free_scratch:
- free_scratch(vm);
+ while (i--)
+ i915_gem_object_put(vm->scratch[i]);
return -ENOMEM;
}
drivers/gpu/drm/i915/gt/intel_engine_types.h
View filediff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index c400aaa..ee63126 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -278,7 +278,7 @@ struct intel_engine_execlists {
*
* Note these register may be either mmio or HWSP shadow.
*/
- u32 *csb_status;
+ u64 *csb_status;
/**
* @csb_size: context status buffer FIFO size
drivers/gpu/drm/i915/gt/intel_lrc.c
View filediff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 0412a44..a32aabc 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1140,9 +1140,8 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
/* Check in case we rollback so far we wrap [size/2] */
if (intel_ring_direction(rq->ring,
- intel_ring_wrap(rq->ring,
- rq->tail),
- rq->ring->tail) > 0)
+ rq->tail,
+ rq->ring->tail + 8) > 0)
rq->context->lrc.desc |= CTX_DESC_FORCE_RESTORE;
active = rq;
@@ -2464,7 +2463,7 @@ cancel_port_requests(struct intel_engine_execlists * const execlists)
}
static inline void
-invalidate_csb_entries(const u32 *first, const u32 *last)
+invalidate_csb_entries(const u64 *first, const u64 *last)
{
clflush((void *)first);
clflush((void *)last);
@@ -2496,14 +2495,25 @@ invalidate_csb_entries(const u32 *first, const u32 *last)
* bits 47-57: sw context id of the lrc the GT switched away from
* bits 58-63: sw counter of the lrc the GT switched away from
*/
-static inline bool
-gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
-{
- u32 lower_dw = csb[0];
- u32 upper_dw = csb[1];
- bool ctx_to_valid = GEN12_CSB_CTX_VALID(lower_dw);
- bool ctx_away_valid = GEN12_CSB_CTX_VALID(upper_dw);
- bool new_queue = lower_dw & GEN12_CTX_STATUS_SWITCHED_TO_NEW_QUEUE;
+static inline bool gen12_csb_parse(const u64 *csb)
+{
+ bool ctx_away_valid;
+ bool new_queue;
+ u64 entry;
+
+ /* HSD#22011248461 */
+ entry = READ_ONCE(*csb);
+ if (unlikely(entry == -1)) {
+ preempt_disable();
+ if (wait_for_atomic_us((entry = READ_ONCE(*csb)) != -1, 50))
+ GEM_WARN_ON("50us CSB timeout");
+ preempt_enable();
+ }
+ WRITE_ONCE(*(u64 *)csb, -1);
+
+ ctx_away_valid = GEN12_CSB_CTX_VALID(upper_32_bits(entry));
+ new_queue =
+ lower_32_bits(entry) & GEN12_CTX_STATUS_SWITCHED_TO_NEW_QUEUE;
/*
* The context switch detail is not guaranteed to be 5 when a preemption
@@ -2513,7 +2523,7 @@ gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
* would require some extra handling, but we don't support that.
*/
if (!ctx_away_valid || new_queue) {
- GEM_BUG_ON(!ctx_to_valid);
+ GEM_BUG_ON(!GEN12_CSB_CTX_VALID(lower_32_bits(entry)));
return true;
}
@@ -2522,12 +2532,11 @@ gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
* context switch on an unsuccessful wait instruction since we always
* use polling mode.
*/
- GEM_BUG_ON(GEN12_CTX_SWITCH_DETAIL(upper_dw));
+ GEM_BUG_ON(GEN12_CTX_SWITCH_DETAIL(upper_32_bits(entry)));
return false;
}
-static inline bool
-gen8_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
+static inline bool gen8_csb_parse(const u64 *csb)
{
return *csb & (GEN8_CTX_STATUS_IDLE_ACTIVE | GEN8_CTX_STATUS_PREEMPTED);
}
@@ -2535,7 +2544,7 @@ gen8_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
static void process_csb(struct intel_engine_cs *engine)
{
struct intel_engine_execlists * const execlists = &engine->execlists;
- const u32 * const buf = execlists->csb_status;
+ const u64 * const buf = execlists->csb_status;
const u8 num_entries = execlists->csb_size;
u8 head, tail;
@@ -2616,12 +2625,14 @@ static void process_csb(struct intel_engine_cs *engine)
*/
ENGINE_TRACE(engine, "csb[%d]: status=0x%08x:0x%08x\n",
- head, buf[2 * head + 0], buf[2 * head + 1]);
+ head,
+ upper_32_bits(buf[head]),
+ lower_32_bits(buf[head]));
if (INTEL_GEN(engine->i915) >= 12)
- promote = gen12_csb_parse(execlists, buf + 2 * head);
+ promote = gen12_csb_parse(buf + head);
else
- promote = gen8_csb_parse(execlists, buf + 2 * head);
+ promote = gen8_csb_parse(buf + head);
if (promote) {
struct i915_request * const *old = execlists->active;
@@ -2649,6 +2660,9 @@ static void process_csb(struct intel_engine_cs *engine)
smp_wmb(); /* complete the seqlock */
WRITE_ONCE(execlists->active, execlists->inflight);
+ /* XXX Magic delay for tgl */
+ ENGINE_POSTING_READ(engine, RING_CONTEXT_STATUS_PTR);
+
WRITE_ONCE(execlists->pending[0], NULL);
} else {
if (GEM_WARN_ON(!*execlists->active)) {
@@ -4005,6 +4019,8 @@ static void reset_csb_pointers(struct intel_engine_cs *engine)
WRITE_ONCE(*execlists->csb_write, reset_value);
wmb(); /* Make sure this is visible to HW (paranoia?) */
+ /* Check that the GPU does indeed update the CSB entries! */
+ memset(execlists->csb_status, -1, (reset_value + 1) * sizeof(u64));
invalidate_csb_entries(&execlists->csb_status[0],
&execlists->csb_status[reset_value]);
@@ -5157,7 +5173,7 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine)
}
execlists->csb_status =
- &engine->status_page.addr[I915_HWS_CSB_BUF0_INDEX];
+ (u64 *)&engine->status_page.addr[I915_HWS_CSB_BUF0_INDEX];
execlists->csb_write =
&engine->status_page.addr[intel_hws_csb_write_index(i915)];
drivers/gpu/drm/i915/gt/intel_mocs.c
View filediff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c
index 632e08a..b8f56e6 100644
--- a/drivers/gpu/drm/i915/gt/intel_mocs.c
+++ b/drivers/gpu/drm/i915/gt/intel_mocs.c
@@ -234,11 +234,17 @@ static const struct drm_i915_mocs_entry broxton_mocs_table[] = {
L3_1_UC)
static const struct drm_i915_mocs_entry tgl_mocs_table[] = {
- /* Base - Error (Reserved for Non-Use) */
- MOCS_ENTRY(0, 0x0, 0x0),
- /* Base - Reserved */
- MOCS_ENTRY(1, 0x0, 0x0),
-
+ /*
+ * NOTE:
+ * Reserved and unspecified MOCS indices have been set to (L3 + LCC).
+ * These reserved entries should never be used, they may be changed
+ * to low performant variants with better coherency in the future if
+ * more entries are needed. We are programming index I915_MOCS_PTE(1)
+ * only, __init_mocs_table() take care to program unused index with
+ * this entry.
+ */
+ MOCS_ENTRY(1, LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
+ L3_3_WB),
GEN11_MOCS_ENTRIES,
/* Implicitly enable L1 - HDC:L1 + L3 + LLC */
drivers/gpu/drm/i915/gt/selftest_reset.c
View filediff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c
index 35406ec..ef5aeeb 100644
--- a/drivers/gpu/drm/i915/gt/selftest_reset.c
+++ b/drivers/gpu/drm/i915/gt/selftest_reset.c
@@ -3,9 +3,203 @@
* Copyright © 2018 Intel Corporation
*/
+#include <linux/crc32.h>
+
+#include "gem/i915_gem_stolen.h"
+
+#include "i915_memcpy.h"
#include "i915_selftest.h"
#include "selftests/igt_reset.h"
#include "selftests/igt_atomic.h"
+#include "selftests/igt_spinner.h"
+
+static int
+__igt_reset_stolen(struct intel_gt *gt,
+ intel_engine_mask_t mask,
+ const char *msg)
+{
+ struct i915_ggtt *ggtt = >->i915->ggtt;
+ const struct resource *dsm = >->i915->dsm;
+ resource_size_t num_pages, page;
+ struct intel_engine_cs *engine;
+ intel_wakeref_t wakeref;
+ enum intel_engine_id id;
+ struct igt_spinner spin;
+ long max, count;
+ void *tmp;
+ u32 *crc;
+ int err;
+
+ if (!drm_mm_node_allocated(&ggtt->error_capture))
+ return 0;
+
+ num_pages = resource_size(dsm) >> PAGE_SHIFT;
+ if (!num_pages)
+ return 0;
+
+ crc = kmalloc_array(num_pages, sizeof(u32), GFP_KERNEL);
+ if (!crc)
+ return -ENOMEM;
+
+ tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!tmp) {
+ err = -ENOMEM;
+ goto err_crc;
+ }
+
+ igt_global_reset_lock(gt);
+ wakeref = intel_runtime_pm_get(gt->uncore->rpm);
+
+ err = igt_spinner_init(&spin, gt);
+ if (err)
+ goto err_lock;
+
+ for_each_engine(engine, gt, id) {
+ struct intel_context *ce;
+ struct i915_request *rq;
+
+ if (!(mask & engine->mask))
+ continue;
+
+ if (!intel_engine_can_store_dword(engine))
+ continue;
+
+ ce = intel_context_create(engine);
+ if (IS_ERR(ce)) {
+ err = PTR_ERR(ce);
+ goto err_spin;
+ }
+ rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
+ intel_context_put(ce);
+ if (IS_ERR(rq)) {
+ err = PTR_ERR(rq);
+ goto err_spin;
+ }
+ i915_request_add(rq);
+ }
+
+ for (page = 0; page < num_pages; page++) {
+ dma_addr_t dma = (dma_addr_t)dsm->start + (page << PAGE_SHIFT);
+ void __iomem *s;
+ void *in;
+
+ ggtt->vm.insert_page(&ggtt->vm, dma,
+ ggtt->error_capture.start,
+ I915_CACHE_NONE, 0);
+ mb();
+
+ s = io_mapping_map_wc(&ggtt->iomap,
+ ggtt->error_capture.start,
+ PAGE_SIZE);
+
+ if (!__drm_mm_interval_first(>->i915->mm.stolen,
+ page << PAGE_SHIFT,
+ ((page + 1) << PAGE_SHIFT) - 1))
+ memset32(s, STACK_MAGIC, PAGE_SIZE / sizeof(u32));
+
+ in = s;
+ if (i915_memcpy_from_wc(tmp, s, PAGE_SIZE))
+ in = tmp;
+ crc[page] = crc32_le(0, in, PAGE_SIZE);
+
+ io_mapping_unmap(s);
+ }
+ mb();
+ ggtt->vm.clear_range(&ggtt->vm, ggtt->error_capture.start, PAGE_SIZE);
+
+ if (mask == ALL_ENGINES) {
+ intel_gt_reset(gt, mask, NULL);
+ } else {
+ for_each_engine(engine, gt, id) {
+ if (mask & engine->mask)
+ intel_engine_reset(engine, NULL);
+ }
+ }
+
+ max = -1;
+ count = 0;
+ for (page = 0; page < num_pages; page++) {
+ dma_addr_t dma = (dma_addr_t)dsm->start + (page << PAGE_SHIFT);
+ void __iomem *s;
+ void *in;
+ u32 x;
+
+ ggtt->vm.insert_page(&ggtt->vm, dma,
+ ggtt->error_capture.start,
+ I915_CACHE_NONE, 0);
+ mb();
+
+ s = io_mapping_map_wc(&ggtt->iomap,
+ ggtt->error_capture.start,
+ PAGE_SIZE);
+
+ in = s;
+ if (i915_memcpy_from_wc(tmp, s, PAGE_SIZE))
+ in = tmp;
+ x = crc32_le(0, in, PAGE_SIZE);
+
+ if (x != crc[page] &&
+ !__drm_mm_interval_first(>->i915->mm.stolen,
+ page << PAGE_SHIFT,
+ ((page + 1) << PAGE_SHIFT) - 1)) {
+ pr_debug("unused stolen page %pa modified by GPU reset\n",
+ &page);
+ if (count++ == 0)
+ igt_hexdump(in, PAGE_SIZE);
+ max = page;
+ }
+
+ io_mapping_unmap(s);
+ }
+ mb();
+ ggtt->vm.clear_range(&ggtt->vm, ggtt->error_capture.start, PAGE_SIZE);
+
+ if (count > 0) {
+ pr_info("%s reset clobbered %ld pages of stolen, last clobber at page %ld\n",
+ msg, count, max);
+ }
+ if (max >= I915_GEM_STOLEN_BIAS >> PAGE_SHIFT) {
+ pr_err("%s reset clobbered unreserved area [above %x] of stolen; may cause severe faults\n",
+ msg, I915_GEM_STOLEN_BIAS);
+ err = -EINVAL;
+ }
+
+err_spin:
+ igt_spinner_fini(&spin);
+
+err_lock:
+ intel_runtime_pm_put(gt->uncore->rpm, wakeref);
+ igt_global_reset_unlock(gt);
+
+ kfree(tmp);
+err_crc:
+ kfree(crc);
+ return err;
+}
+
+static int igt_reset_device_stolen(void *arg)
+{
+ return __igt_reset_stolen(arg, ALL_ENGINES, "device");
+}
+
+static int igt_reset_engines_stolen(void *arg)
+{
+ struct intel_gt *gt = arg;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+ int err;
+
+ if (!intel_has_reset_engine(gt))
+ return 0;
+
+ for_each_engine(engine, gt, id) {
+ err = __igt_reset_stolen(gt, engine->mask, engine->name);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
This diff is incomplete. Download the complete patch.
drivers/gpu/drm/i915/i915_drv.h
View fileThis diff is incomplete. Download the complete patch.
drivers/gpu/drm/i915/i915_gpu_error.c
View fileThis diff is incomplete. Download the complete patch.
drivers/gpu/drm/i915/intel_uncore.c
View fileThis diff is incomplete. Download the complete patch.