Message ID | 20211206122952.74139-1-kirill.shutemov@linux.intel.com |
---|---|
Headers | show |
Series | ACPI/ACPICA: Only flush caches on S1/S2/S3 and C3 | expand |
On Mon, Dec 06, 2021 at 03:29:51PM +0300, Kirill A. Shutemov wrote: > According to the ACPI spec v6.4, section 8.2, cache flushing required > on entering C3 power state. > > Avoid flushing cache on entering other power states. > > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > --- > drivers/acpi/processor_idle.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c > index 76ef1bcc8848..01495aca850e 100644 > --- a/drivers/acpi/processor_idle.c > +++ b/drivers/acpi/processor_idle.c > @@ -567,7 +567,8 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) > { > struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); > > - ACPI_FLUSH_CPU_CACHE(); > + if (cx->type == ACPI_STATE_C3) > + ACPI_FLUSH_CPU_CACHE(); > acpi_idle_enter() already does this, acpi_idle_enter_s2idle() has it confused again, Also, I think acpi_idle_enter() does it too late; consider acpi_idle_enter_mb(). Either that or the BM crud needs more comments.
On Mon, Dec 6, 2021 at 1:30 PM Kirill A. Shutemov <kirill.shutemov@linux.intel.com> wrote: > > ACPICA code takes care about cache flushing on S1/S2/S3 in > acpi_hw_extended_sleep() and acpi_hw_legacy_sleep(). > > acpi_suspend_enter() calls into ACPICA code via acpi_enter_sleep_state() > for S1 or x86_acpi_suspend_lowlevel() for S3. It only need to flush > cache for S2 (not sure if this call path is ever used for S2). > > acpi_sleep_prepare() call tree: > __acpi_pm_prepare() > acpi_pm_prepare() > acpi_suspend_ops::prepare_late() > acpi_hibernation_ops::pre_snapshot() > acpi_hibernation_ops::prepare() > acpi_suspend_begin_old() > acpi_suspend_begin_old::begin() > acpi_hibernation_begin_old() > acpi_hibernation_ops_old::acpi_hibernation_begin_old() > acpi_power_off_prepare() > pm_power_off_prepare() > > Hibernation (S4) and Power Off (S5) don't require cache flushing. So, > the only interesting callsites are acpi_suspend_ops::prepare_late() and > acpi_suspend_begin_old::begin(). Both of them have cache flush on > ->enter() operation in acpi_suspend_enter(). > > Remove redundant ACPI_FLUSH_CPU_CACHE() in acpi_sleep_prepare() and > acpi_suspend_enter(). > > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > --- > drivers/acpi/sleep.c | 7 +++---- > 1 file changed, 3 insertions(+), 4 deletions(-) > > diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c > index eaa47753b758..14e8df0ac762 100644 > --- a/drivers/acpi/sleep.c > +++ b/drivers/acpi/sleep.c > @@ -73,7 +73,6 @@ static int acpi_sleep_prepare(u32 acpi_state) > acpi_set_waking_vector(acpi_wakeup_address); > > } > - ACPI_FLUSH_CPU_CACHE(); > #endif > pr_info("Preparing to enter system sleep state S%d\n", acpi_state); > acpi_enable_wakeup_devices(acpi_state); > @@ -566,15 +565,15 @@ static int acpi_suspend_enter(suspend_state_t pm_state) > u32 acpi_state = acpi_target_sleep_state; > int error; > > - ACPI_FLUSH_CPU_CACHE(); > - > trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true); > switch (acpi_state) { > case ACPI_STATE_S1: > barrier(); > status = acpi_enter_sleep_state(acpi_state); > break; > - > + case ACPI_STATE_S2: > + ACPI_FLUSH_CPU_CACHE(); > + break; I don't think this is needed for S2, because the function doesn't do anything low-level in that case and simply returns (IOW, S2 isn't really supported). > case ACPI_STATE_S3: > if (!acpi_suspend_lowlevel) > return -ENOSYS; > -- > 2.32.0 >
On Mon, Dec 6, 2021 at 4:03 PM Peter Zijlstra <peterz@infradead.org> wrote: > > On Mon, Dec 06, 2021 at 03:29:51PM +0300, Kirill A. Shutemov wrote: > > According to the ACPI spec v6.4, section 8.2, cache flushing required > > on entering C3 power state. > > > > Avoid flushing cache on entering other power states. > > > > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > > --- > > drivers/acpi/processor_idle.c | 3 ++- > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c > > index 76ef1bcc8848..01495aca850e 100644 > > --- a/drivers/acpi/processor_idle.c > > +++ b/drivers/acpi/processor_idle.c > > @@ -567,7 +567,8 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) > > { > > struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); > > > > - ACPI_FLUSH_CPU_CACHE(); > > + if (cx->type == ACPI_STATE_C3) > > + ACPI_FLUSH_CPU_CACHE(); > > > > acpi_idle_enter() already does this, acpi_idle_enter_s2idle() has it > confused again, No, they do the same thing: acpi_idle_enter_bm() if flags.bm_check is set. > Also, I think acpi_idle_enter() does it too late; consider > acpi_idle_enter_mb(). Either that or the BM crud needs more comments. I think the latter. Evidently, acpi_idle_play_dead(() doesn't support FFH and the BM thing, so it is only necessary to flush the cache when using ACPI_CSTATE_SYSTEMIO and when cx->type is C3.
On Tue, Dec 07, 2021 at 05:35:38PM +0100, Rafael J. Wysocki wrote: > I don't think this is needed for S2, because the function doesn't do > anything low-level in that case and simply returns (IOW, S2 isn't > really supported). Updated patch is below. Does it look good?
On Wed, Dec 08, 2021 at 05:26:12PM +0100, Rafael J. Wysocki wrote: > On Mon, Dec 6, 2021 at 4:03 PM Peter Zijlstra <peterz@infradead.org> wrote: > > > > On Mon, Dec 06, 2021 at 03:29:51PM +0300, Kirill A. Shutemov wrote: > > > According to the ACPI spec v6.4, section 8.2, cache flushing required > > > on entering C3 power state. > > > > > > Avoid flushing cache on entering other power states. > > > > > > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > > > --- > > > drivers/acpi/processor_idle.c | 3 ++- > > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c > > > index 76ef1bcc8848..01495aca850e 100644 > > > --- a/drivers/acpi/processor_idle.c > > > +++ b/drivers/acpi/processor_idle.c > > > @@ -567,7 +567,8 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) > > > { > > > struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); > > > > > > - ACPI_FLUSH_CPU_CACHE(); > > > + if (cx->type == ACPI_STATE_C3) > > > + ACPI_FLUSH_CPU_CACHE(); > > > > > > > acpi_idle_enter() already does this, acpi_idle_enter_s2idle() has it > > confused again, > > No, they do the same thing: acpi_idle_enter_bm() if flags.bm_check is set. > > > Also, I think acpi_idle_enter() does it too late; consider > > acpi_idle_enter_mb(). Either that or the BM crud needs more comments. > > I think the latter. > > Evidently, acpi_idle_play_dead(() doesn't support FFH and the BM > thing, so it is only necessary to flush the cache when using > ACPI_CSTATE_SYSTEMIO and when cx->type is C3. I'm new to this and not completely follow what I need to change. Does it look correct?
On Thu, Dec 9, 2021 at 2:33 PM Kirill A. Shutemov <kirill.shutemov@linux.intel.com> wrote: > > On Wed, Dec 08, 2021 at 05:26:12PM +0100, Rafael J. Wysocki wrote: > > On Mon, Dec 6, 2021 at 4:03 PM Peter Zijlstra <peterz@infradead.org> wrote: > > > > > > On Mon, Dec 06, 2021 at 03:29:51PM +0300, Kirill A. Shutemov wrote: > > > > According to the ACPI spec v6.4, section 8.2, cache flushing required > > > > on entering C3 power state. > > > > > > > > Avoid flushing cache on entering other power states. > > > > > > > > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > > > > --- > > > > drivers/acpi/processor_idle.c | 3 ++- > > > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c > > > > index 76ef1bcc8848..01495aca850e 100644 > > > > --- a/drivers/acpi/processor_idle.c > > > > +++ b/drivers/acpi/processor_idle.c > > > > @@ -567,7 +567,8 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) > > > > { > > > > struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); > > > > > > > > - ACPI_FLUSH_CPU_CACHE(); > > > > + if (cx->type == ACPI_STATE_C3) > > > > + ACPI_FLUSH_CPU_CACHE(); > > > > > > > > > > acpi_idle_enter() already does this, acpi_idle_enter_s2idle() has it > > > confused again, > > > > No, they do the same thing: acpi_idle_enter_bm() if flags.bm_check is set. > > > > > Also, I think acpi_idle_enter() does it too late; consider > > > acpi_idle_enter_mb(). Either that or the BM crud needs more comments. > > > > I think the latter. > > > > Evidently, acpi_idle_play_dead(() doesn't support FFH and the BM > > thing, so it is only necessary to flush the cache when using > > ACPI_CSTATE_SYSTEMIO and when cx->type is C3. > > I'm new to this and not completely follow what I need to change. > > Does it look correct? It does, but I liked the original one more and so that one has been applied as 5.17 material (with some edits in the changelog). Thanks! > From 3c544bc95a16d6a23dcb0aa50ee905d5e97c9ce5 Mon Sep 17 00:00:00 2001 > From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> > Date: Thu, 9 Dec 2021 16:24:44 +0300 > Subject: [PATCH] ACPI: processor idle: Only flush cache on entering C3 > > According to the ACPI spec v6.4, section 8.2, cache flushing required > on entering C3 power state. > > Avoid flushing cache on entering other power states. > > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > --- > drivers/acpi/processor_idle.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c > index 76ef1bcc8848..d2a4d4446eff 100644 > --- a/drivers/acpi/processor_idle.c > +++ b/drivers/acpi/processor_idle.c > @@ -567,7 +567,9 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) > { > struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); > > - ACPI_FLUSH_CPU_CACHE(); > + if (cx->entry_method == ACPI_CSTATE_SYSTEMIO && > + cx->type == ACPI_STATE_C3) > + ACPI_FLUSH_CPU_CACHE(); > > while (1) { > > -- > Kirill A. Shutemov
On Thu, Dec 9, 2021 at 2:32 PM Kirill A. Shutemov <kirill.shutemov@linux.intel.com> wrote: > > On Tue, Dec 07, 2021 at 05:35:38PM +0100, Rafael J. Wysocki wrote: > > I don't think this is needed for S2, because the function doesn't do > > anything low-level in that case and simply returns (IOW, S2 isn't > > really supported). > > Updated patch is below. Does it look good? It does, and so applied as 5.17 material with some minor edits in the changelog. Thanks! > From 5eb4ec7d8dd463ba186b779dcef2a802d999c59c Mon Sep 17 00:00:00 2001 > From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> > Date: Thu, 9 Dec 2021 16:08:02 +0300 > Subject: [PATCH 1/2] ACPI: PM: Remove redundant cache flushing > > ACPICA code takes care about cache flushing on S1/S2/S3 in > acpi_hw_extended_sleep() and acpi_hw_legacy_sleep(). > > acpi_suspend_enter() calls into ACPICA code via acpi_enter_sleep_state() > for S1 or x86_acpi_suspend_lowlevel() for S3. > > acpi_sleep_prepare() call tree: > __acpi_pm_prepare() > acpi_pm_prepare() > acpi_suspend_ops::prepare_late() > acpi_hibernation_ops::pre_snapshot() > acpi_hibernation_ops::prepare() > acpi_suspend_begin_old() > acpi_suspend_begin_old::begin() > acpi_hibernation_begin_old() > acpi_hibernation_ops_old::acpi_hibernation_begin_old() > acpi_power_off_prepare() > pm_power_off_prepare() > > Hibernation (S4) and Power Off (S5) don't require cache flushing. So, > the only interesting callsites are acpi_suspend_ops::prepare_late() and > acpi_suspend_begin_old::begin(). Both of them have cache flush on > ->enter() operation in acpi_suspend_enter(). > > Remove redundant ACPI_FLUSH_CPU_CACHE() in acpi_sleep_prepare() and > acpi_suspend_enter(). > > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > --- > drivers/acpi/sleep.c | 3 --- > 1 file changed, 3 deletions(-) > > diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c > index eaa47753b758..5ca6c223ba3d 100644 > --- a/drivers/acpi/sleep.c > +++ b/drivers/acpi/sleep.c > @@ -73,7 +73,6 @@ static int acpi_sleep_prepare(u32 acpi_state) > acpi_set_waking_vector(acpi_wakeup_address); > > } > - ACPI_FLUSH_CPU_CACHE(); > #endif > pr_info("Preparing to enter system sleep state S%d\n", acpi_state); > acpi_enable_wakeup_devices(acpi_state); > @@ -566,8 +565,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) > u32 acpi_state = acpi_target_sleep_state; > int error; > > - ACPI_FLUSH_CPU_CACHE(); > - > trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true); > switch (acpi_state) { > case ACPI_STATE_S1: > -- > Kirill A. Shutemov