[PATCH 14/14] ACPI: Provide /sys/devices/system/cpu/cpuN/deconfigure - Kernel

This is a discussion on [PATCH 14/14] ACPI: Provide /sys/devices/system/cpu/cpuN/deconfigure - Kernel ; Provide a new sysfs interface for CPU deconfiguration. Since no vendors can agree on terminology for related but slightly different features, provide a method for a platform to implement its own version of what it thinks 'deconfiguring' a CPU might ...

+ Reply to Thread
Results 1 to 3 of 3

Thread: [PATCH 14/14] ACPI: Provide /sys/devices/system/cpu/cpuN/deconfigure

  1. [PATCH 14/14] ACPI: Provide /sys/devices/system/cpu/cpuN/deconfigure

    Provide a new sysfs interface for CPU deconfiguration.

    Since no vendors can agree on terminology for related but slightly
    different features, provide a method for a platform to implement
    its own version of what it thinks 'deconfiguring' a CPU might be.

    Provide an HP-specific CPU deconfiguration implementation.

    Signed-off-by: Alex Chiang
    Cc: Andi Kleen
    ---

    drivers/acpi/Kconfig | 18 ++
    drivers/acpi/Makefile | 4
    drivers/acpi/processor_core.c | 8 +
    drivers/acpi/processor_deconfigure.c | 275 ++++++++++++++++++++++++++++++++++
    include/acpi/processor.h | 6 +
    5 files changed, 311 insertions(+), 0 deletions(-)
    create mode 100644 drivers/acpi/processor_deconfigure.c

    diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
    index c52fca8..36ad177 100644
    --- a/drivers/acpi/Kconfig
    +++ b/drivers/acpi/Kconfig
    @@ -188,6 +188,24 @@ config ACPI_HOTPLUG_CPU
    select ACPI_CONTAINER
    default y

    +config ACPI_DECONFIGURE_CPU
    + bool "Processor deconfiguration"
    + depends on ACPI_PROCESSOR
    + default n
    + help
    + This processor driver submodule allows a user to mark a CPU
    + for firmware disabling/enabling. It will create the following
    + sysfs file:
    +
    + /sys/devices/system/cpu/cpuN/deconfigure
    +
    + Behavior of this interface is highly vendor-dependent and
    + requires firmware support.
    +
    + This option is NOT required for CPU hotplug support.
    +
    + If unsure, say N.
    +
    config ACPI_THERMAL
    tristate "Thermal Zone"
    depends on ACPI_PROCESSOR
    diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
    index 40b0fca..92a5037 100644
    --- a/drivers/acpi/Makefile
    +++ b/drivers/acpi/Makefile
    @@ -35,6 +35,10 @@ ifdef CONFIG_CPU_FREQ
    processor-objs += processor_perflib.o
    endif

    +ifdef CONFIG_ACPI_DECONFIGURE_CPU
    +processor-objs += processor_deconfigure.o
    +endif
    +
    obj-y += sleep/
    obj-y += bus.o glue.o
    obj-y += scan.o
    diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
    index 9dd0fa9..ef582ca 100644
    --- a/drivers/acpi/processor_core.c
    +++ b/drivers/acpi/processor_core.c
    @@ -1099,6 +1099,10 @@ static int __init acpi_processor_init(void)

    acpi_processor_throttling_init();

    +#ifdef CONFIG_ACPI_DECONFIGURE_CPU
    + acpi_processor_deconfigure_init();
    +#endif
    +
    return 0;

    out_cpuidle:
    @@ -1112,6 +1116,10 @@ out_proc:

    static void __exit acpi_processor_exit(void)
    {
    +
    +#ifdef CONFIG_ACPI_DECONFIGURE_CPU
    + acpi_processor_deconfigure_exit();
    +#endif
    acpi_processor_ppc_exit();

    acpi_thermal_cpufreq_exit();
    diff --git a/drivers/acpi/processor_deconfigure.c b/drivers/acpi/processor_deconfigure.c
    new file mode 100644
    index 0000000..e656f97
    --- /dev/null
    +++ b/drivers/acpi/processor_deconfigure.c
    @@ -0,0 +1,275 @@
    +/*
    + * processor_deconfigure.c - CPU deconfiguration submodule of the
    + * ACPI processor driver
    + *
    + * (c) Copyright 2008 Hewlett-Packard Development Company, L.P.
    + * Alex Chiang
    + *
    + * This program is free software; you can redistribute it and/or modify it
    + * under the terms and conditions of the GNU General Public License,
    + * version 2, as published by the Free Software Foundation.
    + */
    +
    +#include
    +#include
    +#include
    +
    +static int supports_cpu_deconfigure;
    +
    +/*
    + * These function pointers must be overwritten by platforms supporting
    + * cpu deconfigure.
    + */
    +static ssize_t (*show_deconfigure)(struct sys_device *, char *);
    +static ssize_t (*store_deconfigure)(struct sys_device *, const char *, size_t);
    +
    +/*
    + * Under HP semantics, CPU deconfiguration is defined as removing a
    + * processor core or socket from operation at boot time, typically
    + * due to managability concerns, such as excessive detected errors.
    + *
    + * The HP semantics of 'deconfigure' are defined as:
    + *
    + * Mark CPU for deconfiguration at next boot.
    + * # echo 1 > /sys/devices/system/cpu/cpuN/deconfigure
    + *
    + * Mark CPU as enabled at next boot.
    + * # echo 0 > /sys/devices/system/cpu/cpuN/deconfigure
    + *
    + * Display next boot's deconfigure status
    + * 0x0 - not marked for deconfiguration
    + * 0x1 - scheduled deconfig at next boot
    + * 0x3 - scheduled, OS-requested deconfig at next boot
    + * 0x4 - thread disabled by firmware
    + * # cat /sys/devices/system/cpu/cpuN/deconfigure
    + *
    + * After echo'ing 0 or 1 into deconfigure, cat'ing the file will
    + * return the next boot's status. However, the CPU will not actually
    + * be deconfigured until the next boot.
    + *
    + * Attempting to configure or deconfigure a disabled thread is disallowed.
    + */
    +struct hp_deconfigure_cb_args {
    + int cpu;
    + char *method;
    +};
    +
    +static acpi_status hp_deconfigure_cb(acpi_handle handle,
    + u32 lvl,
    + void *context,
    + void **rv)
    +{
    + int cpu;
    + acpi_status status;
    + acpi_integer scfg;
    + struct hp_deconfigure_cb_args *args = context;
    + union acpi_object object = { 0 };
    + struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
    +
    + status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
    + if (ACPI_FAILURE(status))
    + return AE_OK;
    +
    + cpu = object.processor.proc_id;
    + if (cpu != args->cpu)
    + return AE_OK;
    +
    + /*
    + * Always check SCFG. If this is what the user actually wanted,
    + * great, just return the answer. If the user wanted something
    + * else, check to see if they were trying to poke a disabled
    + * hardware thread and disallow it if so.
    + */
    + status = acpi_evaluate_object(handle, "SCFG", NULL, &buffer);
    + scfg = object.integer.value;
    + if (!strcmp(args->method, "SCFG"))
    + **(int **)rv = ACPI_SUCCESS(status) ? scfg : -1;
    + /*
    + * Disallow E/DCFG on disabled threads
    + */
    + else if (scfg == 0x4)
    + **(int **)rv = -1;
    + else {
    + status = acpi_evaluate_object(handle, args->method,
    + NULL, &buffer);
    + **(int **)rv = ACPI_SUCCESS(status) ? status : -1;
    + }
    +
    + return AE_CTRL_TERMINATE;
    +}
    +
    +/*
    + * We can do this the easy way or the hard way. The easy way is,
    + * if the CPU is online, we have easy access to its ACPI handle
    + * via its per_cpu() data area, and we can call SCFG directly.
    + *
    + * The hard way is when the CPU is not online, and does not have
    + * a valid per_cpu() data area. In that case, we have to walk the
    + * ACPI namespace, looking for the CPU and calling SCFG that way.
    + */
    +static ssize_t hp_show_deconfigure(struct sys_device *dev, char *buf)
    +{
    + int logical_cpu;
    + unsigned long cfg;
    + struct cpu *cpu = container_of(dev, struct cpu, sysdev);
    +
    + logical_cpu = cpu->sysdev.id;
    +
    + if (cpu_isset(logical_cpu, cpu_online_map)) {
    + unsigned long tmp;
    + acpi_status status;
    + struct acpi_processor *pr;
    +
    + pr = processors[logical_cpu];
    + status = acpi_evaluate_integer(pr->handle, "SCFG", NULL, &tmp);
    + cfg = ACPI_SUCCESS(status) ? tmp : -1;
    + } else {
    + int ret;
    + void *ret_ptr = &ret;
    + struct hp_deconfigure_cb_args args;
    +
    + args.cpu = logical_cpu;
    + args.method = "SCFG";
    + acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
    + ACPI_ROOT_OBJECT,
    + ACPI_UINT32_MAX,
    + hp_deconfigure_cb,
    + &args,
    + (void *)&ret_ptr);
    + cfg = ret;
    + }
    +
    + return sprintf(buf, "%#lx\n", cfg);
    +}
    +
    +/*
    + * We can do this the easy way or the hard way. The easy way is,
    + * if the CPU is online, we have easy access to its ACPI handle
    + * via its per_cpu() data area, and we can call E/D-CFG directly.
    + *
    + * The hard way is when the CPU is not online, and does not have
    + * a valid per_cpu() data area. In that case, we have to walk the
    + * ACPI namespace, looking for the CPU and calling E/D-CFG that way.
    + */
    +static ssize_t hp_store_deconfigure(struct sys_device *dev, const char *buf,
    + size_t count)
    +{
    + ssize_t ret;
    + char *method;
    + int logical_cpu;
    + struct cpu *cpu = container_of(dev, struct cpu, sysdev);
    +
    + logical_cpu = cpu->sysdev.id;
    + switch (buf[0]) {
    + case '0':
    + method = "ECFG";
    + break;
    + case '1':
    + method = "DCFG";
    + break;
    + default:
    + ret = -EINVAL;
    + goto out;
    + }
    +
    + if (cpu_isset(logical_cpu, cpu_online_map)) {
    + struct acpi_processor *pr;
    + pr = processors[logical_cpu];
    + ret = acpi_evaluate_object(pr->handle, method, NULL, NULL);
    + } else {
    + int r;
    + void *ret_ptr = &r;
    + struct hp_deconfigure_cb_args args;
    +
    + args.cpu = logical_cpu;
    + args.method = method;
    + acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
    + ACPI_ROOT_OBJECT,
    + ACPI_UINT32_MAX,
    + hp_deconfigure_cb,
    + &args,
    + (void *)&ret_ptr);
    + ret = r;
    + }
    +
    + if (ret == 0)
    + if (!strcmp(method, "ECFG"))
    + cpu_set(logical_cpu, cpu_enabled_map);
    + else
    + cpu_clear(logical_cpu, cpu_enabled_map);
    +
    +out:
    + if (ret >= 0)
    + ret = count;
    + return ret;
    +}
    +
    +static int hp_check_cpu_deconfigure(const struct dmi_system_id *d)
    +{
    + acpi_handle hnd;
    + struct acpi_processor *pr;
    +
    + /*
    + * Operating assumption is that either all or none of the CPUs
    + * will support deconfiguration.
    + */
    + pr = processors[0];
    + if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "SCFG", &hnd))) {
    + supports_cpu_deconfigure = 1;
    + show_deconfigure = hp_show_deconfigure;
    + store_deconfigure = hp_store_deconfigure;
    + }
    +
    + return 0;
    +}
    +
    +static struct dmi_system_id cpu_deconfigure_dmi_table[] __initdata = {
    + {
    + .callback = hp_check_cpu_deconfigure,
    + .ident = "Hewlett-Packard",
    + .matches = {
    + DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
    + },
    + },
    + {
    + .callback = hp_check_cpu_deconfigure,
    + .ident = "Hewlett-Packard",
    + .matches = {
    + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
    + },
    + },
    + {}
    +};
    +
    +static SYSDEV_ATTR(deconfigure, 0644, NULL, NULL);
    +
    +void __init acpi_processor_deconfigure_init(void)
    +{
    + int i;
    + struct sys_device *sysdev;
    +
    + dmi_check_system(cpu_deconfigure_dmi_table);
    +
    + if (supports_cpu_deconfigure) {
    + attr_deconfigure.show = show_deconfigure;
    + attr_deconfigure.store = store_deconfigure;
    +
    + for_each_present_cpu(i) {
    + sysdev = get_cpu_sysdev(i);
    + sysdev_create_file(sysdev, &attr_deconfigure);
    + }
    + }
    +}
    +
    +void acpi_processor_deconfigure_exit(void)
    +{
    + int i;
    + struct sys_device *sysdev;
    +
    + if (supports_cpu_deconfigure) {
    + for_each_present_cpu(i) {
    + sysdev = get_cpu_sysdev(i);
    + sysdev_remove_file(sysdev, &attr_deconfigure);
    + }
    + }
    +}
    diff --git a/include/acpi/processor.h b/include/acpi/processor.h
    index 06ebb6e..071fd42 100644
    --- a/include/acpi/processor.h
    +++ b/include/acpi/processor.h
    @@ -289,6 +289,12 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx
    }
    #endif

    +#ifdef CONFIG_ACPI_DECONFIGURE_CPU
    +/* in processor_deconfigure.c */
    +void __init acpi_processor_deconfigure_init(void);
    +void acpi_processor_deconfigure_exit(void);
    +#endif
    +
    /* in processor_perflib.c */

    #ifdef CONFIG_CPU_FREQ

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  2. Re: [PATCH 14/14] ACPI: Provide /sys/devices/system/cpu/cpuN/deconfigure

    Alex Chiang wrote:
    > Provide a new sysfs interface for CPU deconfiguration.
    >
    > Since no vendors can agree on terminology for related but slightly
    > different features, provide a method for a platform to implement
    > its own version of what it thinks 'deconfiguring' a CPU might be.
    >
    > Provide an HP-specific CPU deconfiguration implementation.


    Why are you ccing this to linux-arch? Dropped.

    What is the standard status of these new SCFG and ECFG tables? Have they
    been submitted for possible inclusion in ACPI? And is there a spec
    available? I can't say I'm really thrilled with having HP specific
    support in there.

    It would be better at least if you could reserve the table names and
    then drop the HP DMI check. This is needed anyways, otherwise the
    standard at some point could add different ECFG/SCFG tables.

    > + * After echo'ing 0 or 1 into deconfigure, cat'ing the file will
    > + * return the next boot's status. However, the CPU will not actually
    > + * be deconfigured until the next boot.


    Now that seems like weird semantics for a public fixed API. What happens
    when some other vendor adds hot deconfiguration?

    My feeling is that this seems to be overly specific to your BIOS
    and might better belong into some separate management tool. At least
    until we can define a nice general API for this with clear semantics.
    For what systems is this anyways?

    -Andi

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  3. Re: [PATCH 14/14] ACPI: Provide /sys/devices/system/cpu/cpuN/deconfigure

    * Andi Kleen :
    > Alex Chiang wrote:
    >> Provide a new sysfs interface for CPU deconfiguration.
    >>
    >> Since no vendors can agree on terminology for related but slightly
    >> different features, provide a method for a platform to implement
    >> its own version of what it thinks 'deconfiguring' a CPU might be.
    >>
    >> Provide an HP-specific CPU deconfiguration implementation.

    >
    > Why are you ccing this to linux-arch? Dropped.


    Hm, sorry.

    I thought it would have been weird to send patches 1-13 / 14 to
    linux-arch, but not send 14 / 14. Perhaps I should set a Reply-to:
    in the future?

    > What is the standard status of these new SCFG and ECFG tables?
    > Have they been submitted for possible inclusion in ACPI? And is
    > there a spec available? I can't say I'm really thrilled with
    > having HP specific support in there.
    >
    > It would be better at least if you could reserve the table
    > names and then drop the HP DMI check. This is needed anyways,
    > otherwise the standard at some point could add different
    > ECFG/SCFG tables.


    These are not new tables -- they are methods that live underneath
    processor objects in the namespace.

    Yes, they are specific to HP, but because they are methods, there
    shouldn't be any collision with other vendors defining methods
    with the same name (with the DMI check).

    >> + * After echo'ing 0 or 1 into deconfigure, cat'ing the file will
    >> + * return the next boot's status. However, the CPU will not actually
    >> + * be deconfigured until the next boot.

    >
    > Now that seems like weird semantics for a public fixed API.
    > What happens when some other vendor adds hot deconfiguration?


    Yeah, I'm not totally happy with it either. But I'd like to
    clarify -- are you concerned with the name of the interface
    (deconfigure) or the "nothing happens until next boot" behavior?

    Would it help if I renamed it to "enabled" and had something
    like:

    echo 0 > enabled
    echo 1 > enabled
    cat enabled

    And then that would map to vendor-specific behavior?

    Or is it really the "nothing happens until next boot" thing that
    bothers you?

    > My feeling is that this seems to be overly specific to your
    > BIOS and might better belong into some separate management
    > tool. At least until we can define a nice general API for this
    > with clear semantics.


    Well, life would be a lot easier if we had a generic way to poke
    at ACPI methods, but dev_acpi has been rejected multiple times.


    On a more serious note, my fear is that an interface like this is
    not going to have agreement / clear semantics for a long time
    because one vendor is going to want to call it 'deconfigured' and
    another one might want to call it 'disabled' and a third might
    want to call it 'puppy_dogs' and they'll all be kinda related but
    not exactly the same.

    That's why I was going down the road of creating at least one
    generic interface, but with vendor-specific semantics.

    Calling it 'enabled' might be a better idea.

    > For what systems is this anyways?


    We have HP ia64 systems shipping today that support this.

    Thanks.

    /ac

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

+ Reply to Thread