linux/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
<<
>>
Prefs
   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
  54static 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
  72static 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
  90static 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 ((intel_de_read(dev_priv, reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0)
  99                return;
 100
 101        enable_mask = i915_pipestat_enable_mask(dev_priv, crtc->pipe);
 102        intel_de_write(dev_priv, reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
 103        intel_de_posting_read(dev_priv, reg);
 104
 105        trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe);
 106        drm_err(&dev_priv->drm, "pipe %c underrun\n", pipe_name(crtc->pipe));
 107}
 108
 109static 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                intel_de_write(dev_priv, reg,
 122                               enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
 123                intel_de_posting_read(dev_priv, reg);
 124        } else {
 125                if (old && intel_de_read(dev_priv, reg) & PIPE_FIFO_UNDERRUN_STATUS)
 126                        drm_err(&dev_priv->drm, "pipe %c underrun\n",
 127                                pipe_name(pipe));
 128        }
 129}
 130
 131static void ilk_set_fifo_underrun_reporting(struct drm_device *dev,
 132                                            enum pipe pipe, bool enable)
 133{
 134        struct drm_i915_private *dev_priv = to_i915(dev);
 135        u32 bit = (pipe == PIPE_A) ?
 136                DE_PIPEA_FIFO_UNDERRUN : DE_PIPEB_FIFO_UNDERRUN;
 137
 138        if (enable)
 139                ilk_enable_display_irq(dev_priv, bit);
 140        else
 141                ilk_disable_display_irq(dev_priv, bit);
 142}
 143
 144static void ivb_check_fifo_underruns(struct intel_crtc *crtc)
 145{
 146        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 147        enum pipe pipe = crtc->pipe;
 148        u32 err_int = intel_de_read(dev_priv, GEN7_ERR_INT);
 149
 150        lockdep_assert_held(&dev_priv->irq_lock);
 151
 152        if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0)
 153                return;
 154
 155        intel_de_write(dev_priv, GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
 156        intel_de_posting_read(dev_priv, GEN7_ERR_INT);
 157
 158        trace_intel_cpu_fifo_underrun(dev_priv, pipe);
 159        drm_err(&dev_priv->drm, "fifo underrun on pipe %c\n", pipe_name(pipe));
 160}
 161
 162static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
 163                                            enum pipe pipe, bool enable,
 164                                            bool old)
 165{
 166        struct drm_i915_private *dev_priv = to_i915(dev);
 167        if (enable) {
 168                intel_de_write(dev_priv, GEN7_ERR_INT,
 169                               ERR_INT_FIFO_UNDERRUN(pipe));
 170
 171                if (!ivb_can_enable_err_int(dev))
 172                        return;
 173
 174                ilk_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
 175        } else {
 176                ilk_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
 177
 178                if (old &&
 179                    intel_de_read(dev_priv, GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
 180                        drm_err(&dev_priv->drm,
 181                                "uncleared fifo underrun on pipe %c\n",
 182                                pipe_name(pipe));
 183                }
 184        }
 185}
 186
 187static void bdw_set_fifo_underrun_reporting(struct drm_device *dev,
 188                                            enum pipe pipe, bool enable)
 189{
 190        struct drm_i915_private *dev_priv = to_i915(dev);
 191
 192        if (enable)
 193                bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
 194        else
 195                bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
 196}
 197
 198static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
 199                                            enum pipe pch_transcoder,
 200                                            bool enable)
 201{
 202        struct drm_i915_private *dev_priv = to_i915(dev);
 203        u32 bit = (pch_transcoder == PIPE_A) ?
 204                SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
 205
 206        if (enable)
 207                ibx_enable_display_interrupt(dev_priv, bit);
 208        else
 209                ibx_disable_display_interrupt(dev_priv, bit);
 210}
 211
 212static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
 213{
 214        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 215        enum pipe pch_transcoder = crtc->pipe;
 216        u32 serr_int = intel_de_read(dev_priv, SERR_INT);
 217
 218        lockdep_assert_held(&dev_priv->irq_lock);
 219
 220        if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0)
 221                return;
 222
 223        intel_de_write(dev_priv, SERR_INT,
 224                       SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
 225        intel_de_posting_read(dev_priv, SERR_INT);
 226
 227        trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
 228        drm_err(&dev_priv->drm, "pch fifo underrun on pch transcoder %c\n",
 229                pipe_name(pch_transcoder));
 230}
 231
 232static 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                intel_de_write(dev_priv, 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 && intel_de_read(dev_priv, SERR_INT) &
 250                    SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
 251                        drm_err(&dev_priv->drm,
 252                                "uncleared pch fifo underrun on pch transcoder %c\n",
 253                                pipe_name(pch_transcoder));
 254                }
 255        }
 256}
 257
 258static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
 259                                                    enum pipe pipe, bool enable)
 260{
 261        struct drm_i915_private *dev_priv = to_i915(dev);
 262        struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 263        bool old;
 264
 265        lockdep_assert_held(&dev_priv->irq_lock);
 266
 267        old = !crtc->cpu_fifo_underrun_disabled;
 268        crtc->cpu_fifo_underrun_disabled = !enable;
 269
 270        if (HAS_GMCH(dev_priv))
 271                i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
 272        else if (IS_GEN_RANGE(dev_priv, 5, 6))
 273                ilk_set_fifo_underrun_reporting(dev, pipe, enable);
 274        else if (IS_GEN(dev_priv, 7))
 275                ivb_set_fifo_underrun_reporting(dev, pipe, enable, old);
 276        else if (INTEL_GEN(dev_priv) >= 8)
 277                bdw_set_fifo_underrun_reporting(dev, pipe, enable);
 278
 279        return old;
 280}
 281
 282/**
 283 * intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrrun reporting state
 284 * @dev_priv: i915 device instance
 285 * @pipe: (CPU) pipe to set state for
 286 * @enable: whether underruns should be reported or not
 287 *
 288 * This function sets the fifo underrun state for @pipe. It is used in the
 289 * modeset code to avoid false positives since on many platforms underruns are
 290 * expected when disabling or enabling the pipe.
 291 *
 292 * Notice that on some platforms disabling underrun reports for one pipe
 293 * disables for all due to shared interrupts. Actual reporting is still per-pipe
 294 * though.
 295 *
 296 * Returns the previous state of underrun reporting.
 297 */
 298bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
 299                                           enum pipe pipe, bool enable)
 300{
 301        unsigned long flags;
 302        bool ret;
 303
 304        spin_lock_irqsave(&dev_priv->irq_lock, flags);
 305        ret = __intel_set_cpu_fifo_underrun_reporting(&dev_priv->drm, pipe,
 306                                                      enable);
 307        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 308
 309        return ret;
 310}
 311
 312/**
 313 * intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state
 314 * @dev_priv: i915 device instance
 315 * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
 316 * @enable: whether underruns should be reported or not
 317 *
 318 * This function makes us disable or enable PCH fifo underruns for a specific
 319 * PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO
 320 * underrun reporting for one transcoder may also disable all the other PCH
 321 * error interruts for the other transcoders, due to the fact that there's just
 322 * one interrupt mask/enable bit for all the transcoders.
 323 *
 324 * Returns the previous state of underrun reporting.
 325 */
 326bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
 327                                           enum pipe pch_transcoder,
 328                                           bool enable)
 329{
 330        struct intel_crtc *crtc =
 331                intel_get_crtc_for_pipe(dev_priv, pch_transcoder);
 332        unsigned long flags;
 333        bool old;
 334
 335        /*
 336         * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
 337         * has only one pch transcoder A that all pipes can use. To avoid racy
 338         * pch transcoder -> pipe lookups from interrupt code simply store the
 339         * underrun statistics in crtc A. Since we never expose this anywhere
 340         * nor use it outside of the fifo underrun code here using the "wrong"
 341         * crtc on LPT won't cause issues.
 342         */
 343
 344        spin_lock_irqsave(&dev_priv->irq_lock, flags);
 345
 346        old = !crtc->pch_fifo_underrun_disabled;
 347        crtc->pch_fifo_underrun_disabled = !enable;
 348
 349        if (HAS_PCH_IBX(dev_priv))
 350                ibx_set_fifo_underrun_reporting(&dev_priv->drm,
 351                                                pch_transcoder,
 352                                                enable);
 353        else
 354                cpt_set_fifo_underrun_reporting(&dev_priv->drm,
 355                                                pch_transcoder,
 356                                                enable, old);
 357
 358        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 359        return old;
 360}
 361
 362/**
 363 * intel_cpu_fifo_underrun_irq_handler - handle CPU fifo underrun interrupt
 364 * @dev_priv: i915 device instance
 365 * @pipe: (CPU) pipe to set state for
 366 *
 367 * This handles a CPU fifo underrun interrupt, generating an underrun warning
 368 * into dmesg if underrun reporting is enabled and then disables the underrun
 369 * interrupt to avoid an irq storm.
 370 */
 371void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
 372                                         enum pipe pipe)
 373{
 374        struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 375
 376        /* We may be called too early in init, thanks BIOS! */
 377        if (crtc == NULL)
 378                return;
 379
 380        /* GMCH can't disable fifo underruns, filter them. */
 381        if (HAS_GMCH(dev_priv) &&
 382            crtc->cpu_fifo_underrun_disabled)
 383                return;
 384
 385        if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
 386                trace_intel_cpu_fifo_underrun(dev_priv, pipe);
 387                drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n",
 388                        pipe_name(pipe));
 389        }
 390
 391        intel_fbc_handle_fifo_underrun_irq(dev_priv);
 392}
 393
 394/**
 395 * intel_pch_fifo_underrun_irq_handler - handle PCH fifo underrun interrupt
 396 * @dev_priv: i915 device instance
 397 * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
 398 *
 399 * This handles a PCH fifo underrun interrupt, generating an underrun warning
 400 * into dmesg if underrun reporting is enabled and then disables the underrun
 401 * interrupt to avoid an irq storm.
 402 */
 403void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
 404                                         enum pipe pch_transcoder)
 405{
 406        if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
 407                                                  false)) {
 408                trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
 409                drm_err(&dev_priv->drm, "PCH transcoder %c FIFO underrun\n",
 410                        pipe_name(pch_transcoder));
 411        }
 412}
 413
 414/**
 415 * intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately
 416 * @dev_priv: i915 device instance
 417 *
 418 * Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared
 419 * error interrupt may have been disabled, and so CPU fifo underruns won't
 420 * necessarily raise an interrupt, and on GMCH platforms where underruns never
 421 * raise an interrupt.
 422 */
 423void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
 424{
 425        struct intel_crtc *crtc;
 426
 427        spin_lock_irq(&dev_priv->irq_lock);
 428
 429        for_each_intel_crtc(&dev_priv->drm, crtc) {
 430                if (crtc->cpu_fifo_underrun_disabled)
 431                        continue;
 432
 433                if (HAS_GMCH(dev_priv))
 434                        i9xx_check_fifo_underruns(crtc);
 435                else if (IS_GEN(dev_priv, 7))
 436                        ivb_check_fifo_underruns(crtc);
 437        }
 438
 439        spin_unlock_irq(&dev_priv->irq_lock);
 440}
 441
 442/**
 443 * intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately
 444 * @dev_priv: i915 device instance
 445 *
 446 * Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared
 447 * error interrupt may have been disabled, and so PCH fifo underruns won't
 448 * necessarily raise an interrupt.
 449 */
 450void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv)
 451{
 452        struct intel_crtc *crtc;
 453
 454        spin_lock_irq(&dev_priv->irq_lock);
 455
 456        for_each_intel_crtc(&dev_priv->drm, crtc) {
 457                if (crtc->pch_fifo_underrun_disabled)
 458                        continue;
 459
 460                if (HAS_PCH_CPT(dev_priv))
 461                        cpt_check_pch_fifo_underruns(crtc);
 462        }
 463
 464        spin_unlock_irq(&dev_priv->irq_lock);
 465}
 466