aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-07-16 18:40:49 -0400
committerDave Airlie <airlied@redhat.com>2013-07-16 18:40:49 -0400
commit6bd2cab2c1fd0616b28bb567543f53b624bf885a (patch)
tree52f8616f78609ab433f68b52ec62d8fdb6506409 /drivers/gpu
parentd1ce3d5496f2a7c90dd00a9133572f931d2acdcc (diff)
parent46a0b638f35b45fc13d3dc0deb6a7e17988170b2 (diff)
Merge tag 'drm-intel-fixes-2013-07-11' of git://people.freedesktop.org/~danvet/drm-intel
One feature latecomer, I've forgotten to merge the patch to reeanble the Haswell power well feature now that the audio interaction is fixed up. Since that was the only unfixed issue with it I've figured I could throw it in a bit late, and it's trivial to revert in case I'm wrong. Otherwise all bug/regression fixes: - Fix status page reinit after gpu hangs, spotted by more paranoid igt checks. - Fix object list walking fumble regression in the shrinker (only the counting part, the actual shrinking code was correct so no Oops potential), from Xiong Zhang. - Fix DP 1.2 bw limits (Imre). - Restore legacy forcewake on ivb, too many broken biosen out there. We dump a warn though that recent userspace might fall over with that config (Guenter Roeck). - Patch up the gen2 cs tlb w/a. - Improve the fence coherency w/a now that we have a better understanding what's going on. The removed wbinvd+ipi should make -rt folks happy. Big thanks to Jon Bloomfield for figuring this out, patches from Chris. - Fix write-read race when switching ring (Chris). Spotted with code inspection, but now we also have an igt for it. There's an ugly regression we're still working on introduced between 3.10-rc7 and 3.10.0. Unfortunately we can't just revert the offender since that one fixes another regression :( I've asked Steven to include my -fixes branch into linux-next to prevent such fallout in the future, hopefully. * tag 'drm-intel-fixes-2013-07-11' of git://people.freedesktop.org/~danvet/drm-intel: Revert "drm/i915: Workaround incoherence between fences and LLC across multiple CPUs" drm/i915: Fix incoherence with fence updates on Sandybridge+ drm/i915: Fix write-read race with multiple rings Partially revert "drm/i915: unconditionally use mt forcewake on hsw/ivb" drm/i915: fix lane bandwidth capping for DP 1.2 sinks drm/i915: fix up ring cleanup for the i830/i845 CS tlb w/a drm/i915: Correct obj->mm_list link to dev_priv->dev_priv->mm.inactive_list drm/i915: switch disable_power_well default value to 1 drm/i915: reinit status page registers after gpu reset
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c4
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c83
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c5
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c31
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c38
5 files changed, 93 insertions, 68 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 062cbda1bf4a..f4af1ca0fb62 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -123,10 +123,10 @@ module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 060
123MODULE_PARM_DESC(preliminary_hw_support, 123MODULE_PARM_DESC(preliminary_hw_support,
124 "Enable preliminary hardware support. (default: false)"); 124 "Enable preliminary hardware support. (default: false)");
125 125
126int i915_disable_power_well __read_mostly = 0; 126int i915_disable_power_well __read_mostly = 1;
127module_param_named(disable_power_well, i915_disable_power_well, int, 0600); 127module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
128MODULE_PARM_DESC(disable_power_well, 128MODULE_PARM_DESC(disable_power_well,
129 "Disable the power well when possible (default: false)"); 129 "Disable the power well when possible (default: true)");
130 130
131int i915_enable_ips __read_mostly = 1; 131int i915_enable_ips __read_mostly = 1;
132module_param_named(enable_ips, i915_enable_ips, int, 0600); 132module_param_named(enable_ips, i915_enable_ips, int, 0600);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 4200c32407ec..97afd2639fb6 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1880,6 +1880,10 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
1880 u32 seqno = intel_ring_get_seqno(ring); 1880 u32 seqno = intel_ring_get_seqno(ring);
1881 1881
1882 BUG_ON(ring == NULL); 1882 BUG_ON(ring == NULL);
1883 if (obj->ring != ring && obj->last_write_seqno) {
1884 /* Keep the seqno relative to the current ring */
1885 obj->last_write_seqno = seqno;
1886 }
1883 obj->ring = ring; 1887 obj->ring = ring;
1884 1888
1885 /* Add a reference if we're newly entering the active list. */ 1889 /* Add a reference if we're newly entering the active list. */
@@ -2653,7 +2657,6 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
2653 drm_i915_private_t *dev_priv = dev->dev_private; 2657 drm_i915_private_t *dev_priv = dev->dev_private;
2654 int fence_reg; 2658 int fence_reg;
2655 int fence_pitch_shift; 2659 int fence_pitch_shift;
2656 uint64_t val;
2657 2660
2658 if (INTEL_INFO(dev)->gen >= 6) { 2661 if (INTEL_INFO(dev)->gen >= 6) {
2659 fence_reg = FENCE_REG_SANDYBRIDGE_0; 2662 fence_reg = FENCE_REG_SANDYBRIDGE_0;
@@ -2663,8 +2666,23 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
2663 fence_pitch_shift = I965_FENCE_PITCH_SHIFT; 2666 fence_pitch_shift = I965_FENCE_PITCH_SHIFT;
2664 } 2667 }
2665 2668
2669 fence_reg += reg * 8;
2670
2671 /* To w/a incoherency with non-atomic 64-bit register updates,
2672 * we split the 64-bit update into two 32-bit writes. In order
2673 * for a partial fence not to be evaluated between writes, we
2674 * precede the update with write to turn off the fence register,
2675 * and only enable the fence as the last step.
2676 *
2677 * For extra levels of paranoia, we make sure each step lands
2678 * before applying the next step.
2679 */
2680 I915_WRITE(fence_reg, 0);
2681 POSTING_READ(fence_reg);
2682
2666 if (obj) { 2683 if (obj) {
2667 u32 size = obj->gtt_space->size; 2684 u32 size = obj->gtt_space->size;
2685 uint64_t val;
2668 2686
2669 val = (uint64_t)((obj->gtt_offset + size - 4096) & 2687 val = (uint64_t)((obj->gtt_offset + size - 4096) &
2670 0xfffff000) << 32; 2688 0xfffff000) << 32;
@@ -2673,12 +2691,16 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
2673 if (obj->tiling_mode == I915_TILING_Y) 2691 if (obj->tiling_mode == I915_TILING_Y)
2674 val |= 1 << I965_FENCE_TILING_Y_SHIFT; 2692 val |= 1 << I965_FENCE_TILING_Y_SHIFT;
2675 val |= I965_FENCE_REG_VALID; 2693 val |= I965_FENCE_REG_VALID;
2676 } else
2677 val = 0;
2678 2694
2679 fence_reg += reg * 8; 2695 I915_WRITE(fence_reg + 4, val >> 32);
2680 I915_WRITE64(fence_reg, val); 2696 POSTING_READ(fence_reg + 4);
2681 POSTING_READ(fence_reg); 2697
2698 I915_WRITE(fence_reg + 0, val);
2699 POSTING_READ(fence_reg);
2700 } else {
2701 I915_WRITE(fence_reg + 4, 0);
2702 POSTING_READ(fence_reg + 4);
2703 }
2682} 2704}
2683 2705
2684static void i915_write_fence_reg(struct drm_device *dev, int reg, 2706static void i915_write_fence_reg(struct drm_device *dev, int reg,
@@ -2796,56 +2818,17 @@ static inline int fence_number(struct drm_i915_private *dev_priv,
2796 return fence - dev_priv->fence_regs; 2818 return fence - dev_priv->fence_regs;
2797} 2819}
2798 2820
2799struct write_fence {
2800 struct drm_device *dev;
2801 struct drm_i915_gem_object *obj;
2802 int fence;
2803};
2804
2805static void i915_gem_write_fence__ipi(void *data)
2806{
2807 struct write_fence *args = data;
2808
2809 /* Required for SNB+ with LLC */
2810 wbinvd();
2811
2812 /* Required for VLV */
2813 i915_gem_write_fence(args->dev, args->fence, args->obj);
2814}
2815
2816static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, 2821static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
2817 struct drm_i915_fence_reg *fence, 2822 struct drm_i915_fence_reg *fence,
2818 bool enable) 2823 bool enable)
2819{ 2824{
2820 struct drm_i915_private *dev_priv = obj->base.dev->dev_private; 2825 struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
2821 struct write_fence args = { 2826 int reg = fence_number(dev_priv, fence);
2822 .dev = obj->base.dev, 2827
2823 .fence = fence_number(dev_priv, fence), 2828 i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL);
2824 .obj = enable ? obj : NULL,
2825 };
2826
2827 /* In order to fully serialize access to the fenced region and
2828 * the update to the fence register we need to take extreme
2829 * measures on SNB+. In theory, the write to the fence register
2830 * flushes all memory transactions before, and coupled with the
2831 * mb() placed around the register write we serialise all memory
2832 * operations with respect to the changes in the tiler. Yet, on
2833 * SNB+ we need to take a step further and emit an explicit wbinvd()
2834 * on each processor in order to manually flush all memory
2835 * transactions before updating the fence register.
2836 *
2837 * However, Valleyview complicates matter. There the wbinvd is
2838 * insufficient and unlike SNB/IVB requires the serialising
2839 * register write. (Note that that register write by itself is
2840 * conversely not sufficient for SNB+.) To compromise, we do both.
2841 */
2842 if (INTEL_INFO(args.dev)->gen >= 6)
2843 on_each_cpu(i915_gem_write_fence__ipi, &args, 1);
2844 else
2845 i915_gem_write_fence(args.dev, args.fence, args.obj);
2846 2829
2847 if (enable) { 2830 if (enable) {
2848 obj->fence_reg = args.fence; 2831 obj->fence_reg = reg;
2849 fence->obj = obj; 2832 fence->obj = obj;
2850 list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list); 2833 list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
2851 } else { 2834 } else {
@@ -4611,7 +4594,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
4611 list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) 4594 list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
4612 if (obj->pages_pin_count == 0) 4595 if (obj->pages_pin_count == 0)
4613 cnt += obj->base.size >> PAGE_SHIFT; 4596 cnt += obj->base.size >> PAGE_SHIFT;
4614 list_for_each_entry(obj, &dev_priv->mm.inactive_list, global_list) 4597 list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list)
4615 if (obj->pin_count == 0 && obj->pages_pin_count == 0) 4598 if (obj->pin_count == 0 && obj->pages_pin_count == 0)
4616 cnt += obj->base.size >> PAGE_SHIFT; 4599 cnt += obj->base.size >> PAGE_SHIFT;
4617 4600
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b73971234013..26e162bb3a51 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -75,7 +75,12 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp)
75 case DP_LINK_BW_1_62: 75 case DP_LINK_BW_1_62:
76 case DP_LINK_BW_2_7: 76 case DP_LINK_BW_2_7:
77 break; 77 break;
78 case DP_LINK_BW_5_4: /* 1.2 capable displays may advertise higher bw */
79 max_link_bw = DP_LINK_BW_2_7;
80 break;
78 default: 81 default:
82 WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n",
83 max_link_bw);
79 max_link_bw = DP_LINK_BW_1_62; 84 max_link_bw = DP_LINK_BW_1_62;
80 break; 85 break;
81 } 86 }
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ccbdd83f5220..d10e6735771f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5500,9 +5500,38 @@ void intel_gt_init(struct drm_device *dev)
5500 if (IS_VALLEYVIEW(dev)) { 5500 if (IS_VALLEYVIEW(dev)) {
5501 dev_priv->gt.force_wake_get = vlv_force_wake_get; 5501 dev_priv->gt.force_wake_get = vlv_force_wake_get;
5502 dev_priv->gt.force_wake_put = vlv_force_wake_put; 5502 dev_priv->gt.force_wake_put = vlv_force_wake_put;
5503 } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { 5503 } else if (IS_HASWELL(dev)) {
5504 dev_priv->gt.force_wake_get = __gen6_gt_force_wake_mt_get; 5504 dev_priv->gt.force_wake_get = __gen6_gt_force_wake_mt_get;
5505 dev_priv->gt.force_wake_put = __gen6_gt_force_wake_mt_put; 5505 dev_priv->gt.force_wake_put = __gen6_gt_force_wake_mt_put;
5506 } else if (IS_IVYBRIDGE(dev)) {
5507 u32 ecobus;
5508
5509 /* IVB configs may use multi-threaded forcewake */
5510
5511 /* A small trick here - if the bios hasn't configured
5512 * MT forcewake, and if the device is in RC6, then
5513 * force_wake_mt_get will not wake the device and the
5514 * ECOBUS read will return zero. Which will be
5515 * (correctly) interpreted by the test below as MT
5516 * forcewake being disabled.
5517 */
5518 mutex_lock(&dev->struct_mutex);
5519 __gen6_gt_force_wake_mt_get(dev_priv);
5520 ecobus = I915_READ_NOTRACE(ECOBUS);
5521 __gen6_gt_force_wake_mt_put(dev_priv);
5522 mutex_unlock(&dev->struct_mutex);
5523
5524 if (ecobus & FORCEWAKE_MT_ENABLE) {
5525 dev_priv->gt.force_wake_get =
5526 __gen6_gt_force_wake_mt_get;
5527 dev_priv->gt.force_wake_put =
5528 __gen6_gt_force_wake_mt_put;
5529 } else {
5530 DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n");
5531 DRM_INFO("when using vblank-synced partial screen updates.\n");
5532 dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
5533 dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
5534 }
5506 } else if (IS_GEN6(dev)) { 5535 } else if (IS_GEN6(dev)) {
5507 dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; 5536 dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
5508 dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; 5537 dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index e51ab552046c..664118d8c1d6 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -379,6 +379,17 @@ u32 intel_ring_get_active_head(struct intel_ring_buffer *ring)
379 return I915_READ(acthd_reg); 379 return I915_READ(acthd_reg);
380} 380}
381 381
382static void ring_setup_phys_status_page(struct intel_ring_buffer *ring)
383{
384 struct drm_i915_private *dev_priv = ring->dev->dev_private;
385 u32 addr;
386
387 addr = dev_priv->status_page_dmah->busaddr;
388 if (INTEL_INFO(ring->dev)->gen >= 4)
389 addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
390 I915_WRITE(HWS_PGA, addr);
391}
392
382static int init_ring_common(struct intel_ring_buffer *ring) 393static int init_ring_common(struct intel_ring_buffer *ring)
383{ 394{
384 struct drm_device *dev = ring->dev; 395 struct drm_device *dev = ring->dev;
@@ -390,6 +401,11 @@ static int init_ring_common(struct intel_ring_buffer *ring)
390 if (HAS_FORCE_WAKE(dev)) 401 if (HAS_FORCE_WAKE(dev))
391 gen6_gt_force_wake_get(dev_priv); 402 gen6_gt_force_wake_get(dev_priv);
392 403
404 if (I915_NEED_GFX_HWS(dev))
405 intel_ring_setup_status_page(ring);
406 else
407 ring_setup_phys_status_page(ring);
408
393 /* Stop the ring if it's running. */ 409 /* Stop the ring if it's running. */
394 I915_WRITE_CTL(ring, 0); 410 I915_WRITE_CTL(ring, 0);
395 I915_WRITE_HEAD(ring, 0); 411 I915_WRITE_HEAD(ring, 0);
@@ -518,9 +534,6 @@ cleanup_pipe_control(struct intel_ring_buffer *ring)
518 struct pipe_control *pc = ring->private; 534 struct pipe_control *pc = ring->private;
519 struct drm_i915_gem_object *obj; 535 struct drm_i915_gem_object *obj;
520 536
521 if (!ring->private)
522 return;
523
524 obj = pc->obj; 537 obj = pc->obj;
525 538
526 kunmap(sg_page(obj->pages->sgl)); 539 kunmap(sg_page(obj->pages->sgl));
@@ -528,7 +541,6 @@ cleanup_pipe_control(struct intel_ring_buffer *ring)
528 drm_gem_object_unreference(&obj->base); 541 drm_gem_object_unreference(&obj->base);
529 542
530 kfree(pc); 543 kfree(pc);
531 ring->private = NULL;
532} 544}
533 545
534static int init_render_ring(struct intel_ring_buffer *ring) 546static int init_render_ring(struct intel_ring_buffer *ring)
@@ -601,7 +613,10 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
601 if (HAS_BROKEN_CS_TLB(dev)) 613 if (HAS_BROKEN_CS_TLB(dev))
602 drm_gem_object_unreference(to_gem_object(ring->private)); 614 drm_gem_object_unreference(to_gem_object(ring->private));
603 615
604 cleanup_pipe_control(ring); 616 if (INTEL_INFO(dev)->gen >= 5)
617 cleanup_pipe_control(ring);
618
619 ring->private = NULL;
605} 620}
606 621
607static void 622static void
@@ -1223,7 +1238,6 @@ static int init_status_page(struct intel_ring_buffer *ring)
1223 ring->status_page.obj = obj; 1238 ring->status_page.obj = obj;
1224 memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1239 memset(ring->status_page.page_addr, 0, PAGE_SIZE);
1225 1240
1226 intel_ring_setup_status_page(ring);
1227 DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1241 DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
1228 ring->name, ring->status_page.gfx_addr); 1242 ring->name, ring->status_page.gfx_addr);
1229 1243
@@ -1237,10 +1251,9 @@ err:
1237 return ret; 1251 return ret;
1238} 1252}
1239 1253
1240static int init_phys_hws_pga(struct intel_ring_buffer *ring) 1254static int init_phys_status_page(struct intel_ring_buffer *ring)
1241{ 1255{
1242 struct drm_i915_private *dev_priv = ring->dev->dev_private; 1256 struct drm_i915_private *dev_priv = ring->dev->dev_private;
1243 u32 addr;
1244 1257
1245 if (!dev_priv->status_page_dmah) { 1258 if (!dev_priv->status_page_dmah) {
1246 dev_priv->status_page_dmah = 1259 dev_priv->status_page_dmah =
@@ -1249,11 +1262,6 @@ static int init_phys_hws_pga(struct intel_ring_buffer *ring)
1249 return -ENOMEM; 1262 return -ENOMEM;
1250 } 1263 }
1251 1264
1252 addr = dev_priv->status_page_dmah->busaddr;
1253 if (INTEL_INFO(ring->dev)->gen >= 4)
1254 addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
1255 I915_WRITE(HWS_PGA, addr);
1256
1257 ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 1265 ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
1258 memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1266 memset(ring->status_page.page_addr, 0, PAGE_SIZE);
1259 1267
@@ -1281,7 +1289,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
1281 return ret; 1289 return ret;
1282 } else { 1290 } else {
1283 BUG_ON(ring->id != RCS); 1291 BUG_ON(ring->id != RCS);
1284 ret = init_phys_hws_pga(ring); 1292 ret = init_phys_status_page(ring);
1285 if (ret) 1293 if (ret)
1286 return ret; 1294 return ret;
1287 } 1295 }
@@ -1893,7 +1901,7 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
1893 } 1901 }
1894 1902
1895 if (!I915_NEED_GFX_HWS(dev)) { 1903 if (!I915_NEED_GFX_HWS(dev)) {
1896 ret = init_phys_hws_pga(ring); 1904 ret = init_phys_status_page(ring);
1897 if (ret) 1905 if (ret)
1898 return ret; 1906 return ret;
1899 } 1907 }