drm/i915/skl+: Fail the flip if ddb min requirement exceeds pipe allocation
authorKumar, Mahesh <mahesh1.kumar@intel.com>
Wed, 17 May 2017 11:58:26 +0000 (17:28 +0530)
committerMatt Roper <matthew.d.roper@intel.com>
Wed, 17 May 2017 21:32:57 +0000 (14:32 -0700)
DDB minimum requirement of crtc configuration (cumulative of all the
enabled planes in crtc) may exceed the allocated DDB for crtc/pipe.
This patch make changes to fail the flip/ioctl if minimum requirement
for pipe exceeds the total ddb allocated to the pipe.
Previously it succeeded but making alloc_size a negative value. Which
will make subsequent calculations for plane ddb allocation bogus & may
lead to screen corruption or system hang.

Changes from V1:
 - Improve commit message as per Ander's comment
 - Remove extra parentheses (Ander)

Signed-off-by: Mahesh Kumar <mahesh1.kumar@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170517115831.13830-8-mahesh1.kumar@intel.com
drivers/gpu/drm/i915/intel_pm.c

index 37dd3e7..bbc7206 100644 (file)
@@ -4057,6 +4057,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
        int num_active;
        unsigned plane_data_rate[I915_MAX_PLANES] = {};
        unsigned plane_y_data_rate[I915_MAX_PLANES] = {};
+       uint16_t total_min_blocks = 0;
 
        /* Clear the partitioning for disabled planes. */
        memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
@@ -4084,10 +4085,18 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
         */
 
        for_each_plane_id_on_crtc(intel_crtc, plane_id) {
-               alloc_size -= minimum[plane_id];
-               alloc_size -= y_minimum[plane_id];
+               total_min_blocks += minimum[plane_id];
+               total_min_blocks += y_minimum[plane_id];
        }
 
+       if (total_min_blocks > alloc_size) {
+               DRM_DEBUG_KMS("Requested display configuration exceeds system DDB limitations");
+               DRM_DEBUG_KMS("minimum required %d/%d\n", total_min_blocks,
+                                                       alloc_size);
+               return -EINVAL;
+       }
+
+       alloc_size -= total_min_blocks;
        ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - minimum[PLANE_CURSOR];
        ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;