summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Ross <gordon.w.ross@gmail.com>2016-10-28 21:29:32 -0400
committerGordon Ross <gordon.w.ross@gmail.com>2016-11-22 21:55:25 -0500
commit02167e5266a5aecd4fcf8ab713e88c8a91efd314 (patch)
tree78db51fd0dde57c008a5ce4791c097d563f1f339
parent34389f68da0422c10aa2f4edac7a44021b5f4cc8 (diff)
downloadillumos-gfx-drm-02167e5266a5aecd4fcf8ab713e88c8a91efd314.tar.gz
Fix crashes to do with missing scratch_page
Fix panic in i915_gem_context_fini
-rw-r--r--usr/src/uts/intel/io/i915/i915_drv.h2
-rw-r--r--usr/src/uts/intel/io/i915/i915_gem.c6
-rw-r--r--usr/src/uts/intel/io/i915/i915_gem_context.c8
-rw-r--r--usr/src/uts/intel/io/i915/i915_gem_gtt.c37
4 files changed, 42 insertions, 11 deletions
diff --git a/usr/src/uts/intel/io/i915/i915_drv.h b/usr/src/uts/intel/io/i915/i915_drv.h
index a5c6e75..be7745d 100644
--- a/usr/src/uts/intel/io/i915/i915_drv.h
+++ b/usr/src/uts/intel/io/i915/i915_drv.h
@@ -1834,7 +1834,7 @@ void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level);
void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj, uint32_t type);
void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
-void i915_gem_init_global_gtt(struct drm_device *dev);
+int i915_gem_init_global_gtt(struct drm_device *dev);
void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start,
unsigned long mappable_end, unsigned long end);
int setup_scratch_page(struct drm_device *dev);
diff --git a/usr/src/uts/intel/io/i915/i915_gem.c b/usr/src/uts/intel/io/i915/i915_gem.c
index de59d85..4c89a79 100644
--- a/usr/src/uts/intel/io/i915/i915_gem.c
+++ b/usr/src/uts/intel/io/i915/i915_gem.c
@@ -3599,7 +3599,11 @@ int i915_gem_init(struct drm_device *dev)
DRM_DEBUG_DRIVER("allow wake ack timed out\n");
}
- i915_gem_init_global_gtt(dev);
+ ret = i915_gem_init_global_gtt(dev);
+ if (ret) {
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
size = drm_getfb_size(dev);
dev_priv->fbcon_obj = NULL;
diff --git a/usr/src/uts/intel/io/i915/i915_gem_context.c b/usr/src/uts/intel/io/i915/i915_gem_context.c
index 55bc0a7..44b1b09 100644
--- a/usr/src/uts/intel/io/i915/i915_gem_context.c
+++ b/usr/src/uts/intel/io/i915/i915_gem_context.c
@@ -299,6 +299,14 @@ void i915_gem_context_fini(struct drm_device *dev)
* other code, leading to spurious errors. */
intel_gpu_reset(dev);
+ /* Got a panic here with dctx=0 during reboot when Xorg was up.
+ * So... apparentl the context_unreference might already have
+ * happened when we get here? Not sure how, but check...
+ */
+ if (dctx == NULL) {
+ DRM_DEBUG_DRIVER("i915_gem_context_fini, dctx=0\n");
+ return;
+ }
i915_gem_object_unpin(dctx->obj);
/* When default context is created and switched to, base object refcount
diff --git a/usr/src/uts/intel/io/i915/i915_gem_gtt.c b/usr/src/uts/intel/io/i915/i915_gem_gtt.c
index a0db09e..83fbac7 100644
--- a/usr/src/uts/intel/io/i915/i915_gem_gtt.c
+++ b/usr/src/uts/intel/io/i915/i915_gem_gtt.c
@@ -679,10 +679,11 @@ intel_enable_ppgtt(struct drm_device *dev)
return true;
}
-void i915_gem_init_global_gtt(struct drm_device *dev)
+int i915_gem_init_global_gtt(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long gtt_size, mappable_size;
+ int ret;
gtt_size = dev_priv->gtt.total;
mappable_size = dev_priv->gtt.mappable_end;
@@ -697,18 +698,19 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
}
i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
- setup_scratch_page(dev);
+ ret = setup_scratch_page(dev);
+ if (ret)
+ return ret;
if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
- int ret;
ret = i915_gem_init_aliasing_ppgtt(dev);
if (!ret)
- return;
+ return 0;
DRM_ERROR("Aliased PPGTT setup failed %d\n", ret);
drm_mm_takedown(&dev_priv->mm.gtt_space);
gtt_size += I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
}
-
+ return 0;
}
int setup_scratch_page(struct drm_device *dev)
@@ -718,8 +720,10 @@ int setup_scratch_page(struct drm_device *dev)
/* setup scratch page */
dev_priv->gtt.scratch_page = kzalloc(sizeof(struct drm_gem_object), GFP_KERNEL);
- if (dev_priv->gtt.scratch_page == NULL)
+ if (dev_priv->gtt.scratch_page == NULL) {
+ DRM_ERROR("setup_scratch_page: gem object init failed");
return (-ENOMEM);
+ }
if (IS_G33(dev))
gen = 33;
@@ -728,6 +732,8 @@ int setup_scratch_page(struct drm_device *dev)
if (drm_gem_object_init(dev, dev_priv->gtt.scratch_page, DRM_PAGE_SIZE, gen) != 0) {
kmem_free(dev_priv->gtt.scratch_page, sizeof (struct drm_gem_object));
+ dev_priv->gtt.scratch_page = NULL;
+ DRM_ERROR("setup_scratch_page: gem object init failed");
return (-ENOMEM);
}
(void) memset(dev_priv->gtt.scratch_page->kaddr, 0, DRM_PAGE_SIZE);
@@ -739,6 +745,9 @@ void teardown_scratch_page(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ if (dev_priv->gtt.scratch_page == NULL)
+ return;
+
drm_gem_object_release(dev_priv->gtt.scratch_page);
kmem_free(dev_priv->gtt.scratch_page, sizeof (struct drm_gem_object));
}
@@ -1160,18 +1169,28 @@ i915_clean_gtt(struct drm_device *dev, size_t offset)
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned first_entry = offset >> PAGE_SHIFT;
unsigned num_entries = (dev_priv->gtt.total - offset - PAGE_SIZE) >> PAGE_SHIFT;
- uint64_t scratch_page_addr = dev_priv->gtt.scratch_page->pfnarray[0] << PAGE_SHIFT;
+ pfn_t scratch_pfn = 0;
gtt_pte_t *gtt_addr, scratch_pte;
int i;
+ if (dev_priv->gtt.scratch_page != NULL)
+ scratch_pfn = dev_priv->gtt.scratch_page->pfnarray[0];
+
if (INTEL_INFO(dev)->gen <= 5) {
(void) drm_agp_unbind_pages(dev, NULL, num_entries,
- offset, dev_priv->gtt.scratch_page->pfnarray[0] ,1);
+ offset, scratch_pfn, 1);
} else {
+ if (scratch_pfn != 0) {
+ uint64_t scratch_page_addr = scratch_pfn << PAGE_SHIFT;
+ scratch_pte = gen6_pte_encode(dev, scratch_page_addr, I915_CACHE_LLC);
+ } else {
+ /* No scratch page? Use an invalid PTE. */
+ scratch_pte = 0;
+ }
+
for (i = first_entry ; i < ( first_entry + num_entries); i++) {
gtt_addr = (gtt_pte_t *)(uintptr_t)((caddr_t)dev_priv->gtt.virtual_gtt
+ i * sizeof(gtt_pte_t));
- scratch_pte = gen6_pte_encode(dev, scratch_page_addr, I915_CACHE_LLC);
ddi_put32(dev_priv->gtt.gtt_mapping.acc_handle,
gtt_addr, scratch_pte);
}