* [PATCH] drm/i915: Cache the error string
@ 2018-07-18 10:29 Chris Wilson
2018-07-18 10:36 ` Chris Wilson
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Chris Wilson @ 2018-07-18 10:29 UTC (permalink / raw)
To: intel-gfx
Currently, we convert the error state into a string every time we read
from sysfs (and sysfs reads in page size (4KiB) chunks). We do try to
window the string and only capture the portion that is being read, but
that means that we must always convert up to the window to find the
start. For a very large error state bordering on EXEC_OBJECT_CAPTURE
abuse, this is noticeable as it degrades to O(N^2)!
As we do not have a convenient hook for sysfs open(), and we would like
to keep the lazy conversion into a string, do the conversion of the
whole string on the first read and keep the string until the error state
is freed.
Reported-by: Jason Ekstrand <jason@jlekstrand.net>
Testcase: igt/gem_exec_capture/many*
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Jason Ekstrand <jason@jlekstrand.net>
---
drivers/gpu/drm/i915/i915_debugfs.c | 19 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 309 +++++++++++---------------
drivers/gpu/drm/i915/i915_gpu_error.h | 26 +--
drivers/gpu/drm/i915/i915_sysfs.c | 20 +-
4 files changed, 155 insertions(+), 219 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 54509e44a856..24aa2e4d0845 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -944,29 +944,22 @@ static ssize_t gpu_state_read(struct file *file, char __user *ubuf,
size_t count, loff_t *pos)
{
struct i915_gpu_state *error = file->private_data;
- struct drm_i915_error_state_buf str;
+ const char *error_str;
+ size_t error_len;
ssize_t ret;
- loff_t tmp;
if (!error)
return 0;
- ret = i915_error_state_buf_init(&str, error->i915, count, *pos);
+ ret = i915_error_state_to_str(error, &error_str, &error_len);
if (ret)
return ret;
- ret = i915_error_state_to_str(&str, error);
- if (ret)
- goto out;
-
- tmp = 0;
- ret = simple_read_from_buffer(ubuf, count, &tmp, str.buf, str.bytes);
+ ret = simple_read_from_buffer(ubuf, count, pos, error_str, error_len);
if (ret < 0)
- goto out;
+ return ret;
- *pos = str.start + ret;
-out:
- i915_error_state_buf_release(&str);
+ *pos += ret;
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 8c81cf3aa182..4e8f1bbdbb07 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -76,112 +76,78 @@ static const char *purgeable_flag(int purgeable)
return purgeable ? " purgeable" : "";
}
-static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
+static bool __i915_error_grow(struct drm_i915_error_state_buf *e, size_t len)
{
-
- if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
- e->err = -ENOSPC;
- return false;
- }
-
- if (e->bytes == e->size - 1 || e->err)
- return false;
-
- return true;
-}
-
-static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
- unsigned len)
-{
- if (e->pos + len <= e->start) {
- e->pos += len;
+ if (!len)
return false;
- }
-
- /* First vsnprintf needs to fit in its entirety for memmove */
- if (len >= e->size) {
- e->err = -EIO;
- return false;
- }
- return true;
-}
+ if (e->bytes + len + 1 > e->size) {
+ size_t size = PAGE_ALIGN(e->bytes + len + 1);
+ char *buf;
-static void __i915_error_advance(struct drm_i915_error_state_buf *e,
- unsigned len)
-{
- /* If this is first printf in this window, adjust it so that
- * start position matches start of the buffer
- */
+ GEM_BUG_ON(size <= e->size);
- if (e->pos < e->start) {
- const size_t off = e->start - e->pos;
-
- /* Should not happen but be paranoid */
- if (off > len || e->bytes) {
- e->err = -EIO;
- return;
+ buf = kvmalloc(size, GFP_KERNEL);
+ if (!buf) {
+ e->err = -ENOMEM;
+ return false;
}
- memmove(e->buf, e->buf + off, len - off);
- e->bytes = len - off;
- e->pos = e->start;
- return;
+ GEM_BUG_ON(e->bytes > size);
+ memcpy(buf, e->buf, e->bytes);
+ kvfree(e->buf);
+
+ e->buf = buf;
+ e->size = size;
}
- e->bytes += len;
- e->pos += len;
+ return true;
}
__printf(2, 0)
static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
- const char *f, va_list args)
+ const char *fmt, va_list args)
{
- unsigned len;
+ va_list ap;
+ int len;
- if (!__i915_error_ok(e))
+ if (e->err)
return;
- /* Seek the first printf which is hits start position */
- if (e->pos < e->start) {
- va_list tmp;
-
- va_copy(tmp, args);
- len = vsnprintf(NULL, 0, f, tmp);
- va_end(tmp);
-
- if (!__i915_error_seek(e, len))
- return;
+ va_copy(ap, args);
+ len = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+ if (len <= 0) {
+ e->err = len;
+ return;
}
- len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
- if (len >= e->size - e->bytes)
- len = e->size - e->bytes - 1;
+ if (!__i915_error_grow(e, len))
+ return;
- __i915_error_advance(e, len);
+ GEM_BUG_ON(e->bytes >= e->size);
+ len = vscnprintf(e->buf + e->bytes, e->size - e->bytes, fmt, args);
+ if (len < 0) {
+ e->err = len;
+ return;
+ }
+ e->bytes += len;
}
-static void i915_error_puts(struct drm_i915_error_state_buf *e,
- const char *str)
+static void i915_error_puts(struct drm_i915_error_state_buf *e, const char *str)
{
unsigned len;
- if (!__i915_error_ok(e))
+ if (e->err || !str)
return;
len = strlen(str);
+ if (!__i915_error_grow(e, len))
+ return;
- /* Seek the first printf which is hits start position */
- if (e->pos < e->start) {
- if (!__i915_error_seek(e, len))
- return;
- }
-
- if (len >= e->size - e->bytes)
- len = e->size - e->bytes - 1;
+ GEM_BUG_ON(e->bytes + len > e->size);
memcpy(e->buf + e->bytes, str, len);
-
- __i915_error_advance(e, len);
+ e->bytes += len;
}
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
@@ -258,6 +224,8 @@ static int compress_page(struct compress *c,
if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK)
return -EIO;
+
+ touch_nmi_watchdog();
} while (zstream->avail_in);
/* Fallback to uncompressed if we increase size? */
@@ -623,33 +591,43 @@ static void err_print_uc(struct drm_i915_error_state_buf *m,
print_error_obj(m, NULL, "GuC log buffer", error_uc->guc_log);
}
-int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
- const struct i915_gpu_state *error)
+int i915_error_state_to_str(struct i915_gpu_state *error,
+ const char **str, size_t *len)
{
- struct drm_i915_private *dev_priv = m->i915;
+ struct drm_i915_error_state_buf m;
struct drm_i915_error_object *obj;
struct timespec64 ts;
int i, j;
if (!error) {
- err_printf(m, "No error state collected\n");
+ *str = "No error state collected\n";
+ *len = strlen(*str);
return 0;
}
+ *str = READ_ONCE(error->buf);
+ if (*str) {
+ *len = error->bytes;
+ return 0;
+ }
+
+ memset(&m, 0, sizeof(m));
+ m.i915 = error->i915;
+
if (*error->error_msg)
- err_printf(m, "%s\n", error->error_msg);
- err_printf(m, "Kernel: " UTS_RELEASE "\n");
+ err_printf(&m, "%s\n", error->error_msg);
+ err_printf(&m, "Kernel: " UTS_RELEASE "\n");
ts = ktime_to_timespec64(error->time);
- err_printf(m, "Time: %lld s %ld us\n",
+ err_printf(&m, "Time: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
ts = ktime_to_timespec64(error->boottime);
- err_printf(m, "Boottime: %lld s %ld us\n",
+ err_printf(&m, "Boottime: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
ts = ktime_to_timespec64(error->uptime);
- err_printf(m, "Uptime: %lld s %ld us\n",
+ err_printf(&m, "Uptime: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
- err_printf(m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ);
- err_printf(m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n",
+ err_printf(&m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ);
+ err_printf(&m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n",
error->capture,
jiffies_to_msecs(jiffies - error->capture),
jiffies_to_msecs(error->capture - error->epoch));
@@ -657,63 +635,63 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].hangcheck_stalled &&
error->engine[i].context.pid) {
- err_printf(m, "Active process (on ring %s): %s [%d], score %d%s\n",
- engine_name(m->i915, i),
+ err_printf(&m, "Active process (on ring %s): %s [%d], score %d%s\n",
+ engine_name(m.i915, i),
error->engine[i].context.comm,
error->engine[i].context.pid,
error->engine[i].context.ban_score,
bannable(&error->engine[i].context));
}
}
- err_printf(m, "Reset count: %u\n", error->reset_count);
- err_printf(m, "Suspend count: %u\n", error->suspend_count);
- err_printf(m, "Platform: %s\n", intel_platform_name(error->device_info.platform));
- err_print_pciid(m, error->i915);
+ err_printf(&m, "Reset count: %u\n", error->reset_count);
+ err_printf(&m, "Suspend count: %u\n", error->suspend_count);
+ err_printf(&m, "Platform: %s\n", intel_platform_name(error->device_info.platform));
+ err_print_pciid(&m, m.i915);
- err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
+ err_printf(&m, "IOMMU enabled?: %d\n", error->iommu);
- if (HAS_CSR(dev_priv)) {
- struct intel_csr *csr = &dev_priv->csr;
+ if (HAS_CSR(m.i915)) {
+ struct intel_csr *csr = &m.i915->csr;
- err_printf(m, "DMC loaded: %s\n",
+ err_printf(&m, "DMC loaded: %s\n",
yesno(csr->dmc_payload != NULL));
- err_printf(m, "DMC fw version: %d.%d\n",
+ err_printf(&m, "DMC fw version: %d.%d\n",
CSR_VERSION_MAJOR(csr->version),
CSR_VERSION_MINOR(csr->version));
}
- err_printf(m, "GT awake: %s\n", yesno(error->awake));
- err_printf(m, "RPM wakelock: %s\n", yesno(error->wakelock));
- err_printf(m, "PM suspended: %s\n", yesno(error->suspended));
- err_printf(m, "EIR: 0x%08x\n", error->eir);
- err_printf(m, "IER: 0x%08x\n", error->ier);
+ err_printf(&m, "GT awake: %s\n", yesno(error->awake));
+ err_printf(&m, "RPM wakelock: %s\n", yesno(error->wakelock));
+ err_printf(&m, "PM suspended: %s\n", yesno(error->suspended));
+ err_printf(&m, "EIR: 0x%08x\n", error->eir);
+ err_printf(&m, "IER: 0x%08x\n", error->ier);
for (i = 0; i < error->ngtier; i++)
- err_printf(m, "GTIER[%d]: 0x%08x\n", i, error->gtier[i]);
- err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
- err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
- err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
- err_printf(m, "CCID: 0x%08x\n", error->ccid);
- err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings);
+ err_printf(&m, "GTIER[%d]: 0x%08x\n", i, error->gtier[i]);
+ err_printf(&m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+ err_printf(&m, "FORCEWAKE: 0x%08x\n", error->forcewake);
+ err_printf(&m, "DERRMR: 0x%08x\n", error->derrmr);
+ err_printf(&m, "CCID: 0x%08x\n", error->ccid);
+ err_printf(&m, "Missed interrupts: 0x%08lx\n", m.i915->gpu_error.missed_irq_rings);
for (i = 0; i < error->nfence; i++)
- err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]);
+ err_printf(&m, " fence[%d] = %08llx\n", i, error->fence[i]);
- if (INTEL_GEN(dev_priv) >= 6) {
- err_printf(m, "ERROR: 0x%08x\n", error->error);
+ if (INTEL_GEN(m.i915) >= 6) {
+ err_printf(&m, "ERROR: 0x%08x\n", error->error);
- if (INTEL_GEN(dev_priv) >= 8)
- err_printf(m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
+ if (INTEL_GEN(m.i915) >= 8)
+ err_printf(&m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
error->fault_data1, error->fault_data0);
- err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
+ err_printf(&m, "DONE_REG: 0x%08x\n", error->done_reg);
}
- if (IS_GEN7(dev_priv))
- err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
+ if (IS_GEN7(m.i915))
+ err_printf(&m, "ERR_INT: 0x%08x\n", error->err_int);
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].engine_id != -1)
- error_print_engine(m, &error->engine[i], error->epoch);
+ error_print_engine(&m, &error->engine[i], error->epoch);
}
for (i = 0; i < ARRAY_SIZE(error->active_vm); i++) {
@@ -730,16 +708,16 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
len += scnprintf(buf + len, sizeof(buf), "%s%s",
first ? "" : ", ",
- dev_priv->engine[j]->name);
+ m.i915->engine[j]->name);
first = 0;
}
scnprintf(buf + len, sizeof(buf), ")");
- print_error_buffers(m, buf,
+ print_error_buffers(&m, buf,
error->active_bo[i],
error->active_bo_count[i]);
}
- print_error_buffers(m, "Pinned (global)",
+ print_error_buffers(&m, "Pinned (global)",
error->pinned_bo,
error->pinned_bo_count);
@@ -748,114 +726,90 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
obj = ee->batchbuffer;
if (obj) {
- err_puts(m, dev_priv->engine[i]->name);
+ err_puts(&m, m.i915->engine[i]->name);
if (ee->context.pid)
- err_printf(m, " (submitted by %s [%d], ctx %d [%d], score %d%s)",
+ err_printf(&m, " (submitted by %s [%d], ctx %d [%d], score %d%s)",
ee->context.comm,
ee->context.pid,
ee->context.handle,
ee->context.hw_id,
ee->context.ban_score,
bannable(&ee->context));
- err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
+ err_printf(&m, " --- gtt_offset = 0x%08x %08x\n",
upper_32_bits(obj->gtt_offset),
lower_32_bits(obj->gtt_offset));
- print_error_obj(m, dev_priv->engine[i], NULL, obj);
+ print_error_obj(&m, m.i915->engine[i], NULL, obj);
}
for (j = 0; j < ee->user_bo_count; j++)
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"user", ee->user_bo[j]);
if (ee->num_requests) {
- err_printf(m, "%s --- %d requests\n",
- dev_priv->engine[i]->name,
+ err_printf(&m, "%s --- %d requests\n",
+ m.i915->engine[i]->name,
ee->num_requests);
for (j = 0; j < ee->num_requests; j++)
- error_print_request(m, " ",
+ error_print_request(&m, " ",
&ee->requests[j],
error->epoch);
}
if (IS_ERR(ee->waiters)) {
- err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n",
- dev_priv->engine[i]->name);
+ err_printf(&m, "%s --- ? waiters [unable to acquire spinlock]\n",
+ m.i915->engine[i]->name);
} else if (ee->num_waiters) {
- err_printf(m, "%s --- %d waiters\n",
- dev_priv->engine[i]->name,
+ err_printf(&m, "%s --- %d waiters\n",
+ m.i915->engine[i]->name,
ee->num_waiters);
for (j = 0; j < ee->num_waiters; j++) {
- err_printf(m, " seqno 0x%08x for %s [%d]\n",
+ err_printf(&m, " seqno 0x%08x for %s [%d]\n",
ee->waiters[j].seqno,
ee->waiters[j].comm,
ee->waiters[j].pid);
}
}
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"ringbuffer", ee->ringbuffer);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"HW Status", ee->hws_page);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"HW context", ee->ctx);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"WA context", ee->wa_ctx);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"WA batchbuffer", ee->wa_batchbuffer);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"NULL context", ee->default_state);
}
if (error->overlay)
- intel_overlay_print_error_state(m, error->overlay);
+ intel_overlay_print_error_state(&m, error->overlay);
if (error->display)
- intel_display_print_error_state(m, error->display);
-
- err_print_capabilities(m, &error->device_info, &error->driver_caps);
- err_print_params(m, &error->params);
- err_print_uc(m, &error->uc);
+ intel_display_print_error_state(&m, error->display);
- if (m->bytes == 0 && m->err)
- return m->err;
-
- return 0;
-}
-
-int i915_error_state_buf_init(struct drm_i915_error_state_buf *ebuf,
- struct drm_i915_private *i915,
- size_t count, loff_t pos)
-{
- memset(ebuf, 0, sizeof(*ebuf));
- ebuf->i915 = i915;
+ err_print_capabilities(&m, &error->device_info, &error->driver_caps);
+ err_print_params(&m, &error->params);
+ err_print_uc(&m, &error->uc);
- /* We need to have enough room to store any i915_error_state printf
- * so that we can move it to start position.
- */
- ebuf->size = count + 1 > PAGE_SIZE ? count + 1 : PAGE_SIZE;
- ebuf->buf = kmalloc(ebuf->size,
- GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
-
- if (ebuf->buf == NULL) {
- ebuf->size = PAGE_SIZE;
- ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
- }
-
- if (ebuf->buf == NULL) {
- ebuf->size = 128;
- ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
+ if (m.err) {
+ kvfree(m.buf);
+ return m.err;
}
- if (ebuf->buf == NULL)
- return -ENOMEM;
-
- ebuf->start = pos;
+ error->bytes = m.bytes;
+ if (cmpxchg(&error->buf, NULL, m.buf))
+ kvfree(m.buf);
+ *len = error->bytes;
+ *str = error->buf;
return 0;
}
@@ -929,6 +883,7 @@ void __i915_gpu_state_free(struct kref *error_ref)
cleanup_params(error);
cleanup_uc_state(error);
+ kvfree(error->buf);
kfree(error);
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h
index f893a4e8b783..aa4e2d8893a1 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.h
+++ b/drivers/gpu/drm/i915/i915_gpu_error.h
@@ -9,6 +9,7 @@
#include <linux/kref.h>
#include <linux/ktime.h>
+#include <linux/nmi.h>
#include <linux/sched.h>
#include <drm/drm_mm.h>
@@ -191,6 +192,9 @@ struct i915_gpu_state {
} *active_bo[I915_NUM_ENGINES], *pinned_bo;
u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count;
struct i915_address_space *active_vm[I915_NUM_ENGINES];
+
+ const char *buf;
+ size_t bytes;
};
struct i915_gpu_error {
@@ -297,29 +301,19 @@ struct i915_gpu_error {
struct drm_i915_error_state_buf {
struct drm_i915_private *i915;
- unsigned int bytes;
- unsigned int size;
+ char *buf;
+
+ size_t bytes;
+ size_t size;
int err;
- u8 *buf;
- loff_t start;
- loff_t pos;
};
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
__printf(2, 3)
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
-int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
- const struct i915_gpu_state *gpu);
-int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb,
- struct drm_i915_private *i915,
- size_t count, loff_t pos);
-
-static inline void
-i915_error_state_buf_release(struct drm_i915_error_state_buf *eb)
-{
- kfree(eb->buf);
-}
+int i915_error_state_to_str(struct i915_gpu_state *error,
+ const char **str, size_t *len);
struct i915_gpu_state *i915_capture_gpu_state(struct drm_i915_private *i915);
void i915_capture_error_state(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index e5e6f6bb2b05..a0d54eb48700 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -516,27 +516,21 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
{
struct device *kdev = kobj_to_dev(kobj);
- struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
- struct drm_i915_error_state_buf error_str;
- struct i915_gpu_state *gpu;
+ struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
+ struct i915_gpu_state *gpu = i915_first_error_state(i915);
+ const char *error_str;
+ size_t error_len;
ssize_t ret;
- ret = i915_error_state_buf_init(&error_str, dev_priv, count, off);
- if (ret)
- return ret;
-
- gpu = i915_first_error_state(dev_priv);
- ret = i915_error_state_to_str(&error_str, gpu);
+ ret = i915_error_state_to_str(gpu, &error_str, &error_len);
if (ret)
goto out;
- ret = count < error_str.bytes ? count : error_str.bytes;
- memcpy(buf, error_str.buf, ret);
+ ret = min_t(size_t, count, error_len - off);
+ memcpy(buf, error_str + off, ret);
out:
i915_gpu_state_put(gpu);
- i915_error_state_buf_release(&error_str);
-
return ret;
}
--
2.18.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH] drm/i915: Cache the error string
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
@ 2018-07-18 10:36 ` Chris Wilson
2018-07-18 10:38 ` ✗ Fi.CI.SPARSE: warning for " Patchwork
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chris Wilson @ 2018-07-18 10:36 UTC (permalink / raw)
To: intel-gfx
Currently, we convert the error state into a string every time we read
from sysfs (and sysfs reads in page size (4KiB) chunks). We do try to
window the string and only capture the portion that is being read, but
that means that we must always convert up to the window to find the
start. For a very large error state bordering on EXEC_OBJECT_CAPTURE
abuse, this is noticeable as it degrades to O(N^2)!
As we do not have a convenient hook for sysfs open(), and we would like
to keep the lazy conversion into a string, do the conversion of the
whole string on the first read and keep the string until the error state
is freed.
v2: Don't double advance simple_read_from_buffer
Reported-by: Jason Ekstrand <jason@jlekstrand.net>
Testcase: igt/gem_exec_capture/many*
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Jason Ekstrand <jason@jlekstrand.net>
---
drivers/gpu/drm/i915/i915_debugfs.c | 22 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 309 +++++++++++---------------
drivers/gpu/drm/i915/i915_gpu_error.h | 26 +--
drivers/gpu/drm/i915/i915_sysfs.c | 20 +-
4 files changed, 154 insertions(+), 223 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 54509e44a856..095028894064 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -944,30 +944,18 @@ static ssize_t gpu_state_read(struct file *file, char __user *ubuf,
size_t count, loff_t *pos)
{
struct i915_gpu_state *error = file->private_data;
- struct drm_i915_error_state_buf str;
- ssize_t ret;
- loff_t tmp;
+ const char *error_str;
+ size_t error_len;
+ int ret;
if (!error)
return 0;
- ret = i915_error_state_buf_init(&str, error->i915, count, *pos);
+ ret = i915_error_state_to_str(error, &error_str, &error_len);
if (ret)
return ret;
- ret = i915_error_state_to_str(&str, error);
- if (ret)
- goto out;
-
- tmp = 0;
- ret = simple_read_from_buffer(ubuf, count, &tmp, str.buf, str.bytes);
- if (ret < 0)
- goto out;
-
- *pos = str.start + ret;
-out:
- i915_error_state_buf_release(&str);
- return ret;
+ return simple_read_from_buffer(ubuf, count, pos, error_str, error_len);
}
static int gpu_state_release(struct inode *inode, struct file *file)
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 8c81cf3aa182..4e8f1bbdbb07 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -76,112 +76,78 @@ static const char *purgeable_flag(int purgeable)
return purgeable ? " purgeable" : "";
}
-static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
+static bool __i915_error_grow(struct drm_i915_error_state_buf *e, size_t len)
{
-
- if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
- e->err = -ENOSPC;
- return false;
- }
-
- if (e->bytes == e->size - 1 || e->err)
- return false;
-
- return true;
-}
-
-static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
- unsigned len)
-{
- if (e->pos + len <= e->start) {
- e->pos += len;
+ if (!len)
return false;
- }
-
- /* First vsnprintf needs to fit in its entirety for memmove */
- if (len >= e->size) {
- e->err = -EIO;
- return false;
- }
- return true;
-}
+ if (e->bytes + len + 1 > e->size) {
+ size_t size = PAGE_ALIGN(e->bytes + len + 1);
+ char *buf;
-static void __i915_error_advance(struct drm_i915_error_state_buf *e,
- unsigned len)
-{
- /* If this is first printf in this window, adjust it so that
- * start position matches start of the buffer
- */
+ GEM_BUG_ON(size <= e->size);
- if (e->pos < e->start) {
- const size_t off = e->start - e->pos;
-
- /* Should not happen but be paranoid */
- if (off > len || e->bytes) {
- e->err = -EIO;
- return;
+ buf = kvmalloc(size, GFP_KERNEL);
+ if (!buf) {
+ e->err = -ENOMEM;
+ return false;
}
- memmove(e->buf, e->buf + off, len - off);
- e->bytes = len - off;
- e->pos = e->start;
- return;
+ GEM_BUG_ON(e->bytes > size);
+ memcpy(buf, e->buf, e->bytes);
+ kvfree(e->buf);
+
+ e->buf = buf;
+ e->size = size;
}
- e->bytes += len;
- e->pos += len;
+ return true;
}
__printf(2, 0)
static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
- const char *f, va_list args)
+ const char *fmt, va_list args)
{
- unsigned len;
+ va_list ap;
+ int len;
- if (!__i915_error_ok(e))
+ if (e->err)
return;
- /* Seek the first printf which is hits start position */
- if (e->pos < e->start) {
- va_list tmp;
-
- va_copy(tmp, args);
- len = vsnprintf(NULL, 0, f, tmp);
- va_end(tmp);
-
- if (!__i915_error_seek(e, len))
- return;
+ va_copy(ap, args);
+ len = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+ if (len <= 0) {
+ e->err = len;
+ return;
}
- len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
- if (len >= e->size - e->bytes)
- len = e->size - e->bytes - 1;
+ if (!__i915_error_grow(e, len))
+ return;
- __i915_error_advance(e, len);
+ GEM_BUG_ON(e->bytes >= e->size);
+ len = vscnprintf(e->buf + e->bytes, e->size - e->bytes, fmt, args);
+ if (len < 0) {
+ e->err = len;
+ return;
+ }
+ e->bytes += len;
}
-static void i915_error_puts(struct drm_i915_error_state_buf *e,
- const char *str)
+static void i915_error_puts(struct drm_i915_error_state_buf *e, const char *str)
{
unsigned len;
- if (!__i915_error_ok(e))
+ if (e->err || !str)
return;
len = strlen(str);
+ if (!__i915_error_grow(e, len))
+ return;
- /* Seek the first printf which is hits start position */
- if (e->pos < e->start) {
- if (!__i915_error_seek(e, len))
- return;
- }
-
- if (len >= e->size - e->bytes)
- len = e->size - e->bytes - 1;
+ GEM_BUG_ON(e->bytes + len > e->size);
memcpy(e->buf + e->bytes, str, len);
-
- __i915_error_advance(e, len);
+ e->bytes += len;
}
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
@@ -258,6 +224,8 @@ static int compress_page(struct compress *c,
if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK)
return -EIO;
+
+ touch_nmi_watchdog();
} while (zstream->avail_in);
/* Fallback to uncompressed if we increase size? */
@@ -623,33 +591,43 @@ static void err_print_uc(struct drm_i915_error_state_buf *m,
print_error_obj(m, NULL, "GuC log buffer", error_uc->guc_log);
}
-int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
- const struct i915_gpu_state *error)
+int i915_error_state_to_str(struct i915_gpu_state *error,
+ const char **str, size_t *len)
{
- struct drm_i915_private *dev_priv = m->i915;
+ struct drm_i915_error_state_buf m;
struct drm_i915_error_object *obj;
struct timespec64 ts;
int i, j;
if (!error) {
- err_printf(m, "No error state collected\n");
+ *str = "No error state collected\n";
+ *len = strlen(*str);
return 0;
}
+ *str = READ_ONCE(error->buf);
+ if (*str) {
+ *len = error->bytes;
+ return 0;
+ }
+
+ memset(&m, 0, sizeof(m));
+ m.i915 = error->i915;
+
if (*error->error_msg)
- err_printf(m, "%s\n", error->error_msg);
- err_printf(m, "Kernel: " UTS_RELEASE "\n");
+ err_printf(&m, "%s\n", error->error_msg);
+ err_printf(&m, "Kernel: " UTS_RELEASE "\n");
ts = ktime_to_timespec64(error->time);
- err_printf(m, "Time: %lld s %ld us\n",
+ err_printf(&m, "Time: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
ts = ktime_to_timespec64(error->boottime);
- err_printf(m, "Boottime: %lld s %ld us\n",
+ err_printf(&m, "Boottime: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
ts = ktime_to_timespec64(error->uptime);
- err_printf(m, "Uptime: %lld s %ld us\n",
+ err_printf(&m, "Uptime: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
- err_printf(m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ);
- err_printf(m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n",
+ err_printf(&m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ);
+ err_printf(&m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n",
error->capture,
jiffies_to_msecs(jiffies - error->capture),
jiffies_to_msecs(error->capture - error->epoch));
@@ -657,63 +635,63 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].hangcheck_stalled &&
error->engine[i].context.pid) {
- err_printf(m, "Active process (on ring %s): %s [%d], score %d%s\n",
- engine_name(m->i915, i),
+ err_printf(&m, "Active process (on ring %s): %s [%d], score %d%s\n",
+ engine_name(m.i915, i),
error->engine[i].context.comm,
error->engine[i].context.pid,
error->engine[i].context.ban_score,
bannable(&error->engine[i].context));
}
}
- err_printf(m, "Reset count: %u\n", error->reset_count);
- err_printf(m, "Suspend count: %u\n", error->suspend_count);
- err_printf(m, "Platform: %s\n", intel_platform_name(error->device_info.platform));
- err_print_pciid(m, error->i915);
+ err_printf(&m, "Reset count: %u\n", error->reset_count);
+ err_printf(&m, "Suspend count: %u\n", error->suspend_count);
+ err_printf(&m, "Platform: %s\n", intel_platform_name(error->device_info.platform));
+ err_print_pciid(&m, m.i915);
- err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
+ err_printf(&m, "IOMMU enabled?: %d\n", error->iommu);
- if (HAS_CSR(dev_priv)) {
- struct intel_csr *csr = &dev_priv->csr;
+ if (HAS_CSR(m.i915)) {
+ struct intel_csr *csr = &m.i915->csr;
- err_printf(m, "DMC loaded: %s\n",
+ err_printf(&m, "DMC loaded: %s\n",
yesno(csr->dmc_payload != NULL));
- err_printf(m, "DMC fw version: %d.%d\n",
+ err_printf(&m, "DMC fw version: %d.%d\n",
CSR_VERSION_MAJOR(csr->version),
CSR_VERSION_MINOR(csr->version));
}
- err_printf(m, "GT awake: %s\n", yesno(error->awake));
- err_printf(m, "RPM wakelock: %s\n", yesno(error->wakelock));
- err_printf(m, "PM suspended: %s\n", yesno(error->suspended));
- err_printf(m, "EIR: 0x%08x\n", error->eir);
- err_printf(m, "IER: 0x%08x\n", error->ier);
+ err_printf(&m, "GT awake: %s\n", yesno(error->awake));
+ err_printf(&m, "RPM wakelock: %s\n", yesno(error->wakelock));
+ err_printf(&m, "PM suspended: %s\n", yesno(error->suspended));
+ err_printf(&m, "EIR: 0x%08x\n", error->eir);
+ err_printf(&m, "IER: 0x%08x\n", error->ier);
for (i = 0; i < error->ngtier; i++)
- err_printf(m, "GTIER[%d]: 0x%08x\n", i, error->gtier[i]);
- err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
- err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
- err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
- err_printf(m, "CCID: 0x%08x\n", error->ccid);
- err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings);
+ err_printf(&m, "GTIER[%d]: 0x%08x\n", i, error->gtier[i]);
+ err_printf(&m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+ err_printf(&m, "FORCEWAKE: 0x%08x\n", error->forcewake);
+ err_printf(&m, "DERRMR: 0x%08x\n", error->derrmr);
+ err_printf(&m, "CCID: 0x%08x\n", error->ccid);
+ err_printf(&m, "Missed interrupts: 0x%08lx\n", m.i915->gpu_error.missed_irq_rings);
for (i = 0; i < error->nfence; i++)
- err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]);
+ err_printf(&m, " fence[%d] = %08llx\n", i, error->fence[i]);
- if (INTEL_GEN(dev_priv) >= 6) {
- err_printf(m, "ERROR: 0x%08x\n", error->error);
+ if (INTEL_GEN(m.i915) >= 6) {
+ err_printf(&m, "ERROR: 0x%08x\n", error->error);
- if (INTEL_GEN(dev_priv) >= 8)
- err_printf(m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
+ if (INTEL_GEN(m.i915) >= 8)
+ err_printf(&m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
error->fault_data1, error->fault_data0);
- err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
+ err_printf(&m, "DONE_REG: 0x%08x\n", error->done_reg);
}
- if (IS_GEN7(dev_priv))
- err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
+ if (IS_GEN7(m.i915))
+ err_printf(&m, "ERR_INT: 0x%08x\n", error->err_int);
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].engine_id != -1)
- error_print_engine(m, &error->engine[i], error->epoch);
+ error_print_engine(&m, &error->engine[i], error->epoch);
}
for (i = 0; i < ARRAY_SIZE(error->active_vm); i++) {
@@ -730,16 +708,16 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
len += scnprintf(buf + len, sizeof(buf), "%s%s",
first ? "" : ", ",
- dev_priv->engine[j]->name);
+ m.i915->engine[j]->name);
first = 0;
}
scnprintf(buf + len, sizeof(buf), ")");
- print_error_buffers(m, buf,
+ print_error_buffers(&m, buf,
error->active_bo[i],
error->active_bo_count[i]);
}
- print_error_buffers(m, "Pinned (global)",
+ print_error_buffers(&m, "Pinned (global)",
error->pinned_bo,
error->pinned_bo_count);
@@ -748,114 +726,90 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
obj = ee->batchbuffer;
if (obj) {
- err_puts(m, dev_priv->engine[i]->name);
+ err_puts(&m, m.i915->engine[i]->name);
if (ee->context.pid)
- err_printf(m, " (submitted by %s [%d], ctx %d [%d], score %d%s)",
+ err_printf(&m, " (submitted by %s [%d], ctx %d [%d], score %d%s)",
ee->context.comm,
ee->context.pid,
ee->context.handle,
ee->context.hw_id,
ee->context.ban_score,
bannable(&ee->context));
- err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
+ err_printf(&m, " --- gtt_offset = 0x%08x %08x\n",
upper_32_bits(obj->gtt_offset),
lower_32_bits(obj->gtt_offset));
- print_error_obj(m, dev_priv->engine[i], NULL, obj);
+ print_error_obj(&m, m.i915->engine[i], NULL, obj);
}
for (j = 0; j < ee->user_bo_count; j++)
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"user", ee->user_bo[j]);
if (ee->num_requests) {
- err_printf(m, "%s --- %d requests\n",
- dev_priv->engine[i]->name,
+ err_printf(&m, "%s --- %d requests\n",
+ m.i915->engine[i]->name,
ee->num_requests);
for (j = 0; j < ee->num_requests; j++)
- error_print_request(m, " ",
+ error_print_request(&m, " ",
&ee->requests[j],
error->epoch);
}
if (IS_ERR(ee->waiters)) {
- err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n",
- dev_priv->engine[i]->name);
+ err_printf(&m, "%s --- ? waiters [unable to acquire spinlock]\n",
+ m.i915->engine[i]->name);
} else if (ee->num_waiters) {
- err_printf(m, "%s --- %d waiters\n",
- dev_priv->engine[i]->name,
+ err_printf(&m, "%s --- %d waiters\n",
+ m.i915->engine[i]->name,
ee->num_waiters);
for (j = 0; j < ee->num_waiters; j++) {
- err_printf(m, " seqno 0x%08x for %s [%d]\n",
+ err_printf(&m, " seqno 0x%08x for %s [%d]\n",
ee->waiters[j].seqno,
ee->waiters[j].comm,
ee->waiters[j].pid);
}
}
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"ringbuffer", ee->ringbuffer);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"HW Status", ee->hws_page);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"HW context", ee->ctx);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"WA context", ee->wa_ctx);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"WA batchbuffer", ee->wa_batchbuffer);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"NULL context", ee->default_state);
}
if (error->overlay)
- intel_overlay_print_error_state(m, error->overlay);
+ intel_overlay_print_error_state(&m, error->overlay);
if (error->display)
- intel_display_print_error_state(m, error->display);
-
- err_print_capabilities(m, &error->device_info, &error->driver_caps);
- err_print_params(m, &error->params);
- err_print_uc(m, &error->uc);
+ intel_display_print_error_state(&m, error->display);
- if (m->bytes == 0 && m->err)
- return m->err;
-
- return 0;
-}
-
-int i915_error_state_buf_init(struct drm_i915_error_state_buf *ebuf,
- struct drm_i915_private *i915,
- size_t count, loff_t pos)
-{
- memset(ebuf, 0, sizeof(*ebuf));
- ebuf->i915 = i915;
+ err_print_capabilities(&m, &error->device_info, &error->driver_caps);
+ err_print_params(&m, &error->params);
+ err_print_uc(&m, &error->uc);
- /* We need to have enough room to store any i915_error_state printf
- * so that we can move it to start position.
- */
- ebuf->size = count + 1 > PAGE_SIZE ? count + 1 : PAGE_SIZE;
- ebuf->buf = kmalloc(ebuf->size,
- GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
-
- if (ebuf->buf == NULL) {
- ebuf->size = PAGE_SIZE;
- ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
- }
-
- if (ebuf->buf == NULL) {
- ebuf->size = 128;
- ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
+ if (m.err) {
+ kvfree(m.buf);
+ return m.err;
}
- if (ebuf->buf == NULL)
- return -ENOMEM;
-
- ebuf->start = pos;
+ error->bytes = m.bytes;
+ if (cmpxchg(&error->buf, NULL, m.buf))
+ kvfree(m.buf);
+ *len = error->bytes;
+ *str = error->buf;
return 0;
}
@@ -929,6 +883,7 @@ void __i915_gpu_state_free(struct kref *error_ref)
cleanup_params(error);
cleanup_uc_state(error);
+ kvfree(error->buf);
kfree(error);
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h
index f893a4e8b783..aa4e2d8893a1 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.h
+++ b/drivers/gpu/drm/i915/i915_gpu_error.h
@@ -9,6 +9,7 @@
#include <linux/kref.h>
#include <linux/ktime.h>
+#include <linux/nmi.h>
#include <linux/sched.h>
#include <drm/drm_mm.h>
@@ -191,6 +192,9 @@ struct i915_gpu_state {
} *active_bo[I915_NUM_ENGINES], *pinned_bo;
u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count;
struct i915_address_space *active_vm[I915_NUM_ENGINES];
+
+ const char *buf;
+ size_t bytes;
};
struct i915_gpu_error {
@@ -297,29 +301,19 @@ struct i915_gpu_error {
struct drm_i915_error_state_buf {
struct drm_i915_private *i915;
- unsigned int bytes;
- unsigned int size;
+ char *buf;
+
+ size_t bytes;
+ size_t size;
int err;
- u8 *buf;
- loff_t start;
- loff_t pos;
};
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
__printf(2, 3)
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
-int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
- const struct i915_gpu_state *gpu);
-int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb,
- struct drm_i915_private *i915,
- size_t count, loff_t pos);
-
-static inline void
-i915_error_state_buf_release(struct drm_i915_error_state_buf *eb)
-{
- kfree(eb->buf);
-}
+int i915_error_state_to_str(struct i915_gpu_state *error,
+ const char **str, size_t *len);
struct i915_gpu_state *i915_capture_gpu_state(struct drm_i915_private *i915);
void i915_capture_error_state(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index e5e6f6bb2b05..a0d54eb48700 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -516,27 +516,21 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
{
struct device *kdev = kobj_to_dev(kobj);
- struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
- struct drm_i915_error_state_buf error_str;
- struct i915_gpu_state *gpu;
+ struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
+ struct i915_gpu_state *gpu = i915_first_error_state(i915);
+ const char *error_str;
+ size_t error_len;
ssize_t ret;
- ret = i915_error_state_buf_init(&error_str, dev_priv, count, off);
- if (ret)
- return ret;
-
- gpu = i915_first_error_state(dev_priv);
- ret = i915_error_state_to_str(&error_str, gpu);
+ ret = i915_error_state_to_str(gpu, &error_str, &error_len);
if (ret)
goto out;
- ret = count < error_str.bytes ? count : error_str.bytes;
- memcpy(buf, error_str.buf, ret);
+ ret = min_t(size_t, count, error_len - off);
+ memcpy(buf, error_str + off, ret);
out:
i915_gpu_state_put(gpu);
- i915_error_state_buf_release(&error_str);
-
return ret;
}
--
2.18.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread
* ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
2018-07-18 10:36 ` Chris Wilson
@ 2018-07-18 10:38 ` Patchwork
2018-07-18 10:59 ` ✓ Fi.CI.BAT: success " Patchwork
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-18 10:38 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string
URL : https://patchwork.freedesktop.org/series/46777/
State : warning
== Summary ==
$ dim sparse origin/drm-tip
Commit: drm/i915: Cache the error string
+drivers/gpu/drm/i915/i915_sysfs.c:529:15: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/i915_sysfs.c:529:15: warning: expression using sizeof(void)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* ✓ Fi.CI.BAT: success for drm/i915: Cache the error string
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
2018-07-18 10:36 ` Chris Wilson
2018-07-18 10:38 ` ✗ Fi.CI.SPARSE: warning for " Patchwork
@ 2018-07-18 10:59 ` Patchwork
2018-07-18 11:21 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev2) Patchwork
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-18 10:59 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string
URL : https://patchwork.freedesktop.org/series/46777/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4503 -> Patchwork_9703 =
== Summary - WARNING ==
Minor unknown changes coming with Patchwork_9703 need to be verified
manually.
If you think the reported changes have nothing to do with the changes
introduced in Patchwork_9703, please notify your bug team to allow them
to document this new failure mode, which will reduce false positives in CI.
External URL: https://patchwork.freedesktop.org/api/1.0/series/46777/revisions/1/mbox/
== Possible new issues ==
Here are the unknown changes that may have been introduced in Patchwork_9703:
=== IGT changes ===
==== Warnings ====
igt@gem_exec_gttfill@basic:
fi-pnv-d510: PASS -> SKIP
== Known issues ==
Here are the changes found in Patchwork_9703 that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@debugfs_test@read_all_entries:
fi-snb-2520m: PASS -> INCOMPLETE (fdo#103713)
igt@drv_selftest@live_hangcheck:
fi-skl-6260u: PASS -> DMESG-FAIL (fdo#107174, fdo#106560)
igt@gem_exec_suspend@basic-s4-devices:
fi-kbl-7500u: PASS -> DMESG-WARN (fdo#107139, fdo#105128)
{fi-kbl-8809g}: NOTRUN -> INCOMPLETE (fdo#107139)
igt@kms_frontbuffer_tracking@basic:
fi-hsw-peppy: PASS -> DMESG-FAIL (fdo#102614, fdo#106103)
==== Possible fixes ====
igt@drv_selftest@live_hangcheck:
fi-skl-guc: DMESG-FAIL (fdo#107174) -> PASS
{fi-cfl-8109u}: DMESG-FAIL (fdo#106560) -> PASS
igt@kms_chamelium@dp-crc-fast:
fi-kbl-7500u: FAIL (fdo#103841) -> PASS +1
igt@kms_flip@basic-flip-vs-dpms:
fi-skl-6700hq: DMESG-WARN (fdo#105998) -> PASS
{name}: This element is suppressed. This means it is ignored when computing
the status of the difference (SUCCESS, WARNING, or FAILURE).
fdo#102614 https://bugs.freedesktop.org/show_bug.cgi?id=102614
fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713
fdo#103841 https://bugs.freedesktop.org/show_bug.cgi?id=103841
fdo#105128 https://bugs.freedesktop.org/show_bug.cgi?id=105128
fdo#105998 https://bugs.freedesktop.org/show_bug.cgi?id=105998
fdo#106103 https://bugs.freedesktop.org/show_bug.cgi?id=106103
fdo#106560 https://bugs.freedesktop.org/show_bug.cgi?id=106560
fdo#107139 https://bugs.freedesktop.org/show_bug.cgi?id=107139
fdo#107174 https://bugs.freedesktop.org/show_bug.cgi?id=107174
== Participating hosts (46 -> 40) ==
Additional (1): fi-kbl-8809g
Missing (7): fi-ilk-m540 fi-hsw-4200u fi-bdw-gvtdvm fi-byt-squawks fi-bsw-cyan fi-ctg-p8600 fi-glk-j4005
== Build changes ==
* Linux: CI_DRM_4503 -> Patchwork_9703
CI_DRM_4503: 4aa6797dfafaf527949bf55d3c8513c6902dfec2 @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4562: 8781fd89a63eabed9359d02b50583cca67ff3673 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_9703: e92978803824794689ba2f25bed3fc9c9cfba505 @ git://anongit.freedesktop.org/gfx-ci/linux
== Linux commits ==
e92978803824 drm/i915: Cache the error string
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9703/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev2)
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (2 preceding siblings ...)
2018-07-18 10:59 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2018-07-18 11:21 ` Patchwork
2018-07-18 11:42 ` ✓ Fi.CI.BAT: success " Patchwork
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-18 11:21 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string (rev2)
URL : https://patchwork.freedesktop.org/series/46777/
State : warning
== Summary ==
$ dim sparse origin/drm-tip
Commit: drm/i915: Cache the error string
+drivers/gpu/drm/i915/i915_sysfs.c:529:15: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/i915_sysfs.c:529:15: warning: expression using sizeof(void)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* ✓ Fi.CI.BAT: success for drm/i915: Cache the error string (rev2)
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (3 preceding siblings ...)
2018-07-18 11:21 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev2) Patchwork
@ 2018-07-18 11:42 ` Patchwork
2018-07-18 14:35 ` ✓ Fi.CI.IGT: " Patchwork
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-18 11:42 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string (rev2)
URL : https://patchwork.freedesktop.org/series/46777/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4503 -> Patchwork_9704 =
== Summary - WARNING ==
Minor unknown changes coming with Patchwork_9704 need to be verified
manually.
If you think the reported changes have nothing to do with the changes
introduced in Patchwork_9704, please notify your bug team to allow them
to document this new failure mode, which will reduce false positives in CI.
External URL: https://patchwork.freedesktop.org/api/1.0/series/46777/revisions/2/mbox/
== Possible new issues ==
Here are the unknown changes that may have been introduced in Patchwork_9704:
=== IGT changes ===
==== Warnings ====
igt@gem_exec_gttfill@basic:
fi-pnv-d510: PASS -> SKIP
== Known issues ==
Here are the changes found in Patchwork_9704 that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@gem_exec_suspend@basic-s4-devices:
{fi-kbl-8809g}: NOTRUN -> INCOMPLETE (fdo#107139)
==== Possible fixes ====
igt@drv_selftest@live_hangcheck:
{fi-cfl-8109u}: DMESG-FAIL (fdo#106560) -> PASS
igt@drv_selftest@live_workarounds:
{fi-cfl-8109u}: DMESG-FAIL -> PASS
igt@kms_chamelium@dp-crc-fast:
fi-kbl-7500u: FAIL (fdo#103841) -> PASS +1
igt@kms_flip@basic-flip-vs-dpms:
fi-skl-6700hq: DMESG-WARN (fdo#105998) -> PASS
igt@kms_pipe_crc_basic@suspend-read-crc-pipe-b:
fi-snb-2520m: INCOMPLETE (fdo#103713) -> PASS
{name}: This element is suppressed. This means it is ignored when computing
the status of the difference (SUCCESS, WARNING, or FAILURE).
fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713
fdo#103841 https://bugs.freedesktop.org/show_bug.cgi?id=103841
fdo#105998 https://bugs.freedesktop.org/show_bug.cgi?id=105998
fdo#106560 https://bugs.freedesktop.org/show_bug.cgi?id=106560
fdo#107139 https://bugs.freedesktop.org/show_bug.cgi?id=107139
== Participating hosts (46 -> 41) ==
Additional (1): fi-kbl-8809g
Missing (6): fi-ilk-m540 fi-hsw-4200u fi-bdw-gvtdvm fi-byt-squawks fi-bsw-cyan fi-ctg-p8600
== Build changes ==
* Linux: CI_DRM_4503 -> Patchwork_9704
CI_DRM_4503: 4aa6797dfafaf527949bf55d3c8513c6902dfec2 @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4562: 8781fd89a63eabed9359d02b50583cca67ff3673 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_9704: 9553151b2427554125498f8f8e58bac314f5802f @ git://anongit.freedesktop.org/gfx-ci/linux
== Linux commits ==
9553151b2427 drm/i915: Cache the error string
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9704/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* ✓ Fi.CI.IGT: success for drm/i915: Cache the error string (rev2)
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (4 preceding siblings ...)
2018-07-18 11:42 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2018-07-18 14:35 ` Patchwork
2018-07-18 19:59 ` [PATCH v3] drm/i915: Cache the error string Chris Wilson
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-18 14:35 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string (rev2)
URL : https://patchwork.freedesktop.org/series/46777/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4503_full -> Patchwork_9704_full =
== Summary - WARNING ==
Minor unknown changes coming with Patchwork_9704_full need to be verified
manually.
If you think the reported changes have nothing to do with the changes
introduced in Patchwork_9704_full, please notify your bug team to allow them
to document this new failure mode, which will reduce false positives in CI.
== Possible new issues ==
Here are the unknown changes that may have been introduced in Patchwork_9704_full:
=== IGT changes ===
==== Warnings ====
igt@gem_mocs_settings@mocs-rc6-vebox:
shard-kbl: SKIP -> PASS +4
igt@kms_cursor_crc@cursor-64x64-offscreen:
shard-snb: SKIP -> PASS
igt@kms_frontbuffer_tracking@fbc-1p-primscrn-shrfb-plflip-blt:
shard-snb: PASS -> SKIP +2
== Known issues ==
Here are the changes found in Patchwork_9704_full that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@kms_frontbuffer_tracking@fbc-suspend:
shard-kbl: PASS -> INCOMPLETE (fdo#103665, fdo#105959)
igt@kms_vblank@pipe-b-query-forked-busy-hang:
shard-snb: PASS -> INCOMPLETE (fdo#105411)
==== Possible fixes ====
igt@gem_exec_big:
shard-hsw: INCOMPLETE (fdo#103540) -> PASS
shard-snb: INCOMPLETE (fdo#105411) -> PASS
igt@gem_exec_suspend@basic-s3:
shard-apl: FAIL (fdo#103375) -> PASS
igt@kms_flip@2x-flip-vs-expired-vblank:
shard-hsw: FAIL (fdo#105363) -> PASS
igt@kms_flip@flip-vs-expired-vblank-interruptible:
shard-apl: FAIL (fdo#102887, fdo#105363) -> PASS
igt@kms_flip@modeset-vs-vblank-race-interruptible:
shard-hsw: FAIL (fdo#103060) -> PASS
igt@kms_flip@plain-flip-ts-check-interruptible:
shard-glk: FAIL (fdo#100368) -> PASS
igt@kms_setmode@basic:
shard-kbl: FAIL (fdo#99912) -> PASS
fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#102887 https://bugs.freedesktop.org/show_bug.cgi?id=102887
fdo#103060 https://bugs.freedesktop.org/show_bug.cgi?id=103060
fdo#103375 https://bugs.freedesktop.org/show_bug.cgi?id=103375
fdo#103540 https://bugs.freedesktop.org/show_bug.cgi?id=103540
fdo#103665 https://bugs.freedesktop.org/show_bug.cgi?id=103665
fdo#105363 https://bugs.freedesktop.org/show_bug.cgi?id=105363
fdo#105411 https://bugs.freedesktop.org/show_bug.cgi?id=105411
fdo#105959 https://bugs.freedesktop.org/show_bug.cgi?id=105959
fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
== Participating hosts (5 -> 5) ==
No changes in participating hosts
== Build changes ==
* Linux: CI_DRM_4503 -> Patchwork_9704
CI_DRM_4503: 4aa6797dfafaf527949bf55d3c8513c6902dfec2 @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4562: 8781fd89a63eabed9359d02b50583cca67ff3673 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_9704: 9553151b2427554125498f8f8e58bac314f5802f @ git://anongit.freedesktop.org/gfx-ci/linux
piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9704/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v3] drm/i915: Cache the error string
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (5 preceding siblings ...)
2018-07-18 14:35 ` ✓ Fi.CI.IGT: " Patchwork
@ 2018-07-18 19:59 ` Chris Wilson
2018-07-18 20:28 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev3) Patchwork
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chris Wilson @ 2018-07-18 19:59 UTC (permalink / raw)
To: intel-gfx
Currently, we convert the error state into a string every time we read
from sysfs (and sysfs reads in page size (4KiB) chunks). We do try to
window the string and only capture the portion that is being read, but
that means that we must always convert up to the window to find the
start. For a very large error state bordering on EXEC_OBJECT_CAPTURE
abuse, this is noticeable as it degrades to O(N^2)!
As we do not have a convenient hook for sysfs open(), and we would like
to keep the lazy conversion into a string, do the conversion of the
whole string on the first read and keep the string until the error state
is freed.
v2: Don't double advance simple_read_from_buffer
v3: Due to extreme pain of lack of vrealloc, use a scatterlist
Reported-by: Jason Ekstrand <jason@jlekstrand.net>
Testcase: igt/gem_exec_capture/many*
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Jason Ekstrand <jason@jlekstrand.net>
---
drivers/gpu/drm/i915/i915_debugfs.c | 32 +--
drivers/gpu/drm/i915/i915_gpu_error.c | 394 +++++++++++++++-----------
drivers/gpu/drm/i915/i915_gpu_error.h | 28 +-
drivers/gpu/drm/i915/i915_sysfs.c | 27 +-
4 files changed, 265 insertions(+), 216 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 54509e44a856..8c9afe5487f2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -943,30 +943,28 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
static ssize_t gpu_state_read(struct file *file, char __user *ubuf,
size_t count, loff_t *pos)
{
- struct i915_gpu_state *error = file->private_data;
- struct drm_i915_error_state_buf str;
+ struct i915_gpu_state *error;
ssize_t ret;
- loff_t tmp;
+ void *buf;
+ error = file->private_data;
if (!error)
return 0;
- ret = i915_error_state_buf_init(&str, error->i915, count, *pos);
- if (ret)
- return ret;
-
- ret = i915_error_state_to_str(&str, error);
- if (ret)
- goto out;
+ /* Bounce buffer required because of kernfs __user API convenience. */
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- tmp = 0;
- ret = simple_read_from_buffer(ubuf, count, &tmp, str.buf, str.bytes);
- if (ret < 0)
- goto out;
+ ret = i915_gpu_state_copy_to_buffer(error, buf, *pos, count);
+ if (ret > 0) {
+ if (!copy_to_user(ubuf, buf, ret))
+ *pos += ret;
+ else
+ ret = -EFAULT;
+ }
- *pos = str.start + ret;
-out:
- i915_error_state_buf_release(&str);
+ kfree(buf);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 8c81cf3aa182..4be045c0fb1c 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -28,6 +28,7 @@
*/
#include <generated/utsrelease.h>
+#include <linux/scatterlist.h>
#include <linux/stop_machine.h>
#include <linux/zlib.h>
#include <drm/drm_print.h>
@@ -76,112 +77,107 @@ static const char *purgeable_flag(int purgeable)
return purgeable ? " purgeable" : "";
}
-static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
+static void __sg_set_buf(struct scatterlist *sg, void *addr, unsigned int len)
{
-
- if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
- e->err = -ENOSPC;
- return false;
- }
-
- if (e->bytes == e->size - 1 || e->err)
- return false;
-
- return true;
+ sg->page_link = (unsigned long)virt_to_page(addr);
+ sg->offset = offset_in_page(addr);
+ sg->length = len;
}
-static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
- unsigned len)
+static bool __i915_error_grow(struct drm_i915_error_state_buf *e, size_t len)
{
- if (e->pos + len <= e->start) {
- e->pos += len;
+ if (!len)
return false;
- }
- /* First vsnprintf needs to fit in its entirety for memmove */
- if (len >= e->size) {
- e->err = -EIO;
- return false;
- }
+ if (e->bytes + len + 1 > e->size) {
+ if (e->bytes) {
+ __sg_set_buf(e->cur++, e->buf, e->bytes);
+ e->buf = NULL;
+ e->bytes = 0;
+ }
- return true;
-}
+ if (e->cur == e->end) {
+ struct scatterlist *sgl;
-static void __i915_error_advance(struct drm_i915_error_state_buf *e,
- unsigned len)
-{
- /* If this is first printf in this window, adjust it so that
- * start position matches start of the buffer
- */
+ sgl = (typeof(sgl))__get_free_page(GFP_KERNEL);
+ if (!sgl) {
+ e->err = -ENOMEM;
+ return false;
+ }
- if (e->pos < e->start) {
- const size_t off = e->start - e->pos;
+ if (e->cur) {
+ e->cur->offset = 0;
+ e->cur->length = 0;
+ e->cur->page_link =
+ (unsigned long)sgl | SG_CHAIN;
+ } else {
+ e->sgl = sgl;
+ }
- /* Should not happen but be paranoid */
- if (off > len || e->bytes) {
- e->err = -EIO;
- return;
+ e->cur = sgl;
+ e->end = sgl + SG_MAX_SINGLE_ALLOC - 1;
}
- memmove(e->buf, e->buf + off, len - off);
- e->bytes = len - off;
- e->pos = e->start;
- return;
+ e->size = ALIGN(len + 1, SZ_64K);
+ e->buf = kmalloc(e->size,
+ GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+ if (!e->buf) {
+ e->size = PAGE_ALIGN(len + 1);
+ e->buf = kmalloc(e->size, GFP_KERNEL);
+ }
+ if (!e->buf) {
+ e->err = -ENOMEM;
+ return false;
+ }
}
- e->bytes += len;
- e->pos += len;
+ return true;
}
__printf(2, 0)
static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
- const char *f, va_list args)
+ const char *fmt, va_list args)
{
- unsigned len;
+ va_list ap;
+ int len;
- if (!__i915_error_ok(e))
+ if (e->err)
return;
- /* Seek the first printf which is hits start position */
- if (e->pos < e->start) {
- va_list tmp;
-
- va_copy(tmp, args);
- len = vsnprintf(NULL, 0, f, tmp);
- va_end(tmp);
-
- if (!__i915_error_seek(e, len))
- return;
+ va_copy(ap, args);
+ len = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+ if (len <= 0) {
+ e->err = len;
+ return;
}
- len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
- if (len >= e->size - e->bytes)
- len = e->size - e->bytes - 1;
+ if (!__i915_error_grow(e, len))
+ return;
- __i915_error_advance(e, len);
+ GEM_BUG_ON(e->bytes >= e->size);
+ len = vscnprintf(e->buf + e->bytes, e->size - e->bytes, fmt, args);
+ if (len < 0) {
+ e->err = len;
+ return;
+ }
+ e->bytes += len;
}
-static void i915_error_puts(struct drm_i915_error_state_buf *e,
- const char *str)
+static void i915_error_puts(struct drm_i915_error_state_buf *e, const char *str)
{
unsigned len;
- if (!__i915_error_ok(e))
+ if (e->err || !str)
return;
len = strlen(str);
+ if (!__i915_error_grow(e, len))
+ return;
- /* Seek the first printf which is hits start position */
- if (e->pos < e->start) {
- if (!__i915_error_seek(e, len))
- return;
- }
-
- if (len >= e->size - e->bytes)
- len = e->size - e->bytes - 1;
+ GEM_BUG_ON(e->bytes + len > e->size);
memcpy(e->buf + e->bytes, str, len);
-
- __i915_error_advance(e, len);
+ e->bytes += len;
}
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
@@ -258,6 +254,8 @@ static int compress_page(struct compress *c,
if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK)
return -EIO;
+
+ touch_nmi_watchdog();
} while (zstream->avail_in);
/* Fallback to uncompressed if we increase size? */
@@ -623,33 +621,50 @@ static void err_print_uc(struct drm_i915_error_state_buf *m,
print_error_obj(m, NULL, "GuC log buffer", error_uc->guc_log);
}
-int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
- const struct i915_gpu_state *error)
+static void err_free_sgl(struct scatterlist *sgl)
+{
+ while (sgl) {
+ struct scatterlist *sg;
+
+ for (sg = sgl; !sg_is_chain(sg); sg++) {
+ kfree(sg_virt(sg));
+ if (sg_is_last(sg))
+ break;
+ }
+
+ sg = sg_is_last(sg) ? NULL : sg_chain_ptr(sg);
+ free_page((unsigned long)sgl);
+ sgl = sg;
+ }
+}
+
+static int err_print_to_sgl(struct i915_gpu_state *error)
{
- struct drm_i915_private *dev_priv = m->i915;
+ struct drm_i915_error_state_buf m;
struct drm_i915_error_object *obj;
struct timespec64 ts;
int i, j;
- if (!error) {
- err_printf(m, "No error state collected\n");
+ if (READ_ONCE(error->sgl))
return 0;
- }
+
+ memset(&m, 0, sizeof(m));
+ m.i915 = error->i915;
if (*error->error_msg)
- err_printf(m, "%s\n", error->error_msg);
- err_printf(m, "Kernel: " UTS_RELEASE "\n");
+ err_printf(&m, "%s\n", error->error_msg);
+ err_printf(&m, "Kernel: " UTS_RELEASE "\n");
ts = ktime_to_timespec64(error->time);
- err_printf(m, "Time: %lld s %ld us\n",
+ err_printf(&m, "Time: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
ts = ktime_to_timespec64(error->boottime);
- err_printf(m, "Boottime: %lld s %ld us\n",
+ err_printf(&m, "Boottime: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
ts = ktime_to_timespec64(error->uptime);
- err_printf(m, "Uptime: %lld s %ld us\n",
+ err_printf(&m, "Uptime: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
- err_printf(m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ);
- err_printf(m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n",
+ err_printf(&m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ);
+ err_printf(&m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n",
error->capture,
jiffies_to_msecs(jiffies - error->capture),
jiffies_to_msecs(error->capture - error->epoch));
@@ -657,63 +672,63 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].hangcheck_stalled &&
error->engine[i].context.pid) {
- err_printf(m, "Active process (on ring %s): %s [%d], score %d%s\n",
- engine_name(m->i915, i),
+ err_printf(&m, "Active process (on ring %s): %s [%d], score %d%s\n",
+ engine_name(m.i915, i),
error->engine[i].context.comm,
error->engine[i].context.pid,
error->engine[i].context.ban_score,
bannable(&error->engine[i].context));
}
}
- err_printf(m, "Reset count: %u\n", error->reset_count);
- err_printf(m, "Suspend count: %u\n", error->suspend_count);
- err_printf(m, "Platform: %s\n", intel_platform_name(error->device_info.platform));
- err_print_pciid(m, error->i915);
+ err_printf(&m, "Reset count: %u\n", error->reset_count);
+ err_printf(&m, "Suspend count: %u\n", error->suspend_count);
+ err_printf(&m, "Platform: %s\n", intel_platform_name(error->device_info.platform));
+ err_print_pciid(&m, m.i915);
- err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
+ err_printf(&m, "IOMMU enabled?: %d\n", error->iommu);
- if (HAS_CSR(dev_priv)) {
- struct intel_csr *csr = &dev_priv->csr;
+ if (HAS_CSR(m.i915)) {
+ struct intel_csr *csr = &m.i915->csr;
- err_printf(m, "DMC loaded: %s\n",
+ err_printf(&m, "DMC loaded: %s\n",
yesno(csr->dmc_payload != NULL));
- err_printf(m, "DMC fw version: %d.%d\n",
+ err_printf(&m, "DMC fw version: %d.%d\n",
CSR_VERSION_MAJOR(csr->version),
CSR_VERSION_MINOR(csr->version));
}
- err_printf(m, "GT awake: %s\n", yesno(error->awake));
- err_printf(m, "RPM wakelock: %s\n", yesno(error->wakelock));
- err_printf(m, "PM suspended: %s\n", yesno(error->suspended));
- err_printf(m, "EIR: 0x%08x\n", error->eir);
- err_printf(m, "IER: 0x%08x\n", error->ier);
+ err_printf(&m, "GT awake: %s\n", yesno(error->awake));
+ err_printf(&m, "RPM wakelock: %s\n", yesno(error->wakelock));
+ err_printf(&m, "PM suspended: %s\n", yesno(error->suspended));
+ err_printf(&m, "EIR: 0x%08x\n", error->eir);
+ err_printf(&m, "IER: 0x%08x\n", error->ier);
for (i = 0; i < error->ngtier; i++)
- err_printf(m, "GTIER[%d]: 0x%08x\n", i, error->gtier[i]);
- err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
- err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
- err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
- err_printf(m, "CCID: 0x%08x\n", error->ccid);
- err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings);
+ err_printf(&m, "GTIER[%d]: 0x%08x\n", i, error->gtier[i]);
+ err_printf(&m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+ err_printf(&m, "FORCEWAKE: 0x%08x\n", error->forcewake);
+ err_printf(&m, "DERRMR: 0x%08x\n", error->derrmr);
+ err_printf(&m, "CCID: 0x%08x\n", error->ccid);
+ err_printf(&m, "Missed interrupts: 0x%08lx\n", m.i915->gpu_error.missed_irq_rings);
for (i = 0; i < error->nfence; i++)
- err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]);
+ err_printf(&m, " fence[%d] = %08llx\n", i, error->fence[i]);
- if (INTEL_GEN(dev_priv) >= 6) {
- err_printf(m, "ERROR: 0x%08x\n", error->error);
+ if (INTEL_GEN(m.i915) >= 6) {
+ err_printf(&m, "ERROR: 0x%08x\n", error->error);
- if (INTEL_GEN(dev_priv) >= 8)
- err_printf(m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
+ if (INTEL_GEN(m.i915) >= 8)
+ err_printf(&m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
error->fault_data1, error->fault_data0);
- err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
+ err_printf(&m, "DONE_REG: 0x%08x\n", error->done_reg);
}
- if (IS_GEN7(dev_priv))
- err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
+ if (IS_GEN7(m.i915))
+ err_printf(&m, "ERR_INT: 0x%08x\n", error->err_int);
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].engine_id != -1)
- error_print_engine(m, &error->engine[i], error->epoch);
+ error_print_engine(&m, &error->engine[i], error->epoch);
}
for (i = 0; i < ARRAY_SIZE(error->active_vm); i++) {
@@ -730,16 +745,16 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
len += scnprintf(buf + len, sizeof(buf), "%s%s",
first ? "" : ", ",
- dev_priv->engine[j]->name);
+ m.i915->engine[j]->name);
first = 0;
}
scnprintf(buf + len, sizeof(buf), ")");
- print_error_buffers(m, buf,
+ print_error_buffers(&m, buf,
error->active_bo[i],
error->active_bo_count[i]);
}
- print_error_buffers(m, "Pinned (global)",
+ print_error_buffers(&m, "Pinned (global)",
error->pinned_bo,
error->pinned_bo_count);
@@ -748,115 +763,159 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
obj = ee->batchbuffer;
if (obj) {
- err_puts(m, dev_priv->engine[i]->name);
+ err_puts(&m, m.i915->engine[i]->name);
if (ee->context.pid)
- err_printf(m, " (submitted by %s [%d], ctx %d [%d], score %d%s)",
+ err_printf(&m, " (submitted by %s [%d], ctx %d [%d], score %d%s)",
ee->context.comm,
ee->context.pid,
ee->context.handle,
ee->context.hw_id,
ee->context.ban_score,
bannable(&ee->context));
- err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
+ err_printf(&m, " --- gtt_offset = 0x%08x %08x\n",
upper_32_bits(obj->gtt_offset),
lower_32_bits(obj->gtt_offset));
- print_error_obj(m, dev_priv->engine[i], NULL, obj);
+ print_error_obj(&m, m.i915->engine[i], NULL, obj);
}
for (j = 0; j < ee->user_bo_count; j++)
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"user", ee->user_bo[j]);
if (ee->num_requests) {
- err_printf(m, "%s --- %d requests\n",
- dev_priv->engine[i]->name,
+ err_printf(&m, "%s --- %d requests\n",
+ m.i915->engine[i]->name,
ee->num_requests);
for (j = 0; j < ee->num_requests; j++)
- error_print_request(m, " ",
+ error_print_request(&m, " ",
&ee->requests[j],
error->epoch);
}
if (IS_ERR(ee->waiters)) {
- err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n",
- dev_priv->engine[i]->name);
+ err_printf(&m, "%s --- ? waiters [unable to acquire spinlock]\n",
+ m.i915->engine[i]->name);
} else if (ee->num_waiters) {
- err_printf(m, "%s --- %d waiters\n",
- dev_priv->engine[i]->name,
+ err_printf(&m, "%s --- %d waiters\n",
+ m.i915->engine[i]->name,
ee->num_waiters);
for (j = 0; j < ee->num_waiters; j++) {
- err_printf(m, " seqno 0x%08x for %s [%d]\n",
+ err_printf(&m, " seqno 0x%08x for %s [%d]\n",
ee->waiters[j].seqno,
ee->waiters[j].comm,
ee->waiters[j].pid);
}
}
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"ringbuffer", ee->ringbuffer);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"HW Status", ee->hws_page);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"HW context", ee->ctx);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"WA context", ee->wa_ctx);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"WA batchbuffer", ee->wa_batchbuffer);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"NULL context", ee->default_state);
}
if (error->overlay)
- intel_overlay_print_error_state(m, error->overlay);
+ intel_overlay_print_error_state(&m, error->overlay);
if (error->display)
- intel_display_print_error_state(m, error->display);
+ intel_display_print_error_state(&m, error->display);
- err_print_capabilities(m, &error->device_info, &error->driver_caps);
- err_print_params(m, &error->params);
- err_print_uc(m, &error->uc);
+ err_print_capabilities(&m, &error->device_info, &error->driver_caps);
+ err_print_params(&m, &error->params);
+ err_print_uc(&m, &error->uc);
- if (m->bytes == 0 && m->err)
- return m->err;
+ if (m.buf) {
+ __sg_set_buf(m.cur++, m.buf, m.bytes);
+ m.bytes = 0;
+ m.buf = 0;
+ }
+ if (m.cur) {
+ GEM_BUG_ON(m.end < m.cur);
+ sg_mark_end(m.cur - 1);
+ }
+ GEM_BUG_ON(m.sgl && !m.cur);
+
+ if (m.err) {
+ err_free_sgl(m.sgl);
+ return m.err;
+ }
+
+ if (cmpxchg(&error->sgl, NULL, m.sgl))
+ err_free_sgl(m.sgl);
return 0;
}
-int i915_error_state_buf_init(struct drm_i915_error_state_buf *ebuf,
- struct drm_i915_private *i915,
- size_t count, loff_t pos)
+ssize_t i915_gpu_state_copy_to_buffer(struct i915_gpu_state *error,
+ char *buf, loff_t off, size_t rem)
{
- memset(ebuf, 0, sizeof(*ebuf));
- ebuf->i915 = i915;
+ struct scatterlist *sg;
+ size_t count;
+ loff_t pos;
+ int err;
- /* We need to have enough room to store any i915_error_state printf
- * so that we can move it to start position.
- */
- ebuf->size = count + 1 > PAGE_SIZE ? count + 1 : PAGE_SIZE;
- ebuf->buf = kmalloc(ebuf->size,
- GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
+ if (!error || !rem)
+ return 0;
- if (ebuf->buf == NULL) {
- ebuf->size = PAGE_SIZE;
- ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
- }
+ err = err_print_to_sgl(error);
+ if (err)
+ return err;
- if (ebuf->buf == NULL) {
- ebuf->size = 128;
- ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
- }
+ sg = error->sgl;
+ if (!sg)
+ return 0;
- if (ebuf->buf == NULL)
- return -ENOMEM;
+ pos = 0;
+ count = 0;
+ do {
+ size_t len, start;
- ebuf->start = pos;
+ if (sg_is_chain(sg)) {
+ sg = sg_chain_ptr(sg);
+ GEM_BUG_ON(sg_is_chain(sg));
+ }
- return 0;
+ len = sg->length;
+ if (pos + len <= off) {
+ pos += len;
+ continue;
+ }
+
+ start = sg->offset;
+ if (pos < off) {
+ GEM_BUG_ON(off - pos > len);
+ len -= off - pos;
+ start += off - pos;
+ pos = off;
+ }
+
+ len = min(len, rem);
+ GEM_BUG_ON(!len || len > sg->length);
+
+ memcpy(buf, page_address(sg_page(sg)) + start, len);
+
+ count += len;
+ pos += len;
+
+ buf += len;
+ rem -= len;
+ if (!rem)
+ break;
+ } while (!sg_is_last(sg++));
+
+ return count;
}
static void i915_error_object_free(struct drm_i915_error_object *obj)
@@ -929,6 +988,7 @@ void __i915_gpu_state_free(struct kref *error_ref)
cleanup_params(error);
cleanup_uc_state(error);
+ err_free_sgl(error->sgl);
kfree(error);
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h
index f893a4e8b783..a17f87286d22 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.h
+++ b/drivers/gpu/drm/i915/i915_gpu_error.h
@@ -9,6 +9,7 @@
#include <linux/kref.h>
#include <linux/ktime.h>
+#include <linux/nmi.h>
#include <linux/sched.h>
#include <drm/drm_mm.h>
@@ -191,6 +192,8 @@ struct i915_gpu_state {
} *active_bo[I915_NUM_ENGINES], *pinned_bo;
u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count;
struct i915_address_space *active_vm[I915_NUM_ENGINES];
+
+ struct scatterlist *sgl;
};
struct i915_gpu_error {
@@ -297,29 +300,19 @@ struct i915_gpu_error {
struct drm_i915_error_state_buf {
struct drm_i915_private *i915;
- unsigned int bytes;
- unsigned int size;
+ struct scatterlist *sgl, *cur, *end;
+
+ char *buf;
+ size_t bytes;
+ size_t size;
+
int err;
- u8 *buf;
- loff_t start;
- loff_t pos;
};
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
__printf(2, 3)
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
-int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
- const struct i915_gpu_state *gpu);
-int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb,
- struct drm_i915_private *i915,
- size_t count, loff_t pos);
-
-static inline void
-i915_error_state_buf_release(struct drm_i915_error_state_buf *eb)
-{
- kfree(eb->buf);
-}
struct i915_gpu_state *i915_capture_gpu_state(struct drm_i915_private *i915);
void i915_capture_error_state(struct drm_i915_private *dev_priv,
@@ -333,6 +326,9 @@ i915_gpu_state_get(struct i915_gpu_state *gpu)
return gpu;
}
+ssize_t i915_gpu_state_copy_to_buffer(struct i915_gpu_state *error,
+ char *buf, loff_t offset, size_t count);
+
void __i915_gpu_state_free(struct kref *kref);
static inline void i915_gpu_state_put(struct i915_gpu_state *gpu)
{
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index e5e6f6bb2b05..ae63a7d0f51d 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -516,26 +516,21 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
{
struct device *kdev = kobj_to_dev(kobj);
- struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
- struct drm_i915_error_state_buf error_str;
+ struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
struct i915_gpu_state *gpu;
ssize_t ret;
- ret = i915_error_state_buf_init(&error_str, dev_priv, count, off);
- if (ret)
- return ret;
-
- gpu = i915_first_error_state(dev_priv);
- ret = i915_error_state_to_str(&error_str, gpu);
- if (ret)
- goto out;
-
- ret = count < error_str.bytes ? count : error_str.bytes;
- memcpy(buf, error_str.buf, ret);
+ gpu = i915_first_error_state(i915);
+ if (gpu) {
+ ret = i915_gpu_state_copy_to_buffer(gpu, buf, off, count);
+ i915_gpu_state_put(gpu);
+ } else {
+ const char *str = "No error state collected\n";
+ size_t len = strlen(str);
-out:
- i915_gpu_state_put(gpu);
- i915_error_state_buf_release(&error_str);
+ ret = min_t(size_t, count, len - off);
+ memcpy(buf, str + off, ret);
+ }
return ret;
}
--
2.18.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread
* ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev3)
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (6 preceding siblings ...)
2018-07-18 19:59 ` [PATCH v3] drm/i915: Cache the error string Chris Wilson
@ 2018-07-18 20:28 ` Patchwork
2018-07-18 20:50 ` ✓ Fi.CI.BAT: success " Patchwork
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-18 20:28 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string (rev3)
URL : https://patchwork.freedesktop.org/series/46777/
State : warning
== Summary ==
$ dim sparse origin/drm-tip
Commit: drm/i915: Cache the error string
+drivers/gpu/drm/i915/i915_gpu_error.c:842:25: warning: Using plain integer as NULL pointer
+drivers/gpu/drm/i915/i915_gpu_error.c:904:23: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/i915_gpu_error.c:904:23: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/i915_sysfs.c:531:23: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/i915_sysfs.c:531:23: warning: expression using sizeof(void)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* ✓ Fi.CI.BAT: success for drm/i915: Cache the error string (rev3)
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (7 preceding siblings ...)
2018-07-18 20:28 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev3) Patchwork
@ 2018-07-18 20:50 ` Patchwork
2018-07-18 22:11 ` ✓ Fi.CI.IGT: " Patchwork
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-18 20:50 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string (rev3)
URL : https://patchwork.freedesktop.org/series/46777/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4505 -> Patchwork_9710 =
== Summary - WARNING ==
Minor unknown changes coming with Patchwork_9710 need to be verified
manually.
If you think the reported changes have nothing to do with the changes
introduced in Patchwork_9710, please notify your bug team to allow them
to document this new failure mode, which will reduce false positives in CI.
External URL: https://patchwork.freedesktop.org/api/1.0/series/46777/revisions/3/mbox/
== Possible new issues ==
Here are the unknown changes that may have been introduced in Patchwork_9710:
=== IGT changes ===
==== Warnings ====
igt@drv_selftest@live_guc:
fi-kbl-7560u: PASS -> SKIP +1
igt@gem_exec_gttfill@basic:
fi-pnv-d510: PASS -> SKIP
== Known issues ==
Here are the changes found in Patchwork_9710 that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@drv_selftest@live_hangcheck:
fi-kbl-7560u: PASS -> DMESG-FAIL (fdo#106947, fdo#106560)
igt@kms_flip@basic-flip-vs-dpms:
fi-glk-j4005: PASS -> DMESG-WARN (fdo#106000)
igt@kms_flip@basic-flip-vs-wf_vblank:
fi-glk-j4005: PASS -> FAIL (fdo#100368)
==== Possible fixes ====
igt@drv_selftest@live_hangcheck:
fi-skl-guc: DMESG-FAIL (fdo#107174) -> PASS
{fi-cfl-8109u}: DMESG-FAIL (fdo#106560) -> PASS
igt@gem_exec_suspend@basic-s4-devices:
fi-kbl-7500u: DMESG-WARN (fdo#107139, fdo#105128) -> PASS
igt@prime_vgem@basic-fence-flip:
fi-ilk-650: FAIL (fdo#104008) -> PASS
{name}: This element is suppressed. This means it is ignored when computing
the status of the difference (SUCCESS, WARNING, or FAILURE).
fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#104008 https://bugs.freedesktop.org/show_bug.cgi?id=104008
fdo#105128 https://bugs.freedesktop.org/show_bug.cgi?id=105128
fdo#106000 https://bugs.freedesktop.org/show_bug.cgi?id=106000
fdo#106560 https://bugs.freedesktop.org/show_bug.cgi?id=106560
fdo#106947 https://bugs.freedesktop.org/show_bug.cgi?id=106947
fdo#107139 https://bugs.freedesktop.org/show_bug.cgi?id=107139
fdo#107174 https://bugs.freedesktop.org/show_bug.cgi?id=107174
== Participating hosts (47 -> 40) ==
Missing (7): fi-ilk-m540 fi-bxt-dsi fi-hsw-4200u fi-byt-j1900 fi-byt-squawks fi-bsw-cyan fi-ctg-p8600
== Build changes ==
* Linux: CI_DRM_4505 -> Patchwork_9710
CI_DRM_4505: 702a75323cd03527548a4de95f4fc073096870b0 @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4566: 7270e39a0e6238804827ea7f8db433ad743ed745 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_9710: d961c677fad4f51825e8e846ebc5e5b810266a04 @ git://anongit.freedesktop.org/gfx-ci/linux
== Linux commits ==
d961c677fad4 drm/i915: Cache the error string
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9710/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* ✓ Fi.CI.IGT: success for drm/i915: Cache the error string (rev3)
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (8 preceding siblings ...)
2018-07-18 20:50 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2018-07-18 22:11 ` Patchwork
2018-07-19 16:52 ` [PATCH v4] drm/i915: Cache the error string Chris Wilson
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-18 22:11 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string (rev3)
URL : https://patchwork.freedesktop.org/series/46777/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4505_full -> Patchwork_9710_full =
== Summary - WARNING ==
Minor unknown changes coming with Patchwork_9710_full need to be verified
manually.
If you think the reported changes have nothing to do with the changes
introduced in Patchwork_9710_full, please notify your bug team to allow them
to document this new failure mode, which will reduce false positives in CI.
== Possible new issues ==
Here are the unknown changes that may have been introduced in Patchwork_9710_full:
=== IGT changes ===
==== Warnings ====
igt@gem_exec_schedule@deep-blt:
shard-kbl: PASS -> SKIP
igt@gem_exec_schedule@deep-vebox:
shard-kbl: SKIP -> PASS +2
== Known issues ==
Here are the changes found in Patchwork_9710_full that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@kms_flip@plain-flip-ts-check-interruptible:
shard-glk: PASS -> FAIL (fdo#100368) +1
igt@perf_pmu@init-wait-vecs0:
shard-snb: NOTRUN -> INCOMPLETE (fdo#105411)
==== Possible fixes ====
igt@gem_wait@write-wait-bsd2:
shard-snb: INCOMPLETE (fdo#105411) -> SKIP
igt@kms_cursor_legacy@cursor-vs-flip-toggle:
shard-hsw: FAIL (fdo#103355) -> PASS
igt@kms_setmode@basic:
shard-kbl: FAIL (fdo#99912) -> PASS
fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#103355 https://bugs.freedesktop.org/show_bug.cgi?id=103355
fdo#105411 https://bugs.freedesktop.org/show_bug.cgi?id=105411
fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
== Participating hosts (5 -> 5) ==
No changes in participating hosts
== Build changes ==
* Linux: CI_DRM_4505 -> Patchwork_9710
CI_DRM_4505: 702a75323cd03527548a4de95f4fc073096870b0 @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4566: 7270e39a0e6238804827ea7f8db433ad743ed745 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_9710: d961c677fad4f51825e8e846ebc5e5b810266a04 @ git://anongit.freedesktop.org/gfx-ci/linux
piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9710/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4] drm/i915: Cache the error string
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (9 preceding siblings ...)
2018-07-18 22:11 ` ✓ Fi.CI.IGT: " Patchwork
@ 2018-07-19 16:52 ` Chris Wilson
2018-07-19 17:08 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev4) Patchwork
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Chris Wilson @ 2018-07-19 16:52 UTC (permalink / raw)
To: intel-gfx
Currently, we convert the error state into a string every time we read
from sysfs (and sysfs reads in page size (4KiB) chunks). We do try to
window the string and only capture the portion that is being read, but
that means that we must always convert up to the window to find the
start. For a very large error state bordering on EXEC_OBJECT_CAPTURE
abuse, this is noticeable as it degrades to O(N^2)!
As we do not have a convenient hook for sysfs open(), and we would like
to keep the lazy conversion into a string, do the conversion of the
whole string on the first read and keep the string until the error state
is freed.
v2: Don't double advance simple_read_from_buffer
v3: Due to extreme pain of lack of vrealloc, use a scatterlist
v4: Keep the forward iterator loosely cached
Reported-by: Jason Ekstrand <jason@jlekstrand.net>
Testcase: igt/gem_exec_capture/many*
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Jason Ekstrand <jason@jlekstrand.net>
---
drivers/gpu/drm/i915/i915_debugfs.c | 32 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 402 +++++++++++++++-----------
drivers/gpu/drm/i915/i915_gpu_error.h | 28 +-
drivers/gpu/drm/i915/i915_sysfs.c | 27 +-
4 files changed, 273 insertions(+), 216 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index b3aefd623557..543ac6bfb08a 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -943,30 +943,28 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
static ssize_t gpu_state_read(struct file *file, char __user *ubuf,
size_t count, loff_t *pos)
{
- struct i915_gpu_state *error = file->private_data;
- struct drm_i915_error_state_buf str;
+ struct i915_gpu_state *error;
ssize_t ret;
- loff_t tmp;
+ void *buf;
+ error = file->private_data;
if (!error)
return 0;
- ret = i915_error_state_buf_init(&str, error->i915, count, *pos);
- if (ret)
- return ret;
-
- ret = i915_error_state_to_str(&str, error);
- if (ret)
- goto out;
+ /* Bounce buffer required because of kernfs __user API convenience. */
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- tmp = 0;
- ret = simple_read_from_buffer(ubuf, count, &tmp, str.buf, str.bytes);
- if (ret < 0)
- goto out;
+ ret = i915_gpu_state_copy_to_buffer(error, buf, *pos, count);
+ if (ret > 0) {
+ if (!copy_to_user(ubuf, buf, ret))
+ *pos += ret;
+ else
+ ret = -EFAULT;
+ }
- *pos = str.start + ret;
-out:
- i915_error_state_buf_release(&str);
+ kfree(buf);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 8c81cf3aa182..b23416826598 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -28,6 +28,8 @@
*/
#include <generated/utsrelease.h>
+#include <linux/nmi.h>
+#include <linux/scatterlist.h>
#include <linux/stop_machine.h>
#include <linux/zlib.h>
#include <drm/drm_print.h>
@@ -76,112 +78,110 @@ static const char *purgeable_flag(int purgeable)
return purgeable ? " purgeable" : "";
}
-static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
+static void __sg_set_buf(struct scatterlist *sg,
+ void *addr, unsigned int len, loff_t it)
{
-
- if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
- e->err = -ENOSPC;
- return false;
- }
-
- if (e->bytes == e->size - 1 || e->err)
- return false;
-
- return true;
+ sg->page_link = (unsigned long)virt_to_page(addr);
+ sg->offset = offset_in_page(addr);
+ sg->length = len;
+ sg->dma_address = it;
}
-static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
- unsigned len)
+static bool __i915_error_grow(struct drm_i915_error_state_buf *e, size_t len)
{
- if (e->pos + len <= e->start) {
- e->pos += len;
+ if (!len)
return false;
- }
- /* First vsnprintf needs to fit in its entirety for memmove */
- if (len >= e->size) {
- e->err = -EIO;
- return false;
- }
+ if (e->bytes + len + 1 > e->size) {
+ if (e->bytes) {
+ __sg_set_buf(e->cur++, e->buf, e->bytes, e->iter);
+ e->iter += e->bytes;
+ e->buf = NULL;
+ e->bytes = 0;
+ }
- return true;
-}
+ if (e->cur == e->end) {
+ struct scatterlist *sgl;
-static void __i915_error_advance(struct drm_i915_error_state_buf *e,
- unsigned len)
-{
- /* If this is first printf in this window, adjust it so that
- * start position matches start of the buffer
- */
+ sgl = (typeof(sgl))__get_free_page(GFP_KERNEL);
+ if (!sgl) {
+ e->err = -ENOMEM;
+ return false;
+ }
- if (e->pos < e->start) {
- const size_t off = e->start - e->pos;
+ if (e->cur) {
+ e->cur->offset = 0;
+ e->cur->length = 0;
+ e->cur->page_link =
+ (unsigned long)sgl | SG_CHAIN;
+ } else {
+ e->sgl = sgl;
+ }
- /* Should not happen but be paranoid */
- if (off > len || e->bytes) {
- e->err = -EIO;
- return;
+ e->cur = sgl;
+ e->end = sgl + SG_MAX_SINGLE_ALLOC - 1;
}
- memmove(e->buf, e->buf + off, len - off);
- e->bytes = len - off;
- e->pos = e->start;
- return;
+ e->size = ALIGN(len + 1, SZ_64K);
+ e->buf = kmalloc(e->size,
+ GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+ if (!e->buf) {
+ e->size = PAGE_ALIGN(len + 1);
+ e->buf = kmalloc(e->size, GFP_KERNEL);
+ }
+ if (!e->buf) {
+ e->err = -ENOMEM;
+ return false;
+ }
}
- e->bytes += len;
- e->pos += len;
+ return true;
}
__printf(2, 0)
static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
- const char *f, va_list args)
+ const char *fmt, va_list args)
{
- unsigned len;
+ va_list ap;
+ int len;
- if (!__i915_error_ok(e))
+ if (e->err)
return;
- /* Seek the first printf which is hits start position */
- if (e->pos < e->start) {
- va_list tmp;
-
- va_copy(tmp, args);
- len = vsnprintf(NULL, 0, f, tmp);
- va_end(tmp);
-
- if (!__i915_error_seek(e, len))
- return;
+ va_copy(ap, args);
+ len = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+ if (len <= 0) {
+ e->err = len;
+ return;
}
- len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
- if (len >= e->size - e->bytes)
- len = e->size - e->bytes - 1;
+ if (!__i915_error_grow(e, len))
+ return;
- __i915_error_advance(e, len);
+ GEM_BUG_ON(e->bytes >= e->size);
+ len = vscnprintf(e->buf + e->bytes, e->size - e->bytes, fmt, args);
+ if (len < 0) {
+ e->err = len;
+ return;
+ }
+ e->bytes += len;
}
-static void i915_error_puts(struct drm_i915_error_state_buf *e,
- const char *str)
+static void i915_error_puts(struct drm_i915_error_state_buf *e, const char *str)
{
unsigned len;
- if (!__i915_error_ok(e))
+ if (e->err || !str)
return;
len = strlen(str);
+ if (!__i915_error_grow(e, len))
+ return;
- /* Seek the first printf which is hits start position */
- if (e->pos < e->start) {
- if (!__i915_error_seek(e, len))
- return;
- }
-
- if (len >= e->size - e->bytes)
- len = e->size - e->bytes - 1;
+ GEM_BUG_ON(e->bytes + len > e->size);
memcpy(e->buf + e->bytes, str, len);
-
- __i915_error_advance(e, len);
+ e->bytes += len;
}
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
@@ -258,6 +258,8 @@ static int compress_page(struct compress *c,
if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK)
return -EIO;
+
+ touch_nmi_watchdog();
} while (zstream->avail_in);
/* Fallback to uncompressed if we increase size? */
@@ -623,33 +625,50 @@ static void err_print_uc(struct drm_i915_error_state_buf *m,
print_error_obj(m, NULL, "GuC log buffer", error_uc->guc_log);
}
-int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
- const struct i915_gpu_state *error)
+static void err_free_sgl(struct scatterlist *sgl)
{
- struct drm_i915_private *dev_priv = m->i915;
+ while (sgl) {
+ struct scatterlist *sg;
+
+ for (sg = sgl; !sg_is_chain(sg); sg++) {
+ kfree(sg_virt(sg));
+ if (sg_is_last(sg))
+ break;
+ }
+
+ sg = sg_is_last(sg) ? NULL : sg_chain_ptr(sg);
+ free_page((unsigned long)sgl);
+ sgl = sg;
+ }
+}
+
+static int err_print_to_sgl(struct i915_gpu_state *error)
+{
+ struct drm_i915_error_state_buf m;
struct drm_i915_error_object *obj;
struct timespec64 ts;
int i, j;
- if (!error) {
- err_printf(m, "No error state collected\n");
+ if (READ_ONCE(error->sgl))
return 0;
- }
+
+ memset(&m, 0, sizeof(m));
+ m.i915 = error->i915;
if (*error->error_msg)
- err_printf(m, "%s\n", error->error_msg);
- err_printf(m, "Kernel: " UTS_RELEASE "\n");
+ err_printf(&m, "%s\n", error->error_msg);
+ err_printf(&m, "Kernel: " UTS_RELEASE "\n");
ts = ktime_to_timespec64(error->time);
- err_printf(m, "Time: %lld s %ld us\n",
+ err_printf(&m, "Time: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
ts = ktime_to_timespec64(error->boottime);
- err_printf(m, "Boottime: %lld s %ld us\n",
+ err_printf(&m, "Boottime: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
ts = ktime_to_timespec64(error->uptime);
- err_printf(m, "Uptime: %lld s %ld us\n",
+ err_printf(&m, "Uptime: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
- err_printf(m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ);
- err_printf(m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n",
+ err_printf(&m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ);
+ err_printf(&m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n",
error->capture,
jiffies_to_msecs(jiffies - error->capture),
jiffies_to_msecs(error->capture - error->epoch));
@@ -657,63 +676,63 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].hangcheck_stalled &&
error->engine[i].context.pid) {
- err_printf(m, "Active process (on ring %s): %s [%d], score %d%s\n",
- engine_name(m->i915, i),
+ err_printf(&m, "Active process (on ring %s): %s [%d], score %d%s\n",
+ engine_name(m.i915, i),
error->engine[i].context.comm,
error->engine[i].context.pid,
error->engine[i].context.ban_score,
bannable(&error->engine[i].context));
}
}
- err_printf(m, "Reset count: %u\n", error->reset_count);
- err_printf(m, "Suspend count: %u\n", error->suspend_count);
- err_printf(m, "Platform: %s\n", intel_platform_name(error->device_info.platform));
- err_print_pciid(m, error->i915);
+ err_printf(&m, "Reset count: %u\n", error->reset_count);
+ err_printf(&m, "Suspend count: %u\n", error->suspend_count);
+ err_printf(&m, "Platform: %s\n", intel_platform_name(error->device_info.platform));
+ err_print_pciid(&m, m.i915);
- err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
+ err_printf(&m, "IOMMU enabled?: %d\n", error->iommu);
- if (HAS_CSR(dev_priv)) {
- struct intel_csr *csr = &dev_priv->csr;
+ if (HAS_CSR(m.i915)) {
+ struct intel_csr *csr = &m.i915->csr;
- err_printf(m, "DMC loaded: %s\n",
+ err_printf(&m, "DMC loaded: %s\n",
yesno(csr->dmc_payload != NULL));
- err_printf(m, "DMC fw version: %d.%d\n",
+ err_printf(&m, "DMC fw version: %d.%d\n",
CSR_VERSION_MAJOR(csr->version),
CSR_VERSION_MINOR(csr->version));
}
- err_printf(m, "GT awake: %s\n", yesno(error->awake));
- err_printf(m, "RPM wakelock: %s\n", yesno(error->wakelock));
- err_printf(m, "PM suspended: %s\n", yesno(error->suspended));
- err_printf(m, "EIR: 0x%08x\n", error->eir);
- err_printf(m, "IER: 0x%08x\n", error->ier);
+ err_printf(&m, "GT awake: %s\n", yesno(error->awake));
+ err_printf(&m, "RPM wakelock: %s\n", yesno(error->wakelock));
+ err_printf(&m, "PM suspended: %s\n", yesno(error->suspended));
+ err_printf(&m, "EIR: 0x%08x\n", error->eir);
+ err_printf(&m, "IER: 0x%08x\n", error->ier);
for (i = 0; i < error->ngtier; i++)
- err_printf(m, "GTIER[%d]: 0x%08x\n", i, error->gtier[i]);
- err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
- err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
- err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
- err_printf(m, "CCID: 0x%08x\n", error->ccid);
- err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings);
+ err_printf(&m, "GTIER[%d]: 0x%08x\n", i, error->gtier[i]);
+ err_printf(&m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+ err_printf(&m, "FORCEWAKE: 0x%08x\n", error->forcewake);
+ err_printf(&m, "DERRMR: 0x%08x\n", error->derrmr);
+ err_printf(&m, "CCID: 0x%08x\n", error->ccid);
+ err_printf(&m, "Missed interrupts: 0x%08lx\n", m.i915->gpu_error.missed_irq_rings);
for (i = 0; i < error->nfence; i++)
- err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]);
+ err_printf(&m, " fence[%d] = %08llx\n", i, error->fence[i]);
- if (INTEL_GEN(dev_priv) >= 6) {
- err_printf(m, "ERROR: 0x%08x\n", error->error);
+ if (INTEL_GEN(m.i915) >= 6) {
+ err_printf(&m, "ERROR: 0x%08x\n", error->error);
- if (INTEL_GEN(dev_priv) >= 8)
- err_printf(m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
+ if (INTEL_GEN(m.i915) >= 8)
+ err_printf(&m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
error->fault_data1, error->fault_data0);
- err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
+ err_printf(&m, "DONE_REG: 0x%08x\n", error->done_reg);
}
- if (IS_GEN7(dev_priv))
- err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
+ if (IS_GEN7(m.i915))
+ err_printf(&m, "ERR_INT: 0x%08x\n", error->err_int);
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].engine_id != -1)
- error_print_engine(m, &error->engine[i], error->epoch);
+ error_print_engine(&m, &error->engine[i], error->epoch);
}
for (i = 0; i < ARRAY_SIZE(error->active_vm); i++) {
@@ -730,16 +749,16 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
len += scnprintf(buf + len, sizeof(buf), "%s%s",
first ? "" : ", ",
- dev_priv->engine[j]->name);
+ m.i915->engine[j]->name);
first = 0;
}
scnprintf(buf + len, sizeof(buf), ")");
- print_error_buffers(m, buf,
+ print_error_buffers(&m, buf,
error->active_bo[i],
error->active_bo_count[i]);
}
- print_error_buffers(m, "Pinned (global)",
+ print_error_buffers(&m, "Pinned (global)",
error->pinned_bo,
error->pinned_bo_count);
@@ -748,115 +767,163 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
obj = ee->batchbuffer;
if (obj) {
- err_puts(m, dev_priv->engine[i]->name);
+ err_puts(&m, m.i915->engine[i]->name);
if (ee->context.pid)
- err_printf(m, " (submitted by %s [%d], ctx %d [%d], score %d%s)",
+ err_printf(&m, " (submitted by %s [%d], ctx %d [%d], score %d%s)",
ee->context.comm,
ee->context.pid,
ee->context.handle,
ee->context.hw_id,
ee->context.ban_score,
bannable(&ee->context));
- err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
+ err_printf(&m, " --- gtt_offset = 0x%08x %08x\n",
upper_32_bits(obj->gtt_offset),
lower_32_bits(obj->gtt_offset));
- print_error_obj(m, dev_priv->engine[i], NULL, obj);
+ print_error_obj(&m, m.i915->engine[i], NULL, obj);
}
for (j = 0; j < ee->user_bo_count; j++)
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"user", ee->user_bo[j]);
if (ee->num_requests) {
- err_printf(m, "%s --- %d requests\n",
- dev_priv->engine[i]->name,
+ err_printf(&m, "%s --- %d requests\n",
+ m.i915->engine[i]->name,
ee->num_requests);
for (j = 0; j < ee->num_requests; j++)
- error_print_request(m, " ",
+ error_print_request(&m, " ",
&ee->requests[j],
error->epoch);
}
if (IS_ERR(ee->waiters)) {
- err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n",
- dev_priv->engine[i]->name);
+ err_printf(&m, "%s --- ? waiters [unable to acquire spinlock]\n",
+ m.i915->engine[i]->name);
} else if (ee->num_waiters) {
- err_printf(m, "%s --- %d waiters\n",
- dev_priv->engine[i]->name,
+ err_printf(&m, "%s --- %d waiters\n",
+ m.i915->engine[i]->name,
ee->num_waiters);
for (j = 0; j < ee->num_waiters; j++) {
- err_printf(m, " seqno 0x%08x for %s [%d]\n",
+ err_printf(&m, " seqno 0x%08x for %s [%d]\n",
ee->waiters[j].seqno,
ee->waiters[j].comm,
ee->waiters[j].pid);
}
}
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"ringbuffer", ee->ringbuffer);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"HW Status", ee->hws_page);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"HW context", ee->ctx);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"WA context", ee->wa_ctx);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"WA batchbuffer", ee->wa_batchbuffer);
- print_error_obj(m, dev_priv->engine[i],
+ print_error_obj(&m, m.i915->engine[i],
"NULL context", ee->default_state);
}
if (error->overlay)
- intel_overlay_print_error_state(m, error->overlay);
+ intel_overlay_print_error_state(&m, error->overlay);
if (error->display)
- intel_display_print_error_state(m, error->display);
+ intel_display_print_error_state(&m, error->display);
- err_print_capabilities(m, &error->device_info, &error->driver_caps);
- err_print_params(m, &error->params);
- err_print_uc(m, &error->uc);
+ err_print_capabilities(&m, &error->device_info, &error->driver_caps);
+ err_print_params(&m, &error->params);
+ err_print_uc(&m, &error->uc);
- if (m->bytes == 0 && m->err)
- return m->err;
+ if (m.buf) {
+ __sg_set_buf(m.cur++, m.buf, m.bytes, m.iter);
+ m.bytes = 0;
+ m.buf = 0;
+ }
+ if (m.cur) {
+ GEM_BUG_ON(m.end < m.cur);
+ sg_mark_end(m.cur - 1);
+ }
+ GEM_BUG_ON(m.sgl && !m.cur);
+
+ if (m.err) {
+ err_free_sgl(m.sgl);
+ return m.err;
+ }
+
+ if (cmpxchg(&error->sgl, NULL, m.sgl))
+ err_free_sgl(m.sgl);
return 0;
}
-int i915_error_state_buf_init(struct drm_i915_error_state_buf *ebuf,
- struct drm_i915_private *i915,
- size_t count, loff_t pos)
+ssize_t i915_gpu_state_copy_to_buffer(struct i915_gpu_state *error,
+ char *buf, loff_t off, size_t rem)
{
- memset(ebuf, 0, sizeof(*ebuf));
- ebuf->i915 = i915;
+ struct scatterlist *sg;
+ size_t count;
+ loff_t pos;
+ int err;
- /* We need to have enough room to store any i915_error_state printf
- * so that we can move it to start position.
- */
- ebuf->size = count + 1 > PAGE_SIZE ? count + 1 : PAGE_SIZE;
- ebuf->buf = kmalloc(ebuf->size,
- GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
+ if (!error || !rem)
+ return 0;
- if (ebuf->buf == NULL) {
- ebuf->size = PAGE_SIZE;
- ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
- }
+ err = err_print_to_sgl(error);
+ if (err)
+ return err;
- if (ebuf->buf == NULL) {
- ebuf->size = 128;
- ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
- }
+ sg = READ_ONCE(error->fit);
+ if (!sg || off < sg->dma_address)
+ sg = error->sgl;
+ if (!sg)
+ return 0;
- if (ebuf->buf == NULL)
- return -ENOMEM;
+ pos = sg->dma_address;
+ count = 0;
+ do {
+ size_t len, start;
- ebuf->start = pos;
+ if (sg_is_chain(sg)) {
+ sg = sg_chain_ptr(sg);
+ GEM_BUG_ON(sg_is_chain(sg));
+ }
- return 0;
+ len = sg->length;
+ if (pos + len <= off) {
+ pos += len;
+ continue;
+ }
+
+ start = sg->offset;
+ if (pos < off) {
+ GEM_BUG_ON(off - pos > len);
+ len -= off - pos;
+ start += off - pos;
+ pos = off;
+ }
+
+ len = min(len, rem);
+ GEM_BUG_ON(!len || len > sg->length);
+
+ memcpy(buf, page_address(sg_page(sg)) + start, len);
+
+ count += len;
+ pos += len;
+
+ buf += len;
+ rem -= len;
+ if (!rem) {
+ WRITE_ONCE(error->fit, sg);
+ break;
+ }
+ } while (!sg_is_last(sg++));
+
+ return count;
}
static void i915_error_object_free(struct drm_i915_error_object *obj)
@@ -929,6 +996,7 @@ void __i915_gpu_state_free(struct kref *error_ref)
cleanup_params(error);
cleanup_uc_state(error);
+ err_free_sgl(error->sgl);
kfree(error);
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h
index f893a4e8b783..1c1bc0c23468 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.h
+++ b/drivers/gpu/drm/i915/i915_gpu_error.h
@@ -191,6 +191,8 @@ struct i915_gpu_state {
} *active_bo[I915_NUM_ENGINES], *pinned_bo;
u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count;
struct i915_address_space *active_vm[I915_NUM_ENGINES];
+
+ struct scatterlist *sgl, *fit;
};
struct i915_gpu_error {
@@ -297,29 +299,20 @@ struct i915_gpu_error {
struct drm_i915_error_state_buf {
struct drm_i915_private *i915;
- unsigned int bytes;
- unsigned int size;
+ struct scatterlist *sgl, *cur, *end;
+
+ char *buf;
+ size_t bytes;
+ size_t size;
+ loff_t iter;
+
int err;
- u8 *buf;
- loff_t start;
- loff_t pos;
};
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
__printf(2, 3)
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
-int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
- const struct i915_gpu_state *gpu);
-int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb,
- struct drm_i915_private *i915,
- size_t count, loff_t pos);
-
-static inline void
-i915_error_state_buf_release(struct drm_i915_error_state_buf *eb)
-{
- kfree(eb->buf);
-}
struct i915_gpu_state *i915_capture_gpu_state(struct drm_i915_private *i915);
void i915_capture_error_state(struct drm_i915_private *dev_priv,
@@ -333,6 +326,9 @@ i915_gpu_state_get(struct i915_gpu_state *gpu)
return gpu;
}
+ssize_t i915_gpu_state_copy_to_buffer(struct i915_gpu_state *error,
+ char *buf, loff_t offset, size_t count);
+
void __i915_gpu_state_free(struct kref *kref);
static inline void i915_gpu_state_put(struct i915_gpu_state *gpu)
{
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index e5e6f6bb2b05..ae63a7d0f51d 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -516,26 +516,21 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
{
struct device *kdev = kobj_to_dev(kobj);
- struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
- struct drm_i915_error_state_buf error_str;
+ struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
struct i915_gpu_state *gpu;
ssize_t ret;
- ret = i915_error_state_buf_init(&error_str, dev_priv, count, off);
- if (ret)
- return ret;
-
- gpu = i915_first_error_state(dev_priv);
- ret = i915_error_state_to_str(&error_str, gpu);
- if (ret)
- goto out;
-
- ret = count < error_str.bytes ? count : error_str.bytes;
- memcpy(buf, error_str.buf, ret);
+ gpu = i915_first_error_state(i915);
+ if (gpu) {
+ ret = i915_gpu_state_copy_to_buffer(gpu, buf, off, count);
+ i915_gpu_state_put(gpu);
+ } else {
+ const char *str = "No error state collected\n";
+ size_t len = strlen(str);
-out:
- i915_gpu_state_put(gpu);
- i915_error_state_buf_release(&error_str);
+ ret = min_t(size_t, count, len - off);
+ memcpy(buf, str + off, ret);
+ }
return ret;
}
--
2.18.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread
* ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev4)
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (10 preceding siblings ...)
2018-07-19 16:52 ` [PATCH v4] drm/i915: Cache the error string Chris Wilson
@ 2018-07-19 17:08 ` Patchwork
2018-07-19 17:30 ` ✓ Fi.CI.BAT: success " Patchwork
2018-07-19 21:13 ` ✓ Fi.CI.IGT: " Patchwork
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-19 17:08 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string (rev4)
URL : https://patchwork.freedesktop.org/series/46777/
State : warning
== Summary ==
$ dim sparse origin/drm-tip
Commit: drm/i915: Cache the error string
+drivers/gpu/drm/i915/i915_gpu_error.c:846:25: warning: Using plain integer as NULL pointer
+drivers/gpu/drm/i915/i915_gpu_error.c:910:23: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/i915_gpu_error.c:910:23: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/i915_sysfs.c:531:23: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/i915_sysfs.c:531:23: warning: expression using sizeof(void)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* ✓ Fi.CI.BAT: success for drm/i915: Cache the error string (rev4)
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (11 preceding siblings ...)
2018-07-19 17:08 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev4) Patchwork
@ 2018-07-19 17:30 ` Patchwork
2018-07-19 21:13 ` ✓ Fi.CI.IGT: " Patchwork
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-19 17:30 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string (rev4)
URL : https://patchwork.freedesktop.org/series/46777/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4513 -> Patchwork_9718 =
== Summary - SUCCESS ==
No regressions found.
External URL: https://patchwork.freedesktop.org/api/1.0/series/46777/revisions/4/mbox/
== Known issues ==
Here are the changes found in Patchwork_9718 that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@drv_selftest@live_coherency:
fi-gdg-551: PASS -> DMESG-FAIL (fdo#107164)
igt@drv_selftest@live_hangcheck:
fi-skl-guc: PASS -> DMESG-FAIL (fdo#107174)
igt@drv_selftest@live_workarounds:
{fi-cfl-8109u}: PASS -> DMESG-FAIL (fdo#107292)
igt@kms_pipe_crc_basic@suspend-read-crc-pipe-c:
fi-bxt-dsi: PASS -> INCOMPLETE (fdo#103927)
==== Possible fixes ====
igt@kms_frontbuffer_tracking@basic:
fi-hsw-peppy: DMESG-FAIL (fdo#106103, fdo#102614) -> PASS
igt@kms_pipe_crc_basic@suspend-read-crc-pipe-b:
fi-snb-2520m: INCOMPLETE (fdo#103713) -> PASS
{name}: This element is suppressed. This means it is ignored when computing
the status of the difference (SUCCESS, WARNING, or FAILURE).
fdo#102614 https://bugs.freedesktop.org/show_bug.cgi?id=102614
fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713
fdo#103927 https://bugs.freedesktop.org/show_bug.cgi?id=103927
fdo#106103 https://bugs.freedesktop.org/show_bug.cgi?id=106103
fdo#107164 https://bugs.freedesktop.org/show_bug.cgi?id=107164
fdo#107174 https://bugs.freedesktop.org/show_bug.cgi?id=107174
fdo#107292 https://bugs.freedesktop.org/show_bug.cgi?id=107292
== Participating hosts (47 -> 42) ==
Missing (5): fi-ctg-p8600 fi-ilk-m540 fi-byt-squawks fi-bsw-cyan fi-hsw-4200u
== Build changes ==
* Linux: CI_DRM_4513 -> Patchwork_9718
CI_DRM_4513: d592f2da0236d6d7ce4d4cccb40441c54dce5d91 @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4568: 86f7b724ef18986bc58d35558d22e1ed3f8df4f9 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_9718: f146b4a83eece6f2d42b30911d9fc6a922dff824 @ git://anongit.freedesktop.org/gfx-ci/linux
== Linux commits ==
f146b4a83eec drm/i915: Cache the error string
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9718/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* ✓ Fi.CI.IGT: success for drm/i915: Cache the error string (rev4)
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
` (12 preceding siblings ...)
2018-07-19 17:30 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2018-07-19 21:13 ` Patchwork
13 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2018-07-19 21:13 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Cache the error string (rev4)
URL : https://patchwork.freedesktop.org/series/46777/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4513_full -> Patchwork_9718_full =
== Summary - WARNING ==
Minor unknown changes coming with Patchwork_9718_full need to be verified
manually.
If you think the reported changes have nothing to do with the changes
introduced in Patchwork_9718_full, please notify your bug team to allow them
to document this new failure mode, which will reduce false positives in CI.
== Possible new issues ==
Here are the unknown changes that may have been introduced in Patchwork_9718_full:
=== IGT changes ===
==== Warnings ====
igt@gem_exec_schedule@deep-bsd2:
shard-kbl: PASS -> SKIP +1
igt@gem_exec_schedule@deep-vebox:
shard-kbl: SKIP -> PASS
== Known issues ==
Here are the changes found in Patchwork_9718_full that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@kms_flip@2x-flip-vs-expired-vblank-interruptible:
shard-glk: PASS -> FAIL (fdo#105363)
igt@kms_flip@plain-flip-fb-recreate:
shard-glk: PASS -> FAIL (fdo#100368) +1
igt@kms_setmode@basic:
shard-glk: PASS -> FAIL (fdo#99912)
igt@perf@blocking:
shard-hsw: PASS -> FAIL (fdo#102252)
==== Possible fixes ====
igt@kms_flip@2x-wf_vblank-ts-check-interruptible:
shard-glk: FAIL (fdo#100368) -> PASS
igt@kms_rotation_crc@sprite-rotation-180:
shard-hsw: FAIL (fdo#103925) -> PASS
fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#102252 https://bugs.freedesktop.org/show_bug.cgi?id=102252
fdo#103925 https://bugs.freedesktop.org/show_bug.cgi?id=103925
fdo#105363 https://bugs.freedesktop.org/show_bug.cgi?id=105363
fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
== Participating hosts (5 -> 5) ==
No changes in participating hosts
== Build changes ==
* Linux: CI_DRM_4513 -> Patchwork_9718
CI_DRM_4513: d592f2da0236d6d7ce4d4cccb40441c54dce5d91 @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4568: 86f7b724ef18986bc58d35558d22e1ed3f8df4f9 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_9718: f146b4a83eece6f2d42b30911d9fc6a922dff824 @ git://anongit.freedesktop.org/gfx-ci/linux
piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9718/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2018-07-19 21:13 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-18 10:29 [PATCH] drm/i915: Cache the error string Chris Wilson
2018-07-18 10:36 ` Chris Wilson
2018-07-18 10:38 ` ✗ Fi.CI.SPARSE: warning for " Patchwork
2018-07-18 10:59 ` ✓ Fi.CI.BAT: success " Patchwork
2018-07-18 11:21 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev2) Patchwork
2018-07-18 11:42 ` ✓ Fi.CI.BAT: success " Patchwork
2018-07-18 14:35 ` ✓ Fi.CI.IGT: " Patchwork
2018-07-18 19:59 ` [PATCH v3] drm/i915: Cache the error string Chris Wilson
2018-07-18 20:28 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev3) Patchwork
2018-07-18 20:50 ` ✓ Fi.CI.BAT: success " Patchwork
2018-07-18 22:11 ` ✓ Fi.CI.IGT: " Patchwork
2018-07-19 16:52 ` [PATCH v4] drm/i915: Cache the error string Chris Wilson
2018-07-19 17:08 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cache the error string (rev4) Patchwork
2018-07-19 17:30 ` ✓ Fi.CI.BAT: success " Patchwork
2018-07-19 21:13 ` ✓ Fi.CI.IGT: " Patchwork
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).