[Intel-gfx] [PATCH] drm/i915: Stop calling intel_opregion unregister/register in suspend/resume
Imre Deak
imre.deak at intel.com
Mon Oct 8 14:04:04 UTC 2018
On Mon, Oct 08, 2018 at 09:44:08AM +0300, Jani Nikula wrote:
> On Fri, 05 Oct 2018, Chris Wilson <chris at chris-wilson.co.uk> wrote:
> > If we reduce the suspend function for intel_opregion to do the minimum
> > required, the resume function can also do the simple task of notifier
> > the ACPI bios that we are back. This avoid some nasty restrictions on
> > the likes of register_acpi_notifier() that are not allowed during the
> > early phase of resume.
>
> Something like this has been on the back of my mind for a long time, but
> never got around to it. Couple of nitpicks/observations inline.
>
> >
> > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> > Cc: Imre Deak <imre.deak at intel.com>
> > Cc: Jani Nikula <jani.nikula at intel.com>
Simplifies the task of moving some steps from the suspend/resume hooks
to the suspend_late/resume_early hooks, which is needed by the audio/
CDCLK workaround we are working towards, so:
Acked-by: Imre Deak <imre.deak at intel.com>
> > ---
> > drivers/gpu/drm/i915/i915_drv.c | 9 +-
> > drivers/gpu/drm/i915/intel_opregion.c | 155 +++++++++++++++-----------
> > drivers/gpu/drm/i915/intel_opregion.h | 15 +++
> > 3 files changed, 108 insertions(+), 71 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 193023427b40..9b0887746bac 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -1919,9 +1919,7 @@ static int i915_drm_suspend(struct drm_device *dev)
> > i915_save_state(dev_priv);
> >
> > opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
> > - intel_opregion_notify_adapter(dev_priv, opregion_target_state);
> > -
> > - intel_opregion_unregister(dev_priv);
> > + intel_opregion_suspend(dev_priv, opregion_target_state);
> >
> > intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
> >
> > @@ -2040,7 +2038,6 @@ static int i915_drm_resume(struct drm_device *dev)
> >
> > i915_restore_state(dev_priv);
> > intel_pps_unlock_regs_wa(dev_priv);
> > - intel_opregion_setup(dev_priv);
> >
> > intel_init_pch_refclk(dev_priv);
> >
> > @@ -2082,12 +2079,10 @@ static int i915_drm_resume(struct drm_device *dev)
> > * */
> > intel_hpd_init(dev_priv);
> >
> > - intel_opregion_register(dev_priv);
> > + intel_opregion_resume(dev_priv);
> >
> > intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
> >
> > - intel_opregion_notify_adapter(dev_priv, PCI_D0);
> > -
> > intel_power_domains_enable(dev_priv);
> >
> > enable_rpm_wakeref_asserts(dev_priv);
> > diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
> > index e034b4166d32..379e8c64a248 100644
> > --- a/drivers/gpu/drm/i915/intel_opregion.c
> > +++ b/drivers/gpu/drm/i915/intel_opregion.c
> > @@ -773,70 +773,6 @@ static void intel_setup_cadls(struct drm_i915_private *dev_priv)
> > opregion->acpi->cadl[i] = 0;
> > }
> >
> > -void intel_opregion_register(struct drm_i915_private *dev_priv)
> > -{
> > - struct intel_opregion *opregion = &dev_priv->opregion;
> > -
> > - if (!opregion->header)
> > - return;
> > -
> > - if (opregion->acpi) {
> > - intel_didl_outputs(dev_priv);
> > - intel_setup_cadls(dev_priv);
> > -
> > - /* Notify BIOS we are ready to handle ACPI video ext notifs.
> > - * Right now, all the events are handled by the ACPI video module.
> > - * We don't actually need to do anything with them. */
> > - opregion->acpi->csts = 0;
> > - opregion->acpi->drdy = 1;
> > -
> > - opregion->acpi_notifier.notifier_call = intel_opregion_video_event;
> > - register_acpi_notifier(&opregion->acpi_notifier);
> > - }
> > -
> > - if (opregion->asle) {
> > - opregion->asle->tche = ASLE_TCHE_BLC_EN;
> > - opregion->asle->ardy = ASLE_ARDY_READY;
> > - }
> > -}
> > -
> > -void intel_opregion_unregister(struct drm_i915_private *dev_priv)
> > -{
> > - struct intel_opregion *opregion = &dev_priv->opregion;
> > -
> > - if (!opregion->header)
> > - return;
> > -
> > - if (opregion->asle)
> > - opregion->asle->ardy = ASLE_ARDY_NOT_READY;
> > -
> > - cancel_work_sync(&dev_priv->opregion.asle_work);
> > -
> > - if (opregion->acpi) {
> > - opregion->acpi->drdy = 0;
> > -
> > - unregister_acpi_notifier(&opregion->acpi_notifier);
> > - opregion->acpi_notifier.notifier_call = NULL;
> > - }
> > -
> > - /* just clear all opregion memory pointers now */
> > - memunmap(opregion->header);
> > - if (opregion->rvda) {
> > - memunmap(opregion->rvda);
> > - opregion->rvda = NULL;
> > - }
> > - if (opregion->vbt_firmware) {
> > - kfree(opregion->vbt_firmware);
> > - opregion->vbt_firmware = NULL;
> > - }
> > - opregion->header = NULL;
> > - opregion->acpi = NULL;
> > - opregion->swsci = NULL;
> > - opregion->asle = NULL;
> > - opregion->vbt = NULL;
> > - opregion->lid_state = NULL;
> > -}
> > -
> > static void swsci_setup(struct drm_i915_private *dev_priv)
> > {
> > struct intel_opregion *opregion = &dev_priv->opregion;
> > @@ -1115,3 +1051,94 @@ intel_opregion_get_panel_type(struct drm_i915_private *dev_priv)
> >
> > return ret - 1;
> > }
> > +
> > +void intel_opregion_register(struct drm_i915_private *i915)
> > +{
> > + struct intel_opregion *opregion = &i915->opregion;
> > +
> > + if (!opregion->header)
> > + return;
> > +
> > + if (opregion->acpi) {
> > + opregion->acpi_notifier.notifier_call = intel_opregion_video_event;
> > + register_acpi_notifier(&opregion->acpi_notifier);
> > + }
> > +
> > + intel_opregion_resume(i915);
> > +}
> > +
> > +void intel_opregion_resume(struct drm_i915_private *i915)
> > +{
> > + struct intel_opregion *opregion = &i915->opregion;
> > +
> > + if (!opregion->header)
> > + return;
> > +
> > + if (opregion->acpi) {
> > + intel_didl_outputs(i915);
> > + intel_setup_cadls(i915);
> > +
> > + /* Notify BIOS we are ready to handle ACPI video ext notifs.
> > + * Right now, all the events are handled by the ACPI video module.
> > + * We don't actually need to do anything with them. */
> > + opregion->acpi->csts = 0;
> > + opregion->acpi->drdy = 1;
> > + }
> > +
> > + if (opregion->asle) {
> > + opregion->asle->tche = ASLE_TCHE_BLC_EN;
> > + opregion->asle->ardy = ASLE_ARDY_READY;
> > + }
> > +
> > + intel_opregion_notify_adapter(i915, PCI_D0);
> > +}
> > +
> > +void intel_opregion_suspend(struct drm_i915_private *i915, pci_power_t state)
> > +{
> > + struct intel_opregion *opregion = &i915->opregion;
> > +
> > + if (!opregion->header)
> > + return;
> > +
> > + if (opregion->asle)
> > + opregion->asle->ardy = ASLE_ARDY_NOT_READY;
> > +
> > + cancel_work_sync(&i915->opregion.asle_work);
> > +
> > + if (opregion->acpi)
> > + opregion->acpi->drdy = 0;
> > +
> > + intel_opregion_notify_adapter(i915, state);
>
> The order between drdy clear and notify changes. Depends on the BIOS
> whether that has any significance, i.e. I have no clue. If you think the
> reordering is justified, please split it out to a separate patch. Or
> just drop the order change completely. With that,
>
> Reviewed-by: Jani Nikula <jani.nikula at intel.com>
>
> Side note, it would seem like drdy clear should happen before canceling
> the work. In theory that should block new asle interrupts. But that's
> another change anyway, and perhaps not worth the risk.
>
> > +}
> > +
> > +void intel_opregion_unregister(struct drm_i915_private *i915)
> > +{
> > + struct intel_opregion *opregion = &i915->opregion;
> > +
> > + intel_opregion_suspend(i915, PCI_D1);
> > +
> > + if (!opregion->header)
> > + return;
> > +
> > + if (opregion->acpi_notifier.notifier_call) {
> > + unregister_acpi_notifier(&opregion->acpi_notifier);
> > + opregion->acpi_notifier.notifier_call = NULL;
> > + }
> > +
> > + /* just clear all opregion memory pointers now */
> > + memunmap(opregion->header);
> > + if (opregion->rvda) {
> > + memunmap(opregion->rvda);
> > + opregion->rvda = NULL;
> > + }
> > + if (opregion->vbt_firmware) {
> > + kfree(opregion->vbt_firmware);
> > + opregion->vbt_firmware = NULL;
> > + }
> > + opregion->header = NULL;
> > + opregion->acpi = NULL;
> > + opregion->swsci = NULL;
> > + opregion->asle = NULL;
> > + opregion->vbt = NULL;
> > + opregion->lid_state = NULL;
>
> Side note #2, this patch highlights (but does not change) how we have
> two init functions setup and register undone by a single unregister
> function. The asymmetry has always bugged me, but it's no fault of this
> patch.
>
> > +}
> > diff --git a/drivers/gpu/drm/i915/intel_opregion.h b/drivers/gpu/drm/i915/intel_opregion.h
> > index e8498a8cda3d..d84b6d2d2fae 100644
> > --- a/drivers/gpu/drm/i915/intel_opregion.h
> > +++ b/drivers/gpu/drm/i915/intel_opregion.h
> > @@ -57,8 +57,14 @@ struct intel_opregion {
> > #ifdef CONFIG_ACPI
> >
> > int intel_opregion_setup(struct drm_i915_private *dev_priv);
> > +
> > void intel_opregion_register(struct drm_i915_private *dev_priv);
> > void intel_opregion_unregister(struct drm_i915_private *dev_priv);
> > +
> > +void intel_opregion_resume(struct drm_i915_private *dev_priv);
> > +void intel_opregion_suspend(struct drm_i915_private *dev_priv,
> > + pci_power_t state);
> > +
> > void intel_opregion_asle_intr(struct drm_i915_private *dev_priv);
> > int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
> > bool enable);
> > @@ -81,6 +87,15 @@ static inline void intel_opregion_unregister(struct drm_i915_private *dev_priv)
> > {
> > }
> >
> > +void intel_opregion_resume(struct drm_i915_private *dev_priv)
> > +{
> > +}
> > +
> > +void intel_opregion_suspend(struct drm_i915_private *dev_priv,
> > + pci_power_t state)
> > +{
> > +}
> > +
> > static inline void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
> > {
> > }
>
> --
> Jani Nikula, Intel Open Source Graphics Center
More information about the Intel-gfx
mailing list