<html><head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
</head><body bgcolor="#FFFFFF" text="#000000">This looks like it's good 
to go. <br>
<br>
As an aside, I don't *think* any of the compliance testing stuff I'm 
working on cares whether it's short of long pulse (1.1a compliance), but
 it will be interesting to see if/when/where it might have an effect.<br>
<br>
Reviewed-by: Todd Previte <a class="moz-txt-link-rfc2396E" href="mailto:tprevite@gmail.com"><tprevite@gmail.com></a><br>
<br>
<blockquote style="border: 0px none;" 
cite="mid:1403054975-12576-3-git-send-email-airlied@gmail.com" 
type="cite">
  <div style="margin:30px 25px 10px 25px;" class="__pbConvHr"><div 
style="display:table;width:100%;border-top:1px solid 
#EDEEF0;padding-top:5px">       <div 
style="display:table-cell;vertical-align:middle;padding-right:6px;"><img
 photoaddress="airlied@gmail.com" photoname="Dave Airlie" 
src="cid:part1.02070802.03080302@gmail.com" name="postbox-contact.jpg" 
height="25px" width="25px"></div>   <div 
style="display:table-cell;white-space:nowrap;vertical-align:middle;width:100%">
        <a moz-do-not-send="true" href="mailto:airlied@gmail.com" 
style="color:#737F92 
!important;padding-right:6px;font-weight:bold;text-decoration:none 
!important;">Dave Airlie</a></div>   <div 
style="display:table-cell;white-space:nowrap;vertical-align:middle;">   
  <font color="#9FA2A5"><span style="padding-left:6px">Tuesday, June 17,
 2014 6:29 PM</span></font></div></div></div>
  <div style="color:#888888;margin-left:24px;margin-right:24px;" 
__pbrmquotes="true" class="__pbConvBody"><div>From: Dave Airlie 
<a class="moz-txt-link-rfc2396E" href="mailto:airlied@redhat.com"><airlied@redhat.com></a><br><br>The digital ports from Ironlake and up
 have the ability to distinguish<br>between long and short HPD pulses. 
Displayport 1.1 only uses the short<br>form to request link retraining 
usually, so we haven't really needed<br>support for it until now.<br><br>However
 with DP 1.2 MST we need to handle the short irqs on their<br>own 
outside the modesetting locking the long hpd's involve. This<br>patch 
adds the framework to distinguish between short/long to the<br>current 
code base, to lay the basis for future DP 1.2 MST work.<br><br>This 
should mean we get better bisectability in case of regression<br>due to 
the new irq handling.<br><br>v2: add GM45 support (untested, due to lack
 of hw)<br><br>Signed-off-by: Dave Airlie <a class="moz-txt-link-rfc2396E" href="mailto:airlied@redhat.com"><airlied@redhat.com></a><br>---<br>
 drivers/gpu/drm/i915/i915_drv.h  |   5 ++<br> 
drivers/gpu/drm/i915/i915_irq.c  | 160 
+++++++++++++++++++++++++++++++++++++--<br> 
drivers/gpu/drm/i915/intel_ddi.c |   3 +<br> 
drivers/gpu/drm/i915/intel_dp.c  |  20 +++++<br> 
drivers/gpu/drm/i915/intel_drv.h |   2 +<br> 5 files changed, 182 
insertions(+), 8 deletions(-)<br><br>diff --git 
a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h<br>index
 8f68678..5fd5bf3 100644<br>--- a/drivers/gpu/drm/i915/i915_drv.h<br>+++
 b/drivers/gpu/drm/i915/i915_drv.h<br>@@ -1551,6 +1551,11 @@ struct 
drm_i915_private {<br> <br>         struct i915_runtime_pm pm;<br> <br>+        struct
 intel_digital_port *hpd_irq_port[I915_MAX_PORTS];<br>+   u32 
long_hpd_port_mask;<br>+  u32 short_hpd_port_mask;<br>+     struct 
work_struct dig_port_work;<br>+<br>         /* Old dri1 support infrastructure,
 beware the dragons ya fools entering<br>          * here! */<br>   struct 
i915_dri1_state dri1;<br>diff --git a/drivers/gpu/drm/i915/i915_irq.c 
b/drivers/gpu/drm/i915/i915_irq.c<br>index cbf31cb..9913c08 100644<br>---
 a/drivers/gpu/drm/i915/i915_irq.c<br>+++ 
b/drivers/gpu/drm/i915/i915_irq.c<br>@@ -1096,6 +1096,53 @@ static bool 
intel_hpd_irq_event(struct drm_device *dev,<br>   return true;<br> }<br> <br>+static
 void i915_digport_work_func(struct work_struct *work)<br>+{<br>+   struct
 drm_i915_private *dev_priv =<br>+                container_of(work, struct 
drm_i915_private, dig_port_work);<br>+    unsigned long irqflags;<br>+      u32 
long_port_mask, short_port_mask;<br>+     struct intel_digital_port 
*intel_dig_port;<br>+     int i, ret;<br>+  u32 old_bits = 0;<br>+<br>+ 
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);<br>+     
long_port_mask = dev_priv->long_hpd_port_mask;<br>+    
dev_priv->long_hpd_port_mask = 0;<br>+ short_port_mask = 
dev_priv->short_hpd_port_mask;<br>+    dev_priv->short_hpd_port_mask =
 0;<br>+  spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);<br>+<br>+
        for (i = 0; i < I915_MAX_PORTS; i++) {<br>+            bool valid = false;<br>+
                bool long_hpd = false;<br>+               intel_dig_port = 
dev_priv->hpd_irq_port[i];<br>+                if (!intel_dig_port || 
!intel_dig_port->hpd_pulse)<br>+                       continue;<br>+<br>+         if 
(long_port_mask & (1 << i))  {<br>+                     valid = true;<br>+                        
long_hpd = true;<br>+             } else if (short_port_mask & (1 << i))<br>+
                        valid = true;<br>+<br>+             if (valid) {<br>+                 ret = 
intel_dig_port->hpd_pulse(intel_dig_port, long_hpd);<br>+                      if (ret 
== true) {<br>+                           /* if we get true fallback to old school hpd */<br>+      
                        old_bits |= (1 << intel_dig_port->base.hpd_pin);<br>+                    }<br>+
                }<br>+    }<br>+<br>+ if (old_bits) {<br>+              
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);<br>+             
dev_priv->hpd_event_bits |= old_bits;<br>+             
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);<br>+                
schedule_work(&dev_priv->hotplug_work);<br>+       }<br>+}<br>+<br> /*<br>
  * Handle hotplug events outside the interrupt handler proper.<br>  */<br>@@
 -1520,23 +1567,104 @@ static irqreturn_t gen8_gt_irq_handler(struct 
drm_device *dev,<br> #define HPD_STORM_DETECT_PERIOD 1000<br> #define 
HPD_STORM_THRESHOLD 5<br> <br>+static int ilk_port_to_hotplug_shift(enum
 port port)<br>+{<br>+      switch (port) {<br>+      case PORT_A:<br>+ case 
PORT_E:<br>+      default:<br>+             return -1;<br>+   case PORT_B:<br>+         return 0;<br>+
        case PORT_C:<br>+         return 8;<br>+    case PORT_D:<br>+         return 16;<br>+   }<br>+}<br>+<br>+static
 int g4x_port_to_hotplug_shift(enum port port)<br>+{<br>+   switch (port) {<br>+
        case PORT_A:<br>+ case PORT_E:<br>+ default:<br>+             return -1;<br>+   case
 PORT_B:<br>+             return 17;<br>+   case PORT_C:<br>+         return 19;<br>+   case 
PORT_D:<br>+              return 21;<br>+   }<br>+}<br>+<br>+static inline enum port 
get_port_from_pin(enum hpd_pin pin)<br>+{<br>+      switch (pin) {<br>+       case 
HPD_PORT_B:<br>+          return PORT_B;<br>+       case HPD_PORT_C:<br>+             return 
PORT_C;<br>+      case HPD_PORT_D:<br>+             return PORT_D;<br>+       default:<br>+             
return PORT_A; /* no hpd */<br>+  }<br>+}<br>+<br> static inline void 
intel_hpd_irq_handler(struct drm_device *dev,<br>                                          u32 
hotplug_trigger,<br>+                                      u32 dig_hotplug_reg,<br>                                          const u32 
*hpd)<br> {<br>     struct drm_i915_private *dev_priv = 
dev->dev_private;<br>  int i;<br>+       enum port port;<br>       bool 
storm_detected = false;<br>+      bool queue_dig = false, queue_hp = false;<br>+
        u32 dig_shift;<br>+       u32 dig_port_mask = 0;<br> <br>     if 
(!hotplug_trigger)<br>            return;<br> <br>-   DRM_DEBUG_DRIVER("hotplug 
event received, stat 0x%08x\n",<br>-                   hotplug_trigger);<br>+  
DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x, dig 0x%08x\n",<br>+
                         hotplug_trigger, dig_hotplug_reg);<br> <br>        
spin_lock(&dev_priv->irq_lock);<br>        for (i = 1; i < 
HPD_NUM_PINS; i++) {<br>+         if (!(hpd[i] & hotplug_trigger))<br>+                 
continue;<br>+<br>+         port = get_port_from_pin(i);<br>+         if (port 
&& dev_priv->hpd_irq_port[port]) {<br>+                        bool long_hpd;<br>+<br>+
                        if (IS_G4X(dev)) {<br>+                           dig_shift = 
g4x_port_to_hotplug_shift(port);<br>+                             long_hpd = (hotplug_trigger 
>> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;<br>+                 } else {<br>+
                                dig_shift = ilk_port_to_hotplug_shift(port);<br>+                         long_hpd = 
(dig_hotplug_reg >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;<br>+
                        }<br>+<br>+                 DRM_DEBUG_DRIVER("digital hpd port %d %d\n", port, 
long_hpd);<br>+                   /* for long HPD pulses we want to have the digital 
queue happen,<br>+                           but we still want HPD storm detection to 
function. */<br>+                 if (long_hpd) {<br>+                              
dev_priv->long_hpd_port_mask |= (1 << port);<br>+                                
dig_port_mask |= hpd[i];<br>+                     } else {<br>+                             /* for short HPD just 
trigger the digital queue */<br>+                         dev_priv->short_hpd_port_mask |=
 (1 << port);<br>+                          hotplug_trigger &= ~hpd[i];<br>+                      }<br>+
                        queue_dig = true;<br>+            }<br>+    }<br> <br>+ for (i = 1; i < 
HPD_NUM_PINS; i++) {<br>          if (hpd[i] & hotplug_trigger &&<br>
                    dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED) {<br>                     /*<br>@@
 -1556,7 +1684,11 @@ static inline void intel_hpd_irq_handler(struct 
drm_device *dev,<br>                  dev_priv->hpd_stats[i].hpd_mark != 
HPD_ENABLED)<br>                  continue;<br> <br>-         dev_priv->hpd_event_bits |= 
(1 << i);<br>+              if (!(dig_port_mask & hpd[i])) {<br>+                 
dev_priv->hpd_event_bits |= (1 << i);<br>+                       queue_hp = true;<br>+
                }<br>+<br>          if (!time_in_range(jiffies, 
dev_priv->hpd_stats[i].hpd_last_jiffies,<br>                              
dev_priv->hpd_stats[i].hpd_last_jiffies<br>                               + 
msecs_to_jiffies(HPD_STORM_DETECT_PERIOD))) {<br>@@ -1585,7 +1717,10 @@ 
static inline void intel_hpd_irq_handler(struct drm_device *dev,<br>       *
 queue for otherwise the flush_work in the pageflip code will<br>          * 
deadlock.<br>      */<br>-  schedule_work(&dev_priv->hotplug_work);<br>+
        if (queue_dig)<br>+               schedule_work(&dev_priv->dig_port_work);<br>+
        if (queue_hp)<br>+                schedule_work(&dev_priv->hotplug_work);<br> }<br>
 <br> static void gmbus_irq_handler(struct drm_device *dev)<br>@@ 
-1818,11 +1953,11 @@ static void i9xx_hpd_irq_handler(struct drm_device 
*dev)<br>         if (IS_G4X(dev)) {<br>            u32 hotplug_trigger = hotplug_status
 & HOTPLUG_INT_STATUS_G4X;<br> <br>-            intel_hpd_irq_handler(dev, 
hotplug_trigger, hpd_status_g4x);<br>+            intel_hpd_irq_handler(dev, 
hotplug_trigger, 0, hpd_status_g4x);<br>  } else {<br>              u32 
hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;<br> <br>-
                intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);<br>+                
intel_hpd_irq_handler(dev, hotplug_trigger, 0, hpd_status_i915);<br>      }<br>
 <br>     if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) &&<br>@@ -1913,8 
+2048,12 @@ static void ibx_irq_handler(struct drm_device *dev, u32 
pch_iir)<br>      struct drm_i915_private *dev_priv = dev->dev_private;<br>
        int pipe;<br>     u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;<br>+
        u32 dig_hotplug_reg;<br>+<br>+      dig_hotplug_reg = 
I915_READ(PCH_PORT_HOTPLUG);<br>+ I915_WRITE(PCH_PORT_HOTPLUG, 
dig_hotplug_reg);<br> <br>- intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_ibx);<br>+    intel_hpd_irq_handler(dev, hotplug_trigger, 
dig_hotplug_reg, hpd_ibx);<br> <br>         if (pch_iir & 
SDE_AUDIO_POWER_MASK) {<br>               int port = ffs((pch_iir & 
SDE_AUDIO_POWER_MASK) >><br>@@ -2020,8 +2159,12 @@ static void 
cpt_irq_handler(struct drm_device *dev, u32 pch_iir)<br>  struct 
drm_i915_private *dev_priv = dev->dev_private;<br>     int pipe;<br>     
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;<br>+    u32 
dig_hotplug_reg;<br>+<br>+  dig_hotplug_reg = 
I915_READ(PCH_PORT_HOTPLUG);<br>+ I915_WRITE(PCH_PORT_HOTPLUG, 
dig_hotplug_reg);<br> <br>- intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_cpt);<br>+    intel_hpd_irq_handler(dev, hotplug_trigger, 
dig_hotplug_reg, hpd_cpt);<br> <br>         if (pch_iir & 
SDE_AUDIO_POWER_MASK_CPT) {<br>           int port = ffs((pch_iir & 
SDE_AUDIO_POWER_MASK_CPT) >><br>@@ -4338,6 +4481,7 @@ void 
intel_irq_init(struct drm_device *dev)<br>        struct drm_i915_private 
*dev_priv = dev->dev_private;<br> <br>   
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);<br>+   
INIT_WORK(&dev_priv->dig_port_work, i915_digport_work_func);<br> 
        INIT_WORK(&dev_priv->gpu_error.work, i915_error_work_func);<br> 
        INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);<br>      
INIT_WORK(&dev_priv->l3_parity.error_work, 
ivybridge_parity_work);<br>diff --git a/drivers/gpu/drm/i915/intel_ddi.c
 b/drivers/gpu/drm/i915/intel_ddi.c<br>index b17b9c7..a80cb3e 100644<br>---
 a/drivers/gpu/drm/i915/intel_ddi.c<br>+++ 
b/drivers/gpu/drm/i915/intel_ddi.c<br>@@ -1705,6 +1705,9 @@ void 
intel_ddi_init(struct drm_device *dev, enum port port)<br>        
intel_encoder->cloneable = 0;<br>      intel_encoder->hot_plug = 
intel_ddi_hot_plug;<br> <br>+       intel_dig_port->hpd_pulse = 
intel_dp_hpd_pulse;<br>+  dev_priv->hpd_irq_port[port] = 
intel_dig_port;<br>+<br>    if (init_dp)<br>          dp_connector = 
intel_ddi_init_dp_connector(intel_dig_port);<br> <br>diff --git 
a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c<br>index
 d01bb43..f110522 100644<br>--- a/drivers/gpu/drm/i915/intel_dp.c<br>+++
 b/drivers/gpu/drm/i915/intel_dp.c<br>@@ -3699,6 +3699,22 @@ 
intel_dp_hot_plug(struct intel_encoder *intel_encoder)<br>        
intel_dp_check_link_status(intel_dp);<br> }<br> <br>+bool<br>+intel_dp_hpd_pulse(struct
 intel_digital_port *intel_dig_port, bool long_hpd)<br>+{<br>+      struct 
intel_dp *intel_dp = &intel_dig_port->dp;<br>+<br>+  if (long_hpd)<br>+
                return true;<br>+<br>+      /*<br>+    * we'll check the link status via the 
normal hot plug path later -<br>+  * but for short hpds we should check 
it now<br>+        */<br>+  intel_dp_check_link_status(intel_dp);<br>+        return 
false;<br>+}<br>+<br> /* Return which DP Port should be selected for 
Transcoder DP control */<br> int<br> intel_trans_dp_port_sel(struct 
drm_crtc *crtc)<br>@@ -4273,6 +4289,7 @@ intel_dp_init_connector(struct 
intel_digital_port *intel_dig_port,<br> void<br> intel_dp_init(struct 
drm_device *dev, int output_reg, enum port port)<br> {<br>+ struct 
drm_i915_private *dev_priv = dev->dev_private;<br>     struct 
intel_digital_port *intel_dig_port;<br>   struct intel_encoder 
*intel_encoder;<br>       struct drm_encoder *encoder;<br>@@ -4328,6 +4345,9 
@@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)<br>
        intel_encoder->cloneable = 0;<br>      intel_encoder->hot_plug = 
intel_dp_hot_plug;<br> <br>+        intel_dig_port->hpd_pulse = 
intel_dp_hpd_pulse;<br>+  dev_priv->hpd_irq_port[port] = 
intel_dig_port;<br>+<br>    if (!intel_dp_init_connector(intel_dig_port, 
intel_connector)) {<br>           drm_encoder_cleanup(encoder);<br>                 
kfree(intel_dig_port);<br>diff --git a/drivers/gpu/drm/i915/intel_drv.h 
b/drivers/gpu/drm/i915/intel_drv.h<br>index f1d5897..9666ec3 100644<br>---
 a/drivers/gpu/drm/i915/intel_drv.h<br>+++ 
b/drivers/gpu/drm/i915/intel_drv.h<br>@@ -563,6 +563,7 @@ struct 
intel_digital_port {<br>  u32 saved_port_bits;<br>  struct intel_dp dp;<br>
        struct intel_hdmi hdmi;<br>+      bool (*hpd_pulse)(struct 
intel_digital_port *, bool);<br> };<br> <br> static inline int<br>@@ 
-830,6 +831,7 @@ void intel_edp_psr_enable(struct intel_dp *intel_dp);<br>
 void intel_edp_psr_disable(struct intel_dp *intel_dp);<br> void 
intel_edp_psr_update(struct drm_device *dev);<br> void 
intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);<br>+bool
 intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool 
long_hpd);<br> <br> /* intel_dsi.c */<br> bool intel_dsi_init(struct 
drm_device *dev);<br></div></div>
  <div style="margin:30px 25px 10px 25px;" class="__pbConvHr"><div 
style="display:table;width:100%;border-top:1px solid 
#EDEEF0;padding-top:5px">       <div 
style="display:table-cell;vertical-align:middle;padding-right:6px;"><img
 photoaddress="airlied@gmail.com" photoname="Dave Airlie" 
src="cid:part1.02070802.03080302@gmail.com" name="postbox-contact.jpg" 
height="25px" width="25px"></div>   <div 
style="display:table-cell;white-space:nowrap;vertical-align:middle;width:100%">
        <a moz-do-not-send="true" href="mailto:airlied@gmail.com" 
style="color:#737F92 
!important;padding-right:6px;font-weight:bold;text-decoration:none 
!important;">Dave Airlie</a></div>   <div 
style="display:table-cell;white-space:nowrap;vertical-align:middle;">   
  <font color="#9FA2A5"><span style="padding-left:6px">Tuesday, June 17,
 2014 6:29 PM</span></font></div></div></div>
  <div style="color:#888888;margin-left:24px;margin-right:24px;" 
__pbrmquotes="true" class="__pbConvBody"><div>Can we get these merged or
 even looked at?, they are blocking the whole MST progress,<br>and I 
don't have any insight to secret Intel review process. :-)<br><br>Dave.<br><br>_______________________________________________<br>Intel-gfx
 mailing list<br><a class="moz-txt-link-abbreviated" href="mailto:Intel-gfx@lists.freedesktop.org">Intel-gfx@lists.freedesktop.org</a><br><a class="moz-txt-link-freetext" href="http://lists.freedesktop.org/mailman/listinfo/intel-gfx">http://lists.freedesktop.org/mailman/listinfo/intel-gfx</a><br></div></div>
</blockquote>
<br>
<div class="moz-signature">-- <br>
<div>Sent with <a href="http://www.getpostbox.com"><span style="color: 
rgb(51, 102, 153);">Postbox</span></a></div></div>
</body></html>