Commit c4a1e57b authored by Imre Deak's avatar Imre Deak

drm/i915/opregion: Fix opregion setup during system resume on platforms without display

Atm, during system resume, the driver updates the display connector
information required by the opregion video extensions during system
resume, on platforms both with and without display being present. On
!HAS_DISPLAY platforms this will result in the crash with the stack
trace below, since the driver's connector state is not initialized on
those.

Bspec doesn't specify when each of the opregion functionality is
supported (depending on the presence of display), however we can presume
that none of the video extensions, nor the ACPI _DSM functions are
supported on !HAS_DISPLAY platforms; accordingly skip the corresponding
opregion/ACPI setup on those (also matching the Windows driver in this).

Keep sending the opregion notification about suspending/resuming the
whole adapter (vs. the display only which is a separate power state
notification) on all platforms, similarly to runtime suspend/resume.

This fixes the following:
Oops: 0000 [#1] PREEMPT SMP NOPTI
CPU: 4 PID: 1443 Comm: kworker/u40:55 Tainted: G U 6.2.0-rc8+ #58
Hardware name: LENOVO 82VB/LNVNB161216, BIOS KMCN09WW 04/26/2022
Workqueue: events_unbound async_run_entry_fn
RIP: 0010:drm_connector_list_iter_next+0x4f/0xb0

Call Trace:
 <TASK>
 intel_acpi_device_id_update+0x80/0x160 [i915]
 intel_opregion_resume+0x2f/0x1e0 [i915]
 ? dg2_init_clock_gating+0x49/0xf0 [i915]
 i915_drm_resume+0x137/0x190 [i915]
 ? __pfx_pci_pm_resume+0x10/0x10
 dpm_run_callback+0x47/0x150

Cc: iczero <iczero@hellomouse.net>
Reported-and-tested-by: default avatariczero <iczero@hellomouse.net>
References: https://gitlab.freedesktop.org/drm/intel/-/issues/8015Reviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230308162503.3219200-1-imre.deak@intel.com
parent 2553baca
......@@ -1159,13 +1159,10 @@ void intel_opregion_register(struct drm_i915_private *i915)
intel_opregion_resume(i915);
}
void intel_opregion_resume(struct drm_i915_private *i915)
static void intel_opregion_resume_display(struct drm_i915_private *i915)
{
struct intel_opregion *opregion = &i915->display.opregion;
if (!opregion->header)
return;
if (opregion->acpi) {
intel_didl_outputs(i915);
intel_setup_cadls(i915);
......@@ -1186,18 +1183,24 @@ void intel_opregion_resume(struct drm_i915_private *i915)
/* Some platforms abuse the _DSM to enable MUX */
intel_dsm_get_bios_data_funcs_supported(i915);
intel_opregion_notify_adapter(i915, PCI_D0);
}
void intel_opregion_suspend(struct drm_i915_private *i915, pci_power_t state)
void intel_opregion_resume(struct drm_i915_private *i915)
{
struct intel_opregion *opregion = &i915->display.opregion;
if (!opregion->header)
return;
intel_opregion_notify_adapter(i915, state);
if (HAS_DISPLAY(i915))
intel_opregion_resume_display(i915);
intel_opregion_notify_adapter(i915, PCI_D0);
}
static void intel_opregion_suspend_display(struct drm_i915_private *i915)
{
struct intel_opregion *opregion = &i915->display.opregion;
if (opregion->asle)
opregion->asle->ardy = ASLE_ARDY_NOT_READY;
......@@ -1208,6 +1211,19 @@ void intel_opregion_suspend(struct drm_i915_private *i915, pci_power_t state)
opregion->acpi->drdy = 0;
}
void intel_opregion_suspend(struct drm_i915_private *i915, pci_power_t state)
{
struct intel_opregion *opregion = &i915->display.opregion;
if (!opregion->header)
return;
intel_opregion_notify_adapter(i915, state);
if (HAS_DISPLAY(i915))
intel_opregion_suspend_display(i915);
}
void intel_opregion_unregister(struct drm_i915_private *i915)
{
struct intel_opregion *opregion = &i915->display.opregion;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment