Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 371485
b: refs/heads/master
c: b543fb0
h: refs/heads/master
i:
  371483: fdef296
v: v3
  • Loading branch information
Egbert Eich authored and Daniel Vetter committed Apr 18, 2013
1 parent b034eb5 commit 0786d98
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 08e1413d95b50b19259fe2e425885030f93c7b85
refs/heads/master: b543fb0464ddf30a5b554957fd212eb7a2acac65
9 changes: 9 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,15 @@ typedef struct drm_i915_private {

struct work_struct hotplug_work;
bool enable_hotplug_processing;
struct {
unsigned long hpd_last_jiffies;
int hpd_cnt;
enum {
HPD_ENABLED = 0,
HPD_DISABLED = 1,
HPD_MARK_DISABLED = 2
} hpd_mark;
} hpd_stats[HPD_NUM_PINS];

int num_pch_pll;
int num_plane;
Expand Down
69 changes: 57 additions & 12 deletions trunk/drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,40 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
queue_work(dev_priv->wq, &dev_priv->rps.work);
}

#define HPD_STORM_DETECT_PERIOD 1000
#define HPD_STORM_THRESHOLD 5

static inline void hotplug_irq_storm_detect(struct drm_device *dev,
u32 hotplug_trigger,
const u32 *hpd)
{
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long irqflags;
int i;

spin_lock_irqsave(&dev_priv->irq_lock, irqflags);

for (i = 1; i < HPD_NUM_PINS; i++) {
if (!(hpd[i] & hotplug_trigger) ||
dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
continue;

if (!time_in_range(jiffies, dev_priv->hpd_stats[i].hpd_last_jiffies,
dev_priv->hpd_stats[i].hpd_last_jiffies
+ msecs_to_jiffies(HPD_STORM_DETECT_PERIOD))) {
dev_priv->hpd_stats[i].hpd_last_jiffies = jiffies;
dev_priv->hpd_stats[i].hpd_cnt = 0;
} else if (dev_priv->hpd_stats[i].hpd_cnt > HPD_STORM_THRESHOLD) {
dev_priv->hpd_stats[i].hpd_mark = HPD_MARK_DISABLED;
DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", i);
} else {
dev_priv->hpd_stats[i].hpd_cnt++;
}
}

spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}

static void gmbus_irq_handler(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = (drm_i915_private_t *) dev->dev_private;
Expand Down Expand Up @@ -650,13 +684,15 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
/* Consume port. Then clear IIR or we'll miss events */
if (iir & I915_DISPLAY_PORT_INTERRUPT) {
u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;

DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
hotplug_status);
if (hotplug_status & HOTPLUG_INT_STATUS_I915)
if (hotplug_trigger) {
hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_status_i915);
queue_work(dev_priv->wq,
&dev_priv->hotplug_work);

}
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
}
Expand All @@ -680,10 +716,12 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int pipe;
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;

if (pch_iir & SDE_HOTPLUG_MASK)
if (hotplug_trigger) {
hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_ibx);
queue_work(dev_priv->wq, &dev_priv->hotplug_work);

}
if (pch_iir & SDE_AUDIO_POWER_MASK)
DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
(pch_iir & SDE_AUDIO_POWER_MASK) >>
Expand Down Expand Up @@ -726,10 +764,12 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int pipe;
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;

if (pch_iir & SDE_HOTPLUG_MASK_CPT)
if (hotplug_trigger) {
hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_cpt);
queue_work(dev_priv->wq, &dev_priv->hotplug_work);

}
if (pch_iir & SDE_AUDIO_POWER_MASK_CPT)
DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
(pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
Expand Down Expand Up @@ -2621,13 +2661,15 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
if ((I915_HAS_HOTPLUG(dev)) &&
(iir & I915_DISPLAY_PORT_INTERRUPT)) {
u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;

DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
hotplug_status);
if (hotplug_status & HOTPLUG_INT_STATUS_I915)
if (hotplug_trigger) {
hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_status_i915);
queue_work(dev_priv->wq,
&dev_priv->hotplug_work);

}
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
POSTING_READ(PORT_HOTPLUG_STAT);
}
Expand Down Expand Up @@ -2854,15 +2896,18 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
/* Consume port. Then clear IIR or we'll miss events */
if (iir & I915_DISPLAY_PORT_INTERRUPT) {
u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
u32 hotplug_trigger = hotplug_status & (IS_G4X(dev) ?
HOTPLUG_INT_STATUS_G4X :
HOTPLUG_INT_STATUS_I965);

DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
hotplug_status);
if (hotplug_status & (IS_G4X(dev) ?
HOTPLUG_INT_STATUS_G4X :
HOTPLUG_INT_STATUS_I965))
if (hotplug_trigger) {
hotplug_irq_storm_detect(dev, hotplug_trigger,
IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i965);
queue_work(dev_priv->wq,
&dev_priv->hotplug_work);

}
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
}
Expand Down

0 comments on commit 0786d98

Please sign in to comment.