diff options
author | Gordon Ross <gordon.w.ross@gmail.com> | 2016-10-28 21:29:32 -0400 |
---|---|---|
committer | Gordon Ross <gordon.w.ross@gmail.com> | 2016-11-22 21:55:25 -0500 |
commit | 02167e5266a5aecd4fcf8ab713e88c8a91efd314 (patch) | |
tree | 78db51fd0dde57c008a5ce4791c097d563f1f339 | |
parent | 34389f68da0422c10aa2f4edac7a44021b5f4cc8 (diff) | |
download | illumos-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.h | 2 | ||||
-rw-r--r-- | usr/src/uts/intel/io/i915/i915_gem.c | 6 | ||||
-rw-r--r-- | usr/src/uts/intel/io/i915/i915_gem_context.c | 8 | ||||
-rw-r--r-- | usr/src/uts/intel/io/i915/i915_gem_gtt.c | 37 |
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); } |