Home | History | Annotate | Line # | Download | only in display
      1 /*	$NetBSD: intel_fifo_underrun.c,v 1.2 2021/12/18 23:45:30 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright  2014 Intel Corporation
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     23  * IN THE SOFTWARE.
     24  *
     25  * Authors:
     26  *    Daniel Vetter <daniel.vetter (at) ffwll.ch>
     27  *
     28  */
     29 
     30 #include <sys/cdefs.h>
     31 __KERNEL_RCSID(0, "$NetBSD: intel_fifo_underrun.c,v 1.2 2021/12/18 23:45:30 riastradh Exp $");
     32 
     33 #include "i915_drv.h"
     34 #include "i915_trace.h"
     35 #include "intel_display_types.h"
     36 #include "intel_fbc.h"
     37 #include "intel_fifo_underrun.h"
     38 
     39 /**
     40  * DOC: fifo underrun handling
     41  *
     42  * The i915 driver checks for display fifo underruns using the interrupt signals
     43  * provided by the hardware. This is enabled by default and fairly useful to
     44  * debug display issues, especially watermark settings.
     45  *
     46  * If an underrun is detected this is logged into dmesg. To avoid flooding logs
     47  * and occupying the cpu underrun interrupts are disabled after the first
     48  * occurrence until the next modeset on a given pipe.
     49  *
     50  * Note that underrun detection on gmch platforms is a bit more ugly since there
     51  * is no interrupt (despite that the signalling bit is in the PIPESTAT pipe
     52  * interrupt register). Also on some other platforms underrun interrupts are
     53  * shared, which means that if we detect an underrun we need to disable underrun
     54  * reporting on all pipes.
     55  *
     56  * The code also supports underrun detection on the PCH transcoder.
     57  */
     58 
     59 static bool ivb_can_enable_err_int(struct drm_device *dev)
     60 {
     61 	struct drm_i915_private *dev_priv = to_i915(dev);
     62 	struct intel_crtc *crtc;
     63 	enum pipe pipe;
     64 
     65 	lockdep_assert_held(&dev_priv->irq_lock);
     66 
     67 	for_each_pipe(dev_priv, pipe) {
     68 		crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
     69 
     70 		if (crtc->cpu_fifo_underrun_disabled)
     71 			return false;
     72 	}
     73 
     74 	return true;
     75 }
     76 
     77 static bool cpt_can_enable_serr_int(struct drm_device *dev)
     78 {
     79 	struct drm_i915_private *dev_priv = to_i915(dev);
     80 	enum pipe pipe;
     81 	struct intel_crtc *crtc;
     82 
     83 	lockdep_assert_held(&dev_priv->irq_lock);
     84 
     85 	for_each_pipe(dev_priv, pipe) {
     86 		crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
     87 
     88 		if (crtc->pch_fifo_underrun_disabled)
     89 			return false;
     90 	}
     91 
     92 	return true;
     93 }
     94 
     95 static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
     96 {
     97 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
     98 	i915_reg_t reg = PIPESTAT(crtc->pipe);
     99 	u32 enable_mask;
    100 
    101 	lockdep_assert_held(&dev_priv->irq_lock);
    102 
    103 	if ((I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0)
    104 		return;
    105 
    106 	enable_mask = i915_pipestat_enable_mask(dev_priv, crtc->pipe);
    107 	I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
    108 	POSTING_READ(reg);
    109 
    110 	trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe);
    111 	DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
    112 }
    113 
    114 static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
    115 					     enum pipe pipe,
    116 					     bool enable, bool old)
    117 {
    118 	struct drm_i915_private *dev_priv = to_i915(dev);
    119 	i915_reg_t reg = PIPESTAT(pipe);
    120 
    121 	lockdep_assert_held(&dev_priv->irq_lock);
    122 
    123 	if (enable) {
    124 		u32 enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
    125 
    126 		I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
    127 		POSTING_READ(reg);
    128 	} else {
    129 		if (old && I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS)
    130 			DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
    131 	}
    132 }
    133 
    134 static void ilk_set_fifo_underrun_reporting(struct drm_device *dev,
    135 					    enum pipe pipe, bool enable)
    136 {
    137 	struct drm_i915_private *dev_priv = to_i915(dev);
    138 	u32 bit = (pipe == PIPE_A) ?
    139 		DE_PIPEA_FIFO_UNDERRUN : DE_PIPEB_FIFO_UNDERRUN;
    140 
    141 	if (enable)
    142 		ilk_enable_display_irq(dev_priv, bit);
    143 	else
    144 		ilk_disable_display_irq(dev_priv, bit);
    145 }
    146 
    147 static void ivb_check_fifo_underruns(struct intel_crtc *crtc)
    148 {
    149 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
    150 	enum pipe pipe = crtc->pipe;
    151 	u32 err_int = I915_READ(GEN7_ERR_INT);
    152 
    153 	lockdep_assert_held(&dev_priv->irq_lock);
    154 
    155 	if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0)
    156 		return;
    157 
    158 	I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
    159 	POSTING_READ(GEN7_ERR_INT);
    160 
    161 	trace_intel_cpu_fifo_underrun(dev_priv, pipe);
    162 	DRM_ERROR("fifo underrun on pipe %c\n", pipe_name(pipe));
    163 }
    164 
    165 static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
    166 					    enum pipe pipe, bool enable,
    167 					    bool old)
    168 {
    169 	struct drm_i915_private *dev_priv = to_i915(dev);
    170 	if (enable) {
    171 		I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
    172 
    173 		if (!ivb_can_enable_err_int(dev))
    174 			return;
    175 
    176 		ilk_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
    177 	} else {
    178 		ilk_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
    179 
    180 		if (old &&
    181 		    I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
    182 			DRM_ERROR("uncleared fifo underrun on pipe %c\n",
    183 				  pipe_name(pipe));
    184 		}
    185 	}
    186 }
    187 
    188 static void bdw_set_fifo_underrun_reporting(struct drm_device *dev,
    189 					    enum pipe pipe, bool enable)
    190 {
    191 	struct drm_i915_private *dev_priv = to_i915(dev);
    192 
    193 	if (enable)
    194 		bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
    195 	else
    196 		bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
    197 }
    198 
    199 static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
    200 					    enum pipe pch_transcoder,
    201 					    bool enable)
    202 {
    203 	struct drm_i915_private *dev_priv = to_i915(dev);
    204 	u32 bit = (pch_transcoder == PIPE_A) ?
    205 		SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
    206 
    207 	if (enable)
    208 		ibx_enable_display_interrupt(dev_priv, bit);
    209 	else
    210 		ibx_disable_display_interrupt(dev_priv, bit);
    211 }
    212 
    213 static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
    214 {
    215 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
    216 	enum pipe pch_transcoder = crtc->pipe;
    217 	u32 serr_int = I915_READ(SERR_INT);
    218 
    219 	lockdep_assert_held(&dev_priv->irq_lock);
    220 
    221 	if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0)
    222 		return;
    223 
    224 	I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
    225 	POSTING_READ(SERR_INT);
    226 
    227 	trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
    228 	DRM_ERROR("pch fifo underrun on pch transcoder %c\n",
    229 		  pipe_name(pch_transcoder));
    230 }
    231 
    232 static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
    233 					    enum pipe pch_transcoder,
    234 					    bool enable, bool old)
    235 {
    236 	struct drm_i915_private *dev_priv = to_i915(dev);
    237 
    238 	if (enable) {
    239 		I915_WRITE(SERR_INT,
    240 			   SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
    241 
    242 		if (!cpt_can_enable_serr_int(dev))
    243 			return;
    244 
    245 		ibx_enable_display_interrupt(dev_priv, SDE_ERROR_CPT);
    246 	} else {
    247 		ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
    248 
    249 		if (old && I915_READ(SERR_INT) &
    250 		    SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
    251 			DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
    252 				  pipe_name(pch_transcoder));
    253 		}
    254 	}
    255 }
    256 
    257 static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
    258 						    enum pipe pipe, bool enable)
    259 {
    260 	struct drm_i915_private *dev_priv = to_i915(dev);
    261 	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
    262 	bool old;
    263 
    264 	lockdep_assert_held(&dev_priv->irq_lock);
    265 
    266 	old = !crtc->cpu_fifo_underrun_disabled;
    267 	crtc->cpu_fifo_underrun_disabled = !enable;
    268 
    269 	if (HAS_GMCH(dev_priv))
    270 		i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
    271 	else if (IS_GEN_RANGE(dev_priv, 5, 6))
    272 		ilk_set_fifo_underrun_reporting(dev, pipe, enable);
    273 	else if (IS_GEN(dev_priv, 7))
    274 		ivb_set_fifo_underrun_reporting(dev, pipe, enable, old);
    275 	else if (INTEL_GEN(dev_priv) >= 8)
    276 		bdw_set_fifo_underrun_reporting(dev, pipe, enable);
    277 
    278 	return old;
    279 }
    280 
    281 /**
    282  * intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrrun reporting state
    283  * @dev_priv: i915 device instance
    284  * @pipe: (CPU) pipe to set state for
    285  * @enable: whether underruns should be reported or not
    286  *
    287  * This function sets the fifo underrun state for @pipe. It is used in the
    288  * modeset code to avoid false positives since on many platforms underruns are
    289  * expected when disabling or enabling the pipe.
    290  *
    291  * Notice that on some platforms disabling underrun reports for one pipe
    292  * disables for all due to shared interrupts. Actual reporting is still per-pipe
    293  * though.
    294  *
    295  * Returns the previous state of underrun reporting.
    296  */
    297 bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
    298 					   enum pipe pipe, bool enable)
    299 {
    300 	unsigned long flags;
    301 	bool ret;
    302 
    303 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
    304 	ret = __intel_set_cpu_fifo_underrun_reporting(&dev_priv->drm, pipe,
    305 						      enable);
    306 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
    307 
    308 	return ret;
    309 }
    310 
    311 /**
    312  * intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state
    313  * @dev_priv: i915 device instance
    314  * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
    315  * @enable: whether underruns should be reported or not
    316  *
    317  * This function makes us disable or enable PCH fifo underruns for a specific
    318  * PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO
    319  * underrun reporting for one transcoder may also disable all the other PCH
    320  * error interruts for the other transcoders, due to the fact that there's just
    321  * one interrupt mask/enable bit for all the transcoders.
    322  *
    323  * Returns the previous state of underrun reporting.
    324  */
    325 bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
    326 					   enum pipe pch_transcoder,
    327 					   bool enable)
    328 {
    329 	struct intel_crtc *crtc =
    330 		intel_get_crtc_for_pipe(dev_priv, pch_transcoder);
    331 	unsigned long flags;
    332 	bool old;
    333 
    334 	/*
    335 	 * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
    336 	 * has only one pch transcoder A that all pipes can use. To avoid racy
    337 	 * pch transcoder -> pipe lookups from interrupt code simply store the
    338 	 * underrun statistics in crtc A. Since we never expose this anywhere
    339 	 * nor use it outside of the fifo underrun code here using the "wrong"
    340 	 * crtc on LPT won't cause issues.
    341 	 */
    342 
    343 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
    344 
    345 	old = !crtc->pch_fifo_underrun_disabled;
    346 	crtc->pch_fifo_underrun_disabled = !enable;
    347 
    348 	if (HAS_PCH_IBX(dev_priv))
    349 		ibx_set_fifo_underrun_reporting(&dev_priv->drm,
    350 						pch_transcoder,
    351 						enable);
    352 	else
    353 		cpt_set_fifo_underrun_reporting(&dev_priv->drm,
    354 						pch_transcoder,
    355 						enable, old);
    356 
    357 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
    358 	return old;
    359 }
    360 
    361 /**
    362  * intel_cpu_fifo_underrun_irq_handler - handle CPU fifo underrun interrupt
    363  * @dev_priv: i915 device instance
    364  * @pipe: (CPU) pipe to set state for
    365  *
    366  * This handles a CPU fifo underrun interrupt, generating an underrun warning
    367  * into dmesg if underrun reporting is enabled and then disables the underrun
    368  * interrupt to avoid an irq storm.
    369  */
    370 void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
    371 					 enum pipe pipe)
    372 {
    373 	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
    374 
    375 	/* We may be called too early in init, thanks BIOS! */
    376 	if (crtc == NULL)
    377 		return;
    378 
    379 	/* GMCH can't disable fifo underruns, filter them. */
    380 	if (HAS_GMCH(dev_priv) &&
    381 	    crtc->cpu_fifo_underrun_disabled)
    382 		return;
    383 
    384 	if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
    385 		trace_intel_cpu_fifo_underrun(dev_priv, pipe);
    386 		DRM_ERROR("CPU pipe %c FIFO underrun\n",
    387 			  pipe_name(pipe));
    388 	}
    389 
    390 	intel_fbc_handle_fifo_underrun_irq(dev_priv);
    391 }
    392 
    393 /**
    394  * intel_pch_fifo_underrun_irq_handler - handle PCH fifo underrun interrupt
    395  * @dev_priv: i915 device instance
    396  * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
    397  *
    398  * This handles a PCH fifo underrun interrupt, generating an underrun warning
    399  * into dmesg if underrun reporting is enabled and then disables the underrun
    400  * interrupt to avoid an irq storm.
    401  */
    402 void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
    403 					 enum pipe pch_transcoder)
    404 {
    405 	if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
    406 						  false)) {
    407 		trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
    408 		DRM_ERROR("PCH transcoder %c FIFO underrun\n",
    409 			  pipe_name(pch_transcoder));
    410 	}
    411 }
    412 
    413 /**
    414  * intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately
    415  * @dev_priv: i915 device instance
    416  *
    417  * Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared
    418  * error interrupt may have been disabled, and so CPU fifo underruns won't
    419  * necessarily raise an interrupt, and on GMCH platforms where underruns never
    420  * raise an interrupt.
    421  */
    422 void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
    423 {
    424 	struct intel_crtc *crtc;
    425 
    426 	spin_lock_irq(&dev_priv->irq_lock);
    427 
    428 	for_each_intel_crtc(&dev_priv->drm, crtc) {
    429 		if (crtc->cpu_fifo_underrun_disabled)
    430 			continue;
    431 
    432 		if (HAS_GMCH(dev_priv))
    433 			i9xx_check_fifo_underruns(crtc);
    434 		else if (IS_GEN(dev_priv, 7))
    435 			ivb_check_fifo_underruns(crtc);
    436 	}
    437 
    438 	spin_unlock_irq(&dev_priv->irq_lock);
    439 }
    440 
    441 /**
    442  * intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately
    443  * @dev_priv: i915 device instance
    444  *
    445  * Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared
    446  * error interrupt may have been disabled, and so PCH fifo underruns won't
    447  * necessarily raise an interrupt.
    448  */
    449 void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv)
    450 {
    451 	struct intel_crtc *crtc;
    452 
    453 	spin_lock_irq(&dev_priv->irq_lock);
    454 
    455 	for_each_intel_crtc(&dev_priv->drm, crtc) {
    456 		if (crtc->pch_fifo_underrun_disabled)
    457 			continue;
    458 
    459 		if (HAS_PCH_CPT(dev_priv))
    460 			cpt_check_pch_fifo_underruns(crtc);
    461 	}
    462 
    463 	spin_unlock_irq(&dev_priv->irq_lock);
    464 }
    465