|
@@ -656,7 +656,7 @@ static void i915_error_object_free(struct drm_i915_error_object *obj)
|
|
return;
|
|
return;
|
|
|
|
|
|
for (page = 0; page < obj->page_count; page++)
|
|
for (page = 0; page < obj->page_count; page++)
|
|
- kfree(obj->pages[page]);
|
|
|
|
|
|
+ free_page((unsigned long)obj->pages[page]);
|
|
|
|
|
|
kfree(obj);
|
|
kfree(obj);
|
|
}
|
|
}
|
|
@@ -693,98 +693,69 @@ static void i915_error_state_free(struct kref *error_ref)
|
|
kfree(error);
|
|
kfree(error);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int compress_page(void *src, struct drm_i915_error_object *dst)
|
|
|
|
+{
|
|
|
|
+ unsigned long page;
|
|
|
|
+
|
|
|
|
+ page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN);
|
|
|
|
+ if (!page)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ dst->pages[dst->page_count++] = (void *)page;
|
|
|
|
+
|
|
|
|
+ memcpy((void *)page, src, PAGE_SIZE);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static struct drm_i915_error_object *
|
|
static struct drm_i915_error_object *
|
|
-i915_error_object_create(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
+i915_error_object_create(struct drm_i915_private *i915,
|
|
struct i915_vma *vma)
|
|
struct i915_vma *vma)
|
|
{
|
|
{
|
|
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
|
|
|
- struct drm_i915_gem_object *src;
|
|
|
|
|
|
+ struct i915_ggtt *ggtt = &i915->ggtt;
|
|
|
|
+ const u64 slot = ggtt->error_capture.start;
|
|
struct drm_i915_error_object *dst;
|
|
struct drm_i915_error_object *dst;
|
|
- int num_pages;
|
|
|
|
- bool use_ggtt;
|
|
|
|
- int i = 0;
|
|
|
|
- u64 reloc_offset;
|
|
|
|
|
|
+ unsigned long num_pages;
|
|
|
|
+ struct sgt_iter iter;
|
|
|
|
+ dma_addr_t dma;
|
|
|
|
|
|
if (!vma)
|
|
if (!vma)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
- src = vma->obj;
|
|
|
|
- if (!src->pages)
|
|
|
|
- return NULL;
|
|
|
|
-
|
|
|
|
- num_pages = src->base.size >> PAGE_SHIFT;
|
|
|
|
-
|
|
|
|
- dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
|
|
|
|
|
|
+ num_pages = min_t(u64, vma->size, vma->obj->base.size) >> PAGE_SHIFT;
|
|
|
|
+ dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *),
|
|
|
|
+ GFP_ATOMIC | __GFP_NOWARN);
|
|
if (!dst)
|
|
if (!dst)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
dst->gtt_offset = vma->node.start;
|
|
dst->gtt_offset = vma->node.start;
|
|
dst->gtt_size = vma->node.size;
|
|
dst->gtt_size = vma->node.size;
|
|
|
|
+ dst->page_count = 0;
|
|
|
|
|
|
- reloc_offset = dst->gtt_offset;
|
|
|
|
- use_ggtt = (src->cache_level == I915_CACHE_NONE &&
|
|
|
|
- (vma->flags & I915_VMA_GLOBAL_BIND) &&
|
|
|
|
- reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end);
|
|
|
|
-
|
|
|
|
- /* Cannot access stolen address directly, try to use the aperture */
|
|
|
|
- if (src->stolen) {
|
|
|
|
- use_ggtt = true;
|
|
|
|
-
|
|
|
|
- if (!(vma->flags & I915_VMA_GLOBAL_BIND))
|
|
|
|
- goto unwind;
|
|
|
|
-
|
|
|
|
- reloc_offset = vma->node.start;
|
|
|
|
- if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end)
|
|
|
|
- goto unwind;
|
|
|
|
- }
|
|
|
|
|
|
+ for_each_sgt_dma(dma, iter, vma->pages) {
|
|
|
|
+ void __iomem *s;
|
|
|
|
+ int ret;
|
|
|
|
|
|
- /* Cannot access snooped pages through the aperture */
|
|
|
|
- if (use_ggtt && src->cache_level != I915_CACHE_NONE &&
|
|
|
|
- !HAS_LLC(dev_priv))
|
|
|
|
- goto unwind;
|
|
|
|
|
|
+ ggtt->base.insert_page(&ggtt->base, dma, slot,
|
|
|
|
+ I915_CACHE_NONE, 0);
|
|
|
|
|
|
- dst->page_count = num_pages;
|
|
|
|
- while (num_pages--) {
|
|
|
|
- void *d;
|
|
|
|
|
|
+ s = io_mapping_map_atomic_wc(&ggtt->mappable, slot);
|
|
|
|
+ ret = compress_page((void * __force)s, dst);
|
|
|
|
+ io_mapping_unmap_atomic(s);
|
|
|
|
|
|
- d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
|
|
|
|
- if (d == NULL)
|
|
|
|
|
|
+ if (ret)
|
|
goto unwind;
|
|
goto unwind;
|
|
-
|
|
|
|
- if (use_ggtt) {
|
|
|
|
- void __iomem *s;
|
|
|
|
-
|
|
|
|
- /* Simply ignore tiling or any overlapping fence.
|
|
|
|
- * It's part of the error state, and this hopefully
|
|
|
|
- * captures what the GPU read.
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
- s = io_mapping_map_atomic_wc(&ggtt->mappable,
|
|
|
|
- reloc_offset);
|
|
|
|
- memcpy_fromio(d, s, PAGE_SIZE);
|
|
|
|
- io_mapping_unmap_atomic(s);
|
|
|
|
- } else {
|
|
|
|
- struct page *page;
|
|
|
|
- void *s;
|
|
|
|
-
|
|
|
|
- page = i915_gem_object_get_page(src, i);
|
|
|
|
-
|
|
|
|
- s = kmap_atomic(page);
|
|
|
|
- memcpy(d, s, PAGE_SIZE);
|
|
|
|
- kunmap_atomic(s);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- dst->pages[i++] = d;
|
|
|
|
- reloc_offset += PAGE_SIZE;
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- return dst;
|
|
|
|
|
|
+ goto out;
|
|
|
|
|
|
unwind:
|
|
unwind:
|
|
- while (i--)
|
|
|
|
- kfree(dst->pages[i]);
|
|
|
|
|
|
+ while (dst->page_count--)
|
|
|
|
+ free_page((unsigned long)dst->pages[dst->page_count]);
|
|
kfree(dst);
|
|
kfree(dst);
|
|
- return NULL;
|
|
|
|
|
|
+ dst = NULL;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE, true);
|
|
|
|
+ return dst;
|
|
}
|
|
}
|
|
|
|
|
|
/* The error capture is special as tries to run underneath the normal
|
|
/* The error capture is special as tries to run underneath the normal
|
|
@@ -1445,9 +1416,6 @@ static int capture(void *data)
|
|
{
|
|
{
|
|
struct drm_i915_error_state *error = data;
|
|
struct drm_i915_error_state *error = data;
|
|
|
|
|
|
- /* Ensure that what we readback from memory matches what the GPU sees */
|
|
|
|
- wbinvd();
|
|
|
|
-
|
|
|
|
i915_capture_gen_state(error->i915, error);
|
|
i915_capture_gen_state(error->i915, error);
|
|
i915_capture_reg_state(error->i915, error);
|
|
i915_capture_reg_state(error->i915, error);
|
|
i915_gem_record_fences(error->i915, error);
|
|
i915_gem_record_fences(error->i915, error);
|
|
@@ -1460,9 +1428,6 @@ static int capture(void *data)
|
|
error->overlay = intel_overlay_capture_error_state(error->i915);
|
|
error->overlay = intel_overlay_capture_error_state(error->i915);
|
|
error->display = intel_display_capture_error_state(error->i915);
|
|
error->display = intel_display_capture_error_state(error->i915);
|
|
|
|
|
|
- /* And make sure we don't leave trash in the CPU cache */
|
|
|
|
- wbinvd();
|
|
|
|
-
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1539,7 +1504,6 @@ void i915_error_state_get(struct drm_device *dev,
|
|
if (error_priv->error)
|
|
if (error_priv->error)
|
|
kref_get(&error_priv->error->ref);
|
|
kref_get(&error_priv->error->ref);
|
|
spin_unlock_irq(&dev_priv->gpu_error.lock);
|
|
spin_unlock_irq(&dev_priv->gpu_error.lock);
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void i915_error_state_put(struct i915_error_state_file_priv *error_priv)
|
|
void i915_error_state_put(struct i915_error_state_file_priv *error_priv)
|