LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915/display - intel_hotplug.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 320 0.0 %
Date: 2022-03-28 15:32:58 Functions: 0 15 0.0 %
Branches: 0 161 0.0 %

           Branch data     Line data    Source code
       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/i915_drm.h>
      27                 :            : 
      28                 :            : #include "i915_drv.h"
      29                 :            : #include "intel_display_types.h"
      30                 :            : #include "intel_hotplug.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                 :            : 
      79                 :            : /**
      80                 :            :  * intel_hpd_pin_default - return default pin associated with certain port.
      81                 :            :  * @dev_priv: private driver data pointer
      82                 :            :  * @port: the hpd port to get associated pin
      83                 :            :  *
      84                 :            :  * It is only valid and used by digital port encoder.
      85                 :            :  *
      86                 :            :  * Return pin that is associatade with @port and HDP_NONE if no pin is
      87                 :            :  * hard associated with that @port.
      88                 :            :  */
      89                 :          0 : enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
      90                 :            :                                    enum port port)
      91                 :            : {
      92   [ #  #  #  #  :          0 :         switch (port) {
          #  #  #  #  #  
                      # ]
      93                 :            :         case PORT_A:
      94                 :            :                 return HPD_PORT_A;
      95                 :          0 :         case PORT_B:
      96                 :          0 :                 return HPD_PORT_B;
      97                 :          0 :         case PORT_C:
      98                 :          0 :                 return HPD_PORT_C;
      99                 :          0 :         case PORT_D:
     100                 :          0 :                 return HPD_PORT_D;
     101                 :          0 :         case PORT_E:
     102                 :          0 :                 return HPD_PORT_E;
     103                 :            :         case PORT_F:
     104         [ #  # ]:          0 :                 if (IS_CNL_WITH_PORT_F(dev_priv))
     105                 :          0 :                         return HPD_PORT_E;
     106                 :            :                 return HPD_PORT_F;
     107                 :          0 :         case PORT_G:
     108                 :          0 :                 return HPD_PORT_G;
     109                 :          0 :         case PORT_H:
     110                 :          0 :                 return HPD_PORT_H;
     111                 :          0 :         case PORT_I:
     112                 :          0 :                 return HPD_PORT_I;
     113                 :            :         default:
     114                 :          0 :                 MISSING_CASE(port);
     115                 :          0 :                 return HPD_NONE;
     116                 :            :         }
     117                 :            : }
     118                 :            : 
     119                 :            : #define HPD_STORM_DETECT_PERIOD         1000
     120                 :            : #define HPD_STORM_REENABLE_DELAY        (2 * 60 * 1000)
     121                 :            : #define HPD_RETRY_DELAY                 1000
     122                 :            : 
     123                 :            : /**
     124                 :            :  * intel_hpd_irq_storm_detect - gather stats and detect HPD IRQ storm on a pin
     125                 :            :  * @dev_priv: private driver data pointer
     126                 :            :  * @pin: the pin to gather stats on
     127                 :            :  * @long_hpd: whether the HPD IRQ was long or short
     128                 :            :  *
     129                 :            :  * Gather stats about HPD IRQs from the specified @pin, and detect IRQ
     130                 :            :  * storms. Only the pin specific stats and state are changed, the caller is
     131                 :            :  * responsible for further action.
     132                 :            :  *
     133                 :            :  * The number of IRQs that are allowed within @HPD_STORM_DETECT_PERIOD is
     134                 :            :  * stored in @dev_priv->hotplug.hpd_storm_threshold which defaults to
     135                 :            :  * @HPD_STORM_DEFAULT_THRESHOLD. Long IRQs count as +10 to this threshold, and
     136                 :            :  * short IRQs count as +1. If this threshold is exceeded, it's considered an
     137                 :            :  * IRQ storm and the IRQ state is set to @HPD_MARK_DISABLED.
     138                 :            :  *
     139                 :            :  * By default, most systems will only count long IRQs towards
     140                 :            :  * &dev_priv->hotplug.hpd_storm_threshold. However, some older systems also
     141                 :            :  * suffer from short IRQ storms and must also track these. Because short IRQ
     142                 :            :  * storms are naturally caused by sideband interactions with DP MST devices,
     143                 :            :  * short IRQ detection is only enabled for systems without DP MST support.
     144                 :            :  * Systems which are new enough to support DP MST are far less likely to
     145                 :            :  * suffer from IRQ storms at all, so this is fine.
     146                 :            :  *
     147                 :            :  * The HPD threshold can be controlled through i915_hpd_storm_ctl in debugfs,
     148                 :            :  * and should only be adjusted for automated hotplug testing.
     149                 :            :  *
     150                 :            :  * Return true if an IRQ storm was detected on @pin.
     151                 :            :  */
     152                 :          0 : static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv,
     153                 :            :                                        enum hpd_pin pin, bool long_hpd)
     154                 :            : {
     155                 :          0 :         struct i915_hotplug *hpd = &dev_priv->hotplug;
     156                 :          0 :         unsigned long start = hpd->stats[pin].last_jiffies;
     157         [ #  # ]:          0 :         unsigned long end = start + msecs_to_jiffies(HPD_STORM_DETECT_PERIOD);
     158         [ #  # ]:          0 :         const int increment = long_hpd ? 10 : 1;
     159                 :          0 :         const int threshold = hpd->hpd_storm_threshold;
     160                 :          0 :         bool storm = false;
     161                 :            : 
     162   [ #  #  #  # ]:          0 :         if (!threshold ||
     163         [ #  # ]:          0 :             (!long_hpd && !dev_priv->hotplug.hpd_short_storm_enabled))
     164                 :            :                 return false;
     165                 :            : 
     166   [ #  #  #  # ]:          0 :         if (!time_in_range(jiffies, start, end)) {
     167                 :          0 :                 hpd->stats[pin].last_jiffies = jiffies;
     168                 :          0 :                 hpd->stats[pin].count = 0;
     169                 :            :         }
     170                 :            : 
     171                 :          0 :         hpd->stats[pin].count += increment;
     172         [ #  # ]:          0 :         if (hpd->stats[pin].count > threshold) {
     173                 :          0 :                 hpd->stats[pin].state = HPD_MARK_DISABLED;
     174                 :          0 :                 DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", pin);
     175                 :          0 :                 storm = true;
     176                 :            :         } else {
     177                 :          0 :                 DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: %d\n", pin,
     178                 :            :                               hpd->stats[pin].count);
     179                 :            :         }
     180                 :            : 
     181                 :            :         return storm;
     182                 :            : }
     183                 :            : 
     184                 :            : static void
     185                 :          0 : intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv)
     186                 :            : {
     187                 :          0 :         struct drm_device *dev = &dev_priv->drm;
     188                 :          0 :         struct intel_connector *intel_connector;
     189                 :          0 :         struct intel_encoder *intel_encoder;
     190                 :          0 :         struct drm_connector *connector;
     191                 :          0 :         struct drm_connector_list_iter conn_iter;
     192                 :          0 :         enum hpd_pin pin;
     193                 :          0 :         bool hpd_disabled = false;
     194                 :            : 
     195                 :          0 :         lockdep_assert_held(&dev_priv->irq_lock);
     196                 :            : 
     197                 :          0 :         drm_connector_list_iter_begin(dev, &conn_iter);
     198         [ #  # ]:          0 :         drm_for_each_connector_iter(connector, &conn_iter) {
     199         [ #  # ]:          0 :                 if (connector->polled != DRM_CONNECTOR_POLL_HPD)
     200                 :          0 :                         continue;
     201                 :            : 
     202                 :          0 :                 intel_connector = to_intel_connector(connector);
     203                 :          0 :                 intel_encoder = intel_connector->encoder;
     204         [ #  # ]:          0 :                 if (!intel_encoder)
     205                 :          0 :                         continue;
     206                 :            : 
     207                 :          0 :                 pin = intel_encoder->hpd_pin;
     208         [ #  # ]:          0 :                 if (pin == HPD_NONE ||
     209         [ #  # ]:          0 :                     dev_priv->hotplug.stats[pin].state != HPD_MARK_DISABLED)
     210                 :          0 :                         continue;
     211                 :            : 
     212                 :          0 :                 DRM_INFO("HPD interrupt storm detected on connector %s: "
     213                 :            :                          "switching from hotplug detection to polling\n",
     214                 :            :                          connector->name);
     215                 :            : 
     216                 :          0 :                 dev_priv->hotplug.stats[pin].state = HPD_DISABLED;
     217                 :          0 :                 connector->polled = DRM_CONNECTOR_POLL_CONNECT
     218                 :            :                         | DRM_CONNECTOR_POLL_DISCONNECT;
     219                 :          0 :                 hpd_disabled = true;
     220                 :            :         }
     221                 :          0 :         drm_connector_list_iter_end(&conn_iter);
     222                 :            : 
     223                 :            :         /* Enable polling and queue hotplug re-enabling. */
     224         [ #  # ]:          0 :         if (hpd_disabled) {
     225                 :          0 :                 drm_kms_helper_poll_enable(dev);
     226                 :          0 :                 mod_delayed_work(system_wq, &dev_priv->hotplug.reenable_work,
     227                 :            :                                  msecs_to_jiffies(HPD_STORM_REENABLE_DELAY));
     228                 :            :         }
     229                 :          0 : }
     230                 :            : 
     231                 :          0 : static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
     232                 :            : {
     233                 :          0 :         struct drm_i915_private *dev_priv =
     234                 :          0 :                 container_of(work, typeof(*dev_priv),
     235                 :            :                              hotplug.reenable_work.work);
     236                 :          0 :         struct drm_device *dev = &dev_priv->drm;
     237                 :          0 :         intel_wakeref_t wakeref;
     238                 :          0 :         enum hpd_pin pin;
     239                 :            : 
     240                 :          0 :         wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
     241                 :            : 
     242                 :          0 :         spin_lock_irq(&dev_priv->irq_lock);
     243         [ #  # ]:          0 :         for_each_hpd_pin(pin) {
     244                 :          0 :                 struct drm_connector *connector;
     245                 :          0 :                 struct drm_connector_list_iter conn_iter;
     246                 :            : 
     247         [ #  # ]:          0 :                 if (dev_priv->hotplug.stats[pin].state != HPD_DISABLED)
     248                 :          0 :                         continue;
     249                 :            : 
     250                 :          0 :                 dev_priv->hotplug.stats[pin].state = HPD_ENABLED;
     251                 :            : 
     252                 :          0 :                 drm_connector_list_iter_begin(dev, &conn_iter);
     253         [ #  # ]:          0 :                 drm_for_each_connector_iter(connector, &conn_iter) {
     254                 :          0 :                         struct intel_connector *intel_connector = to_intel_connector(connector);
     255                 :            : 
     256                 :            :                         /* Don't check MST ports, they don't have pins */
     257         [ #  # ]:          0 :                         if (!intel_connector->mst_port &&
     258         [ #  # ]:          0 :                             intel_connector->encoder->hpd_pin == pin) {
     259         [ #  # ]:          0 :                                 if (connector->polled != intel_connector->polled)
     260                 :          0 :                                         DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
     261                 :            :                                                          connector->name);
     262                 :          0 :                                 connector->polled = intel_connector->polled;
     263         [ #  # ]:          0 :                                 if (!connector->polled)
     264                 :          0 :                                         connector->polled = DRM_CONNECTOR_POLL_HPD;
     265                 :            :                         }
     266                 :            :                 }
     267                 :          0 :                 drm_connector_list_iter_end(&conn_iter);
     268                 :            :         }
     269   [ #  #  #  # ]:          0 :         if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup)
     270                 :          0 :                 dev_priv->display.hpd_irq_setup(dev_priv);
     271                 :          0 :         spin_unlock_irq(&dev_priv->irq_lock);
     272                 :            : 
     273                 :          0 :         intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
     274                 :          0 : }
     275                 :            : 
     276                 :            : enum intel_hotplug_state
     277                 :          0 : intel_encoder_hotplug(struct intel_encoder *encoder,
     278                 :            :                       struct intel_connector *connector,
     279                 :            :                       bool irq_received)
     280                 :            : {
     281                 :          0 :         struct drm_device *dev = connector->base.dev;
     282                 :          0 :         enum drm_connector_status old_status;
     283                 :            : 
     284         [ #  # ]:          0 :         WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
     285                 :          0 :         old_status = connector->base.status;
     286                 :            : 
     287                 :          0 :         connector->base.status =
     288                 :          0 :                 drm_helper_probe_detect(&connector->base, NULL, false);
     289                 :            : 
     290         [ #  # ]:          0 :         if (old_status == connector->base.status)
     291                 :            :                 return INTEL_HOTPLUG_UNCHANGED;
     292                 :            : 
     293                 :          0 :         DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
     294                 :            :                       connector->base.base.id,
     295                 :            :                       connector->base.name,
     296                 :            :                       drm_get_connector_status_name(old_status),
     297                 :            :                       drm_get_connector_status_name(connector->base.status));
     298                 :            : 
     299                 :          0 :         return INTEL_HOTPLUG_CHANGED;
     300                 :            : }
     301                 :            : 
     302                 :          0 : static bool intel_encoder_has_hpd_pulse(struct intel_encoder *encoder)
     303                 :            : {
     304                 :          0 :         return intel_encoder_is_dig_port(encoder) &&
     305   [ #  #  #  # ]:          0 :                 enc_to_dig_port(encoder)->hpd_pulse != NULL;
     306                 :            : }
     307                 :            : 
     308                 :          0 : static void i915_digport_work_func(struct work_struct *work)
     309                 :            : {
     310                 :          0 :         struct drm_i915_private *dev_priv =
     311                 :          0 :                 container_of(work, struct drm_i915_private, hotplug.dig_port_work);
     312                 :          0 :         u32 long_port_mask, short_port_mask;
     313                 :          0 :         struct intel_encoder *encoder;
     314                 :          0 :         u32 old_bits = 0;
     315                 :            : 
     316                 :          0 :         spin_lock_irq(&dev_priv->irq_lock);
     317                 :          0 :         long_port_mask = dev_priv->hotplug.long_port_mask;
     318                 :          0 :         dev_priv->hotplug.long_port_mask = 0;
     319                 :          0 :         short_port_mask = dev_priv->hotplug.short_port_mask;
     320                 :          0 :         dev_priv->hotplug.short_port_mask = 0;
     321                 :          0 :         spin_unlock_irq(&dev_priv->irq_lock);
     322                 :            : 
     323         [ #  # ]:          0 :         for_each_intel_encoder(&dev_priv->drm, encoder) {
     324                 :          0 :                 struct intel_digital_port *dig_port;
     325                 :          0 :                 enum port port = encoder->port;
     326                 :          0 :                 bool long_hpd, short_hpd;
     327                 :          0 :                 enum irqreturn ret;
     328                 :            : 
     329   [ #  #  #  # ]:          0 :                 if (!intel_encoder_has_hpd_pulse(encoder))
     330                 :          0 :                         continue;
     331                 :            : 
     332                 :          0 :                 long_hpd = long_port_mask & BIT(port);
     333                 :          0 :                 short_hpd = short_port_mask & BIT(port);
     334                 :            : 
     335         [ #  # ]:          0 :                 if (!long_hpd && !short_hpd)
     336                 :          0 :                         continue;
     337                 :            : 
     338         [ #  # ]:          0 :                 dig_port = enc_to_dig_port(encoder);
     339                 :            : 
     340                 :          0 :                 ret = dig_port->hpd_pulse(dig_port, long_hpd);
     341         [ #  # ]:          0 :                 if (ret == IRQ_NONE) {
     342                 :            :                         /* fall back to old school hpd */
     343                 :          0 :                         old_bits |= BIT(encoder->hpd_pin);
     344                 :            :                 }
     345                 :            :         }
     346                 :            : 
     347         [ #  # ]:          0 :         if (old_bits) {
     348                 :          0 :                 spin_lock_irq(&dev_priv->irq_lock);
     349                 :          0 :                 dev_priv->hotplug.event_bits |= old_bits;
     350                 :          0 :                 spin_unlock_irq(&dev_priv->irq_lock);
     351                 :          0 :                 queue_delayed_work(system_wq, &dev_priv->hotplug.hotplug_work, 0);
     352                 :            :         }
     353                 :          0 : }
     354                 :            : 
     355                 :            : /*
     356                 :            :  * Handle hotplug events outside the interrupt handler proper.
     357                 :            :  */
     358                 :          0 : static void i915_hotplug_work_func(struct work_struct *work)
     359                 :            : {
     360                 :          0 :         struct drm_i915_private *dev_priv =
     361                 :          0 :                 container_of(work, struct drm_i915_private,
     362                 :            :                              hotplug.hotplug_work.work);
     363                 :          0 :         struct drm_device *dev = &dev_priv->drm;
     364                 :          0 :         struct intel_connector *intel_connector;
     365                 :          0 :         struct intel_encoder *intel_encoder;
     366                 :          0 :         struct drm_connector *connector;
     367                 :          0 :         struct drm_connector_list_iter conn_iter;
     368                 :          0 :         u32 changed = 0, retry = 0;
     369                 :          0 :         u32 hpd_event_bits;
     370                 :          0 :         u32 hpd_retry_bits;
     371                 :            : 
     372                 :          0 :         mutex_lock(&dev->mode_config.mutex);
     373                 :          0 :         DRM_DEBUG_KMS("running encoder hotplug functions\n");
     374                 :            : 
     375                 :          0 :         spin_lock_irq(&dev_priv->irq_lock);
     376                 :            : 
     377                 :          0 :         hpd_event_bits = dev_priv->hotplug.event_bits;
     378                 :          0 :         dev_priv->hotplug.event_bits = 0;
     379                 :          0 :         hpd_retry_bits = dev_priv->hotplug.retry_bits;
     380                 :          0 :         dev_priv->hotplug.retry_bits = 0;
     381                 :            : 
     382                 :            :         /* Enable polling for connectors which had HPD IRQ storms */
     383                 :          0 :         intel_hpd_irq_storm_switch_to_polling(dev_priv);
     384                 :            : 
     385                 :          0 :         spin_unlock_irq(&dev_priv->irq_lock);
     386                 :            : 
     387                 :          0 :         drm_connector_list_iter_begin(dev, &conn_iter);
     388         [ #  # ]:          0 :         drm_for_each_connector_iter(connector, &conn_iter) {
     389                 :          0 :                 u32 hpd_bit;
     390                 :            : 
     391                 :          0 :                 intel_connector = to_intel_connector(connector);
     392         [ #  # ]:          0 :                 if (!intel_connector->encoder)
     393                 :          0 :                         continue;
     394                 :          0 :                 intel_encoder = intel_connector->encoder;
     395                 :          0 :                 hpd_bit = BIT(intel_encoder->hpd_pin);
     396         [ #  # ]:          0 :                 if ((hpd_event_bits | hpd_retry_bits) & hpd_bit) {
     397                 :          0 :                         DRM_DEBUG_KMS("Connector %s (pin %i) received hotplug event.\n",
     398                 :            :                                       connector->name, intel_encoder->hpd_pin);
     399                 :            : 
     400      [ #  #  # ]:          0 :                         switch (intel_encoder->hotplug(intel_encoder,
     401                 :            :                                                        intel_connector,
     402                 :          0 :                                                        hpd_event_bits & hpd_bit)) {
     403                 :            :                         case INTEL_HOTPLUG_UNCHANGED:
     404                 :            :                                 break;
     405                 :          0 :                         case INTEL_HOTPLUG_CHANGED:
     406                 :          0 :                                 changed |= hpd_bit;
     407                 :          0 :                                 break;
     408                 :          0 :                         case INTEL_HOTPLUG_RETRY:
     409                 :          0 :                                 retry |= hpd_bit;
     410                 :          0 :                                 break;
     411                 :            :                         }
     412                 :          0 :                 }
     413                 :            :         }
     414                 :          0 :         drm_connector_list_iter_end(&conn_iter);
     415                 :          0 :         mutex_unlock(&dev->mode_config.mutex);
     416                 :            : 
     417         [ #  # ]:          0 :         if (changed)
     418                 :          0 :                 drm_kms_helper_hotplug_event(dev);
     419                 :            : 
     420                 :            :         /* Remove shared HPD pins that have changed */
     421                 :          0 :         retry &= ~changed;
     422         [ #  # ]:          0 :         if (retry) {
     423                 :          0 :                 spin_lock_irq(&dev_priv->irq_lock);
     424                 :          0 :                 dev_priv->hotplug.retry_bits |= retry;
     425                 :          0 :                 spin_unlock_irq(&dev_priv->irq_lock);
     426                 :            : 
     427                 :          0 :                 mod_delayed_work(system_wq, &dev_priv->hotplug.hotplug_work,
     428                 :            :                                  msecs_to_jiffies(HPD_RETRY_DELAY));
     429                 :            :         }
     430                 :          0 : }
     431                 :            : 
     432                 :            : 
     433                 :            : /**
     434                 :            :  * intel_hpd_irq_handler - main hotplug irq handler
     435                 :            :  * @dev_priv: drm_i915_private
     436                 :            :  * @pin_mask: a mask of hpd pins that have triggered the irq
     437                 :            :  * @long_mask: a mask of hpd pins that may be long hpd pulses
     438                 :            :  *
     439                 :            :  * This is the main hotplug irq handler for all platforms. The platform specific
     440                 :            :  * irq handlers call the platform specific hotplug irq handlers, which read and
     441                 :            :  * decode the appropriate registers into bitmasks about hpd pins that have
     442                 :            :  * triggered (@pin_mask), and which of those pins may be long pulses
     443                 :            :  * (@long_mask). The @long_mask is ignored if the port corresponding to the pin
     444                 :            :  * is not a digital port.
     445                 :            :  *
     446                 :            :  * Here, we do hotplug irq storm detection and mitigation, and pass further
     447                 :            :  * processing to appropriate bottom halves.
     448                 :            :  */
     449                 :          0 : void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
     450                 :            :                            u32 pin_mask, u32 long_mask)
     451                 :            : {
     452                 :          0 :         struct intel_encoder *encoder;
     453                 :          0 :         bool storm_detected = false;
     454                 :          0 :         bool queue_dig = false, queue_hp = false;
     455                 :          0 :         u32 long_hpd_pulse_mask = 0;
     456                 :          0 :         u32 short_hpd_pulse_mask = 0;
     457                 :          0 :         enum hpd_pin pin;
     458                 :            : 
     459         [ #  # ]:          0 :         if (!pin_mask)
     460                 :            :                 return;
     461                 :            : 
     462                 :          0 :         spin_lock(&dev_priv->irq_lock);
     463                 :            : 
     464                 :            :         /*
     465                 :            :          * Determine whether ->hpd_pulse() exists for each pin, and
     466                 :            :          * whether we have a short or a long pulse. This is needed
     467                 :            :          * as each pin may have up to two encoders (HDMI and DP) and
     468                 :            :          * only the one of them (DP) will have ->hpd_pulse().
     469                 :            :          */
     470         [ #  # ]:          0 :         for_each_intel_encoder(&dev_priv->drm, encoder) {
     471         [ #  # ]:          0 :                 bool has_hpd_pulse = intel_encoder_has_hpd_pulse(encoder);
     472                 :          0 :                 enum port port = encoder->port;
     473                 :          0 :                 bool long_hpd;
     474                 :            : 
     475                 :          0 :                 pin = encoder->hpd_pin;
     476         [ #  # ]:          0 :                 if (!(BIT(pin) & pin_mask))
     477                 :          0 :                         continue;
     478                 :            : 
     479         [ #  # ]:          0 :                 if (!has_hpd_pulse)
     480                 :          0 :                         continue;
     481                 :            : 
     482                 :          0 :                 long_hpd = long_mask & BIT(pin);
     483                 :            : 
     484         [ #  # ]:          0 :                 DRM_DEBUG_DRIVER("digital hpd on [ENCODER:%d:%s] - %s\n",
     485                 :            :                                  encoder->base.base.id, encoder->base.name,
     486                 :            :                                  long_hpd ? "long" : "short");
     487                 :          0 :                 queue_dig = true;
     488                 :            : 
     489         [ #  # ]:          0 :                 if (long_hpd) {
     490                 :          0 :                         long_hpd_pulse_mask |= BIT(pin);
     491                 :          0 :                         dev_priv->hotplug.long_port_mask |= BIT(port);
     492                 :            :                 } else {
     493                 :          0 :                         short_hpd_pulse_mask |= BIT(pin);
     494                 :          0 :                         dev_priv->hotplug.short_port_mask |= BIT(port);
     495                 :            :                 }
     496                 :            :         }
     497                 :            : 
     498                 :            :         /* Now process each pin just once */
     499         [ #  # ]:          0 :         for_each_hpd_pin(pin) {
     500                 :          0 :                 bool long_hpd;
     501                 :            : 
     502         [ #  # ]:          0 :                 if (!(BIT(pin) & pin_mask))
     503                 :          0 :                         continue;
     504                 :            : 
     505         [ #  # ]:          0 :                 if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) {
     506                 :            :                         /*
     507                 :            :                          * On GMCH platforms the interrupt mask bits only
     508                 :            :                          * prevent irq generation, not the setting of the
     509                 :            :                          * hotplug bits itself. So only WARN about unexpected
     510                 :            :                          * interrupts on saner platforms.
     511                 :            :                          */
     512   [ #  #  #  # ]:          0 :                         WARN_ONCE(!HAS_GMCH(dev_priv),
     513                 :            :                                   "Received HPD interrupt on pin %d although disabled\n", pin);
     514                 :          0 :                         continue;
     515                 :            :                 }
     516                 :            : 
     517         [ #  # ]:          0 :                 if (dev_priv->hotplug.stats[pin].state != HPD_ENABLED)
     518                 :          0 :                         continue;
     519                 :            : 
     520                 :            :                 /*
     521                 :            :                  * Delegate to ->hpd_pulse() if one of the encoders for this
     522                 :            :                  * pin has it, otherwise let the hotplug_work deal with this
     523                 :            :                  * pin directly.
     524                 :            :                  */
     525         [ #  # ]:          0 :                 if (((short_hpd_pulse_mask | long_hpd_pulse_mask) & BIT(pin))) {
     526                 :          0 :                         long_hpd = long_hpd_pulse_mask & BIT(pin);
     527                 :            :                 } else {
     528                 :          0 :                         dev_priv->hotplug.event_bits |= BIT(pin);
     529                 :          0 :                         long_hpd = true;
     530                 :          0 :                         queue_hp = true;
     531                 :            :                 }
     532                 :            : 
     533         [ #  # ]:          0 :                 if (intel_hpd_irq_storm_detect(dev_priv, pin, long_hpd)) {
     534                 :          0 :                         dev_priv->hotplug.event_bits &= ~BIT(pin);
     535                 :          0 :                         storm_detected = true;
     536                 :          0 :                         queue_hp = true;
     537                 :            :                 }
     538                 :            :         }
     539                 :            : 
     540                 :            :         /*
     541                 :            :          * Disable any IRQs that storms were detected on. Polling enablement
     542                 :            :          * happens later in our hotplug work.
     543                 :            :          */
     544   [ #  #  #  # ]:          0 :         if (storm_detected && dev_priv->display_irqs_enabled)
     545                 :          0 :                 dev_priv->display.hpd_irq_setup(dev_priv);
     546                 :          0 :         spin_unlock(&dev_priv->irq_lock);
     547                 :            : 
     548                 :            :         /*
     549                 :            :          * Our hotplug handler can grab modeset locks (by calling down into the
     550                 :            :          * fb helpers). Hence it must not be run on our own dev-priv->wq work
     551                 :            :          * queue for otherwise the flush_work in the pageflip code will
     552                 :            :          * deadlock.
     553                 :            :          */
     554         [ #  # ]:          0 :         if (queue_dig)
     555                 :          0 :                 queue_work(dev_priv->hotplug.dp_wq, &dev_priv->hotplug.dig_port_work);
     556         [ #  # ]:          0 :         if (queue_hp)
     557                 :          0 :                 queue_delayed_work(system_wq, &dev_priv->hotplug.hotplug_work, 0);
     558                 :            : }
     559                 :            : 
     560                 :            : /**
     561                 :            :  * intel_hpd_init - initializes and enables hpd support
     562                 :            :  * @dev_priv: i915 device instance
     563                 :            :  *
     564                 :            :  * This function enables the hotplug support. It requires that interrupts have
     565                 :            :  * already been enabled with intel_irq_init_hw(). From this point on hotplug and
     566                 :            :  * poll request can run concurrently to other code, so locking rules must be
     567                 :            :  * obeyed.
     568                 :            :  *
     569                 :            :  * This is a separate step from interrupt enabling to simplify the locking rules
     570                 :            :  * in the driver load and resume code.
     571                 :            :  *
     572                 :            :  * Also see: intel_hpd_poll_init(), which enables connector polling
     573                 :            :  */
     574                 :          0 : void intel_hpd_init(struct drm_i915_private *dev_priv)
     575                 :            : {
     576                 :          0 :         int i;
     577                 :            : 
     578         [ #  # ]:          0 :         for_each_hpd_pin(i) {
     579                 :          0 :                 dev_priv->hotplug.stats[i].count = 0;
     580                 :          0 :                 dev_priv->hotplug.stats[i].state = HPD_ENABLED;
     581                 :            :         }
     582                 :            : 
     583                 :          0 :         WRITE_ONCE(dev_priv->hotplug.poll_enabled, false);
     584                 :          0 :         schedule_work(&dev_priv->hotplug.poll_init_work);
     585                 :            : 
     586                 :            :         /*
     587                 :            :          * Interrupt setup is already guaranteed to be single-threaded, this is
     588                 :            :          * just to make the assert_spin_locked checks happy.
     589                 :            :          */
     590   [ #  #  #  # ]:          0 :         if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup) {
     591                 :          0 :                 spin_lock_irq(&dev_priv->irq_lock);
     592         [ #  # ]:          0 :                 if (dev_priv->display_irqs_enabled)
     593                 :          0 :                         dev_priv->display.hpd_irq_setup(dev_priv);
     594                 :          0 :                 spin_unlock_irq(&dev_priv->irq_lock);
     595                 :            :         }
     596                 :          0 : }
     597                 :            : 
     598                 :          0 : static void i915_hpd_poll_init_work(struct work_struct *work)
     599                 :            : {
     600                 :          0 :         struct drm_i915_private *dev_priv =
     601                 :          0 :                 container_of(work, struct drm_i915_private,
     602                 :            :                              hotplug.poll_init_work);
     603                 :          0 :         struct drm_device *dev = &dev_priv->drm;
     604                 :          0 :         struct drm_connector *connector;
     605                 :          0 :         struct drm_connector_list_iter conn_iter;
     606                 :          0 :         bool enabled;
     607                 :            : 
     608                 :          0 :         mutex_lock(&dev->mode_config.mutex);
     609                 :            : 
     610                 :          0 :         enabled = READ_ONCE(dev_priv->hotplug.poll_enabled);
     611                 :            : 
     612                 :          0 :         drm_connector_list_iter_begin(dev, &conn_iter);
     613         [ #  # ]:          0 :         drm_for_each_connector_iter(connector, &conn_iter) {
     614                 :          0 :                 struct intel_connector *intel_connector =
     615                 :          0 :                         to_intel_connector(connector);
     616                 :          0 :                 connector->polled = intel_connector->polled;
     617                 :            : 
     618                 :            :                 /* MST has a dynamic intel_connector->encoder and it's reprobing
     619                 :            :                  * is all handled by the MST helpers. */
     620         [ #  # ]:          0 :                 if (intel_connector->mst_port)
     621                 :          0 :                         continue;
     622                 :            : 
     623   [ #  #  #  # ]:          0 :                 if (!connector->polled && I915_HAS_HOTPLUG(dev_priv) &&
     624         [ #  # ]:          0 :                     intel_connector->encoder->hpd_pin > HPD_NONE) {
     625         [ #  # ]:          0 :                         connector->polled = enabled ?
     626                 :            :                                 DRM_CONNECTOR_POLL_CONNECT |
     627                 :            :                                 DRM_CONNECTOR_POLL_DISCONNECT :
     628                 :            :                                 DRM_CONNECTOR_POLL_HPD;
     629                 :            :                 }
     630                 :            :         }
     631                 :          0 :         drm_connector_list_iter_end(&conn_iter);
     632                 :            : 
     633         [ #  # ]:          0 :         if (enabled)
     634                 :          0 :                 drm_kms_helper_poll_enable(dev);
     635                 :            : 
     636                 :          0 :         mutex_unlock(&dev->mode_config.mutex);
     637                 :            : 
     638                 :            :         /*
     639                 :            :          * We might have missed any hotplugs that happened while we were
     640                 :            :          * in the middle of disabling polling
     641                 :            :          */
     642         [ #  # ]:          0 :         if (!enabled)
     643                 :          0 :                 drm_helper_hpd_irq_event(dev);
     644                 :          0 : }
     645                 :            : 
     646                 :            : /**
     647                 :            :  * intel_hpd_poll_init - enables/disables polling for connectors with hpd
     648                 :            :  * @dev_priv: i915 device instance
     649                 :            :  *
     650                 :            :  * This function enables polling for all connectors, regardless of whether or
     651                 :            :  * not they support hotplug detection. Under certain conditions HPD may not be
     652                 :            :  * functional. On most Intel GPUs, this happens when we enter runtime suspend.
     653                 :            :  * On Valleyview and Cherryview systems, this also happens when we shut off all
     654                 :            :  * of the powerwells.
     655                 :            :  *
     656                 :            :  * Since this function can get called in contexts where we're already holding
     657                 :            :  * dev->mode_config.mutex, we do the actual hotplug enabling in a seperate
     658                 :            :  * worker.
     659                 :            :  *
     660                 :            :  * Also see: intel_hpd_init(), which restores hpd handling.
     661                 :            :  */
     662                 :          0 : void intel_hpd_poll_init(struct drm_i915_private *dev_priv)
     663                 :            : {
     664                 :          0 :         WRITE_ONCE(dev_priv->hotplug.poll_enabled, true);
     665                 :            : 
     666                 :            :         /*
     667                 :            :          * We might already be holding dev->mode_config.mutex, so do this in a
     668                 :            :          * seperate worker
     669                 :            :          * As well, there's no issue if we race here since we always reschedule
     670                 :            :          * this worker anyway
     671                 :            :          */
     672                 :          0 :         schedule_work(&dev_priv->hotplug.poll_init_work);
     673                 :          0 : }
     674                 :            : 
     675                 :          0 : void intel_hpd_init_work(struct drm_i915_private *dev_priv)
     676                 :            : {
     677                 :          0 :         INIT_DELAYED_WORK(&dev_priv->hotplug.hotplug_work,
     678                 :            :                           i915_hotplug_work_func);
     679                 :          0 :         INIT_WORK(&dev_priv->hotplug.dig_port_work, i915_digport_work_func);
     680                 :          0 :         INIT_WORK(&dev_priv->hotplug.poll_init_work, i915_hpd_poll_init_work);
     681                 :          0 :         INIT_DELAYED_WORK(&dev_priv->hotplug.reenable_work,
     682                 :            :                           intel_hpd_irq_storm_reenable_work);
     683                 :          0 : }
     684                 :            : 
     685                 :          0 : void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
     686                 :            : {
     687                 :          0 :         spin_lock_irq(&dev_priv->irq_lock);
     688                 :            : 
     689                 :          0 :         dev_priv->hotplug.long_port_mask = 0;
     690                 :          0 :         dev_priv->hotplug.short_port_mask = 0;
     691                 :          0 :         dev_priv->hotplug.event_bits = 0;
     692                 :          0 :         dev_priv->hotplug.retry_bits = 0;
     693                 :            : 
     694                 :          0 :         spin_unlock_irq(&dev_priv->irq_lock);
     695                 :            : 
     696                 :          0 :         cancel_work_sync(&dev_priv->hotplug.dig_port_work);
     697                 :          0 :         cancel_delayed_work_sync(&dev_priv->hotplug.hotplug_work);
     698                 :          0 :         cancel_work_sync(&dev_priv->hotplug.poll_init_work);
     699                 :          0 :         cancel_delayed_work_sync(&dev_priv->hotplug.reenable_work);
     700                 :          0 : }
     701                 :            : 
     702                 :          0 : bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin)
     703                 :            : {
     704                 :          0 :         bool ret = false;
     705                 :            : 
     706         [ #  # ]:          0 :         if (pin == HPD_NONE)
     707                 :            :                 return false;
     708                 :            : 
     709                 :          0 :         spin_lock_irq(&dev_priv->irq_lock);
     710         [ #  # ]:          0 :         if (dev_priv->hotplug.stats[pin].state == HPD_ENABLED) {
     711                 :          0 :                 dev_priv->hotplug.stats[pin].state = HPD_DISABLED;
     712                 :          0 :                 ret = true;
     713                 :            :         }
     714                 :          0 :         spin_unlock_irq(&dev_priv->irq_lock);
     715                 :            : 
     716                 :          0 :         return ret;
     717                 :            : }
     718                 :            : 
     719                 :          0 : void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin)
     720                 :            : {
     721         [ #  # ]:          0 :         if (pin == HPD_NONE)
     722                 :            :                 return;
     723                 :            : 
     724                 :          0 :         spin_lock_irq(&dev_priv->irq_lock);
     725                 :          0 :         dev_priv->hotplug.stats[pin].state = HPD_ENABLED;
     726                 :          0 :         spin_unlock_irq(&dev_priv->irq_lock);
     727                 :            : }

Generated by: LCOV version 1.14