Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 08 Jul 2012 13:22:49 +0300
From:      Andriy Gapon <avg@FreeBSD.org>
To:        "freebsd-acpi@freebsd.org" <freebsd-acpi@FreeBSD.org>
Cc:        Vitaly Magerya <vmagerya@gmail.com>, John Baldwin <jhb@FreeBSD.org>, Giovanni Trematerra <gianni@FreeBSD.org>
Subject:   improve cx_lowest logic
Message-ID:  <4FF95F79.30309@FreeBSD.org>

next in thread | raw e-mail | index | archive | help

I would like to propose the following change for review and testing:
http://people.freebsd.org/~avg/acpi_cpu_cx_lowest.diff

The idea is to separate effective cx_lowest (the limit that the idling code
should not currently exceed) from user-set cx_lowest limit/target.
Specifically, this addresses dynamic C-state changes by ACPI platform.
Currently if a user sets cx_lowest to, say, C3, then available C-states change
so that C2 is the deepest available C-state and cx_lowest gets overridden to C2
and all memory of C3 setting is lost.
Also, there is a problem with asynchronous nature of userland notification about
power profile change and kernel notifications of _CST changes for each CPU in
SMP system.  That required work-arounds like one in r209213 which also
introduced quite a bit of confusion about how per-CPU cpu_cx_lowest, global
cpu_cx_lowest and dynamic C-state changes interact with each other.
To this day I can not unwind the complete logic behind the following lines:
if (sc->cpu_cx_lowest < cpu_cx_lowest)
   acpi_cpu_set_cx_lowest(sc, min(cpu_cx_lowest, sc->cpu_cx_count - 1));

So to avoid the problems described above I decided to split the cx_lowest limit
into the persistent user-set limit, cpu_cx_lowest_lim, and dynamic effective limit.
The logic to set cpu_cx_lowest based on cpu_cx_lowest_lim and cpu_cx_count is
moved to acpi_cpu_set_cx_lowest().

Note that per-CPU cpu_cx_lowest_lim does not "interact" with global
cpu_cx_lowest_lim.  Whichever is set later (via sysctl) just overrides the other.

With such a change it no longer makes sense to limit allowed cx_lowest sysctl
values to currently available C-state levels.  Indeed, if a user knows that his
system may provide C6 under some circumstance, but currently only C1 is
available, then there is no reason to disallow setting cx_lowest sysctl
(cpu_cx_lowest_lim) to C6.  So values up to MAX_CX_STATES are allowed.
After this change cpu_cx_count _global_ variable became unused (write-only) and
was removed.

Additionally, I introduced magic value of "Cmax" for cx_lowest sysctls to mean
that there should not be any limit on C-state depth.

The change is partially based on submission from Vitaly:
http://article.gmane.org/gmane.os.freebsd.devel.acpi/6892
-- 
Andriy Gapon




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4FF95F79.30309>