Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c9354c85 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

i915: fix intel graphics suspend breakage due to resume/lid event confusion

In commit c1c7af60 ("drm/i915: force
mode set at lid open time") the intel graphics driver was taught to
restore the LVDS mode on lid open.

That caused problems with interaction with the suspend/resume code,
which commonly runs at the same time (suspend is often caused by the lid
close event, while lid open is commonly a resume event), which was
worked around with in commit 06891e27
("drm/i915: fix suspend/resume breakage in lid notifier").

However, in the meantime the lid event code had also grown a user event
notifier (commit 06324194: "drm/i915:
generate a KMS uevent at lid open/close time"), and now _that_ causes
problems with suspend/resume and some versions of Xorg reacting to those
uevents by setting the mode.

So this effectively reverts that commit 06324194, and makes the lid
open protection logic against suspend/resume more explicit.  This fixes
at least one laptop. See

	http://bugzilla.kernel.org/show_bug.cgi?id=14484



for more details.

Acked-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Cc: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
Cc: Eric Anholt <eric@anholt.net>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b6727b12
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -89,7 +89,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
		pci_set_power_state(dev->pdev, PCI_D3hot);
		pci_set_power_state(dev->pdev, PCI_D3hot);
	}
	}


	dev_priv->suspended = 1;
	/* Modeset on resume, not lid events */
	dev_priv->modeset_on_lid = 0;


	return 0;
	return 0;
}
}
@@ -124,7 +125,7 @@ static int i915_resume(struct drm_device *dev)
		drm_helper_resume_force_mode(dev);
		drm_helper_resume_force_mode(dev);
	}
	}


	dev_priv->suspended = 0;
	dev_priv->modeset_on_lid = 0;


	return ret;
	return ret;
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -274,7 +274,7 @@ typedef struct drm_i915_private {
	struct drm_i915_display_funcs display;
	struct drm_i915_display_funcs display;


	/* Register state */
	/* Register state */
	bool suspended;
	bool modeset_on_lid;
	u8 saveLBB;
	u8 saveLBB;
	u32 saveDSPACNTR;
	u32 saveDSPACNTR;
	u32 saveDSPBCNTR;
	u32 saveDSPBCNTR;
+20 −5
Original line number Original line Diff line number Diff line
@@ -656,6 +656,15 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
	return 0;
	return 0;
}
}


/*
 * Lid events. Note the use of 'modeset_on_lid':
 *  - we set it on lid close, and reset it on open
 *  - we use it as a "only once" bit (ie we ignore
 *    duplicate events where it was already properly
 *    set/reset)
 *  - the suspend/resume paths will also set it to
 *    zero, since they restore the mode ("lid open").
 */
static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
			    void *unused)
			    void *unused)
{
{
@@ -663,13 +672,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
		container_of(nb, struct drm_i915_private, lid_notifier);
		container_of(nb, struct drm_i915_private, lid_notifier);
	struct drm_device *dev = dev_priv->dev;
	struct drm_device *dev = dev_priv->dev;


	if (acpi_lid_open() && !dev_priv->suspended) {
	if (!acpi_lid_open()) {
		dev_priv->modeset_on_lid = 1;
		return NOTIFY_OK;
	}

	if (!dev_priv->modeset_on_lid)
		return NOTIFY_OK;

	dev_priv->modeset_on_lid = 0;

	mutex_lock(&dev->mode_config.mutex);
	mutex_lock(&dev->mode_config.mutex);
	drm_helper_resume_force_mode(dev);
	drm_helper_resume_force_mode(dev);
	mutex_unlock(&dev->mode_config.mutex);
	mutex_unlock(&dev->mode_config.mutex);
	}

	drm_sysfs_hotplug_event(dev_priv->dev);


	return NOTIFY_OK;
	return NOTIFY_OK;
}
}