root/drivers/gpu/drm/i915/display/intel_fifo_underrun.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ivb_can_enable_err_int
  2. cpt_can_enable_serr_int
  3. i9xx_check_fifo_underruns
  4. i9xx_set_fifo_underrun_reporting
  5. ironlake_set_fifo_underrun_reporting
  6. ivybridge_check_fifo_underruns
  7. ivybridge_set_fifo_underrun_reporting
  8. broadwell_set_fifo_underrun_reporting
  9. ibx_set_fifo_underrun_reporting
  10. cpt_check_pch_fifo_underruns
  11. cpt_set_fifo_underrun_reporting
  12. __intel_set_cpu_fifo_underrun_reporting
  13. intel_set_cpu_fifo_underrun_reporting
  14. intel_set_pch_fifo_underrun_reporting
  15. intel_cpu_fifo_underrun_irq_handler
  16. intel_pch_fifo_underrun_irq_handler
  17. intel_check_cpu_fifo_underruns
  18. intel_check_pch_fifo_underruns

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

/* [<][>][^][v][top][bottom][index][help] */