Unix Technical Forum

acpicpu needs wide testing

This is a discussion on acpicpu needs wide testing within the mailing.openbsd.tech forums, part of the OpenBSD category; --> In order to be able to move proper cpu throttling along I want to get the following diff in. ...


Go Back   Unix Technical Forum > Unix Operating Systems > OpenBSD > mailing.openbsd.tech

Register FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-18-2008, 09:34 AM
Marco Peereboom
 
Posts: n/a
Default acpicpu needs wide testing

In order to be able to move proper cpu throttling along I want to get
the following diff in. It adds support for _PPC which defines which
power states are available after a cable pull or insert. An example is
my Dell D810; if I use a 65W power suppoy I can only run at 800MHz; if I
run unplugged I only have 5 out of 6 power states (depending on the
battery) and when plugged in to 90W power supply it has all power states
available. It also gets the code ready for the addition of duty cycle
throttling (only run the cpu every so many clock cycles). When both
those are in we can move forward to making acpitz do throttling based on
thermal requirements but those diffs are still a few days away.

Please test and send me a report of success / failure. I Particularly
need testing on amd64 laptops.

Index: acpicpu.c
================================================== =================
RCS file: /cvs/src/sys/dev/acpi/acpicpu.c,v
retrieving revision 1.39
diff -u -p -u -p -r1.39 acpicpu.c
--- acpicpu.c 27 Dec 2007 22:32:37 -0000 1.39
+++ acpicpu.c 28 Dec 2007 02:54:16 -0000
@@ -94,9 +94,16 @@ struct acpicpu_softc {
struct aml_node *sc_devnode;

int sc_pss_len;
+ int sc_ppc;
+ int sc_level;
struct acpicpu_pss *sc_pss;

struct acpicpu_pct sc_pct;
+ /* save compensation for pct access for lying bios' */
+ u_int32_t sc_pct_stat_as;
+ u_int32_t sc_pct_ctrl_as;
+ u_int32_t sc_pct_stat_len;
+ u_int32_t sc_pct_ctrl_len;
/*
* XXX: _PPC Change listener
* PPC changes can occur when for example a machine is disconnected
@@ -110,6 +117,7 @@ struct acpicpu_softc {

void acpicpu_set_throttle(struct acpicpu_softc *, int);
void acpicpu_add_cstatepkg(struct aml_value *, void *);
+int acpicpu_getppc(struct acpicpu_softc *);
int acpicpu_getpct(struct acpicpu_softc *);
int acpicpu_getpss(struct acpicpu_softc *);
struct acpi_cstate *acpicpu_add_cstate(struct acpicpu_softc *, int, int, int,
@@ -236,6 +244,7 @@ acpicpu_attach(struct device *parent, st
struct aml_value res;
int i;
struct acpi_cstate *cx;
+ u_int32_t status = 0;

sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_devnode = aa->aaa_node;
@@ -286,7 +295,6 @@ acpicpu_attach(struct device *parent, st
sc->sc_pblk_addr + 5);
}
if (acpicpu_getpss(sc)) {
- /* XXX not the right test but has to do for now */
sc->sc_flags |= FLAGS_NOPSS;
} else {
#ifdef ACPI_DEBUG
@@ -301,6 +309,13 @@ acpicpu_attach(struct device *parent, st
}
dnprintf(20, "\n");
#endif
+ if (sc->sc_pss_len == 0) {
+ /* this should never happen */
+ printf("%s: invalid _PSS length\n");
+ sc->sc_flags |= FLAGS_NOPSS;
+ }
+
+ acpicpu_getppc(sc);
if (acpicpu_getpct(sc))
sc->sc_flags |= FLAGS_NOPCT;
else {
@@ -313,8 +328,15 @@ acpicpu_attach(struct device *parent, st
aml_register_notify(sc->sc_devnode, NULL,
acpicpu_notify, sc, ACPIDEV_NOPOLL);

+ acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
+ sc->sc_pct.pct_status.grd_gas.address_space_id,
+ sc->sc_pct.pct_status.grd_gas.address,
+ sc->sc_pct_stat_as, sc->sc_pct_stat_as, &status);
+ sc->sc_level = (100 / sc->sc_pss_len) *
+ (sc->sc_pss_len - status);
+ dnprintf(20, "%s: cpu index %d, percentage %d\n",
+ DEVNAME(sc), status, sc->sc_level);
if (setperf_prio < 30) {
- printf("acpi does throttle\n");
cpu_setperf = acpicpu_setperf;
setperf_prio = 30;
acpi_hasprocfvs = 1;
@@ -372,19 +394,30 @@ acpicpu_attach(struct device *parent, st
}

int
-acpicpu_getpct(struct acpicpu_softc *sc)
+acpicpu_getppc(struct acpicpu_softc *sc)
{
struct aml_value res;
- int rv = 1;
+
+ sc->sc_ppc = 0;

if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PPC", 0, NULL, &res)) {
dnprintf(10, "%s: no _PPC\n", DEVNAME(sc));
return (1);
}

- dnprintf(10, "_PPC: %d\n", aml_val2int(&res));
+ sc->sc_ppc = aml_val2int(&res);
+ dnprintf(10, "%s: _PPC: %d\n", DEVNAME(sc), sc->sc_ppc);
aml_freevalue(&res);

+ return (0);
+}
+
+int
+acpicpu_getpct(struct acpicpu_softc *sc)
+{
+ struct aml_value res;
+ int rv = 1;
+
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PCT", 0, NULL, &res)) {
dnprintf(20, "%s: no _PCT\n", DEVNAME(sc));
return (1);
@@ -430,6 +463,21 @@ acpicpu_getpct(struct acpicpu_softc *sc)
sc->sc_pct.pct_status.grd_gas.access_size,
sc->sc_pct.pct_status.grd_gas.address);

+ /* if not set assume single 32 bit access */
+ sc->sc_pct_stat_as = sc->sc_pct.pct_status.grd_gas.register_bit_width
+ / 8;
+ if (sc->sc_pct_stat_as == 0)
+ sc->sc_pct_stat_as = 4;
+ sc->sc_pct_ctrl_as = sc->sc_pct.pct_ctrl.grd_gas.register_bit_width / 8;
+ if (sc->sc_pct_ctrl_as == 0)
+ sc->sc_pct_ctrl_as = 4;
+ sc->sc_pct_stat_len = sc->sc_pct.pct_status.grd_gas.access_size;
+ if (sc->sc_pct_stat_len == 0)
+ sc->sc_pct_stat_len = sc->sc_pct_stat_as;
+ sc->sc_pct_ctrl_len = sc->sc_pct.pct_ctrl.grd_gas.access_size;
+ if (sc->sc_pct_ctrl_len == 0)
+ sc->sc_pct_ctrl_len = sc->sc_pct_ctrl_as;
+
rv = 0;
ffh:
aml_freevalue(&res);
@@ -505,10 +553,14 @@ acpicpu_notify(struct aml_node *node, in

switch (notify_type) {
case 0x80: /* _PPC changed, retrieve new values */
- acpicpu_getpct(sc);
+ acpicpu_getppc(sc);
acpicpu_getpss(sc);
if (sc->sc_notify)
sc->sc_notify(sc->sc_pss, sc->sc_pss_len);
+
+ /* reset performance to current percentage */
+ /* XXX will fail for amd64 for now */
+ acpicpu_setperf(sc->sc_level);
break;
default:
printf("%s: unhandled cpu event %x\n", DEVNAME(sc),
@@ -533,8 +585,7 @@ acpicpu_setperf(int level)
{
struct acpicpu_softc *sc;
struct acpicpu_pss *pss = NULL;
- int idx;
- u_int32_t stat_as, ctrl_as, stat_len, ctrl_len;
+ int idx, len;
u_int32_t status = 0;

sc = acpicpu_sc[cpu_number()];
@@ -552,54 +603,44 @@ acpicpu_setperf(int level)
* XXX this should be handled more gracefully and it needs to also do
* the duty cycle method instead of pss exclusively
*/
- if (sc->sc_pss_len == 0) {
- dnprintf(10, "%s: acpicpu no _PSS\n", sc->sc_devnode->name);
+ if (sc->sc_flags & FLAGS_NOPSS || sc->sc_flags & FLAGS_NOPCT) {
+ dnprintf(10, "%s: acpicpu no _PSS or _PCT\n", sc->sc_devnode->name);
return;
}

- idx = (sc->sc_pss_len - 1) - (level / (100 / sc->sc_pss_len));
+ if (sc->sc_ppc)
+ len = sc->sc_ppc;
+ else
+ len = sc->sc_pss_len;
+ idx = (len - 1) - (level / (100 / len));
if (idx < 0)
- idx = 0; /* compensate */
- if (idx > sc->sc_pss_len) {
- /* XXX should never happen */
- printf("%s: acpicpu setperf index out of range\n",
- sc->sc_devnode->name);
- return;
- }
+ idx = 0;

- dnprintf(10, "%s: acpicpu setperf index %d\n",
- sc->sc_devnode->name, idx);
+ if (sc->sc_ppc)
+ idx += sc->sc_pss_len - sc->sc_ppc;

- pss = &sc->sc_pss[idx];
+ if (idx > sc->sc_pss_len)
+ idx = sc->sc_pss_len - 1;

- /* if not set assume single 32 bit access */
- stat_as = sc->sc_pct.pct_status.grd_gas.register_bit_width / 8;
- if (stat_as == 0)
- stat_as = 4;
- ctrl_as = sc->sc_pct.pct_ctrl.grd_gas.register_bit_width / 8;
- if (ctrl_as == 0)
- ctrl_as = 4;
- stat_len = sc->sc_pct.pct_status.grd_gas.access_size;
- if (stat_len == 0)
- stat_len = stat_as;
- ctrl_len = sc->sc_pct.pct_ctrl.grd_gas.access_size;
- if (ctrl_len == 0)
- ctrl_len = ctrl_as;
+ dnprintf(10, "%s: acpicpu setperf index %d pss_len %d ppc %d\n",
+ sc->sc_devnode->name, idx, sc->sc_pss_len, sc->sc_ppc);
+
+ pss = &sc->sc_pss[idx];

#ifdef ACPI_DEBUG
/* keep this for now since we will need this for debug in the field */
printf("0 status: %x %llx %u %u ctrl: %x %llx %u %u\n",
sc->sc_pct.pct_status.grd_gas.address_space_id,
sc->sc_pct.pct_status.grd_gas.address,
- stat_as, stat_len,
+ sc->sc_pct_stat_as, sc->sc_pct_stat_len,
sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
sc->sc_pct.pct_ctrl.grd_gas.address,
- ctrl_as, ctrl_len);
+ sc->sc_pct_ctrl_as, sc->sc_pct_ctrl_len);
#endif
acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
sc->sc_pct.pct_status.grd_gas.address_space_id,
- sc->sc_pct.pct_status.grd_gas.address, stat_as, stat_len,
- &status);
+ sc->sc_pct.pct_status.grd_gas.address, sc->sc_pct_stat_as,
+ sc->sc_pct_stat_len, &status);
dnprintf(20, "1 status: %u <- %u\n", status, pss->pss_status);

/* Are we already at the requested frequency? */
@@ -608,20 +649,21 @@ acpicpu_setperf(int level)

acpi_gasio(sc->sc_acpi, ACPI_IOWRITE,
sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
- sc->sc_pct.pct_ctrl.grd_gas.address, ctrl_as, ctrl_len,
- &pss->pss_ctrl);
+ sc->sc_pct.pct_ctrl.grd_gas.address, sc->sc_pct_ctrl_as,
+ sc->sc_pct_ctrl_len, &pss->pss_ctrl);
dnprintf(20, "pss_ctrl: %x\n", pss->pss_ctrl);

acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
sc->sc_pct.pct_status.grd_gas.address_space_id,
- sc->sc_pct.pct_status.grd_gas.address, stat_as, stat_as,
- &status);
+ sc->sc_pct.pct_status.grd_gas.address, sc->sc_pct_stat_as,
+ sc->sc_pct_stat_as, &status);
dnprintf(20, "2 status: %d\n", status);

/* Did the transition succeed? */
- if (status == pss->pss_status)
+ if (status == pss->pss_status) {
cpuspeed = pss->pss_core_freq;
- else
+ sc->sc_level = level;
+ } else
printf("%s: acpicpu setperf failed to alter frequency\n",
sc->sc_devnode->name);
}

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 01:28 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com