[Intel-gfx] [PATCH v9] drm/i915/skl: Update DDB values atomically with wms/plane attrs

2016-08-08 Thread Lyude
Now that we can hook into update_crtcs and control the order in which we
update CRTCs at each modeset, we can finish the final step of fixing
Skylake's watermark handling by performing DDB updates at the same time
as plane updates and watermark updates.

The first major change in this patch is skl_update_crtcs(), which
handles ensuring that we order each CRTC update in our atomic commits
properly so that they honor the DDB flush order.

The second major change in this patch is the order in which we flush the
pipes. While the previous order may have worked, it can't be used in
this approach since it no longer will do the right thing. For example,
using the old ddb flush order:

We have pipes A, B, and C enabled, and we're disabling C. Initial ddb
allocation looks like this:

|   A   |   B   |xxx|

Since we're performing the ddb updates after performing any CRTC
disablements in intel_atomic_commit_tail(), the space to the right of
pipe B is unallocated.

1. Flush pipes with new allocation contained into old space. None
   apply, so we skip this
2. Flush pipes having their allocation reduced, but overlapping with a
   previous allocation. None apply, so we also skip this
3. Flush pipes that got more space allocated. This applies to A and B,
   giving us the following update order: A, B

This is wrong, since updating pipe A first will cause it to overlap with
B and potentially burst into flames. Our new order (see the code
comments for details) would update the pipes in the proper order: B, A.

As well, we calculate the order for each DDB update during the check
phase, and reference it later in the commit phase when we hit
skl_update_crtcs().

This long overdue patch fixes the rest of the underruns on Skylake.

Changes since v1:
 - Add skl_ddb_entry_write() for cursor into skl_write_cursor_wm()
Changes since v2:
 - Use the method for updating CRTCs that Ville suggested
 - In skl_update_wm(), only copy the watermarks for the crtc that was
   passed to us
Changes since v3:
 - Small comment fix in skl_ddb_allocation_overlaps()

Fixes: 0e8fb7ba7ca5 ("drm/i915/skl: Flush the WM configuration")
Fixes: 8211bd5bdf5e ("drm/i915/skl: Program the DDB allocation")
[omitting CC for stable, since this patch will need to be changed for
such backports first]

Testcase: kms_cursor_legacy
Signed-off-by: Lyude 
Reviewed-by: Maarten Lankhorst 
Cc: Ville Syrjälä 
Cc: Daniel Vetter 
Cc: Radhakrishna Sripada 
Cc: Hans de Goede 
Cc: Matt Roper 
---
 drivers/gpu/drm/i915/intel_display.c | 100 +++--
 drivers/gpu/drm/i915/intel_drv.h |   7 ++
 drivers/gpu/drm/i915/intel_pm.c  | 207 +--
 3 files changed, 144 insertions(+), 170 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 980b6fd..ad5f6e5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12903,16 +12903,23 @@ static void verify_wm_state(struct drm_crtc *crtc,
  hw_entry->start, hw_entry->end);
}
 
-   /* cursor */
-   hw_entry = _ddb.plane[pipe][PLANE_CURSOR];
-   sw_entry = _ddb->plane[pipe][PLANE_CURSOR];
-
-   if (!skl_ddb_entry_equal(hw_entry, sw_entry)) {
-   DRM_ERROR("mismatch in DDB state pipe %c cursor "
- "(expected (%u,%u), found (%u,%u))\n",
- pipe_name(pipe),
- sw_entry->start, sw_entry->end,
- hw_entry->start, hw_entry->end);
+   /*
+* cursor
+* If the cursor plane isn't active, we may not have updated it's ddb
+* allocation. In that case since the ddb allocation will be updated
+* once the plane becomes visible, we can skip this check
+*/
+   if (intel_crtc->cursor_addr) {
+   hw_entry = _ddb.plane[pipe][PLANE_CURSOR];
+   sw_entry = _ddb->plane[pipe][PLANE_CURSOR];
+
+   if (!skl_ddb_entry_equal(hw_entry, sw_entry)) {
+   DRM_ERROR("mismatch in DDB state pipe %c cursor "
+ "(expected (%u,%u), found (%u,%u))\n",
+ pipe_name(pipe),
+ sw_entry->start, sw_entry->end,
+ hw_entry->start, hw_entry->end);
+   }
}
 }
 
@@ -13664,6 +13671,72 @@ static void intel_update_crtcs(struct drm_atomic_state 
*state,
}
 }
 
+static void skl_update_crtcs(struct drm_atomic_state *state,
+unsigned int *crtc_vblank_mask)
+{
+   struct drm_device *dev = state->dev;
+   struct drm_i915_private *dev_priv = to_i915(dev);
+   struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+   

[Intel-gfx] [PATCH v9] drm/i915/skl: Update DDB values atomically with wms/plane attrs

2016-08-08 Thread Lyude
Now that we can hook into update_crtcs and control the order in which we
update CRTCs at each modeset, we can finish the final step of fixing
Skylake's watermark handling by performing DDB updates at the same time
as plane updates and watermark updates.

The first major change in this patch is skl_update_crtcs(), which
handles ensuring that we order each CRTC update in our atomic commits
properly so that they honor the DDB flush order.

The second major change in this patch is the order in which we flush the
pipes. While the previous order may have worked, it can't be used in
this approach since it no longer will do the right thing. For example,
using the old ddb flush order:

We have pipes A, B, and C enabled, and we're disabling C. Initial ddb
allocation looks like this:

|   A   |   B   |xxx|

Since we're performing the ddb updates after performing any CRTC
disablements in intel_atomic_commit_tail(), the space to the right of
pipe B is unallocated.

1. Flush pipes with new allocation contained into old space. None
   apply, so we skip this
2. Flush pipes having their allocation reduced, but overlapping with a
   previous allocation. None apply, so we also skip this
3. Flush pipes that got more space allocated. This applies to A and B,
   giving us the following update order: A, B

This is wrong, since updating pipe A first will cause it to overlap with
B and potentially burst into flames. Our new order (see the code
comments for details) would update the pipes in the proper order: B, A.

As well, we calculate the order for each DDB update during the check
phase, and reference it later in the commit phase when we hit
skl_update_crtcs().

This long overdue patch fixes the rest of the underruns on Skylake.

Changes since v1:
 - Add skl_ddb_entry_write() for cursor into skl_write_cursor_wm()
Changes since v2:
 - Use the method for updating CRTCs that Ville suggested
 - In skl_update_wm(), only copy the watermarks for the crtc that was
   passed to us
Changes since v3:
 - Small comment fix in skl_ddb_allocation_overlaps()

Fixes: 0e8fb7ba7ca5 ("drm/i915/skl: Flush the WM configuration")
Fixes: 8211bd5bdf5e ("drm/i915/skl: Program the DDB allocation")
[omitting CC for stable, since this patch will need to be changed for
such backports first]

Testcase: kms_cursor_legacy
Signed-off-by: Lyude 
Reviewed-by: Maarten Lankhorst 
Cc: Ville Syrjälä 
Cc: Daniel Vetter 
Cc: Radhakrishna Sripada 
Cc: Hans de Goede 
Cc: Matt Roper 
---
 drivers/gpu/drm/i915/intel_display.c | 100 +++--
 drivers/gpu/drm/i915/intel_drv.h |   7 ++
 drivers/gpu/drm/i915/intel_pm.c  | 207 +--
 3 files changed, 144 insertions(+), 170 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 980b6fd..ad5f6e5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12903,16 +12903,23 @@ static void verify_wm_state(struct drm_crtc *crtc,
  hw_entry->start, hw_entry->end);
}
 
-   /* cursor */
-   hw_entry = _ddb.plane[pipe][PLANE_CURSOR];
-   sw_entry = _ddb->plane[pipe][PLANE_CURSOR];
-
-   if (!skl_ddb_entry_equal(hw_entry, sw_entry)) {
-   DRM_ERROR("mismatch in DDB state pipe %c cursor "
- "(expected (%u,%u), found (%u,%u))\n",
- pipe_name(pipe),
- sw_entry->start, sw_entry->end,
- hw_entry->start, hw_entry->end);
+   /*
+* cursor
+* If the cursor plane isn't active, we may not have updated it's ddb
+* allocation. In that case since the ddb allocation will be updated
+* once the plane becomes visible, we can skip this check
+*/
+   if (intel_crtc->cursor_addr) {
+   hw_entry = _ddb.plane[pipe][PLANE_CURSOR];
+   sw_entry = _ddb->plane[pipe][PLANE_CURSOR];
+
+   if (!skl_ddb_entry_equal(hw_entry, sw_entry)) {
+   DRM_ERROR("mismatch in DDB state pipe %c cursor "
+ "(expected (%u,%u), found (%u,%u))\n",
+ pipe_name(pipe),
+ sw_entry->start, sw_entry->end,
+ hw_entry->start, hw_entry->end);
+   }
}
 }
 
@@ -13664,6 +13671,72 @@ static void intel_update_crtcs(struct drm_atomic_state 
*state,
}
 }
 
+static void skl_update_crtcs(struct drm_atomic_state *state,
+unsigned int *crtc_vblank_mask)
+{
+   struct drm_device *dev = state->dev;
+   struct drm_i915_private *dev_priv = to_i915(dev);
+   struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+