* Re: Regarding CPU idle C states
From: Zhichao Li @ 2012-03-30 15:48 UTC (permalink / raw)
To: Valentin, Eduardo; +Cc: ShuoX Liu, linux-pm
In-Reply-To: <CAGF5oy-igUy1GjB86hqnFF_ch5CqnDGO5rSJ_tQk1A6iammmpQ@mail.gmail.com>
Thanks for the email, Eduardo. It's useful.
Basically, we'd like to save power while maintaining performance in
storage systems with domain knowledge aware algorithm. Our previous
research papers can be found here:
http://www.fsl.cs.sunysb.edu/~zhicli/#_Publications
We can now start with the patch adding sysfs entry for C states and
provide kernel support, and try to play with them in the user level.
Regards,
On Fri, Mar 30, 2012 at 2:41 AM, Valentin, Eduardo
<eduardo.valentin@ti.com> wrote:
> Hello Zhichao,
>
> On Thu, Mar 29, 2012 at 11:58 PM, Zhichao Li <lzcmichael@gmail.com> wrote:
>> Hi,
>>
>> I am a third year PhD student working on power management in storage
>> systems, under the Linux platform.
>
> Good :-)
>
>>
>> We are exploring CPU DVFS, and also idle CPU C states. We figured out
>> that the scheduling of CPU frequencies is exported to user level with
>> the "userspace" governor. However, it seems the multiple idle C states
>> are only scheduled in the kernel space (governors like "menu" and
>> "ladder").
>
> OK. Which kind of exploration you are performing? Any published paper
> you would like to point?
>
>>
>> We wonder whether there is any existing kernel module or existing
>> kernel patch that can export the various idle CPU C states to the user
>> level for user's control as well. If you could guide us to such
>> code/patch, or if you have plan to do so, we'd be more than happy to
>> help you testing the code for various idle CPU C states in the user
>> level.
>
>
> Have you seen this patch?
> https://lkml.org/lkml/2012/3/5/30
>
> It's original purpose is for debugging. One can enable of disable the
> C states available. There has been some discussion about that patch
> regarding its usage for userspace based governors. But it should be
> enough for your purpose. In theory you could keep enabled only the C
> state you want to force to be reached.
>
>
>>
>> Thanks for your time. Appreciated it!
>>
>> Regards,
>>
>> --
>> Zhichao Li
>> File Systems and Storage Lab
>> Computer Science Department
>> Stony Brook University
>> _______________________________________________
>> linux-pm mailing list
>> linux-pm@lists.linux-foundation.org
>> https://lists.linuxfoundation.org/mailman/listinfo/linux-pm
>
>
>
> --
>
> Eduardo Valentin
--
Zhichao Li
File Systems and Storage Lab
Computer Science Department
Stony Brook University
^ permalink raw reply
* Re: [linux-pm] [PATCH 17/76] thermal_sys: convert printks to pr_<level>
From: Eduardo Valentin @ 2012-03-30 13:41 UTC (permalink / raw)
To: Len Brown
Cc: linux-acpi, linux-pm, Joe Perches, Len Brown, Andrew Morton,
Jesper Juhl, linux-kernel
In-Reply-To: <c5a01dd52dc4903772f464ea580895ccc36e911d.1333101989.git.len.brown@intel.com>
Hello Joe, Len,
On Fri, Mar 30, 2012 at 06:13:20AM -0400, Len Brown wrote:
> From: Joe Perches <joe@perches.com>
>
> Use the current logging style.
>
> Remove PREFIX, add pr_fmt, convert the printks. All dmesg output now
> prefixed with "thermal_sys: ".
>
> Signed-off-by: Joe Perches <joe@perches.com>
> Cc: Jesper Juhl <jj@chaosbits.net>
> Cc: Len Brown <lenb@kernel.org>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Len Brown <len.brown@intel.com>
> ---
> drivers/thermal/thermal_sys.c | 14 ++++++--------
> 1 file changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index db5d8f8..fab970d 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -23,6 +23,8 @@
> * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> */
>
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> #include <linux/module.h>
> #include <linux/device.h>
> #include <linux/err.h>
> @@ -39,8 +41,6 @@ MODULE_AUTHOR("Zhang Rui");
> MODULE_DESCRIPTION("Generic thermal management sysfs support");
> MODULE_LICENSE("GPL");
>
> -#define PREFIX "Thermal: "
> -
> struct thermal_cooling_device_instance {
> int id;
> char name[THERMAL_NAME_LENGTH];
> @@ -1023,8 +1023,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>
> if (tz->ops->get_temp(tz, &temp)) {
> /* get_temp failed - retry it later */
> - printk(KERN_WARNING PREFIX "failed to read out thermal zone "
> - "%d\n", tz->id);
> + pr_warn("failed to read out thermal zone %d\n", tz->id);
We should get the struct dev in thermal_zone_device, I think it makes more sense to use the dev_* helper functions.
> goto leave;
> }
>
> @@ -1039,9 +1038,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
> ret = tz->ops->notify(tz, count,
> trip_type);
> if (!ret) {
> - printk(KERN_EMERG
> - "Critical temperature reached (%ld C), shutting down.\n",
> - temp/1000);
> + pr_emerg("Critical temperature reached (%ld C), shutting down\n",
> + temp/1000);
dito.
> orderly_poweroff(true);
> }
> }
> @@ -1345,7 +1343,7 @@ int thermal_generate_netlink_event(u32 orig, enum events event)
>
> result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC);
> if (result)
> - printk(KERN_INFO "failed to send netlink event:%d", result);
> + pr_info("failed to send netlink event:%d\n", result);
Here we probably would want to do the same, but we don't have the reference for the thermal zone device.
The orig argument could probably be changed to a thermal zone device and the we use it's id as orig for the message.
What do you think?
>
> return result;
> }
> --
> 1.7.10.rc2.19.gfae9d
>
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/linux-pm
^ permalink raw reply
* Re: [PATCH 04/76] ACPICA: Fix regression in FADT revision checks
From: Josh Boyer @ 2012-03-30 13:14 UTC (permalink / raw)
To: Len Brown; +Cc: linux-acpi, linux-pm, linux-kernel, Julian Anastasov, Len Brown
In-Reply-To: <3e80acd1af40fcd91a200b0416a7616b20c5d647.1333101989.git.len.brown@intel.com>
On Fri, Mar 30, 2012 at 6:13 AM, Len Brown <lenb@kernel.org> wrote:
> From: Julian Anastasov <ja@ssi.bg>
>
> commit 64b3db22c04586997ab4be46dd5a5b99f8a2d390 (2.6.39),
> "Remove use of unreliable FADT revision field" causes regression
> for old P4 systems because now cst_control and other fields are
> not reset to 0.
>
> The effect is that acpi_processor_power_init will notice
> cst_control != 0 and a write to CST_CNT register is performed
> that should not happen. As result, the system oopses after the
> "No _CST, giving up" message, sometimes in acpi_ns_internalize_name,
> sometimes in acpi_ns_get_type, usually at random places. May be
> during migration to CPU 1 in acpi_processor_get_throttling.
>
> Every one of these settings help to avoid this problem:
> - acpi=off
> - processor.nocst=1
> - maxcpus=1
>
> The fix is to update acpi_gbl_FADT.header.length after
> the original value is used to check for old revisions.
>
> https://bugzilla.kernel.org/show_bug.cgi?id=42700
> https://bugzilla.redhat.com/show_bug.cgi?id=727865
>
> Signed-off-by: Julian Anastasov <ja@ssi.bg>
> Acked-by: Bob Moore <robert.moore@intel.com>
> Signed-off-by: Len Brown <len.brown@intel.com>
This one should go into the stable trees. The bug it fixes causes a
number of machines to not boot with anything newer than 2.6.38.
josh
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv2 0/5] coupled cpuidle state support
From: Santosh Shilimkar @ 2012-03-30 12:53 UTC (permalink / raw)
To: Colin Cross
Cc: Kevin Hilman, Len Brown, Kay Sievers, Greg Kroah-Hartman,
linux-kernel, Amit Kucheria, linux-pm, Arjan van de Ven, Rob Lee,
linux-arm-kernel
In-Reply-To: <CAMbhsRQAw2+as13NVvWkh7ojyRs+jNpFist2gmiiEY52U=o84A@mail.gmail.com>
Colin,
On Friday 16 March 2012 05:07 AM, Colin Cross wrote:
> On Wed, Mar 14, 2012 at 11:29 AM, Colin Cross <ccross@android.com> wrote:
[...]
>>
>> v2:
>> * removed the coupled lock, replacing it with atomic counters
>> * added a check for outstanding pokes before beginning the
>> final transition to avoid extra wakeups
>> * made the cpuidle_coupled struct completely private
>> * fixed kerneldoc comment formatting
>> * added a patch with a helper function for resynchronizing
>> cpus after aborting idle
>> * added a patch (not for merging) to add trace events for
>> verification and performance testing
>
> I forgot to mention, this patch series is on v3.3-rc7, and will
> conflict with the cpuidle timekeeping patches. If those go in first
> (which is likely), I will rework this series on top of it. I left it
> on v3.3-rc7 now to make testing easier.
I have re-based your series against Len Browns
next branch [1] which has time keeping and other cpuidle patches.
Have also folded the CPU hotplug fix which I posted in the
original coupled idle patch.
If you want, the updated branch can be pulled from:
git://gitorious.org/omap-sw-develoment/linux-omap-dev.git
for_3.5/coupled_cpuidle-rebase
Regards
Santosh
[1] Power Management
git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git
^ permalink raw reply
* Re: [PATCH 57/76] ACPI / Video: blacklist some samsung laptops
From: Len Brown @ 2012-03-30 12:16 UTC (permalink / raw)
To: Corentin Chary; +Cc: linux-acpi, linux-pm, linux-kernel, Matthew Garrett
In-Reply-To: <CAHR064iEVsoMiP1PYzXeZeZzOFCPTk1YDBty6nHAfzej2qh_qA@mail.gmail.com>
> Sorry for that but this patch was re-sent recently, and Matthew told
> me to do that this should be done in samsung-laptop.c instead.
Okay, I'll revert the (soon to be un-necessary) blacklist entries.
thanks,
-Len
^ permalink raw reply
* Re: [PATCH 57/76] ACPI / Video: blacklist some samsung laptops
From: Corentin Chary @ 2012-03-30 12:07 UTC (permalink / raw)
To: Len Brown; +Cc: linux-acpi, linux-pm, Matthew Garrett, linux-kernel, Len Brown
In-Reply-To: <0e569b120d19c35dcc4f5549956cd884c3241270.1333101989.git.len.brown@intel.com>
On Fri, Mar 30, 2012 at 12:14 PM, Len Brown <lenb@kernel.org> wrote:
> From: Corentin Chary <corentincj@iksaif.net>
>
> On these laptops, the ACPI video is not functional, and very unlikely
> to be fixed by the vendor. Note that intel_backlight works for some
> of these laptops, and the backlight from samsung-laptop always work.
>
> The good news is that newer laptops have functional ACPI video device
> and won't end up growing this list.
>
> Signed-off-by: Corentin Chary <corentincj@iksaif.net>
> Signed-off-by: Len Brown <len.brown@intel.com>
> ---
> drivers/acpi/video_detect.c | 49 +++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 49 insertions(+)
>
> diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
> index f3f0fe7..b6f6979 100644
> --- a/drivers/acpi/video_detect.c
> +++ b/drivers/acpi/video_detect.c
> @@ -132,6 +132,53 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
> return AE_OK;
> }
>
> +/* Force to use vendor driver when the ACPI device is known to be
> + * buggy */
> +static int video_detect_force_vendor(const struct dmi_system_id *d)
> +{
> + acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
> + return 0;
> +}
> +
> +static struct dmi_system_id video_detect_dmi_table[] = {
> + {
> + .callback = video_detect_force_vendor,
> + .ident = "N150P",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "N150P"),
> + DMI_MATCH(DMI_BOARD_NAME, "N150P"),
> + },
> + },
> + {
> + .callback = video_detect_force_vendor,
> + .ident = "N145P/N250P/N260P",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
> + DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
> + },
> + },
> + {
> + .callback = video_detect_force_vendor,
> + .ident = "N150/N210/N220",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
> + DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
> + },
> + },
> + {
> + .callback = video_detect_force_vendor,
> + .ident = "NF110/NF210/NF310",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
> + DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
> + },
> + },
> +};
> +
> /*
> * Returns the video capabilities of a specific ACPI graphics device
> *
> @@ -164,6 +211,8 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle)
> * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
> *}
> */
> +
> + dmi_check_system(video_detect_dmi_table);
> } else {
> status = acpi_bus_get_device(graphics_handle, &tmp_dev);
> if (ACPI_FAILURE(status)) {
> --
> 1.7.10.rc2.19.gfae9d
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Len,
Sorry for that but this patch was re-sent recently, and Matthew told
me to do that this should be done in samsung-laptop.c instead.
The resulting patch has been merged in Matthew's tree:
http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=blobdiff;f=drivers/platform/x86/samsung-laptop.c;h=e2a34b42ddc1d584b5333fe9921d0d2c2b12dda4;hp=4787afdf11dc20e69af8fe5324366d4bd65aeb98;hb=a979e2e2af7d5b4bb3b20f6a716c627bb23a6753;hpb=5719b81988f3c24ff694dc3a37e35b35630a3966
One of these patches should be reverted, but which one ?
Note that apple-gmux and acer-wmi are also using the
acpi_video_unregister() trick in linux-next.
Thanks,
--
Corentin Chary
http://xf.iksaif.net
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-pm
^ permalink raw reply
* Re: [PATCH] cpuidle : use percpu cpuidle in the core code
From: Srivatsa S. Bhat @ 2012-03-30 11:59 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: linux-pm, linaro-dev, patches
In-Reply-To: <4F759CDE.9060108@linaro.org>
On 03/30/2012 05:15 PM, Daniel Lezcano wrote:
> On 03/30/2012 01:25 PM, Srivatsa S. Bhat wrote:
>> On 03/30/2012 04:18 PM, Daniel Lezcano wrote:
>>
>>> The usual cpuidle initialization routines are to register the
>>> driver, then register a cpuidle device per cpu.
>>>
>>> With the device's state count default initialization with the
>>> driver's state count, the code initialization remains mostly the
>>> same in the different drivers.
>>>
>>> We can then add a new function 'cpuidle_register' where we register
>>> the driver and the devices. These devices can be defined in a global
>>> static variable in cpuidle.c. We will be able to factor out and
>>> remove a lot of duplicate lines of code.
>>>
>>> As we still have some drivers, with different initialization routines,
>>> we keep 'cpuidle_register_driver' and 'cpuidle_register_device' as low
>>> level initialization routines to do some specific operations on the
>>> cpuidle devices.
>>>
>>> Signed-off-by: Daniel Lezcano<daniel.lezcano@linaro.org>
>>> ---
>>> drivers/cpuidle/cpuidle.c | 34 ++++++++++++++++++++++++++++++++++
>>> include/linux/cpuidle.h | 3 +++
>>> 2 files changed, 37 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
>>> index b8a1faf..2a174e8 100644
>>> --- a/drivers/cpuidle/cpuidle.c
>>> +++ b/drivers/cpuidle/cpuidle.c
>>> @@ -23,6 +23,7 @@
>>> #include "cpuidle.h"
>>>
>>> DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
>>> +DEFINE_PER_CPU(struct cpuidle_device, cpuidle_device);
>>>
>>> DEFINE_MUTEX(cpuidle_lock);
>>> LIST_HEAD(cpuidle_detected_devices);
>>> @@ -391,6 +392,39 @@ int cpuidle_register_device(struct
>>> cpuidle_device *dev)
>>>
>>> EXPORT_SYMBOL_GPL(cpuidle_register_device);
>>>
>>> +int cpuidle_register(struct cpuidle_driver *drv)
>>> +{
>>> + int ret, cpu;
>>> + struct cpuidle_device *dev;
>>> +
>>> + ret = cpuidle_register_driver(drv);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + for_each_online_cpu(cpu) {
>>> + dev =&per_cpu(cpuidle_device, cpu);
>>> + dev->cpu = cpu;
>>> +
>>> + ret = cpuidle_register_device(dev);
>>> + if (ret)
>>> + goto out_unregister;
>>> + }
>>> +
>>
>>
>> Isn't this racy with respect to CPU hotplug?
>
> No, I don't think so. Do you see a race ?
Well, that depends on when/where this function gets called.
This patch introduces the function. Where is the caller?
As of now, if you are calling this in boot-up code, its not racy.
However, there have been attempts to speed up boot times by trying
to online cpus in parallel with the rest of the kernel initialization[1].
In that case, unless your call is an early init call, it can race
with CPU hotplug.
[1]. https://lkml.org/lkml/2012/1/30/647
>
>>> +out:
>>> + return ret;
>>> +
>>> +out_unregister:
>>> + for_each_online_cpu(cpu) {
>>> + dev =&per_cpu(cpuidle_device, cpu);
>>> + cpuidle_unregister_device(dev);
>>> + }
>>> +
>>
>>
>> This could be improved I guess.. What if the registration fails
>> for the first cpu itself? Then looping over entire online cpumask
>> would be a waste of time..
>
> Certainly in a critical section that would make sense, but for 4,8 or 16
> cpus in an initialization path at boot time... Anyway, I can add what is
> proposed in https://lkml.org/lkml/2012/3/22/143.
>
What about servers with a lot more CPUs, like say 128 or even more? :-)
Moreover I don't see any downsides to the optimization. So should be good
to add it in any case...
Regards,
Srivatsa S. Bhat
>
>> Here is a discussion on some very similar code:
>> https://lkml.org/lkml/2012/3/22/72
>> https://lkml.org/lkml/2012/3/22/143
>>
>>> + cpuidle_unregister_driver(drv);
>>> +
>>> + goto out;
>>> +}
>>> +EXPORT_SYMBOL_GPL(cpuidle_register);
>>> +
>>> /**
>>> * cpuidle_unregister_device - unregisters a CPU's idle PM feature
>>> * @dev: the cpu
>>> diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
>>> index f3ebbba..17e3d33 100644
>>> --- a/include/linux/cpuidle.h
>>> +++ b/include/linux/cpuidle.h
>>> @@ -133,6 +133,7 @@ struct cpuidle_driver {
>>> #ifdef CONFIG_CPU_IDLE
>>> extern void disable_cpuidle(void);
>>> extern int cpuidle_idle_call(void);
>>> +extern int cpuidle_register(struct cpuidle_driver *drv);
>>> extern int cpuidle_register_driver(struct cpuidle_driver *drv);
>>> struct cpuidle_driver *cpuidle_get_driver(void);
>>> extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
>>> @@ -150,6 +151,8 @@ extern int cpuidle_wrap_enter(struct
>>> cpuidle_device *dev,
>>> #else
>>> static inline void disable_cpuidle(void) { }
>>> static inline int cpuidle_idle_call(void) { return -ENODEV; }
>>> +static inline int cpuidle_register(struct cpuidle_driver *drv)
>>> +{return -ENODEV; }
>>> static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
>>> {return -ENODEV; }
>>> static inline struct cpuidle_driver *cpuidle_get_driver(void)
>>> {return NULL; }
>>
>>
^ permalink raw reply
* Re: [PATCH] cpuidle : use percpu cpuidle in the core code
From: Daniel Lezcano @ 2012-03-30 11:45 UTC (permalink / raw)
To: Srivatsa S. Bhat; +Cc: linux-pm, patches, linaro-dev
In-Reply-To: <4F759838.4060007@linux.vnet.ibm.com>
On 03/30/2012 01:25 PM, Srivatsa S. Bhat wrote:
> On 03/30/2012 04:18 PM, Daniel Lezcano wrote:
>
>> The usual cpuidle initialization routines are to register the
>> driver, then register a cpuidle device per cpu.
>>
>> With the device's state count default initialization with the
>> driver's state count, the code initialization remains mostly the
>> same in the different drivers.
>>
>> We can then add a new function 'cpuidle_register' where we register
>> the driver and the devices. These devices can be defined in a global
>> static variable in cpuidle.c. We will be able to factor out and
>> remove a lot of duplicate lines of code.
>>
>> As we still have some drivers, with different initialization routines,
>> we keep 'cpuidle_register_driver' and 'cpuidle_register_device' as low
>> level initialization routines to do some specific operations on the
>> cpuidle devices.
>>
>> Signed-off-by: Daniel Lezcano<daniel.lezcano@linaro.org>
>> ---
>> drivers/cpuidle/cpuidle.c | 34 ++++++++++++++++++++++++++++++++++
>> include/linux/cpuidle.h | 3 +++
>> 2 files changed, 37 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
>> index b8a1faf..2a174e8 100644
>> --- a/drivers/cpuidle/cpuidle.c
>> +++ b/drivers/cpuidle/cpuidle.c
>> @@ -23,6 +23,7 @@
>> #include "cpuidle.h"
>>
>> DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
>> +DEFINE_PER_CPU(struct cpuidle_device, cpuidle_device);
>>
>> DEFINE_MUTEX(cpuidle_lock);
>> LIST_HEAD(cpuidle_detected_devices);
>> @@ -391,6 +392,39 @@ int cpuidle_register_device(struct cpuidle_device *dev)
>>
>> EXPORT_SYMBOL_GPL(cpuidle_register_device);
>>
>> +int cpuidle_register(struct cpuidle_driver *drv)
>> +{
>> + int ret, cpu;
>> + struct cpuidle_device *dev;
>> +
>> + ret = cpuidle_register_driver(drv);
>> + if (ret)
>> + return ret;
>> +
>> + for_each_online_cpu(cpu) {
>> + dev =&per_cpu(cpuidle_device, cpu);
>> + dev->cpu = cpu;
>> +
>> + ret = cpuidle_register_device(dev);
>> + if (ret)
>> + goto out_unregister;
>> + }
>> +
>
>
> Isn't this racy with respect to CPU hotplug?
No, I don't think so. Do you see a race ?
>> +out:
>> + return ret;
>> +
>> +out_unregister:
>> + for_each_online_cpu(cpu) {
>> + dev =&per_cpu(cpuidle_device, cpu);
>> + cpuidle_unregister_device(dev);
>> + }
>> +
>
>
> This could be improved I guess.. What if the registration fails
> for the first cpu itself? Then looping over entire online cpumask
> would be a waste of time..
Certainly in a critical section that would make sense, but for 4,8 or 16
cpus in an initialization path at boot time... Anyway, I can add what is
proposed in https://lkml.org/lkml/2012/3/22/143.
Thanks
-- Daniel
> Here is a discussion on some very similar code:
> https://lkml.org/lkml/2012/3/22/72
> https://lkml.org/lkml/2012/3/22/143
>
>> + cpuidle_unregister_driver(drv);
>> +
>> + goto out;
>> +}
>> +EXPORT_SYMBOL_GPL(cpuidle_register);
>> +
>> /**
>> * cpuidle_unregister_device - unregisters a CPU's idle PM feature
>> * @dev: the cpu
>> diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
>> index f3ebbba..17e3d33 100644
>> --- a/include/linux/cpuidle.h
>> +++ b/include/linux/cpuidle.h
>> @@ -133,6 +133,7 @@ struct cpuidle_driver {
>> #ifdef CONFIG_CPU_IDLE
>> extern void disable_cpuidle(void);
>> extern int cpuidle_idle_call(void);
>> +extern int cpuidle_register(struct cpuidle_driver *drv);
>> extern int cpuidle_register_driver(struct cpuidle_driver *drv);
>> struct cpuidle_driver *cpuidle_get_driver(void);
>> extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
>> @@ -150,6 +151,8 @@ extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
>> #else
>> static inline void disable_cpuidle(void) { }
>> static inline int cpuidle_idle_call(void) { return -ENODEV; }
>> +static inline int cpuidle_register(struct cpuidle_driver *drv)
>> +{return -ENODEV; }
>> static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
>> {return -ENODEV; }
>> static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
>
>
>
> Regards,
> Srivatsa S. Bhat
>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-pm
^ permalink raw reply
* Re: [PATCH] cpuidle : use percpu cpuidle in the core code
From: Srivatsa S. Bhat @ 2012-03-30 11:25 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: linux-pm, patches, linaro-dev
In-Reply-To: <1333104499-8627-1-git-send-email-daniel.lezcano@linaro.org>
On 03/30/2012 04:18 PM, Daniel Lezcano wrote:
> The usual cpuidle initialization routines are to register the
> driver, then register a cpuidle device per cpu.
>
> With the device's state count default initialization with the
> driver's state count, the code initialization remains mostly the
> same in the different drivers.
>
> We can then add a new function 'cpuidle_register' where we register
> the driver and the devices. These devices can be defined in a global
> static variable in cpuidle.c. We will be able to factor out and
> remove a lot of duplicate lines of code.
>
> As we still have some drivers, with different initialization routines,
> we keep 'cpuidle_register_driver' and 'cpuidle_register_device' as low
> level initialization routines to do some specific operations on the
> cpuidle devices.
>
> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> drivers/cpuidle/cpuidle.c | 34 ++++++++++++++++++++++++++++++++++
> include/linux/cpuidle.h | 3 +++
> 2 files changed, 37 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
> index b8a1faf..2a174e8 100644
> --- a/drivers/cpuidle/cpuidle.c
> +++ b/drivers/cpuidle/cpuidle.c
> @@ -23,6 +23,7 @@
> #include "cpuidle.h"
>
> DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
> +DEFINE_PER_CPU(struct cpuidle_device, cpuidle_device);
>
> DEFINE_MUTEX(cpuidle_lock);
> LIST_HEAD(cpuidle_detected_devices);
> @@ -391,6 +392,39 @@ int cpuidle_register_device(struct cpuidle_device *dev)
>
> EXPORT_SYMBOL_GPL(cpuidle_register_device);
>
> +int cpuidle_register(struct cpuidle_driver *drv)
> +{
> + int ret, cpu;
> + struct cpuidle_device *dev;
> +
> + ret = cpuidle_register_driver(drv);
> + if (ret)
> + return ret;
> +
> + for_each_online_cpu(cpu) {
> + dev = &per_cpu(cpuidle_device, cpu);
> + dev->cpu = cpu;
> +
> + ret = cpuidle_register_device(dev);
> + if (ret)
> + goto out_unregister;
> + }
> +
Isn't this racy with respect to CPU hotplug?
> +out:
> + return ret;
> +
> +out_unregister:
> + for_each_online_cpu(cpu) {
> + dev = &per_cpu(cpuidle_device, cpu);
> + cpuidle_unregister_device(dev);
> + }
> +
This could be improved I guess.. What if the registration fails
for the first cpu itself? Then looping over entire online cpumask
would be a waste of time..
Here is a discussion on some very similar code:
https://lkml.org/lkml/2012/3/22/72
https://lkml.org/lkml/2012/3/22/143
> + cpuidle_unregister_driver(drv);
> +
> + goto out;
> +}
> +EXPORT_SYMBOL_GPL(cpuidle_register);
> +
> /**
> * cpuidle_unregister_device - unregisters a CPU's idle PM feature
> * @dev: the cpu
> diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
> index f3ebbba..17e3d33 100644
> --- a/include/linux/cpuidle.h
> +++ b/include/linux/cpuidle.h
> @@ -133,6 +133,7 @@ struct cpuidle_driver {
> #ifdef CONFIG_CPU_IDLE
> extern void disable_cpuidle(void);
> extern int cpuidle_idle_call(void);
> +extern int cpuidle_register(struct cpuidle_driver *drv);
> extern int cpuidle_register_driver(struct cpuidle_driver *drv);
> struct cpuidle_driver *cpuidle_get_driver(void);
> extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
> @@ -150,6 +151,8 @@ extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
> #else
> static inline void disable_cpuidle(void) { }
> static inline int cpuidle_idle_call(void) { return -ENODEV; }
> +static inline int cpuidle_register(struct cpuidle_driver *drv)
> +{return -ENODEV; }
> static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
> {return -ENODEV; }
> static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
Regards,
Srivatsa S. Bhat
^ permalink raw reply
* [PATCH] cpuidle : use percpu cpuidle in the core code
From: Daniel Lezcano @ 2012-03-30 10:48 UTC (permalink / raw)
To: lenb; +Cc: linux-pm, linaro-dev, patches
The usual cpuidle initialization routines are to register the
driver, then register a cpuidle device per cpu.
With the device's state count default initialization with the
driver's state count, the code initialization remains mostly the
same in the different drivers.
We can then add a new function 'cpuidle_register' where we register
the driver and the devices. These devices can be defined in a global
static variable in cpuidle.c. We will be able to factor out and
remove a lot of duplicate lines of code.
As we still have some drivers, with different initialization routines,
we keep 'cpuidle_register_driver' and 'cpuidle_register_device' as low
level initialization routines to do some specific operations on the
cpuidle devices.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/cpuidle/cpuidle.c | 34 ++++++++++++++++++++++++++++++++++
include/linux/cpuidle.h | 3 +++
2 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index b8a1faf..2a174e8 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -23,6 +23,7 @@
#include "cpuidle.h"
DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+DEFINE_PER_CPU(struct cpuidle_device, cpuidle_device);
DEFINE_MUTEX(cpuidle_lock);
LIST_HEAD(cpuidle_detected_devices);
@@ -391,6 +392,39 @@ int cpuidle_register_device(struct cpuidle_device *dev)
EXPORT_SYMBOL_GPL(cpuidle_register_device);
+int cpuidle_register(struct cpuidle_driver *drv)
+{
+ int ret, cpu;
+ struct cpuidle_device *dev;
+
+ ret = cpuidle_register_driver(drv);
+ if (ret)
+ return ret;
+
+ for_each_online_cpu(cpu) {
+ dev = &per_cpu(cpuidle_device, cpu);
+ dev->cpu = cpu;
+
+ ret = cpuidle_register_device(dev);
+ if (ret)
+ goto out_unregister;
+ }
+
+out:
+ return ret;
+
+out_unregister:
+ for_each_online_cpu(cpu) {
+ dev = &per_cpu(cpuidle_device, cpu);
+ cpuidle_unregister_device(dev);
+ }
+
+ cpuidle_unregister_driver(drv);
+
+ goto out;
+}
+EXPORT_SYMBOL_GPL(cpuidle_register);
+
/**
* cpuidle_unregister_device - unregisters a CPU's idle PM feature
* @dev: the cpu
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index f3ebbba..17e3d33 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -133,6 +133,7 @@ struct cpuidle_driver {
#ifdef CONFIG_CPU_IDLE
extern void disable_cpuidle(void);
extern int cpuidle_idle_call(void);
+extern int cpuidle_register(struct cpuidle_driver *drv);
extern int cpuidle_register_driver(struct cpuidle_driver *drv);
struct cpuidle_driver *cpuidle_get_driver(void);
extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
@@ -150,6 +151,8 @@ extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
#else
static inline void disable_cpuidle(void) { }
static inline int cpuidle_idle_call(void) { return -ENODEV; }
+static inline int cpuidle_register(struct cpuidle_driver *drv)
+{return -ENODEV; }
static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
{return -ENODEV; }
static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
--
1.7.5.4
^ permalink raw reply related
* [PATCH 76/76] ACPI throttling: fix endian bug in acpi_read_throttling_status()
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Dan Carpenter, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Dan Carpenter <dan.carpenter@oracle.com>
Using a u64 here creates an endian bug. We store a u32 number in the
top byte which is a larger number than intended on big endian systems.
There is no reason to use a 64 bit data type here, I guess it was just
an oversight.
I removed the initialization to zero as well. It's needed with a u64
but with a u32, the variable gets initialized properly inside the call
to acpi_os_read_port().
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/processor_throttling.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 605a295..1d02b7b 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -769,7 +769,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr,
u64 *value)
{
u32 bit_width, bit_offset;
- u64 ptc_value;
+ u32 ptc_value;
u64 ptc_mask;
struct acpi_processor_throttling *throttling;
int ret = -1;
@@ -777,12 +777,11 @@ static int acpi_read_throttling_status(struct acpi_processor *pr,
throttling = &pr->throttling;
switch (throttling->status_register.space_id) {
case ACPI_ADR_SPACE_SYSTEM_IO:
- ptc_value = 0;
bit_width = throttling->status_register.bit_width;
bit_offset = throttling->status_register.bit_offset;
acpi_os_read_port((acpi_io_address) throttling->status_register.
- address, (u32 *) &ptc_value,
+ address, &ptc_value,
(u32) (bit_width + bit_offset));
ptc_mask = (1 << bit_width) - 1;
*value = (u64) ((ptc_value >> bit_offset) & ptc_mask);
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 75/76] Disable MCP limit exceeded messages from Intel IPS driver
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Andi Kleen, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Andi Kleen <ak@linux.intel.com>
On a system on the thermal limit these are quite noisy and flood the logs.
Better would be a counter anyways. But given that we don't even have
anything for normal throttling this doesn't seem to be urgent either.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/platform/x86/intel_ips.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index 88a98cf..f7ba316 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -609,25 +609,16 @@ static bool mcp_exceeded(struct ips_driver *ips)
bool ret = false;
u32 temp_limit;
u32 avg_power;
- const char *msg = "MCP limit exceeded: ";
spin_lock_irqsave(&ips->turbo_status_lock, flags);
temp_limit = ips->mcp_temp_limit * 100;
- if (ips->mcp_avg_temp > temp_limit) {
- dev_info(&ips->dev->dev,
- "%sAvg temp %u, limit %u\n", msg, ips->mcp_avg_temp,
- temp_limit);
+ if (ips->mcp_avg_temp > temp_limit)
ret = true;
- }
avg_power = ips->cpu_avg_power + ips->mch_avg_power;
- if (avg_power > ips->mcp_power_limit) {
- dev_info(&ips->dev->dev,
- "%sAvg power %u, limit %u\n", msg, avg_power,
- ips->mcp_power_limit);
+ if (avg_power > ips->mcp_power_limit)
ret = true;
- }
spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 74/76] ACPI: Add support for exposing BGRT data
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Len Brown, linux-kernel, Matthew Garrett
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Matthew Garrett <mjg@redhat.com>
ACPI 5.0 adds the BGRT, a table that contains a pointer to the firmware
boot splash and associated metadata. This simple driver exposes it via
/sys/firmware/acpi in order to allow bootsplash applications to draw their
splash around the firmware image and reduce the number of jarring graphical
transitions during boot.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
Documentation/ABI/testing/sysfs-firmware-acpi | 20 +++
drivers/acpi/Kconfig | 9 ++
drivers/acpi/Makefile | 1 +
drivers/acpi/bgrt.c | 175 +++++++++++++++++++++++++
4 files changed, 205 insertions(+)
create mode 100644 drivers/acpi/bgrt.c
diff --git a/Documentation/ABI/testing/sysfs-firmware-acpi b/Documentation/ABI/testing/sysfs-firmware-acpi
index 4f9ba3c..dd930c8 100644
--- a/Documentation/ABI/testing/sysfs-firmware-acpi
+++ b/Documentation/ABI/testing/sysfs-firmware-acpi
@@ -1,3 +1,23 @@
+What: /sys/firmware/acpi/bgrt/
+Date: January 2012
+Contact: Matthew Garrett <mjg@redhat.com>
+Description:
+ The BGRT is an ACPI 5.0 feature that allows the OS
+ to obtain a copy of the firmware boot splash and
+ some associated metadata. This is intended to be used
+ by boot splash applications in order to interact with
+ the firmware boot splash in order to avoid jarring
+ transitions.
+
+ image: The image bitmap. Currently a 32-bit BMP.
+ status: 1 if the image is valid, 0 if firmware invalidated it.
+ type: 0 indicates image is in BMP format.
+ version: The version of the BGRT. Currently 1.
+ xoffset: The number of pixels between the left of the screen
+ and the left edge of the image.
+ yoffset: The number of pixels between the top of the screen
+ and the top edge of the image.
+
What: /sys/firmware/acpi/interrupts/
Date: February 2008
Contact: Len Brown <lenb@kernel.org>
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 7556913..47768ff 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -384,6 +384,15 @@ config ACPI_CUSTOM_METHOD
load additional kernel modules after boot, this feature may be used
to override that restriction).
+config ACPI_BGRT
+ tristate "Boottime Graphics Resource Table support"
+ default n
+ help
+ This driver adds support for exposing the ACPI Boottime Graphics
+ Resource Table, which allows the operating system to obtain
+ data from the firmware boot splash. It will appear under
+ /sys/firmware/acpi/bgrt/ .
+
source "drivers/acpi/apei/Kconfig"
endif # ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 1567028..47199e2 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_HED) += hed.o
obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
+obj-$(CONFIG_ACPI_BGRT) += bgrt.o
# processor has its own "processor." module_param namespace
processor-y := processor_driver.o processor_throttling.o
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c
new file mode 100644
index 0000000..8cf6c46
--- /dev/null
+++ b/drivers/acpi/bgrt.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2012 Red Hat, Inc <mjg@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+
+static struct acpi_table_bgrt *bgrt_tab;
+static struct kobject *bgrt_kobj;
+
+struct bmp_header {
+ u16 id;
+ u32 size;
+} __attribute ((packed));
+
+static struct bmp_header bmp_header;
+
+static ssize_t show_version(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->version);
+}
+static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
+
+static ssize_t show_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->status);
+}
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
+static ssize_t show_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_type);
+}
+static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
+
+static ssize_t show_xoffset(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_x);
+}
+static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL);
+
+static ssize_t show_yoffset(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_y);
+}
+static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL);
+
+static ssize_t show_image(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t off, size_t count)
+{
+ int size = attr->size;
+ void __iomem *image = attr->private;
+
+ if (off >= size) {
+ count = 0;
+ } else {
+ if (off + count > size)
+ count = size - off;
+
+ memcpy_fromio(buf, image+off, count);
+ }
+
+ return count;
+}
+
+static struct bin_attribute image_attr = {
+ .attr = {
+ .name = "image",
+ .mode = S_IRUGO,
+ },
+ .read = show_image,
+};
+
+static struct attribute *bgrt_attributes[] = {
+ &dev_attr_version.attr,
+ &dev_attr_status.attr,
+ &dev_attr_type.attr,
+ &dev_attr_xoffset.attr,
+ &dev_attr_yoffset.attr,
+ NULL,
+};
+
+static struct attribute_group bgrt_attribute_group = {
+ .attrs = bgrt_attributes,
+};
+
+static int __init bgrt_init(void)
+{
+ acpi_status status;
+ int ret;
+ void __iomem *bgrt;
+
+ if (acpi_disabled)
+ return -ENODEV;
+
+ status = acpi_get_table("BGRT", 0,
+ (struct acpi_table_header **)&bgrt_tab);
+
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ sysfs_bin_attr_init(&image_attr);
+
+ bgrt = ioremap(bgrt_tab->image_address, sizeof(struct bmp_header));
+
+ if (!bgrt) {
+ ret = -EINVAL;
+ goto out_err;
+ }
+
+ memcpy_fromio(&bmp_header, bgrt, sizeof(bmp_header));
+ image_attr.size = bmp_header.size;
+ iounmap(bgrt);
+
+ image_attr.private = ioremap(bgrt_tab->image_address, image_attr.size);
+
+ if (!image_attr.private) {
+ ret = -EINVAL;
+ goto out_err;
+ }
+
+
+ bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj);
+ if (!bgrt_kobj) {
+ ret = -EINVAL;
+ goto out_iounmap;
+ }
+
+ ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group);
+ if (ret)
+ goto out_kobject;
+
+ ret = sysfs_create_bin_file(bgrt_kobj, &image_attr);
+ if (ret)
+ goto out_group;
+
+ return 0;
+
+out_group:
+ sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
+out_kobject:
+ kobject_put(bgrt_kobj);
+out_iounmap:
+ iounmap(image_attr.private);
+out_err:
+ return ret;
+}
+
+static void __exit bgrt_exit(void)
+{
+ iounmap(image_attr.private);
+ sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
+ sysfs_remove_bin_file(bgrt_kobj, &image_attr);
+}
+
+module_init(bgrt_init);
+module_exit(bgrt_exit);
+
+MODULE_AUTHOR("Matthew Garrett");
+MODULE_DESCRIPTION("BGRT boot graphic support");
+MODULE_LICENSE("GPL");
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 73/76] ACPI: export acpi_kobj
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Matthew Garrett, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Matthew Garrett <mjg@redhat.com>
Drivers may wish to add entries to /sys/firmware/acpi, so export acpi_kobj
in order to let them do that.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/bus.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 9ecec98..3263b68 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1010,6 +1010,7 @@ static int __init acpi_bus_init(void)
}
struct kobject *acpi_kobj;
+EXPORT_SYMBOL_GPL(acpi_kobj);
static int __init acpi_init(void)
{
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 72/76] ACPI: Fix logic for removing mappings in 'acpi_unmap'
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Len Brown, Myron Stowe, linux-kernel, Myron Stowe
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Myron Stowe <mstowe@redhat.com>
Make sure the removal of mappings uses the same logic that put the
mappings in place.
Signed-off-by: Myron Stowe <myron.stowe@redhat.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/osl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 412a1e0..5aef087 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -347,7 +347,7 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
unsigned long pfn;
pfn = pg_off >> PAGE_SHIFT;
- if (page_is_ram(pfn))
+ if (should_use_kmap(pfn))
kunmap(pfn_to_page(pfn));
else
iounmap(vaddr);
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 71/76] CPER failed to handle generic error records with multiple sections
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Len Brown, linux-kernel, Jiang Liu, Jiang Liu
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Jiang Liu <liuj97@gmail.com>
The function apei_estatus_print() and apei_estatus_check() forget to move ahead
the gdata pointer when dealing with multiple generic error data sections.
Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/apei/cper.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c
index 5d41894..e6defd8 100644
--- a/drivers/acpi/apei/cper.c
+++ b/drivers/acpi/apei/cper.c
@@ -362,6 +362,7 @@ void apei_estatus_print(const char *pfx,
gedata_len = gdata->error_data_length;
apei_estatus_print_section(pfx, gdata, sec_no);
data_len -= gedata_len + sizeof(*gdata);
+ gdata = (void *)(gdata + 1) + gedata_len;
sec_no++;
}
}
@@ -396,6 +397,7 @@ int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
if (gedata_len > data_len - sizeof(*gdata))
return -EINVAL;
data_len -= gedata_len + sizeof(*gdata);
+ gdata = (void *)(gdata + 1) + gedata_len;
}
if (data_len)
return -EINVAL;
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 70/76] ACPI: Clean redundant codes in scan.c
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Alex He, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Alex He <alex.he@amd.com>
Clean the redundant codes of apci_bus_get_power_flags().
Signed-off-by: Alex He <alex.he@amd.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/scan.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 8ab80ba..5d24a17 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -880,7 +880,6 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
int j;
device->power.flags.power_resources = 1;
- ps->flags.valid = 1;
for (j = 0; j < ps->resources.count; j++)
acpi_bus_add_power_resource(ps->resources.handles[j]);
}
@@ -888,10 +887,8 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
/* Evaluate "_PSx" to see if we can do explicit sets */
object_name[2] = 'S';
status = acpi_get_handle(device->handle, object_name, &handle);
- if (ACPI_SUCCESS(status)) {
+ if (ACPI_SUCCESS(status))
ps->flags.explicit_set = 1;
- ps->flags.valid = 1;
- }
/* State is valid if we have some power control */
if (ps->resources.count || ps->flags.explicit_set)
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 69/76] ACPI: Fix unprotected smp_processor_id() in acpi_processor_cst_has_changed()
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm
Cc: Paul E. McKenney, Paul E. McKenney, linux-kernel, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
The acpi_processor_cst_has_changed() function is invoked from a
CPU_ONLINE or CPU_DEAD function, which might well execute on CPU 0
even though the CPU being hotplugged is some other CPU. In addition,
acpi_processor_cst_has_changed() invokes smp_processor_id() without
protection, resulting in splats when onlining CPUs.
This commit therefore changes the smp_processor_id() to pr->id, as is
used elsewhere in the code, for example, in acpi_processor_add().
Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Tested-by: Yong Zhang <yong.zhang0@gmail.com>
Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/processor_idle.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 0e8e2de..9e57b06 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -1159,8 +1159,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
* to make the code that updates C-States be called once.
*/
- if (smp_processor_id() == 0 &&
- cpuidle_get_driver() == &acpi_idle_driver) {
+ if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) {
cpuidle_pause_and_lock();
/* Protect against cpu-hotplug */
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 68/76] ACPI: consistently use should_use_kmap()
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Jan Beulich, Jan Beulich, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Jan Beulich <JBeulich@suse.com>
... so that acpi_unmap()'s behavior gets in sync with acpi_map()'s.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/osl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 412a1e0..5aef087 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -347,7 +347,7 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
unsigned long pfn;
pfn = pg_off >> PAGE_SHIFT;
- if (page_is_ram(pfn))
+ if (should_use_kmap(pfn))
kunmap(pfn_to_page(pfn));
else
iounmap(vaddr);
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 67/76] PNPACPI: Fix device ref leaking in acpi_pnp_match
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Len Brown, Yinghai Lu, linux-kernel, stable
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Yinghai Lu <yinghai@kernel.org>
During testing pci root bus removal, found some root bus bridge is not freed.
If booting with pnpacpi=off, those hostbridge could be freed without problem.
It turns out that some devices reference are not released during acpi_pnp_match.
that match should not hold one device ref during every calling.
Add pu_device calling before returning.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: stable@vger.kernel.org
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/pnp/pnpacpi/core.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index b00c176..d21e8f5 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -321,9 +321,14 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp)
{
struct acpi_device *acpi = to_acpi_device(dev);
struct pnp_dev *pnp = _pnp;
+ struct device *physical_device;
+
+ physical_device = acpi_get_physical_device(acpi->handle);
+ if (physical_device)
+ put_device(physical_device);
/* true means it matched */
- return !acpi_get_physical_device(acpi->handle)
+ return !physical_device
&& compare_pnp_id(pnp->id, acpi_device_hid(acpi));
}
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 66/76] ACPI: Fix use-after-free in acpi_map_lsapic
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm
Cc: Len Brown, Alok N Kataria, Petr Vandrovec, linux-kernel
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Petr Vandrovec <petr@vmware.com>
When processor is being hot-added to the system, acpi_map_lsapic invokes
ACPI _MAT method to find APIC ID and flags, verifies that returned structure
is indeed ACPI's local APIC structure, and that flags contain MADT_ENABLED
bit. Then saves APIC ID, frees structure - and accesses structure when
computing arguments for acpi_register_lapic call. Which sometime leads
to acpi_register_lapic call being made with second argument zero, failing
to bring processor online with error 'Unable to map lapic to logical cpu
number'.
As lapic->lapic_flags & ACPI_MADT_ENABLED was already confirmed to be non-zero
few lines above, we can just pass unconditional ACPI_MADT_ENABLED to the
acpi_register_lapic.
Signed-off-by: Petr Vandrovec <petr@vmware.com>
Signed-off-by: Alok N Kataria <akataria@vmware.com>
Reviewed-by: Toshi Kani <toshi.kani@hp.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/kernel/acpi/boot.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index ce664f3..bbcc2c3 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -642,6 +642,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
kfree(buffer.pointer);
buffer.length = ACPI_ALLOCATE_BUFFER;
buffer.pointer = NULL;
+ lapic = NULL;
if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL))
goto out;
@@ -650,7 +651,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
goto free_tmp_map;
cpumask_copy(tmp_map, cpu_present_mask);
- acpi_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
+ acpi_register_lapic(physid, ACPI_MADT_ENABLED);
/*
* If mp_register_lapic successfully generates a new logical cpu
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 65/76] ACPI: processor_driver: add missing kfree
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Julia Lawall, linux-kernel, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Julia Lawall <Julia.Lawall@lip6.fr>
The function acpi_processor_add is stored in the ops.add field of a
acpi_driver structure. This function is then called in
acpi_bus_driver_init. On failure, this function clears the field
device->driver_data, but does not free its contents. Thus the free has to
be done by the add function. In acpi_processor_add, the corresponding
value is pr. This value is currently freed on failure before storing it in
device->driver_data, but not after. This free is added in the error
handling code at the end of the function. The per_cpu variable
processors is also cleared so that it does not refer to a dangling pointer.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
Reviewed-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Acked-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/processor_driver.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 8ae05ce..fce0066 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -535,8 +535,8 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
return -ENOMEM;
if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
- kfree(pr);
- return -ENOMEM;
+ result = -ENOMEM;
+ goto err_free_pr;
}
pr->handle = device->handle;
@@ -576,7 +576,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
dev = get_cpu_device(pr->id);
if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) {
result = -EFAULT;
- goto err_free_cpumask;
+ goto err_clear_processor;
}
/*
@@ -594,9 +594,15 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
err_remove_sysfs:
sysfs_remove_link(&device->dev.kobj, "sysdev");
+err_clear_processor:
+ /*
+ * processor_device_array is not cleared to allow checks for buggy BIOS
+ */
+ per_cpu(processors, pr->id) = NULL;
err_free_cpumask:
free_cpumask_var(pr->throttling.shared_cpu_map);
-
+err_free_pr:
+ kfree(pr);
return result;
}
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 64/76] ACPI, APEI: Fix incorrect APEI register bit width check and usage
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Len Brown, linux-kernel
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Gary Hade <garyhade@us.ibm.com>
The current code incorrectly assumes that
(1) the APEI register bit width is always 8, 16, 32, or 64 and
(2) the APEI register bit width is always equal to the APEI
register access width.
ERST serialization instructions entries such as:
[030h 0048 1] Action : 00 [Begin Write Operation]
[031h 0049 1] Instruction : 03 [Write Register Value]
[032h 0050 1] Flags (decoded below) : 01
Preserve Register Bits : 1
[033h 0051 1] Reserved : 00
[034h 0052 12] Register Region : [Generic Address Structure]
[034h 0052 1] Space ID : 00 [SystemMemory]
[035h 0053 1] Bit Width : 03
[036h 0054 1] Bit Offset : 00
[037h 0055 1] Encoded Access Width : 03 [DWord Access:32]
[038h 0056 8] Address : 000000007F2D7038
[040h 0064 8] Value : 0000000000000001
[048h 0072 8] Mask : 0000000000000007
break this assumption by yielding:
[Firmware Bug]: APEI: Invalid bit width in GAR [0x7f2d7038/3/0]
I have found no ACPI specification requirements corresponding
with the above assumptions. There is even a good example in
the Serialization Instruction Entries section (ACPI 4.0 section
17.4,1.2, ACPI 4.0a section 2.5.1.2, ACPI 5.0 section 18.5.1.2)
that mentions a serialization instruction with a bit range of
[6:2] which is 5 bits wide, _not_ 8, 16, 32, or 64 bits wide.
Compile and boot tested with 3.3.0-rc7 on a IBM HX5.
Signed-off-by: Gary Hade <garyhade@us.ibm.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/apei/apei-base.c | 61 +++++++++++++++++++++++++++--------------
1 file changed, 40 insertions(+), 21 deletions(-)
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index e5d53b7..1d3656f 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -558,33 +558,48 @@ void apei_resources_release(struct apei_resources *resources)
}
EXPORT_SYMBOL_GPL(apei_resources_release);
-static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
+static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
+ u32 *access_bit_width)
{
- u32 width, space_id;
+ u32 bit_width, bit_offset, access_size_code, space_id;
- width = reg->bit_width;
+ bit_width = reg->bit_width;
+ bit_offset = reg->bit_offset;
+ access_size_code = reg->access_width;
space_id = reg->space_id;
/* Handle possible alignment issues */
memcpy(paddr, ®->address, sizeof(*paddr));
if (!*paddr) {
pr_warning(FW_BUG APEI_PFX
- "Invalid physical address in GAR [0x%llx/%u/%u]\n",
- *paddr, width, space_id);
+ "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n",
+ *paddr, bit_width, bit_offset, access_size_code,
+ space_id);
return -EINVAL;
}
- if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) {
+ if (access_size_code < 1 || access_size_code > 4) {
pr_warning(FW_BUG APEI_PFX
- "Invalid bit width in GAR [0x%llx/%u/%u]\n",
- *paddr, width, space_id);
+ "Invalid access size code in GAR [0x%llx/%u/%u/%u/%u]\n",
+ *paddr, bit_width, bit_offset, access_size_code,
+ space_id);
+ return -EINVAL;
+ }
+ *access_bit_width = 1UL << (access_size_code + 2);
+
+ if ((bit_width + bit_offset) > *access_bit_width) {
+ pr_warning(FW_BUG APEI_PFX
+ "Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n",
+ *paddr, bit_width, bit_offset, access_size_code,
+ space_id);
return -EINVAL;
}
if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
pr_warning(FW_BUG APEI_PFX
- "Invalid address space type in GAR [0x%llx/%u/%u]\n",
- *paddr, width, space_id);
+ "Invalid address space type in GAR [0x%llx/%u/%u/%u/%u]\n",
+ *paddr, bit_width, bit_offset, access_size_code,
+ space_id);
return -EINVAL;
}
@@ -595,23 +610,25 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
int apei_read(u64 *val, struct acpi_generic_address *reg)
{
int rc;
+ u32 access_bit_width;
u64 address;
acpi_status status;
- rc = apei_check_gar(reg, &address);
+ rc = apei_check_gar(reg, &address, &access_bit_width);
if (rc)
return rc;
*val = 0;
switch(reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- status = acpi_os_read_memory64((acpi_physical_address)
- address, val, reg->bit_width);
+ status = acpi_os_read_memory64((acpi_physical_address) address,
+ val, access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
- status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
+ status = acpi_os_read_port(address, (u32 *)val,
+ access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
@@ -627,22 +644,23 @@ EXPORT_SYMBOL_GPL(apei_read);
int apei_write(u64 val, struct acpi_generic_address *reg)
{
int rc;
+ u32 access_bit_width;
u64 address;
acpi_status status;
- rc = apei_check_gar(reg, &address);
+ rc = apei_check_gar(reg, &address, &access_bit_width);
if (rc)
return rc;
switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- status = acpi_os_write_memory64((acpi_physical_address)
- address, val, reg->bit_width);
+ status = acpi_os_write_memory64((acpi_physical_address) address,
+ val, access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
- status = acpi_os_write_port(address, val, reg->bit_width);
+ status = acpi_os_write_port(address, val, access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
@@ -661,23 +679,24 @@ static int collect_res_callback(struct apei_exec_context *ctx,
struct apei_resources *resources = data;
struct acpi_generic_address *reg = &entry->register_region;
u8 ins = entry->instruction;
+ u32 access_bit_width;
u64 paddr;
int rc;
if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER))
return 0;
- rc = apei_check_gar(reg, &paddr);
+ rc = apei_check_gar(reg, &paddr, &access_bit_width);
if (rc)
return rc;
switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
return apei_res_add(&resources->iomem, paddr,
- reg->bit_width / 8);
+ access_bit_width / 8);
case ACPI_ADR_SPACE_SYSTEM_IO:
return apei_res_add(&resources->ioport, paddr,
- reg->bit_width / 8);
+ access_bit_width / 8);
default:
return -EINVAL;
}
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 63/76] Update documentation for parameter *notrigger* in einj.txt
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Chen Gong, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Chen Gong <gong.chen@linux.intel.com>
Add description of parameter notrigger in the einj.txt.
One can utilize this new parameter to do some SRAR injection
test. Pay attention, the operation is highly depended on the
BIOS implementation. If no proper BIOS supports it, even if
enabling this parameter, expected result will not happen.
v2:
Update the documentation suggested by Tony
Suggested-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Chen Gong <gong.chen@linux.intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
Documentation/acpi/apei/einj.txt | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/acpi/apei/einj.txt b/Documentation/acpi/apei/einj.txt
index e7cc363..e20b6da 100644
--- a/Documentation/acpi/apei/einj.txt
+++ b/Documentation/acpi/apei/einj.txt
@@ -53,6 +53,14 @@ directory apei/einj. The following files are provided.
This file is used to set the second error parameter value. Effect of
parameter depends on error_type specified.
+- notrigger
+ The EINJ mechanism is a two step process. First inject the error, then
+ perform some actions to trigger it. Setting "notrigger" to 1 skips the
+ trigger phase, which *may* allow the user to cause the error in some other
+ context by a simple access to the cpu, memory location, or device that is
+ the target of the error injection. Whether this actually works depends
+ on what operations the BIOS actually includes in the trigger phase.
+
BIOS versions based in the ACPI 4.0 specification have limited options
to control where the errors are injected. Your BIOS may support an
extension (enabled with the param_extension=1 module parameter, or
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 62/76] ACPI, APEI, EINJ, new parameter to control trigger action
From: Len Brown @ 2012-03-30 10:14 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Chen Gong, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Chen Gong <gong.chen@linux.intel.com>
Some APEI firmware implementation will access injected address
specified in param1 to trigger the error when injecting memory
error, which means if one SRAR error is injected, the crash
always happens because it is executed in kernel context. This
new parameter can disable trigger action and control is taken
over by the user. In this way, an SRAR error can happen in user
context instead of crashing the system. This function is highly
depended on BIOS implementation so please ensure you know the
BIOS trigger procedure before you enable this switch.
v2:
notrigger should be created together with param1/param2
Tested-by: Tony Luck <tony.luck@lintel.com>
Signed-off-by: Chen Gong <gong.chen@linux.intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/apei/einj.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 3d3816f..8e17936 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -74,6 +74,8 @@ struct vendor_error_type_extension {
u8 reserved[3];
};
+static u32 notrigger;
+
static u32 vendor_flags;
static struct debugfs_blob_wrapper vendor_blob;
static char vendor_dev[64];
@@ -496,9 +498,11 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
if (rc)
return rc;
trigger_paddr = apei_exec_ctx_get_output(&ctx);
- rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
- if (rc)
- return rc;
+ if (notrigger == 0) {
+ rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
+ if (rc)
+ return rc;
+ }
rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
return rc;
@@ -700,6 +704,11 @@ static int __init einj_init(void)
einj_debug_dir, &error_param2);
if (!fentry)
goto err_unmap;
+
+ fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
+ einj_debug_dir, ¬rigger);
+ if (!fentry)
+ goto err_unmap;
}
if (vendor_dev[0]) {
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox