Skip to content

Commit 32fbded

Browse files
djkurtzchrome-internal-fetch
authored andcommitted
i915: ignore lid open event when resuming
i915 driver needs to do modeset when 1. system resumes from sleep 2. lid is opened In PM_SUSPEND_MEM state, all the GPEs are cleared when system resumes, thus it is the i915_resume code does the modeset rather than intel_lid_notify(). But in PM_SUSPEND_FREEZE state, this will be broken because system is still responsive to the lid events. 1. When we close the lid in Freeze state, intel_lid_notify() sets modeset_on_lid. 2. When we reopen the lid, intel_lid_notify() will do a modeset, before the system is resumed. here is the error log, [92146.548074] WARNING: at drivers/gpu/drm/i915/intel_display.c:1028 intel_wait_for_pipe_off+0x184/0x190 [i915]() [92146.548076] Hardware name: VGN-Z540N [92146.548078] pipe_off wait timed out [92146.548167] Modules linked in: hid_generic usbhid hid snd_hda_codec_realtek snd_hda_intel snd_hda_codec parport_pc snd_hwdep ppdev snd_pcm_oss i915 snd_mixer_oss snd_pcm arc4 iwldvm snd_seq_dummy mac80211 snd_seq_oss snd_seq_midi fbcon tileblit font bitblit softcursor drm_kms_helper snd_rawmidi snd_seq_midi_event coretemp drm snd_seq kvm btusb bluetooth snd_timer iwlwifi pcmcia tpm_infineon i2c_algo_bit joydev snd_seq_device intel_agp cfg80211 snd intel_gtt yenta_socket pcmcia_rsrc sony_laptop agpgart microcode psmouse tpm_tis serio_raw mxm_wmi soundcore snd_page_alloc tpm acpi_cpufreq lpc_ich pcmcia_core tpm_bios mperf processor lp parport firewire_ohci firewire_core crc_itu_t sdhci_pci sdhci thermal e1000e [92146.548173] Pid: 4304, comm: kworker/0:0 Tainted: G W 3.8.0-rc3-s0i3-v3-test+ hardkernel#9 [92146.548175] Call Trace: [92146.548189] [<c10378e2>] warn_slowpath_common+0x72/0xa0 [92146.548227] [<f86398b4>] ? intel_wait_for_pipe_off+0x184/0x190 [i915] [92146.548263] [<f86398b4>] ? intel_wait_for_pipe_off+0x184/0x190 [i915] [92146.548270] [<c10379b3>] warn_slowpath_fmt+0x33/0x40 [92146.548307] [<f86398b4>] intel_wait_for_pipe_off+0x184/0x190 [i915] [92146.548344] [<f86399c2>] intel_disable_pipe+0x102/0x190 [i915] [92146.548380] [<f8639ea4>] ? intel_disable_plane+0x64/0x80 [i915] [92146.548417] [<f8639f7c>] i9xx_crtc_disable+0xbc/0x150 [i915] [92146.548456] [<f863ebee>] intel_crtc_update_dpms+0x5e/0x90 [i915] [92146.548493] [<f86437cf>] intel_modeset_setup_hw_state+0x42f/0x8f0 [i915] [92146.548535] [<f8645b0b>] intel_lid_notify+0x9b/0xc0 [i915] [92146.548543] [<c15610d3>] notifier_call_chain+0x43/0x60 [92146.548550] [<c105d1e1>] __blocking_notifier_call_chain+0x41/0x80 [92146.548556] [<c105d23f>] blocking_notifier_call_chain+0x1f/0x30 [92146.548563] [<c131a684>] acpi_lid_send_state+0x78/0xa4 [92146.548569] [<c131aa9e>] acpi_button_notify+0x3b/0xf1 [92146.548577] [<c12df56a>] ? acpi_os_execute+0x17/0x19 [92146.548582] [<c12e591a>] ? acpi_ec_sync_query+0xa5/0xbc [92146.548589] [<c12e2b82>] acpi_device_notify+0x16/0x18 [92146.548595] [<c12f4904>] acpi_ev_notify_dispatch+0x38/0x4f [92146.548600] [<c12df0e8>] acpi_os_execute_deferred+0x20/0x2b [92146.548607] [<c1051208>] process_one_work+0x128/0x3f0 [92146.548613] [<c1564f73>] ? common_interrupt+0x33/0x38 [92146.548618] [<c104f8c0>] ? wake_up_worker+0x30/0x30 [92146.548624] [<c12df0c8>] ? acpi_os_wait_events_complete+0x1e/0x1e [92146.548629] [<c10524f9>] worker_thread+0x119/0x3b0 [92146.548634] [<c10523e0>] ? manage_workers+0x240/0x240 [92146.548640] [<c1056e84>] kthread+0x94/0xa0 [92146.548647] [<c1060000>] ? ftrace_raw_output_sched_stat_runtime+0x70/0xf0 [92146.548652] [<c15649b7>] ret_from_kernel_thread+0x1b/0x28 [92146.548658] [<c1056df0>] ? kthread_create_on_node+0xc0/0xc0 three different modeset flags are introduced in this patch MODESET_ON_LID_OPEN: do modeset on next lid open event MODESET_DONE: modeset already done MODESET_SUSPENDED: suspended, only do modeset when system is resumed In this way, 1. when lid is closed, MODESET_ON_LID_OPEN is set so that we'll do modeset on next lid open event. 2. when lid is opened, MODESET_DONE is set so that duplicate lid open events will be ignored. 3. when system suspends, MODESET_SUSPENDED is set. In this case, we will not do modeset on any lid events. Plus, locking mechanism is also introduced to avoid racing. Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (cherry picked from commit b8efb17) Conflicts: drivers/gpu/drm/i915/i915_dma.c drivers/gpu/drm/i915/i915_drv.h drivers/gpu/drm/i915/intel_lvds.c Signed-off-by: Daniel Kurtz <djkurtz@chromium.org> BUG=chromium:282706 TEST=Sign in to parrot; close lid; wait for blue light off; open lid; => inspect /var/log/messages => No kernel WARNING from i915/intel driver Change-Id: I1b7835b8f377403a2a2b57c0b801220b6e373863 Reviewed-on: https://chromium-review.googlesource.com/172820 Reviewed-by: Stéphane Marchesin <marcheu@chromium.org> Reviewed-by: Daniel Kurtz <djkurtz@chromium.org> Commit-Queue: Daniel Kurtz <djkurtz@chromium.org> Tested-by: Daniel Kurtz <djkurtz@chromium.org>
1 parent 89b238d commit 32fbded

File tree

4 files changed

+38
-20
lines changed

4 files changed

+38
-20
lines changed

drivers/gpu/drm/i915/i915_dma.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
16091609
if (ret)
16101610
goto out_gem_unload;
16111611

1612+
mutex_init(&dev_priv->modeset_restore_lock);
1613+
16121614
/* Start out suspended */
16131615
dev_priv->mm.suspended = 1;
16141616

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,11 @@ static int i915_drm_freeze(struct drm_device *dev)
493493
{
494494
struct drm_i915_private *dev_priv = dev->dev_private;
495495

496+
/* ignore lid events during suspend */
497+
mutex_lock(&dev_priv->modeset_restore_lock);
498+
dev_priv->modeset_restore = MODESET_SUSPENDED;
499+
mutex_unlock(&dev_priv->modeset_restore_lock);
500+
496501
intel_set_power_well(dev, true);
497502

498503
drm_kms_helper_poll_disable(dev);
@@ -517,9 +522,6 @@ static int i915_drm_freeze(struct drm_device *dev)
517522

518523
intel_opregion_fini(dev);
519524

520-
/* Modeset on resume, not lid events */
521-
dev_priv->modeset_on_lid = 0;
522-
523525
console_lock();
524526
intel_fbdev_set_suspend(dev, 1);
525527
console_unlock();
@@ -596,8 +598,6 @@ static int __i915_drm_thaw(struct drm_device *dev)
596598

597599
intel_opregion_init(dev);
598600

599-
dev_priv->modeset_on_lid = 0;
600-
601601
/*
602602
* The console lock can be pretty contented on resume due
603603
* to all the printk activity. Try to keep it out of the hot
@@ -610,6 +610,9 @@ static int __i915_drm_thaw(struct drm_device *dev)
610610
schedule_work(&dev_priv->console_resume_work);
611611
}
612612

613+
mutex_lock(&dev_priv->modeset_restore_lock);
614+
dev_priv->modeset_restore = MODESET_DONE;
615+
mutex_unlock(&dev_priv->modeset_restore_lock);
613616
return error;
614617
}
615618

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,12 @@ struct intel_l3_parity {
633633
struct work_struct error_work;
634634
};
635635

636+
enum modeset_restore {
637+
MODESET_ON_LID_OPEN,
638+
MODESET_DONE,
639+
MODESET_SUSPENDED,
640+
};
641+
636642
typedef struct drm_i915_private {
637643
struct drm_device *dev;
638644

@@ -777,8 +783,8 @@ typedef struct drm_i915_private {
777783

778784
unsigned long quirks;
779785

780-
/* Register state */
781-
bool modeset_on_lid;
786+
enum modeset_restore modeset_restore;
787+
struct mutex modeset_restore_lock;
782788

783789
struct {
784790
/** Bridge to intel-gtt-ko */

drivers/gpu/drm/i915/intel_lvds.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -368,13 +368,14 @@ static const struct dmi_system_id intel_no_modeset_on_lid[] = {
368368
};
369369

370370
/*
371-
* Lid events. Note the use of 'modeset_on_lid':
372-
* - we set it on lid close, and reset it on open
371+
* Lid events. Note the use of 'modeset':
372+
* - we set it to MODESET_ON_LID_OPEN on lid close,
373+
* and set it to MODESET_DONE on open
373374
* - we use it as a "only once" bit (ie we ignore
374-
* duplicate events where it was already properly
375-
* set/reset)
376-
* - the suspend/resume paths will also set it to
377-
* zero, since they restore the mode ("lid open").
375+
* duplicate events where it was already properly set)
376+
* - the suspend/resume paths will set it to
377+
* MODESET_SUSPENDED and ignore the lid open event,
378+
* because they restore the mode ("lid open").
378379
*/
379380
static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
380381
void *unused)
@@ -388,6 +389,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
388389
if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
389390
return NOTIFY_OK;
390391

392+
mutex_lock(&dev_priv->modeset_restore_lock);
393+
if (dev_priv->modeset_restore == MODESET_SUSPENDED)
394+
goto exit;
391395
/*
392396
* check and update the status of LVDS connector after receiving
393397
* the LID nofication event.
@@ -396,21 +400,24 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
396400

397401
/* Don't force modeset on machines where it causes a GPU lockup */
398402
if (dmi_check_system(intel_no_modeset_on_lid))
399-
return NOTIFY_OK;
403+
goto exit;
400404
if (!acpi_lid_open()) {
401-
dev_priv->modeset_on_lid = 1;
402-
return NOTIFY_OK;
405+
/* do modeset on next lid open event */
406+
dev_priv->modeset_restore = MODESET_ON_LID_OPEN;
407+
goto exit;
403408
}
404409

405-
if (!dev_priv->modeset_on_lid)
406-
return NOTIFY_OK;
407-
408-
dev_priv->modeset_on_lid = 0;
410+
if (dev_priv->modeset_restore == MODESET_DONE)
411+
goto exit;
409412

410413
mutex_lock(&dev->mode_config.mutex);
411414
intel_modeset_setup_hw_state(dev, true);
412415
mutex_unlock(&dev->mode_config.mutex);
413416

417+
dev_priv->modeset_restore = MODESET_DONE;
418+
419+
exit:
420+
mutex_unlock(&dev_priv->modeset_restore_lock);
414421
return NOTIFY_OK;
415422
}
416423

0 commit comments

Comments
 (0)