forked from Minki/linux
drm/i915/irq: abstract irq storm hotplug disabling
Continue abstracting hotplug storm related functions to clarify the code. This time, abstract hotplug irq storm related hotplug disabling. While at it, clean up the loop iterating over connectors for readability. Signed-off-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
a0049865ea
commit
70f71d5ff4
@ -879,7 +879,7 @@ static void i915_digport_work_func(struct work_struct *work)
|
||||
/*
|
||||
* Handle hotplug events outside the interrupt handler proper.
|
||||
*/
|
||||
#define I915_REENABLE_HOTPLUG_DELAY (2*60*1000)
|
||||
static void intel_hpd_irq_storm_disable(struct drm_i915_private *dev_priv);
|
||||
|
||||
static void i915_hotplug_work_func(struct work_struct *work)
|
||||
{
|
||||
@ -890,7 +890,6 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
struct intel_connector *intel_connector;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct drm_connector *connector;
|
||||
bool hpd_disabled = false;
|
||||
bool changed = false;
|
||||
u32 hpd_event_bits;
|
||||
|
||||
@ -901,31 +900,9 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
|
||||
hpd_event_bits = dev_priv->hotplug.event_bits;
|
||||
dev_priv->hotplug.event_bits = 0;
|
||||
list_for_each_entry(connector, &mode_config->connector_list, head) {
|
||||
intel_connector = to_intel_connector(connector);
|
||||
if (!intel_connector->encoder)
|
||||
continue;
|
||||
intel_encoder = intel_connector->encoder;
|
||||
if (intel_encoder->hpd_pin > HPD_NONE &&
|
||||
dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_MARK_DISABLED &&
|
||||
connector->polled == DRM_CONNECTOR_POLL_HPD) {
|
||||
DRM_INFO("HPD interrupt storm detected on connector %s: "
|
||||
"switching from hotplug detection to polling\n",
|
||||
connector->name);
|
||||
dev_priv->hotplug.stats[intel_encoder->hpd_pin].state = HPD_DISABLED;
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT
|
||||
| DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
hpd_disabled = true;
|
||||
}
|
||||
}
|
||||
/* if there were no outputs to poll, poll was disabled,
|
||||
* therefore make sure it's enabled when disabling HPD on
|
||||
* some connectors */
|
||||
if (hpd_disabled) {
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
mod_delayed_work(system_wq, &dev_priv->hotplug.reenable_work,
|
||||
msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
|
||||
}
|
||||
|
||||
/* Disable hotplug on connectors that hit an irq storm. */
|
||||
intel_hpd_irq_storm_disable(dev_priv);
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
|
||||
@ -1411,6 +1388,52 @@ static bool intel_hpd_irq_storm(struct drm_i915_private *dev_priv,
|
||||
return storm;
|
||||
}
|
||||
|
||||
#define I915_REENABLE_HOTPLUG_DELAY (2*60*1000)
|
||||
|
||||
static void intel_hpd_irq_storm_disable(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct intel_connector *intel_connector;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct drm_connector *connector;
|
||||
enum hpd_pin pin;
|
||||
bool hpd_disabled = false;
|
||||
|
||||
assert_spin_locked(&dev_priv->irq_lock);
|
||||
|
||||
list_for_each_entry(connector, &mode_config->connector_list, head) {
|
||||
if (connector->polled != DRM_CONNECTOR_POLL_HPD)
|
||||
continue;
|
||||
|
||||
intel_connector = to_intel_connector(connector);
|
||||
intel_encoder = intel_connector->encoder;
|
||||
if (!intel_encoder)
|
||||
continue;
|
||||
|
||||
pin = intel_encoder->hpd_pin;
|
||||
if (pin == HPD_NONE ||
|
||||
dev_priv->hotplug.stats[pin].state != HPD_MARK_DISABLED)
|
||||
continue;
|
||||
|
||||
DRM_INFO("HPD interrupt storm detected on connector %s: "
|
||||
"switching from hotplug detection to polling\n",
|
||||
connector->name);
|
||||
|
||||
dev_priv->hotplug.stats[pin].state = HPD_DISABLED;
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT
|
||||
| DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
hpd_disabled = true;
|
||||
}
|
||||
|
||||
/* Enable polling and queue hotplug re-enabling. */
|
||||
if (hpd_disabled) {
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
mod_delayed_work(system_wq, &dev_priv->hotplug.reenable_work,
|
||||
msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
|
||||
}
|
||||
}
|
||||
|
||||
static bool pch_port_hotplug_long_detect(enum port port, u32 val)
|
||||
{
|
||||
switch (port) {
|
||||
|
Loading…
Reference in New Issue
Block a user