From 753b1ad4a281b0663329409d410243e91825c323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 11 Feb 2014 19:52:05 +0200 Subject: drm/i915: Add intel_ring_cachline_align() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_ring_cachline_align() emits MI_NOOPs until the ring tail is aligned to a cacheline boundary. Cc: Bjoern C Cc: Alexandru DAMIAN Cc: Enrico Tagliavini Suggested-by: Chris Wilson Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Cc: stable@vger.kernel.org (prereq for the next patch) Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b7f1742..31b36c5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1653,6 +1653,27 @@ int intel_ring_begin(struct intel_ring_buffer *ring, return 0; } +/* Align the ring tail to a cacheline boundary */ +int intel_ring_cacheline_align(struct intel_ring_buffer *ring) +{ + int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t); + int ret; + + if (num_dwords == 0) + return 0; + + ret = intel_ring_begin(ring, num_dwords); + if (ret) + return ret; + + while (num_dwords--) + intel_ring_emit(ring, MI_NOOP); + + intel_ring_advance(ring); + + return 0; +} + void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) { struct drm_i915_private *dev_priv = ring->dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 71a73f4..0b243ce 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -233,6 +233,7 @@ intel_write_status_page(struct intel_ring_buffer *ring, void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring); int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n); +int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring); static inline void intel_ring_emit(struct intel_ring_buffer *ring, u32 data) { -- cgit v0.10.2 From f66fab8e1cd6b3127ba4c5c0d11539fbe1de1e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 11 Feb 2014 19:52:06 +0200 Subject: drm/i915: Prevent MI_DISPLAY_FLIP straddling two cachelines on IVB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to BSpec the entire MI_DISPLAY_FLIP packet must be contained in a single cacheline. Make sure that happens. v2: Use intel_ring_begin_cacheline_safe() v3: Use intel_ring_cacheline_align() (Chris) Cc: Bjoern C Cc: Alexandru DAMIAN Cc: Enrico Tagliavini Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74053 Signed-off-by: Ville Syrjälä Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 40a9338..88ad172 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8586,6 +8586,20 @@ static int intel_gen7_queue_flip(struct drm_device *dev, if (ring->id == RCS) len += 6; + /* + * BSpec MI_DISPLAY_FLIP for IVB: + * "The full packet must be contained within the same cache line." + * + * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same + * cacheline, if we ever start emitting more commands before + * the MI_DISPLAY_FLIP we may need to first emit everything else, + * then do the cacheline alignment, and finally emit the + * MI_DISPLAY_FLIP. + */ + ret = intel_ring_cacheline_align(ring); + if (ret) + goto err_unpin; + ret = intel_ring_begin(ring, len); if (ret) goto err_unpin; -- cgit v0.10.2 From 04eada25d1f72efdecd32d702706594f81de65d5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 11 Feb 2014 11:52:04 +0200 Subject: drm/i915/dp: increase native aux defer retry timeout Give more slack to sink devices before retrying on native aux defer. AFAICT the 100 us timeout was not based on the DP spec. Signed-off-by: Jani Nikula Cc: stable@vger.kernel.org (on Jani's request) Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2f517b8..c3696048 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -556,7 +556,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) break; else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) - udelay(100); + usleep_range(400, 500); else return -EIO; } @@ -608,7 +608,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, return ret - 1; } else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) - udelay(100); + usleep_range(400, 500); else return -EIO; } -- cgit v0.10.2 From f51a44b9a6c4982cc25bfb3727de9bb893621ebc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 11 Feb 2014 11:52:05 +0200 Subject: drm/i915/dp: add native aux defer retry limit Retrying indefinitely places too much trust on the aux implementation of the sink devices. Reported-by: Daniel Martin Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71267 Signed-off-by: Jani Nikula Cc: stable@vger.kernel.org Tested-by: Theodore Ts'o Tested-by: Sree Harsha Totakura Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c3696048..57552eb 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -537,6 +537,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, uint8_t msg[20]; int msg_bytes; uint8_t ack; + int retry; if (WARN_ON(send_bytes > 16)) return -E2BIG; @@ -548,19 +549,21 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, msg[3] = send_bytes - 1; memcpy(&msg[4], send, send_bytes); msg_bytes = send_bytes + 4; - for (;;) { + for (retry = 0; retry < 7; retry++) { ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1); if (ret < 0) return ret; ack >>= 4; if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) - break; + return send_bytes; else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) usleep_range(400, 500); else return -EIO; } - return send_bytes; + + DRM_ERROR("too many retries, giving up\n"); + return -EIO; } /* Write a single byte to the aux channel in native mode */ @@ -582,6 +585,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, int reply_bytes; uint8_t ack; int ret; + int retry; if (WARN_ON(recv_bytes > 19)) return -E2BIG; @@ -595,7 +599,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, msg_bytes = 4; reply_bytes = recv_bytes + 1; - for (;;) { + for (retry = 0; retry < 7; retry++) { ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, reply, reply_bytes); if (ret == 0) @@ -612,6 +616,9 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, else return -EIO; } + + DRM_ERROR("too many retries, giving up\n"); + return -EIO; } static int -- cgit v0.10.2