Quoting Gustavo Sousa (2025-11-05 11:42:54-03:00)
>Quoting Matt Roper (2025-11-03 18:51:11-03:00)
>>On Mon, Nov 03, 2025 at 02:18:07PM -0300, Gustavo Sousa wrote:
>>> From: Sai Teja Pottumuttu <[email protected]>
>>> 
>>> Starting with Xe3p_LPD, we get two new registers and some bits in
>>> existing registers that expose hardware state information at the time of
>>> underrun notification that can be relevant to debugging.
>>> 
>>> Add the necessary logic in the driver to print the available debug
>>> information when an underrun happens.
>>> 
>>> Note that the register FBC_DEBUG_STATUS also got a bit to indicate that
>>> the respective FBC was decompressing when the underrun happened, but we
>>> leave that one to be handled in an upcoming change.
>>> 
>>> v2:
>>>   - Use seq_buf to generate planes string. (Jani)
>>>   - Move definition of FBC_DEBUG_STATUS to intel_fbc_regs.h. (Ville)
>>>   - Change logic for processing UNDERRUN_DBG1 to use loops and move it
>>>     to a separate function. (Gustavo)
>>>   - Always print underrun error message, even if there wouldn't be any
>>>     debug info associated to the underrun. (Gustavo)
>>> v3:
>>>   - Use REG_FIELD_GET() for fields of UNDERRUN_DBG1. (Matt)
>>>   - Move handling of FBC_DEBUG_STATUS to a separate patch that adds
>>>     extra logic to match FBCs by pipe. (Gustavo)
>>> 
>>> Bspec: 69111, 69561, 74411, 74412
>>> Cc: Jani Nikula <[email protected]>
>>> Cc: Matt Roper <[email protected]>
>>> Cc: Ville Syrjälä <[email protected]>
>>> Signed-off-by: Sai Teja Pottumuttu <[email protected]>
>>> Co-developed-by: Gustavo Sousa <[email protected]>
>>> Signed-off-by: Gustavo Sousa <[email protected]>
>>> ---
>>>  drivers/gpu/drm/i915/display/intel_display_regs.h  | 20 ++++++
>>>  drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 72 
>>> ++++++++++++++++++++++
>>>  2 files changed, 92 insertions(+)
>>> 
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h 
>>> b/drivers/gpu/drm/i915/display/intel_display_regs.h
>>> index 9d71e26a4fa2..c9f8b90faa42 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
>>> @@ -882,6 +882,25 @@
>>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK                
>>> REG_GENMASK(2, 0) /* tgl+ */
>>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id)        
>>> REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
>>>  
>>> +#define _UNDERRUN_DBG1_A                                0x70064
>>> +#define _UNDERRUN_DBG1_B                                0x71064
>>> +#define UNDERRUN_DBG1(pipe)                                
>>> _MMIO_PIPE(pipe, \
>>> +                                                                   
>>> _UNDERRUN_DBG1_A, \
>>> +                                                                   
>>> _UNDERRUN_DBG1_B)
>>> +#define   UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK                
>>> REG_GENMASK(29, 24)
>>> +#define   UNDERRUN_DDB_EMPTY_MASK                        REG_GENMASK(21, 
>>> 16)
>>> +#define   UNDERRUN_DBUF_NOT_FILLED_MASK                        
>>> REG_GENMASK(13, 8)
>>> +#define   UNDERRUN_BELOW_WM0_MASK                        REG_GENMASK(5, 0)
>>> +
>>> +#define _UNDERRUN_DBG2_A                                0x70068
>>> +#define _UNDERRUN_DBG2_B                                0x71068
>>> +#define UNDERRUN_DBG2(pipe)                                
>>> _MMIO_PIPE(pipe, \
>>> +                                                                   
>>> _UNDERRUN_DBG2_A, \
>>> +                                                                   
>>> _UNDERRUN_DBG2_B)
>>> +#define   UNDERRUN_FRAME_LINE_COUNTERS_FROZEN                REG_BIT(31)
>>> +#define   UNDERRUN_PIPE_FRAME_COUNT_MASK                REG_GENMASK(30, 20)
>>> +#define   UNDERRUN_LINE_COUNT_MASK                        REG_GENMASK(19, 
>>> 0)
>>> +
>>>  #define DPINVGTT                                _MMIO(VLV_DISPLAY_BASE + 
>>> 0x7002c) /* VLV/CHV only */
>>>  #define   DPINVGTT_EN_MASK_CHV                                
>>> REG_GENMASK(27, 16)
>>>  #define   DPINVGTT_EN_MASK_VLV                                
>>> REG_GENMASK(23, 16)
>>> @@ -1416,6 +1435,7 @@
>>>  
>>>  #define GEN12_DCPR_STATUS_1                                _MMIO(0x46440)
>>>  #define  XELPDP_PMDEMAND_INFLIGHT_STATUS                REG_BIT(26)
>>> +#define  XE3P_UNDERRUN_PKGC                                REG_BIT(21)
>>>  
>>>  #define FUSE_STRAP                _MMIO(0x42014)
>>>  #define   ILK_INTERNAL_GRAPHICS_DISABLE        REG_BIT(31)
>>> diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c 
>>> b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>>> index c2ce8461ac9e..1da90c99f93f 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>>> @@ -25,6 +25,8 @@
>>>   *
>>>   */
>>>  
>>> +#include <linux/seq_buf.h>
>>> +
>>>  #include <drm/drm_print.h>
>>>  
>>>  #include "i915_reg.h"
>>> @@ -352,6 +354,73 @@ bool intel_set_pch_fifo_underrun_reporting(struct 
>>> intel_display *display,
>>>          return old;
>>>  }
>>>  
>>> +#define UNDERRUN_DBG1_NUM_PLANES 6
>>> +
>>> +static void process_underrun_dbg1(struct intel_display *display,
>>> +                                  enum pipe pipe)
>>> +{
>>> +        u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));
>>> +        struct {
>>> +                u32 plane_mask;
>>> +                const char *info;
>>> +        } masks[] = {
>>> +                { REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val), 
>>> "DBUF block not valid" },
>>> +                { REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val), "DDB empty" 
>>> },
>>> +                { REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val), "DBUF 
>>> not completely filled" },
>>> +                { REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val), "DBUF below 
>>> WM0" },
>>> +        };
>>> +        DECLARE_SEQ_BUF(planes_desc, 32);
>>> +
>>> +        intel_de_write(display, UNDERRUN_DBG1(pipe), val);
>>> +
>>> +        for (int i = 0; i < ARRAY_SIZE(masks); i++) {
>>> +                if (!masks[i].plane_mask)
>>> +                        continue;
>>> +
>>> +                seq_buf_clear(&planes_desc);
>>> +
>>> +                for (int j = 0; j < UNDERRUN_DBG1_NUM_PLANES; j++) {
>>> +                        if (!(masks[i].plane_mask & REG_BIT(j)))
>>> +                                continue;
>>> +
>>> +                        if (j == 0)
>>> +                                seq_buf_puts(&planes_desc, "[C]");
>>> +                        else
>>> +                                seq_buf_printf(&planes_desc, "[%d]", j);
>>> +                }
>>> +
>>> +                drm_err(display->drm,
>>> +                        "Pipe %c FIFO underrun info: %s on planes: %s\n",
>>> +                        pipe_name(pipe), masks[i].info, 
>>> seq_buf_str(&planes_desc));
>>> +
>>> +                drm_WARN_ON(display->drm, 
>>> seq_buf_has_overflowed(&planes_desc));
>>> +        }
>>> +}
>>> +
>>> +static void xe3p_lpd_log_underrun(struct intel_display *display,
>>> +                                  enum pipe pipe)
>>> +{
>>> +        u32 val;
>>> +
>>> +        process_underrun_dbg1(display, pipe);
>>> +
>>> +        val = intel_de_read(display, UNDERRUN_DBG2(pipe));
>>> +        if (val & UNDERRUN_FRAME_LINE_COUNTERS_FROZEN) {
>>> +                intel_de_write(display, UNDERRUN_DBG2(pipe), 
>>> UNDERRUN_FRAME_LINE_COUNTERS_FROZEN);
>>> +                drm_err(display->drm, "Pipe %c FIFO underrun info: Frame 
>>> count: %u, Line count: %u\n",
>>> +                        pipe_name(pipe),
>>> +                        REG_FIELD_GET(UNDERRUN_PIPE_FRAME_COUNT_MASK, val),
>>> +                        REG_FIELD_GET(UNDERRUN_LINE_COUNT_MASK, val));
>>> +        }
>>> +
>>> +        val = intel_de_read(display, GEN12_DCPR_STATUS_1);
>>> +        if (val & XE3P_UNDERRUN_PKGC) {
>>> +                intel_de_write(display, GEN12_DCPR_STATUS_1, 
>>> XE3P_UNDERRUN_PKGC);
>>> +                drm_err(display->drm, "Pipe %c FIFO underrun info: Pkgc 
>>> blocking memory\n",
>>> +                        pipe_name(pipe));
>>
>>This is a global (not per-pipe) register here.  So if memory is
>>unavailable due to a package C-state, then presumably all of our active
>>pipes are going to be failing to fetch data (and hitting underruns)
>>because of this.  If we clear the sticky bit here, then the message may
>>only appear once.  I'd remove the "Pipe %c" prefix here so that we're
>>not blaming one specific pipe.
>
>Yeah, good point.
>
>Now, one thing that is bothering me is that we would be showing this
>message in between pipe i and pipe (i+k) underrun error messages.  But
>I'm not sure refactoring the current code so that we "isolate" this
>message is worth the trouble.
>
>What if we replace "Pipe %c" with "General", so that we are explicit
>that this is general and not specific to the pipe?

Hm.. By the way, I think this patch still needs some rework.  We are
only clearing the stick bits when underrung reporting is enabled.  This
means that there is the possibility that we get stale bits, from a
previous underrun that was not reported.

Let me rework this.

--
Gustavo Sousa

>
>--
>Gustavo Sousa
>
>>
>>
>>Matt
>>
>>> +        }
>>> +}
>>> +
>>>  /**
>>>   * intel_cpu_fifo_underrun_irq_handler - handle CPU fifo underrun interrupt
>>>   * @display: display device instance
>>> @@ -379,6 +448,9 @@ void intel_cpu_fifo_underrun_irq_handler(struct 
>>> intel_display *display,
>>>                  trace_intel_cpu_fifo_underrun(display, pipe);
>>>  
>>>                  drm_err(display->drm, "CPU pipe %c FIFO underrun\n", 
>>> pipe_name(pipe));
>>> +
>>> +                if (DISPLAY_VER(display) >= 35)
>>> +                        xe3p_lpd_log_underrun(display, pipe);
>>>          }
>>>  
>>>          intel_fbc_handle_fifo_underrun_irq(display);
>>> 
>>> -- 
>>> 2.51.0
>>> 
>>
>>-- 
>>Matt Roper
>>Graphics Software Engineer
>>Linux GPU Platform Enablement
>>Intel Corporation

Reply via email to