• Matt Roper's avatar
    drm/i915: Switch to level-based DDB allocation algorithm (v5) · d8e87498
    Matt Roper authored
    The DDB allocation algorithm currently used by the driver grants each
    plane a very small minimum allocation of DDB blocks and then divies up
    all of the remaining blocks based on the percentage of the total data
    rate that the plane makes up.  It turns out that this proportional
    allocation approach is overly-generous with the larger planes and can
    leave very small planes wthout a big enough allocation to even hit their
    level 0 watermark requirements (especially on APL, which has a smaller
    DDB in general than other gen9 platforms).  Or there can be situations
    where the smallest planes hit a lower watermark level than they should
    have been able to hit with a more equitable division of DDB blocks, thus
    limiting the overall system sleep state that can be achieved.
    
    The bspec now describes an alternate algorithm that can be used to
    overcome these types of issues.  With the new algorithm, we calculate
    all plane watermark values for all wm levels first, then go back and
    partition a pipe's DDB space second.  The DDB allocation will calculate
    what the highest watermark level that can be achieved on *all* active
    planes, and then grant the blocks necessary to hit that level to each
    plane.  Any remaining blocks are then divided up proportionally
    according to data rate, similar to the old algorithm.
    
    There was a previous attempt to implement this algorithm a couple years
    ago in bb9d85f6 ("drm/i915/skl: New ddb allocation algorithm"), but
    some regressions were reported, the patch was reverted, and nobody
    ever got around to figuring out exactly where the bug was in that
    version.  Our watermark code has evolved significantly in the meantime,
    but we're still getting bug reports caused by the unfair proportional
    algorithm, so let's give this another shot.
    
    v2:
     - Make sure cursor allocation stays constant and fixed at the end of
       the pipe allocation.
     - Fix some watermark level iterators that weren't handling the max
       level.
    
    v3:
     - Ensure we don't leave any DDB blocks unused by using DIV_ROUND_UP+min
       to calculate the extra blocks for each plane.  (Ville)
     - Replace a while() loop with a for() loop to be more consistent with
       surrounding code.  (Ville)
     - Clean unattainable watermark levels with memset rather than directly
       clearing the member fields.  Also do the same for the transition
       watermark values if they can't be achieved.  (Ville)
     - Drop min_disp_buf_needed calculations in skl_compute_plane_wm() since
       the results are no longer needed or used.  (Ville)
     - Drop skl_latency[0] != 0 sanity check; both watermark methods already
       account for an invalid 0 latency by returning FP_16_16_MAX.  (Ville)
    
    v4:
     - Break DDB allocation loop when total_data_rate=0 rather than
       alloc_size=0.  If total_data_rate has dropped to 0, all remaining
       planes are disabled, which isn't true for alloc_size (we might just
       have not had any remaining blocks to hand out).  Plus
       total_data_rate=0 is the case we need to avoid to a prevent a
       div-by-0.  (Ville)
     - s/DIV_ROUND_UP/DIV64_U64_ROUND_UP/ to prevent 32-bit breakage (Ville)
    
    v5:
     - Don't forget to move 'start' pointer forward for UV surface when
       setting plane DDB boundaries.  (Ville)
    
    Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105458Signed-off-by: default avatarMatt Roper <matthew.d.roper@intel.com>
    Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
    Link: https://patchwork.freedesktop.org/patch/msgid/20181211173107.11068-2-matthew.d.roper@intel.com
    d8e87498
intel_pm.c 280 KB