linux/drivers/gpu/drm/i915/intel_hotplug.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2015 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
  24#include <linux/kernel.h>
  25
  26#include <drm/drmP.h>
  27#include <drm/i915_drm.h>
  28
  29#include "i915_drv.h"
  30#include "intel_drv.h"
  31
  32/**
  33 * DOC: Hotplug
  34 *
  35 * Simply put, hotplug occurs when a display is connected to or disconnected
  36 * from the system. However, there may be adapters and docking stations and
  37 * Display Port short pulses and MST devices involved, complicating matters.
  38 *
  39 * Hotplug in i915 is handled in many different levels of abstraction.
  40 *
  41 * The platform dependent interrupt handling code in i915_irq.c enables,
  42 * disables, and does preliminary handling of the interrupts. The interrupt
  43 * handlers gather the hotplug detect (HPD) information from relevant registers
  44 * into a platform independent mask of hotplug pins that have fired.
  45 *
  46 * The platform independent interrupt handler intel_hpd_irq_handler() in
  47 * intel_hotplug.c does hotplug irq storm detection and mitigation, and passes
  48 * further processing to appropriate bottom halves (Display Port specific and
  49 * regular hotplug).
  50 *
  51 * The Display Port work function i915_digport_work_func() calls into
  52 * intel_dp_hpd_pulse() via hooks, which handles DP short pulses and DP MST long
  53 * pulses, with failures and non-MST long pulses triggering regular hotplug
  54 * processing on the connector.
  55 *
  56 * The regular hotplug work function i915_hotplug_work_func() calls connector
  57 * detect hooks, and, if connector status changes, triggers sending of hotplug
  58 * uevent to userspace via drm_kms_helper_hotplug_event().
  59 *
  60 * Finally, the userspace is responsible for triggering a modeset upon receiving
  61 * the hotplug uevent, disabling or enabling the crtc as needed.
  62 *
  63 * The hotplug interrupt storm detection and mitigation code keeps track of the
  64 * number of interrupts per hotplug pin per a period of time, and if the number
  65 * of interrupts exceeds a certain threshold, the interrupt is disabled for a
  66 * while before being re-enabled. The intention is to mitigate issues raising
  67 * from broken hardware triggering massive amounts of interrupts and grinding
  68 * the system to a halt.
  69 *
  70 * Current implementation expects that hotplug interrupt storm will not be
  71 * seen when display port sink is connected, hence on platforms whose DP
  72 * callback is handled by i915_digport_work_func reenabling of hpd is not
  73 * performed (it was never expected to be disabled in the first place ;) )
  74 * this is specific to DP sinks handled by this routine and any other display
  75 * such as HDMI or DVI enabled on the same port will have proper logic since
  76 * it will use i915_hotplug_work_func where this logic is handled.
  77 */
  78
  79bool intel_hpd_pin_to_port(enum hpd_pin pin, enum port *port)
  80{
  81        switch (pin) {
  82        case HPD_PORT_A:
  83                *port = PORT_A;
  84                return true;
  85        case HPD_PORT_B:
  86                *port = PORT_B;
  87                return true;
  88        case HPD_PORT_C:
  89                *port = PORT_C;
  90                return true;
  91        case HPD_PORT_D:
  92                *port = PORT_D;
  93                return true;
  94        case HPD_PORT_E:
  95                *port = PORT_E;
  96                return true;
  97        default:
  98                return false;   /* no hpd */
  99        }
 100}
 101
 102#define HPD_STORM_DETECT_PERIOD         1000
 103#define HPD_STORM_REENABLE_DELAY        (2 * 60 * 1000)
 104
 105/**
 106 * intel_hpd_irq_storm_detect - gather stats and detect HPD irq storm on a pin
 107 * @dev_priv: private driver data pointer
 108 * @pin: the pin to gather stats on
 109 *
 110 * Gather stats about HPD irqs from the specified @pin, and detect irq
 111 * storms. Only the pin specific stats and state are changed, the caller is
 112 * responsible for further action.
 113 *
 114 * The number of irqs that are allowed within @HPD_STORM_DETECT_PERIOD is
 115 * stored in @dev_priv->hotplug.hpd_storm_threshold which defaults to
 116 * @HPD_STORM_DEFAULT_THRESHOLD. If this threshold is exceeded, it's
 117 * considered an irq storm and the irq state is set to @HPD_MARK_DISABLED.
 118 *
 119 * The HPD threshold can be controlled through i915_hpd_storm_ctl in debugfs,
 120 * and should only be adjusted for automated hotplug testing.
 121 *
 122 * Return true if an irq storm was detected on @pin.
 123 */
 124static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv,
 125                                       enum hpd_pin pin)
 126{
 127        unsigned long start = dev_priv->hotplug.stats[pin].last_jiffies;
 128        unsigned long end = start + msecs_to_jiffies(HPD_STORM_DETECT_PERIOD);
 129        const int threshold = dev_priv->hotplug.hpd_storm_threshold;
 130        bool storm = false;
 131
 132        if (!time_in_range(jiffies, start, end)) {
 133                dev_priv->hotplug.stats[pin].last_jiffies = jiffies;
 134                dev_priv->hotplug.stats[pin].count = 0;
 135                DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: 0\n", pin);
 136        } else if (dev_priv->hotplug.stats[pin].count > threshold &&
 137                   threshold) {
 138                dev_priv->hotplug.stats[pin].state = HPD_MARK_DISABLED;
 139                DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", pin);
 140                storm = true;
 141        } else {
 142                dev_priv->hotplug.stats[pin].count++;
 143                DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: %d\n", pin,
 144                              dev_priv->hotplug.stats[pin].count);
 145        }
 146
 147        return storm;
 148}
 149
 150static void intel_hpd_irq_storm_disable(struct drm_i915_private *dev_priv)
 151{
 152        struct drm_device *dev = &dev_priv->drm;
 153        struct intel_connector *intel_connector;
 154        struct intel_encoder *intel_encoder;
 155        struct drm_connector *connector;
 156        struct drm_connector_list_iter conn_iter;
 157        enum hpd_pin pin;
 158        bool hpd_disabled = false;
 159
 160        lockdep_assert_held(&dev_priv->irq_lock);
 161
 162        drm_connector_list_iter_begin(dev, &conn_iter);
 163        drm_for_each_connector_iter(connector, &conn_iter) {
 164                if (connector->polled != DRM_CONNECTOR_POLL_HPD)
 165                        continue;
 166
 167                intel_connector = to_intel_connector(connector);
 168                intel_encoder = intel_connector->encoder;
 169                if (!intel_encoder)
 170                        continue;
 171
 172                pin = intel_encoder->hpd_pin;
 173                if (pin == HPD_NONE ||
 174                    dev_priv->hotplug.stats[pin].state != HPD_MARK_DISABLED)
 175                        continue;
 176
 177                DRM_INFO("HPD interrupt storm detected on connector %s: "
 178                         "switching from hotplug detection to polling\n",
 179                         connector->name);
 180
 181                dev_priv->hotplug.stats[pin].state = HPD_DISABLED;
 182                connector->polled = DRM_CONNECTOR_POLL_CONNECT
 183                        | DRM_CONNECTOR_POLL_DISCONNECT;
 184                hpd_disabled = true;
 185        }
 186        drm_connector_list_iter_end(&conn_iter);
 187
 188        /* Enable polling and queue hotplug re-enabling. */
 189        if (hpd_disabled) {
 190                drm_kms_helper_poll_enable(dev);
 191                mod_delayed_work(system_wq, &dev_priv->hotplug.reenable_work,
 192                                 msecs_to_jiffies(HPD_STORM_REENABLE_DELAY));
 193        }
 194}
 195
 196static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
 197{
 198        struct drm_i915_private *dev_priv =
 199                container_of(work, typeof(*dev_priv),
 200                             hotplug.reenable_work.work);
 201        struct drm_device *dev = &dev_priv->drm;
 202        int i;
 203
 204        intel_runtime_pm_get(dev_priv);
 205
 206        spin_lock_irq(&dev_priv->irq_lock);
 207        for_each_hpd_pin(i) {
 208                struct drm_connector *connector;
 209                struct drm_connector_list_iter conn_iter;
 210
 211                if (dev_priv->hotplug.stats[i].state != HPD_DISABLED)
 212                        continue;
 213
 214                dev_priv->hotplug.stats[i].state = HPD_ENABLED;
 215
 216                drm_connector_list_iter_begin(dev, &conn_iter);
 217                drm_for_each_connector_iter(connector, &conn_iter) {
 218                        struct intel_connector *intel_connector = to_intel_connector(connector);
 219
 220                        if (intel_connector->encoder->hpd_pin == i) {
 221                                if (connector->polled != intel_connector->polled)
 222                                        DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
 223                                                         connector->name);
 224                                connector->polled = intel_connector->polled;
 225                                if (!connector->polled)
 226                                        connector->polled = DRM_CONNECTOR_POLL_HPD;
 227                        }
 228                }
 229                drm_connector_list_iter_end(&conn_iter);
 230        }
 231        if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup)
 232                dev_priv->display.hpd_irq_setup(dev_priv);
 233        spin_unlock_irq(&dev_priv->irq_lock);
 234
 235        intel_runtime_pm_put(dev_priv);
 236}
 237
 238static bool intel_hpd_irq_event(struct drm_device *dev,
 239                                struct drm_connector *connector)
 240{
 241        enum drm_connector_status old_status;
 242
 243        WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
 244        old_status = connector->status;
 245
 246        connector->status = drm_helper_probe_detect(connector, NULL, false);
 247
 248        if (old_status == connector->status)
 249                return false;
 250
 251        DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
 252                      connector->base.id,
 253                      connector->name,
 254                      drm_get_connector_status_name(old_status),
 255                      drm_get_connector_status_name(connector->status));
 256
 257        return true;
 258}
 259
 260static void i915_digport_work_func(struct work_struct *work)
 261{
 262        struct drm_i915_private *dev_priv =
 263                container_of(work, struct drm_i915_private, hotplug.dig_port_work);
 264        u32 long_port_mask, short_port_mask;
 265        struct intel_digital_port *intel_dig_port;
 266        int i;
 267        u32 old_bits = 0;
 268
 269        spin_lock_irq(&dev_priv->irq_lock);
 270        long_port_mask = dev_priv->hotplug.long_port_mask;
 271        dev_priv->hotplug.long_port_mask = 0;
 272        short_port_mask = dev_priv->hotplug.short_port_mask;
 273        dev_priv->hotplug.short_port_mask = 0;
 274        spin_unlock_irq(&dev_priv->irq_lock);
 275
 276        for (i = 0; i < I915_MAX_PORTS; i++) {
 277                bool valid = false;
 278                bool long_hpd = false;
 279                intel_dig_port = dev_priv->hotplug.irq_port[i];
 280                if (!intel_dig_port || !intel_dig_port->hpd_pulse)
 281                        continue;
 282
 283                if (long_port_mask & (1 << i))  {
 284                        valid = true;
 285                        long_hpd = true;
 286                } else if (short_port_mask & (1 << i))
 287                        valid = true;
 288
 289                if (valid) {
 290                        enum irqreturn ret;
 291
 292                        ret = intel_dig_port->hpd_pulse(intel_dig_port, long_hpd);
 293                        if (ret == IRQ_NONE) {
 294                                /* fall back to old school hpd */
 295                                old_bits |= (1 << intel_dig_port->base.hpd_pin);
 296                        }
 297                }
 298        }
 299
 300        if (old_bits) {
 301                spin_lock_irq(&dev_priv->irq_lock);
 302                dev_priv->hotplug.event_bits |= old_bits;
 303                spin_unlock_irq(&dev_priv->irq_lock);
 304                schedule_work(&dev_priv->hotplug.hotplug_work);
 305        }
 306}
 307
 308/*
 309 * Handle hotplug events outside the interrupt handler proper.
 310 */
 311static void i915_hotplug_work_func(struct work_struct *work)
 312{
 313        struct drm_i915_private *dev_priv =
 314                container_of(work, struct drm_i915_private, hotplug.hotplug_work);
 315        struct drm_device *dev = &dev_priv->drm;
 316        struct intel_connector *intel_connector;
 317        struct intel_encoder *intel_encoder;
 318        struct drm_connector *connector;
 319        struct drm_connector_list_iter conn_iter;
 320        bool changed = false;
 321        u32 hpd_event_bits;
 322
 323        mutex_lock(&dev->mode_config.mutex);
 324        DRM_DEBUG_KMS("running encoder hotplug functions\n");
 325
 326        spin_lock_irq(&dev_priv->irq_lock);
 327
 328        hpd_event_bits = dev_priv->hotplug.event_bits;
 329        dev_priv->hotplug.event_bits = 0;
 330
 331        /* Disable hotplug on connectors that hit an irq storm. */
 332        intel_hpd_irq_storm_disable(dev_priv);
 333
 334        spin_unlock_irq(&dev_priv->irq_lock);
 335
 336        drm_connector_list_iter_begin(dev, &conn_iter);
 337        drm_for_each_connector_iter(connector, &conn_iter) {
 338                intel_connector = to_intel_connector(connector);
 339                if (!intel_connector->encoder)
 340                        continue;
 341                intel_encoder = intel_connector->encoder;
 342                if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) {
 343                        DRM_DEBUG_KMS("Connector %s (pin %i) received hotplug event.\n",
 344                                      connector->name, intel_encoder->hpd_pin);
 345                        if (intel_encoder->hot_plug)
 346                                intel_encoder->hot_plug(intel_encoder);
 347                        if (intel_hpd_irq_event(dev, connector))
 348                                changed = true;
 349                }
 350        }
 351        drm_connector_list_iter_end(&conn_iter);
 352        mutex_unlock(&dev->mode_config.mutex);
 353
 354        if (changed)
 355                drm_kms_helper_hotplug_event(dev);
 356}
 357
 358
 359/**
 360 * intel_hpd_irq_handler - main hotplug irq handler
 361 * @dev_priv: drm_i915_private
 362 * @pin_mask: a mask of hpd pins that have triggered the irq
 363 * @long_mask: a mask of hpd pins that may be long hpd pulses
 364 *
 365 * This is the main hotplug irq handler for all platforms. The platform specific
 366 * irq handlers call the platform specific hotplug irq handlers, which read and
 367 * decode the appropriate registers into bitmasks about hpd pins that have
 368 * triggered (@pin_mask), and which of those pins may be long pulses
 369 * (@long_mask). The @long_mask is ignored if the port corresponding to the pin
 370 * is not a digital port.
 371 *
 372 * Here, we do hotplug irq storm detection and mitigation, and pass further
 373 * processing to appropriate bottom halves.
 374 */
 375void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
 376                           u32 pin_mask, u32 long_mask)
 377{
 378        int i;
 379        enum port port;
 380        bool storm_detected = false;
 381        bool queue_dig = false, queue_hp = false;
 382        bool is_dig_port;
 383
 384        if (!pin_mask)
 385                return;
 386
 387        spin_lock(&dev_priv->irq_lock);
 388        for_each_hpd_pin(i) {
 389                if (!(BIT(i) & pin_mask))
 390                        continue;
 391
 392                is_dig_port = intel_hpd_pin_to_port(i, &port) &&
 393                              dev_priv->hotplug.irq_port[port];
 394
 395                if (is_dig_port) {
 396                        bool long_hpd = long_mask & BIT(i);
 397
 398                        DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port),
 399                                         long_hpd ? "long" : "short");
 400                        /*
 401                         * For long HPD pulses we want to have the digital queue happen,
 402                         * but we still want HPD storm detection to function.
 403                         */
 404                        queue_dig = true;
 405                        if (long_hpd) {
 406                                dev_priv->hotplug.long_port_mask |= (1 << port);
 407                        } else {
 408                                /* for short HPD just trigger the digital queue */
 409                                dev_priv->hotplug.short_port_mask |= (1 << port);
 410                                continue;
 411                        }
 412                }
 413
 414                if (dev_priv->hotplug.stats[i].state == HPD_DISABLED) {
 415                        /*
 416                         * On GMCH platforms the interrupt mask bits only
 417                         * prevent irq generation, not the setting of the
 418                         * hotplug bits itself. So only WARN about unexpected
 419                         * interrupts on saner platforms.
 420                         */
 421                        WARN_ONCE(!HAS_GMCH_DISPLAY(dev_priv),
 422                                  "Received HPD interrupt on pin %d although disabled\n", i);
 423                        continue;
 424                }
 425
 426                if (dev_priv->hotplug.stats[i].state != HPD_ENABLED)
 427                        continue;
 428
 429                if (!is_dig_port) {
 430                        dev_priv->hotplug.event_bits |= BIT(i);
 431                        queue_hp = true;
 432                }
 433
 434                if (intel_hpd_irq_storm_detect(dev_priv, i)) {
 435                        dev_priv->hotplug.event_bits &= ~BIT(i);
 436                        storm_detected = true;
 437                }
 438        }
 439
 440        if (storm_detected && dev_priv->display_irqs_enabled)
 441                dev_priv->display.hpd_irq_setup(dev_priv);
 442        spin_unlock(&dev_priv->irq_lock);
 443
 444        /*
 445         * Our hotplug handler can grab modeset locks (by calling down into the
 446         * fb helpers). Hence it must not be run on our own dev-priv->wq work
 447         * queue for otherwise the flush_work in the pageflip code will
 448         * deadlock.
 449         */
 450        if (queue_dig)
 451                queue_work(dev_priv->hotplug.dp_wq, &dev_priv->hotplug.dig_port_work);
 452        if (queue_hp)
 453                schedule_work(&dev_priv->hotplug.hotplug_work);
 454}
 455
 456/**
 457 * intel_hpd_init - initializes and enables hpd support
 458 * @dev_priv: i915 device instance
 459 *
 460 * This function enables the hotplug support. It requires that interrupts have
 461 * already been enabled with intel_irq_init_hw(). From this point on hotplug and
 462 * poll request can run concurrently to other code, so locking rules must be
 463 * obeyed.
 464 *
 465 * This is a separate step from interrupt enabling to simplify the locking rules
 466 * in the driver load and resume code.
 467 *
 468 * Also see: intel_hpd_poll_init(), which enables connector polling
 469 */
 470void intel_hpd_init(struct drm_i915_private *dev_priv)
 471{
 472        int i;
 473
 474        for_each_hpd_pin(i) {
 475                dev_priv->hotplug.stats[i].count = 0;
 476                dev_priv->hotplug.stats[i].state = HPD_ENABLED;
 477        }
 478
 479        WRITE_ONCE(dev_priv->hotplug.poll_enabled, false);
 480        schedule_work(&dev_priv->hotplug.poll_init_work);
 481
 482        /*
 483         * Interrupt setup is already guaranteed to be single-threaded, this is
 484         * just to make the assert_spin_locked checks happy.
 485         */
 486        if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup) {
 487                spin_lock_irq(&dev_priv->irq_lock);
 488                if (dev_priv->display_irqs_enabled)
 489                        dev_priv->display.hpd_irq_setup(dev_priv);
 490                spin_unlock_irq(&dev_priv->irq_lock);
 491        }
 492}
 493
 494static void i915_hpd_poll_init_work(struct work_struct *work)
 495{
 496        struct drm_i915_private *dev_priv =
 497                container_of(work, struct drm_i915_private,
 498                             hotplug.poll_init_work);
 499        struct drm_device *dev = &dev_priv->drm;
 500        struct drm_connector *connector;
 501        struct drm_connector_list_iter conn_iter;
 502        bool enabled;
 503
 504        mutex_lock(&dev->mode_config.mutex);
 505
 506        enabled = READ_ONCE(dev_priv->hotplug.poll_enabled);
 507
 508        drm_connector_list_iter_begin(dev, &conn_iter);
 509        drm_for_each_connector_iter(connector, &conn_iter) {
 510                struct intel_connector *intel_connector =
 511                        to_intel_connector(connector);
 512                connector->polled = intel_connector->polled;
 513
 514                /* MST has a dynamic intel_connector->encoder and it's reprobing
 515                 * is all handled by the MST helpers. */
 516                if (intel_connector->mst_port)
 517                        continue;
 518
 519                if (!connector->polled && I915_HAS_HOTPLUG(dev_priv) &&
 520                    intel_connector->encoder->hpd_pin > HPD_NONE) {
 521                        connector->polled = enabled ?
 522                                DRM_CONNECTOR_POLL_CONNECT |
 523                                DRM_CONNECTOR_POLL_DISCONNECT :
 524                                DRM_CONNECTOR_POLL_HPD;
 525                }
 526        }
 527        drm_connector_list_iter_end(&conn_iter);
 528
 529        if (enabled)
 530                drm_kms_helper_poll_enable(dev);
 531
 532        mutex_unlock(&dev->mode_config.mutex);
 533
 534        /*
 535         * We might have missed any hotplugs that happened while we were
 536         * in the middle of disabling polling
 537         */
 538        if (!enabled)
 539                drm_helper_hpd_irq_event(dev);
 540}
 541
 542/**
 543 * intel_hpd_poll_init - enables/disables polling for connectors with hpd
 544 * @dev_priv: i915 device instance
 545 *
 546 * This function enables polling for all connectors, regardless of whether or
 547 * not they support hotplug detection. Under certain conditions HPD may not be
 548 * functional. On most Intel GPUs, this happens when we enter runtime suspend.
 549 * On Valleyview and Cherryview systems, this also happens when we shut off all
 550 * of the powerwells.
 551 *
 552 * Since this function can get called in contexts where we're already holding
 553 * dev->mode_config.mutex, we do the actual hotplug enabling in a seperate
 554 * worker.
 555 *
 556 * Also see: intel_hpd_init(), which restores hpd handling.
 557 */
 558void intel_hpd_poll_init(struct drm_i915_private *dev_priv)
 559{
 560        WRITE_ONCE(dev_priv->hotplug.poll_enabled, true);
 561
 562        /*
 563         * We might already be holding dev->mode_config.mutex, so do this in a
 564         * seperate worker
 565         * As well, there's no issue if we race here since we always reschedule
 566         * this worker anyway
 567         */
 568        schedule_work(&dev_priv->hotplug.poll_init_work);
 569}
 570
 571void intel_hpd_init_work(struct drm_i915_private *dev_priv)
 572{
 573        INIT_WORK(&dev_priv->hotplug.hotplug_work, i915_hotplug_work_func);
 574        INIT_WORK(&dev_priv->hotplug.dig_port_work, i915_digport_work_func);
 575        INIT_WORK(&dev_priv->hotplug.poll_init_work, i915_hpd_poll_init_work);
 576        INIT_DELAYED_WORK(&dev_priv->hotplug.reenable_work,
 577                          intel_hpd_irq_storm_reenable_work);
 578}
 579
 580void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
 581{
 582        spin_lock_irq(&dev_priv->irq_lock);
 583
 584        dev_priv->hotplug.long_port_mask = 0;
 585        dev_priv->hotplug.short_port_mask = 0;
 586        dev_priv->hotplug.event_bits = 0;
 587
 588        spin_unlock_irq(&dev_priv->irq_lock);
 589
 590        cancel_work_sync(&dev_priv->hotplug.dig_port_work);
 591        cancel_work_sync(&dev_priv->hotplug.hotplug_work);
 592        cancel_work_sync(&dev_priv->hotplug.poll_init_work);
 593        cancel_delayed_work_sync(&dev_priv->hotplug.reenable_work);
 594}
 595
 596bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin)
 597{
 598        bool ret = false;
 599
 600        if (pin == HPD_NONE)
 601                return false;
 602
 603        spin_lock_irq(&dev_priv->irq_lock);
 604        if (dev_priv->hotplug.stats[pin].state == HPD_ENABLED) {
 605                dev_priv->hotplug.stats[pin].state = HPD_DISABLED;
 606                ret = true;
 607        }
 608        spin_unlock_irq(&dev_priv->irq_lock);
 609
 610        return ret;
 611}
 612
 613void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin)
 614{
 615        if (pin == HPD_NONE)
 616                return;
 617
 618        spin_lock_irq(&dev_priv->irq_lock);
 619        dev_priv->hotplug.stats[pin].state = HPD_ENABLED;
 620        spin_unlock_irq(&dev_priv->irq_lock);
 621}
 622