提交 f0f1b336 编写于 作者: L Linus Torvalds

Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (112 commits)
  ACPI: fix build warning
  Revert "cpuidle: build fix for non-x86"
  ACPI: update intrd DSDT override console messages
  ACPI: update DSDT override documentation
  ACPI: Add "acpi_no_initrd_override" kernel parameter
  ACPI: its a directory not a folder....
  ACPI: misc cleanups
  ACPI: add missing prink prefix strings
  ACPI: cleanup acpi.h
  ACPICA: fix CONFIG_ACPI_DEBUG_FUNC_TRACE build
  ACPI: video: Ignore ACPI video devices that aren't present in hardware
  ACPI: video: reset brightness on resume
  ACPI: video: call ACPI notifier chain for ACPI video notifications
  ACPI: create notifier chain to get hotkey events to graphics driver
  ACPI: video: delete unused display switch on hotkey event code
  ACPI: video: create "brightness_switch_enabled" modparam
  cpuidle: Add a poll_idle method
  ACPI: cpuidle: Support C1 idle time accounting
  ACPI: enable MWAIT for C1 idle
  ACPI: idle: Fix acpi_safe_halt usages and interrupt enabling/disabling
  ...
......@@ -14,6 +14,7 @@ Following translations are available on the WWW:
- this file.
ABI/
- info on kernel <-> userspace ABI and relative interface stability.
BUG-HUNTING
- brute force method of doing binary search of patches to find bug.
Changes
......@@ -66,6 +67,8 @@ VGA-softcursor.txt
- how to change your VGA cursor from a blinking underscore.
accounting/
- documentation on accounting and taskstats.
acpi/
- info on ACPI-specific hooks in the kernel.
aoe/
- description of AoE (ATA over Ethernet) along with config examples.
applying-patches.txt
......
What: /sys/firmware/acpi/interrupts/
Date: February 2008
Contact: Len Brown <lenb@kernel.org>
Description:
All ACPI interrupts are handled via a single IRQ,
the System Control Interrupt (SCI), which appears
as "acpi" in /proc/interrupts.
However, one of the main functions of ACPI is to make
the platform understand random hardware without
special driver support. So while the SCI handles a few
well known (fixed feature) interrupts sources, such
as the power button, it can also handle a variable
number of a "General Purpose Events" (GPE).
A GPE vectors to a specified handler in AML, which
can do a anything the BIOS writer wants from
OS context. GPE 0x12, for example, would vector
to a level or edge handler called _L12 or _E12.
The handler may do its business and return.
Or the handler may send send a Notify event
to a Linux device driver registered on an ACPI device,
such as a battery, or a processor.
To figure out where all the SCI's are coming from,
/sys/firmware/acpi/interrupts contains a file listing
every possible source, and the count of how many
times it has triggered.
$ cd /sys/firmware/acpi/interrupts
$ grep . *
error:0
ff_gbl_lock:0
ff_pmtimer:0
ff_pwr_btn:0
ff_rt_clk:0
ff_slp_btn:0
gpe00:0
gpe01:0
gpe02:0
gpe03:0
gpe04:0
gpe05:0
gpe06:0
gpe07:0
gpe08:0
gpe09:174
gpe0A:0
gpe0B:0
gpe0C:0
gpe0D:0
gpe0E:0
gpe0F:0
gpe10:0
gpe11:60
gpe12:0
gpe13:0
gpe14:0
gpe15:0
gpe16:0
gpe17:0
gpe18:0
gpe19:7
gpe1A:0
gpe1B:0
gpe1C:0
gpe1D:0
gpe1E:0
gpe1F:0
gpe_all:241
sci:241
sci - The total number of times the ACPI SCI
has claimed an interrupt.
gpe_all - count of SCI caused by GPEs.
gpeXX - count for individual GPE source
ff_gbl_lock - Global Lock
ff_pmtimer - PM Timer
ff_pwr_btn - Power Button
ff_rt_clk - Real Time Clock
ff_slp_btn - Sleep Button
error - an interrupt that can't be accounted for above.
Root has permission to clear any of these counters. Eg.
# echo 0 > gpe11
All counters can be cleared by clearing the total "sci":
# echo 0 > sci
None of these counters has an effect on the function
of the system, they are simply statistics.
Linux supports two methods of overriding the BIOS DSDT:
CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel.
CONFIG_ACPI_CUSTOM_DSDT_INITRD adds the image to the initrd.
When to use these methods is described in detail on the
Linux/ACPI home page:
http://www.lesswatts.org/projects/acpi/overridingDSDT.php
Note that if both options are used, the DSDT supplied
by the INITRD method takes precedence.
Documentation/initramfs-add-dsdt.sh is provided for convenience
for use with the CONFIG_ACPI_CUSTOM_DSDT_INITRD method.
#!/bin/bash
# Adds a DSDT file to the initrd (if it's an initramfs)
# first argument is the name of archive
# second argument is the name of the file to add
# The file will be copied as /DSDT.aml
# 20060126: fix "Premature end of file" with some old cpio (Roland Robic)
# 20060205: this time it should really work
# check the arguments
if [ $# -ne 2 ]; then
program_name=$(basename $0)
echo "\
$program_name: too few arguments
Usage: $program_name initrd-name.img DSDT-to-add.aml
Adds a DSDT file to an initrd (in initramfs format)
initrd-name.img: filename of the initrd in initramfs format
DSDT-to-add.aml: filename of the DSDT file to add
" 1>&2
exit 1
fi
# we should check it's an initramfs
tempcpio=$(mktemp -d)
# cleanup on exit, hangup, interrupt, quit, termination
trap 'rm -rf $tempcpio' 0 1 2 3 15
# extract the archive
gunzip -c "$1" > "$tempcpio"/initramfs.cpio || exit 1
# copy the DSDT file at the root of the directory so that we can call it "/DSDT.aml"
cp -f "$2" "$tempcpio"/DSDT.aml
# add the file
cd "$tempcpio"
(echo DSDT.aml | cpio --quiet -H newc -o -A -O "$tempcpio"/initramfs.cpio) || exit 1
cd "$OLDPWD"
# re-compress the archive
gzip -c "$tempcpio"/initramfs.cpio > "$1"
/sys/module/acpi/parameters/:
trace_method_name
The AML method name that the user wants to trace
trace_debug_layer
The temporary debug_layer used when tracing the method.
Using 0xffffffff by default if it is 0.
trace_debug_level
The temporary debug_level used when tracing the method.
Using 0x00ffffff by default if it is 0.
trace_state
The status of the tracing feature.
"enabled" means this feature is enabled
and the AML method is traced every time it's executed.
"1" means this feature is enabled and the AML method
will only be traced during the next execution.
"disabled" means this feature is disabled.
Users can enable/disable this debug tracing feature by
"echo string > /sys/module/acpi/parameters/trace_state".
"string" should be one of "enable", "disable" and "1".
......@@ -147,8 +147,10 @@ and is between 256 and 4096 characters. It is defined in the file
default: 0
acpi_sleep= [HW,ACPI] Sleep options
Format: { s3_bios, s3_mode }
See Documentation/power/video.txt
Format: { s3_bios, s3_mode, s3_beep }
See Documentation/power/video.txt for s3_bios and s3_mode.
s3_beep is for debugging; it makes the PC's speaker beep
as soon as the kernel's real-mode entry point is called.
acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode
Format: { level | edge | high | low }
......@@ -175,6 +177,9 @@ and is between 256 and 4096 characters. It is defined in the file
acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT
acpi_no_initrd_override [KNL,ACPI]
Disable loading custom ACPI tables from the initramfs
acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS
Format: To spoof as Windows 98: ="Microsoft Windows"
......
......@@ -386,6 +386,11 @@ before suspending; then remount them after resuming.
There is a work-around for this problem. For more information, see
Documentation/usb/persist.txt.
Q: Can I suspend-to-disk using a swap partition under LVM?
A: No. You can suspend successfully, but you'll not be able to
resume. uswsusp should be able to work with LVM. See suspend.sf.net.
Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were
compiled with the similar configuration files. Anyway I found that
suspend to disk (and resume) is much slower on 2.6.16 compared to
......
Generic Thermal Sysfs driver How To
=========================
Written by Sujith Thomas <sujith.thomas@intel.com>, Zhang Rui <rui.zhang@intel.com>
Updated: 2 January 2008
Copyright (c) 2008 Intel Corporation
0. Introduction
The generic thermal sysfs provides a set of interfaces for thermal zone devices (sensors)
and thermal cooling devices (fan, processor...) to register with the thermal management
solution and to be a part of it.
This how-to focusses on enabling new thermal zone and cooling devices to participate
in thermal management.
This solution is platform independent and any type of thermal zone devices and
cooling devices should be able to make use of the infrastructure.
The main task of the thermal sysfs driver is to expose thermal zone attributes as well
as cooling device attributes to the user space.
An intelligent thermal management application can make decisions based on inputs
from thermal zone attributes (the current temperature and trip point temperature)
and throttle appropriate devices.
[0-*] denotes any positive number starting from 0
[1-*] denotes any positive number starting from 1
1. thermal sysfs driver interface functions
1.1 thermal zone device interface
1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *name, int trips,
void *devdata, struct thermal_zone_device_ops *ops)
This interface function adds a new thermal zone device (sensor) to
/sys/class/thermal folder as thermal_zone[0-*].
It tries to bind all the thermal cooling devices registered at the same time.
name: the thermal zone name.
trips: the total number of trip points this thermal zone supports.
devdata: device private data
ops: thermal zone device callbacks.
.bind: bind the thermal zone device with a thermal cooling device.
.unbind: unbing the thermal zone device with a thermal cooling device.
.get_temp: get the current temperature of the thermal zone.
.get_mode: get the current mode (user/kernel) of the thermal zone.
"kernel" means thermal management is done in kernel.
"user" will prevent kernel thermal driver actions upon trip points
so that user applications can take charge of thermal management.
.set_mode: set the mode (user/kernel) of the thermal zone.
.get_trip_type: get the type of certain trip point.
.get_trip_temp: get the temperature above which the certain trip point
will be fired.
1.1.2 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
This interface function removes the thermal zone device.
It deletes the corresponding entry form /sys/class/thermal folder and unbind all
the thermal cooling devices it uses.
1.2 thermal cooling device interface
1.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name,
void *devdata, struct thermal_cooling_device_ops *)
This interface function adds a new thermal cooling device (fan/processor/...) to
/sys/class/thermal/ folder as cooling_device[0-*].
It tries to bind itself to all the thermal zone devices register at the same time.
name: the cooling device name.
devdata: device private data.
ops: thermal cooling devices callbacks.
.get_max_state: get the Maximum throttle state of the cooling device.
.get_cur_state: get the Current throttle state of the cooling device.
.set_cur_state: set the Current throttle state of the cooling device.
1.2.2 void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
This interface function remove the thermal cooling device.
It deletes the corresponding entry form /sys/class/thermal folder and unbind
itself from all the thermal zone devices using it.
1.3 interface for binding a thermal zone device with a thermal cooling device
1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
int trip, struct thermal_cooling_device *cdev);
This interface function bind a thermal cooling device to the certain trip point
of a thermal zone device.
This function is usually called in the thermal zone device .bind callback.
tz: the thermal zone device
cdev: thermal cooling device
trip: indicates which trip point the cooling devices is associated with
in this thermal zone.
1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
int trip, struct thermal_cooling_device *cdev);
This interface function unbind a thermal cooling device from the certain trip point
of a thermal zone device.
This function is usually called in the thermal zone device .unbind callback.
tz: the thermal zone device
cdev: thermal cooling device
trip: indicates which trip point the cooling devices is associated with
in this thermal zone.
2. sysfs attributes structure
RO read only value
RW read/write value
All thermal sysfs attributes will be represented under /sys/class/thermal
/sys/class/thermal/
Thermal zone device sys I/F, created once it's registered:
|thermal_zone[0-*]:
|-----type: Type of the thermal zone
|-----temp: Current temperature
|-----mode: Working mode of the thermal zone
|-----trip_point_[0-*]_temp: Trip point temperature
|-----trip_point_[0-*]_type: Trip point type
Thermal cooling device sys I/F, created once it's registered:
|cooling_device[0-*]:
|-----type : Type of the cooling device(processor/fan/...)
|-----max_state: Maximum cooling state of the cooling device
|-----cur_state: Current cooling state of the cooling device
These two dynamic attributes are created/removed in pairs.
They represent the relationship between a thermal zone and its associated cooling device.
They are created/removed for each
thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful exection.
|thermal_zone[0-*]
|-----cdev[0-*]: The [0-*]th cooling device in the current thermal zone
|-----cdev[0-*]_trip_point: Trip point that cdev[0-*] is associated with
***************************
* Thermal zone attributes *
***************************
type Strings which represent the thermal zone type.
This is given by thermal zone driver as part of registration.
Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
RO
Optional
temp Current temperature as reported by thermal zone (sensor)
Unit: degree celsius
RO
Required
mode One of the predifned values in [kernel, user]
This file gives information about the algorithm
that is currently managing the thermal zone.
It can be either default kernel based algorithm
or user space application.
RW
Optional
kernel = Thermal management in kernel thermal zone driver.
user = Preventing kernel thermal zone driver actions upon
trip points so that user application can take full
charge of the thermal management.
trip_point_[0-*]_temp The temperature above which trip point will be fired
Unit: degree celsius
RO
Optional
trip_point_[0-*]_type Strings which indicate the type of the trip point
Eg. it can be one of critical, hot, passive,
active[0-*] for ACPI thermal zone.
RO
Optional
cdev[0-*] Sysfs link to the thermal cooling device node where the sys I/F
for cooling device throttling control represents.
RO
Optional
cdev[0-*]_trip_point The trip point with which cdev[0-*] is assocated in this thermal zone
-1 means the cooling device is not associated with any trip point.
RO
Optional
******************************
* Cooling device attributes *
******************************
type String which represents the type of device
eg: For generic ACPI: this should be "Fan",
"Processor" or "LCD"
eg. For memory controller device on intel_menlow platform:
this should be "Memory controller"
RO
Optional
max_state The maximum permissible cooling state of this cooling device.
RO
Required
cur_state The current cooling state of this cooling device.
the value can any integer numbers between 0 and max_state,
cur_state == 0 means no cooling
cur_state == max_state means the maximum cooling.
RW
Required
3. A simple implementation
ACPI thermal zone may support multiple trip points like critical/hot/passive/active.
If an ACPI thermal zone supports critical, passive, active[0] and active[1] at the same time,
it may register itself as a thermale_zone_device (thermal_zone1) with 4 trip points in all.
It has one processor and one fan, which are both registered as thermal_cooling_device.
If the processor is listed in _PSL method, and the fan is listed in _AL0 method,
the sys I/F structure will be built like this:
/sys/class/thermal:
|thermal_zone1:
|-----type: ACPI thermal zone
|-----temp: 37
|-----mode: kernel
|-----trip_point_0_temp: 100
|-----trip_point_0_type: critical
|-----trip_point_1_temp: 80
|-----trip_point_1_type: passive
|-----trip_point_2_temp: 70
|-----trip_point_2_type: active[0]
|-----trip_point_3_temp: 60
|-----trip_point_3_type: active[1]
|-----cdev0: --->/sys/class/thermal/cooling_device0
|-----cdev0_trip_point: 1 /* cdev0 can be used for passive */
|-----cdev1: --->/sys/class/thermal/cooling_device3
|-----cdev1_trip_point: 2 /* cdev1 can be used for active[0]*/
|cooling_device0:
|-----type: Processor
|-----max_state: 8
|-----cur_state: 0
|cooling_device3:
|-----type: Fan
|-----max_state: 2
|-----cur_state: 0
ThinkPad ACPI Extras Driver
Version 0.17
October 04th, 2007
Version 0.19
January 06th, 2008
Borislav Deianov <borislav@users.sf.net>
Henrique de Moraes Holschuh <hmh@hmh.eng.br>
......@@ -215,6 +215,11 @@ The following commands can be written to the /proc/acpi/ibm/hotkey file:
... any other 8-hex-digit mask ...
echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
The procfs interface does not support NVRAM polling control. So as to
maintain maximum bug-to-bug compatibility, it does not report any masks,
nor does it allow one to manipulate the hot key mask when the firmware
does not support masks at all, even if NVRAM polling is in use.
sysfs notes:
hotkey_bios_enabled:
......@@ -231,17 +236,26 @@ sysfs notes:
to this value.
hotkey_enable:
Enables/disables the hot keys feature, and reports
current status of the hot keys feature.
Enables/disables the hot keys feature in the ACPI
firmware, and reports current status of the hot keys
feature. Has no effect on the NVRAM hot key polling
functionality.
0: disables the hot keys feature / feature disabled
1: enables the hot keys feature / feature enabled
hotkey_mask:
bit mask to enable driver-handling and ACPI event
generation for each hot key (see above). Returns the
current status of the hot keys mask, and allows one to
modify it.
bit mask to enable driver-handling (and depending on
the firmware, ACPI event generation) for each hot key
(see above). Returns the current status of the hot keys
mask, and allows one to modify it.
Note: when NVRAM polling is active, the firmware mask
will be different from the value returned by
hotkey_mask. The driver will retain enabled bits for
hotkeys that are under NVRAM polling even if the
firmware refuses them, and will not set these bits on
the firmware hot key mask.
hotkey_all_mask:
bit mask that should enable event reporting for all
......@@ -257,12 +271,48 @@ sysfs notes:
handled by the firmware anyway. Echo it to
hotkey_mask above, to use.
hotkey_source_mask:
bit mask that selects which hot keys will the driver
poll the NVRAM for. This is auto-detected by the driver
based on the capabilities reported by the ACPI firmware,
but it can be overridden at runtime.
Hot keys whose bits are set in both hotkey_source_mask
and also on hotkey_mask are polled for in NVRAM. Only a
few hot keys are available through CMOS NVRAM polling.
Warning: when in NVRAM mode, the volume up/down/mute
keys are synthesized according to changes in the mixer,
so you have to use volume up or volume down to unmute,
as per the ThinkPad volume mixer user interface. When
in ACPI event mode, volume up/down/mute are reported as
separate events, but this behaviour may be corrected in
future releases of this driver, in which case the
ThinkPad volume mixer user interface semanthics will be
enforced.
hotkey_poll_freq:
frequency in Hz for hot key polling. It must be between
0 and 25 Hz. Polling is only carried out when strictly
needed.
Setting hotkey_poll_freq to zero disables polling, and
will cause hot key presses that require NVRAM polling
to never be reported.
Setting hotkey_poll_freq too low will cause repeated
pressings of the same hot key to be misreported as a
single key press, or to not even be detected at all.
The recommended polling frequency is 10Hz.
hotkey_radio_sw:
if the ThinkPad has a hardware radio switch, this
attribute will read 0 if the switch is in the "radios
disabled" postition, and 1 if the switch is in the
"radios enabled" position.
This attribute has poll()/select() support.
hotkey_report_mode:
Returns the state of the procfs ACPI event report mode
filter for hot keys. If it is set to 1 (the default),
......@@ -277,6 +327,25 @@ sysfs notes:
May return -EPERM (write access locked out by module
parameter) or -EACCES (read-only).
wakeup_reason:
Set to 1 if the system is waking up because the user
requested a bay ejection. Set to 2 if the system is
waking up because the user requested the system to
undock. Set to zero for normal wake-ups or wake-ups
due to unknown reasons.
This attribute has poll()/select() support.
wakeup_hotunplug_complete:
Set to 1 if the system was waken up because of an
undock or bay ejection request, and that request
was sucessfully completed. At this point, it might
be useful to send the system back to sleep, at the
user's choice. Refer to HKEY events 0x4003 and
0x3003, below.
This attribute has poll()/select() support.
input layer notes:
A Hot key is mapped to a single input layer EV_KEY event, possibly
......@@ -427,6 +496,23 @@ Non hot-key ACPI HKEY event map:
The above events are not propagated by the driver, except for legacy
compatibility purposes when hotkey_report_mode is set to 1.
0x2304 System is waking up from suspend to undock
0x2305 System is waking up from suspend to eject bay
0x2404 System is waking up from hibernation to undock
0x2405 System is waking up from hibernation to eject bay
The above events are never propagated by the driver.
0x3003 Bay ejection (see 0x2x05) complete, can sleep again
0x4003 Undocked (see 0x2x04), can sleep again
0x5009 Tablet swivel: switched to tablet mode
0x500A Tablet swivel: switched to normal mode
0x500B Tablet pen insterted into its storage bay
0x500C Tablet pen removed from its storage bay
0x5010 Brightness level changed (newer Lenovo BIOSes)
The above events are propagated by the driver.
Compatibility notes:
ibm-acpi and thinkpad-acpi 0.15 (mainline kernels before 2.6.23) never
......@@ -1263,3 +1349,17 @@ Sysfs interface changelog:
and the hwmon class for libsensors4 (lm-sensors 3)
compatibility. Moved all hwmon attributes to this
new platform device.
0x020100: Marker for thinkpad-acpi with hot key NVRAM polling
support. If you must, use it to know you should not
start an userspace NVRAM poller (allows to detect when
NVRAM is compiled out by the user because it is
unneeded/undesired in the first place).
0x020101: Marker for thinkpad-acpi with hot key NVRAM polling
and proper hotkey_mask semanthics (version 8 of the
NVRAM polling patch). Some development snapshots of
0.18 had an earlier version that did strange things
to hotkey_mask.
0x020200: Add poll()/select() support to the following attributes:
hotkey_radio_sw, wakeup_hotunplug_complete, wakeup_reason
......@@ -202,6 +202,13 @@ L: linux-scsi@vger.kernel.org
W: http://www.adaptec.com/
S: Supported
ACER WMI LAPTOP EXTRAS
P: Carlos Corbacho
M: carlos@strangeworlds.co.uk
L: aceracpi@googlegroups.com (subscribers-only)
W: http://code.google.com/p/aceracpi
S: Maintained
ACPI
P: Len Brown
M: len.brown@intel.com
......@@ -252,6 +259,13 @@ L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
S: Supported
ACPI WMI DRIVER
P: Carlos Corbacho
M: carlos@strangeworlds.co.uk
L: linux-acpi@vger.kernel.org
W: http://www.lesswatts.org/projects/acpi/
S: Maintained
ADM1025 HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
......@@ -1790,6 +1804,11 @@ P: Jaroslav Kysela
M: perex@perex.cz
S: Maintained
HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
P: Carlos Corbacho
M: carlos@strangeworlds.co.uk
S: Odd Fixes
HPET: High Precision Event Timers driver (hpet.c)
P: Clemens Ladisch
M: clemens@ladisch.de
......
......@@ -45,6 +45,12 @@ static void init_intel_pdc(struct acpi_processor *pr)
buf[0] = ACPI_PDC_REVISION_ID;
buf[1] = 1;
buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
/*
* The default of PDC_SMP_T_SWCOORD bit is set for IA64 cpu so
* that OSPM is capable of native ACPI throttling software
* coordination using BIOS supplied _TSD info.
*/
buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
obj->type = ACPI_TYPE_BUFFER;
obj->buffer.length = 12;
......
......@@ -69,6 +69,20 @@ unsigned int acpi_cpei_phys_cpuid;
unsigned long acpi_wakeup_address = 0;
#ifdef CONFIG_IA64_GENERIC
static unsigned long __init acpi_find_rsdp(void)
{
unsigned long rsdp_phys = 0;
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
rsdp_phys = efi.acpi20;
else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
printk(KERN_WARNING PREFIX
"v1.0/r0.71 tables no longer supported\n");
return rsdp_phys;
}
#endif
const char __init *
acpi_get_sysname(void)
{
......@@ -152,7 +166,7 @@ int acpi_request_vector(u32 int_type)
return vector;
}
char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
{
return __va(phys_addr);
}
......@@ -601,8 +615,6 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)
IOSAPIC_LEVEL);
}
EXPORT_SYMBOL(acpi_register_gsi);
void acpi_unregister_gsi(u32 gsi)
{
if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
......@@ -611,8 +623,6 @@ void acpi_unregister_gsi(u32 gsi)
iosapic_unregister_intr(gsi);
}
EXPORT_SYMBOL(acpi_unregister_gsi);
static int __init acpi_parse_fadt(struct acpi_table_header *table)
{
struct acpi_table_header *fadt_header;
......@@ -631,18 +641,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
return 0;
}
unsigned long __init acpi_find_rsdp(void)
{
unsigned long rsdp_phys = 0;
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
rsdp_phys = efi.acpi20;
else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
printk(KERN_WARNING PREFIX
"v1.0/r0.71 tables no longer supported\n");
return rsdp_phys;
}
int __init acpi_boot_init(void)
{
......
......@@ -105,6 +105,9 @@ config GENERIC_TIME_VSYSCALL
bool
default X86_64
config ARCH_HAS_CPU_RELAX
def_bool y
config HAVE_SETUP_PER_CPU_AREA
def_bool X86_64
......
......@@ -78,7 +78,6 @@ int acpi_ht __initdata = 1; /* enable HT */
int acpi_lapic;
int acpi_ioapic;
int acpi_strict;
EXPORT_SYMBOL(acpi_strict);
u8 acpi_sci_flags __initdata;
int acpi_sci_override_gsi __initdata;
......@@ -106,7 +105,7 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
#ifdef CONFIG_X86_64
/* rely on all ACPI tables being in the direct mapping */
char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
{
if (!phys_addr || !size)
return NULL;
......@@ -131,7 +130,7 @@ char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
* from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and
* count idx down while incrementing the phys address.
*/
char *__acpi_map_table(unsigned long phys, unsigned long size)
char *__init __acpi_map_table(unsigned long phys, unsigned long size)
{
unsigned long base, offset, mapped_size;
int idx;
......@@ -490,8 +489,6 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)
return irq;
}
EXPORT_SYMBOL(acpi_register_gsi);
/*
* ACPI based hotplug support for CPU
*/
......@@ -587,25 +584,6 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
EXPORT_SYMBOL(acpi_unregister_ioapic);
static unsigned long __init
acpi_scan_rsdp(unsigned long start, unsigned long length)
{
unsigned long offset = 0;
unsigned long sig_len = sizeof("RSD PTR ") - 1;
/*
* Scan all 16-byte boundaries of the physical memory region for the
* RSDP signature.
*/
for (offset = 0; offset < length; offset += 16) {
if (strncmp((char *)(phys_to_virt(start) + offset), "RSD PTR ", sig_len))
continue;
return (start + offset);
}
return 0;
}
static int __init acpi_parse_sbf(struct acpi_table_header *table)
{
struct acpi_table_boot *sb;
......@@ -748,27 +726,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
return 0;
}
unsigned long __init acpi_find_rsdp(void)
{
unsigned long rsdp_phys = 0;
if (efi_enabled) {
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
return efi.acpi20;
else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
return efi.acpi;
}
/*
* Scan memory looking for the RSDP signature. First search EBDA (low
* memory) paragraphs and then search upper memory (E0000-FFFFF).
*/
rsdp_phys = acpi_scan_rsdp(0, 0x400);
if (!rsdp_phys)
rsdp_phys = acpi_scan_rsdp(0xE0000, 0x20000);
return rsdp_phys;
}
#ifdef CONFIG_X86_LOCAL_APIC
/*
* Parse LAPIC entries in MADT
......
......@@ -46,6 +46,12 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
buf[1] = 1;
buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
/*
* The default of PDC_SMP_T_SWCOORD bit is set for intel x86 cpu so
* that OSPM is capable of native ACPI throttling software
* coordination using BIOS supplied _TSD info.
*/
buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
if (cpu_has(c, X86_FEATURE_EST))
buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
......
......@@ -189,10 +189,7 @@ static unsigned int pentium4_get_frequency(void)
printk(KERN_DEBUG "speedstep-lib: couldn't detect FSB speed. Please send an e-mail to <linux@brodo.de>\n");
/* Multiplier. */
if (c->x86_model < 2)
mult = msr_lo >> 27;
else
mult = msr_lo >> 24;
mult = msr_lo >> 24;
dprintk("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n", fsb, mult, (fsb * mult));
......
......@@ -274,7 +274,7 @@ int __init get_memcfg_from_srat(void)
int tables = 0;
int i = 0;
rsdp_address = acpi_find_rsdp();
rsdp_address = acpi_os_get_root_pointer();
if (!rsdp_address) {
printk("%s: System description tables not found\n",
__FUNCTION__);
......
......@@ -60,6 +60,8 @@ source "drivers/power/Kconfig"
source "drivers/hwmon/Kconfig"
source "drivers/thermal/Kconfig"
source "drivers/watchdog/Kconfig"
source "drivers/ssb/Kconfig"
......
......@@ -65,6 +65,7 @@ obj-y += i2c/
obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_POWER_SUPPLY) += power/
obj-$(CONFIG_HWMON) += hwmon/
obj-$(CONFIG_THERMAL) += thermal/
obj-$(CONFIG_WATCHDOG) += watchdog/
obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_MD) += md/
......
......@@ -68,26 +68,28 @@ config ACPI_PROCFS
Say N to delete /proc/acpi/ files that have moved to /sys/
config ACPI_PROCFS_POWER
bool "Deprecated power /proc/acpi folders"
bool "Deprecated power /proc/acpi directories"
depends on PROC_FS
default y
---help---
For backwards compatibility, this option allows
deprecated power /proc/acpi/ folders to exist, even when
deprecated power /proc/acpi/ directories to exist, even when
they have been replaced by functions in /sys.
The deprecated folders (and their replacements) include:
The deprecated directories (and their replacements) include:
/proc/acpi/battery/* (/sys/class/power_supply/*)
/proc/acpi/ac_adapter/* (sys/class/power_supply/*)
This option has no effect on /proc/acpi/ folders
This option has no effect on /proc/acpi/ directories
and functions, which do not yet exist in /sys
Say N to delete power /proc/acpi/ folders that have moved to /sys/
Say N to delete power /proc/acpi/ directories that have moved to /sys/
config ACPI_SYSFS_POWER
bool "Future power /sys interface"
select POWER_SUPPLY
default y
---help---
Say N to disable power /sys interface
config ACPI_PROC_EVENT
bool "Deprecated /proc/acpi/event support"
depends on PROC_FS
......@@ -186,6 +188,7 @@ config ACPI_HOTPLUG_CPU
config ACPI_THERMAL
tristate "Thermal Zone"
depends on ACPI_PROCESSOR
select THERMAL
default y
help
This driver adds support for ACPI thermal zones. Most mobile and
......@@ -199,6 +202,16 @@ config ACPI_NUMA
depends on (X86 || IA64)
default y if IA64_GENERIC || IA64_SGI_SN2
config ACPI_WMI
tristate "WMI (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
This driver adds support for the ACPI-WMI mapper device (PNP0C14)
found on some systems.
NOTE: You will need another driver or userspace application on top of
this to actually use anything defined in the ACPI-WMI mapper.
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras"
depends on X86
......@@ -263,8 +276,10 @@ config ACPI_CUSTOM_DSDT
depends on !STANDALONE
default n
help
This option is to load a custom ACPI DSDT
If you don't know what that is, say N.
This option supports a custom DSDT by linking it into the kernel.
See Documentation/acpi/dsdt-override.txt
If unsure, say N.
config ACPI_CUSTOM_DSDT_FILE
string "Custom DSDT Table file to include"
......@@ -274,6 +289,17 @@ config ACPI_CUSTOM_DSDT_FILE
Enter the full path name to the file which includes the AmlCode
declaration.
config ACPI_CUSTOM_DSDT_INITRD
bool "Read Custom DSDT from initramfs"
depends on BLK_DEV_INITRD
default n
help
This option supports a custom DSDT by optionally loading it from initrd.
See Documentation/acpi/dsdt-override.txt
If you are not using this feature now, but may use it later,
it is safe to say Y here.
config ACPI_BLACKLIST_YEAR
int "Disable ACPI for systems before Jan 1st this year" if X86_32
default 0
......
......@@ -55,6 +55,7 @@ obj-$(CONFIG_ACPI_THERMAL) += thermal.o
obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
obj-$(CONFIG_ACPI_DEBUG) += debug.o
obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_WMI) += wmi.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
......
......@@ -142,6 +142,7 @@ struct asus_hotk {
xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
A4S, //Z81sp
//(Centrino)
F3Sa,
END_MODEL
} model; //Models currently supported
u16 event_count[128]; //count for each event TODO make this better
......@@ -405,7 +406,20 @@ static struct model_data model_conf[END_MODEL] = {
.brightness_get = "GPLV",
.mt_bt_switch = "BLED",
.mt_wled = "WLED"
}
},
{
.name = "F3Sa",
.mt_bt_switch = "BLED",
.mt_wled = "WLED",
.mt_mled = "MLED",
.brightness_get = "GPLV",
.brightness_set = "SPLV",
.mt_lcd_switch = "\\_SB.PCI0.SBRG.EC0._Q10",
.lcd_status = "\\_SB.PCI0.SBRG.EC0.RPIN",
.display_get = "\\ADVG",
.display_set = "SDSP",
},
};
......@@ -710,15 +724,8 @@ static int get_lcd_state(void)
{
int lcd = 0;
if (hotk->model != L3H) {
/* We don't have to check anything if we are here */
if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
printk(KERN_WARNING
"Asus ACPI: Error reading LCD status\n");
if (hotk->model == L2D)
lcd = ~lcd;
} else { /* L3H and the like have to be handled differently */
if (hotk->model == L3H) {
/* L3H and the like have to be handled differently */
acpi_status status = 0;
struct acpi_object_list input;
union acpi_object mt_params[2];
......@@ -745,6 +752,32 @@ static int get_lcd_state(void)
if (out_obj.type == ACPI_TYPE_INTEGER)
/* That's what the AML code does */
lcd = out_obj.integer.value >> 8;
} else if (hotk->model == F3Sa) {
unsigned long tmp;
union acpi_object param;
struct acpi_object_list input;
acpi_status status;
/* Read pin 11 */
param.type = ACPI_TYPE_INTEGER;
param.integer.value = 0x11;
input.count = 1;
input.pointer = &param;
status = acpi_evaluate_integer(NULL, hotk->methods->lcd_status,
&input, &tmp);
if (status != AE_OK)
return -1;
lcd = tmp;
} else {
/* We don't have to check anything if we are here */
if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
printk(KERN_WARNING
"Asus ACPI: Error reading LCD status\n");
if (hotk->model == L2D)
lcd = ~lcd;
}
return (lcd & 1);
......@@ -1134,6 +1167,8 @@ static int asus_model_match(char *model)
return W5A;
else if (strncmp(model, "A4S", 3) == 0)
return A4S;
else if (strncmp(model, "F3Sa", 4) == 0)
return F3Sa;
else
return END_MODEL;
}
......
......@@ -194,6 +194,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_MANUFACTURER:
val->strval = battery->oem_info;
break;
case POWER_SUPPLY_PROP_SERIAL_NUMBER:
val->strval = battery->serial_number;
break;
default:
return -EINVAL;
}
......@@ -212,6 +215,7 @@ static enum power_supply_property charge_battery_props[] = {
POWER_SUPPLY_PROP_CHARGE_NOW,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
POWER_SUPPLY_PROP_SERIAL_NUMBER,
};
static enum power_supply_property energy_battery_props[] = {
......@@ -226,6 +230,7 @@ static enum power_supply_property energy_battery_props[] = {
POWER_SUPPLY_PROP_ENERGY_NOW,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
POWER_SUPPLY_PROP_SERIAL_NUMBER,
};
#endif
......
......@@ -46,6 +46,12 @@ MODULE_LICENSE("GPL");
printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
static void bay_notify(acpi_handle handle, u32 event, void *data);
static const struct acpi_device_id bay_device_ids[] = {
{"LNXIOBAY", 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, bay_device_ids);
struct bay {
acpi_handle handle;
char *name;
......@@ -128,7 +134,7 @@ static ssize_t show_present(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay));
}
DEVICE_ATTR(present, S_IRUGO, show_present, NULL);
static DEVICE_ATTR(present, S_IRUGO, show_present, NULL);
/*
* write_eject - write method for "eject" file in sysfs
......@@ -144,7 +150,7 @@ static ssize_t write_eject(struct device *dev, struct device_attribute *attr,
eject_device(bay->handle);
return count;
}
DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject);
static DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject);
/**
* is_ata - see if a device is an ata device
......
......@@ -70,8 +70,6 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
/* IBM 600E - _ADR should return 7, but it returns 1 */
{"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal,
"Incorrect _ADR", 1},
{"ASUS\0\0", "P2B-S ", 0, ACPI_SIG_DSDT, all_versions,
"Bogus PCI routing", 1},
{""}
};
......@@ -208,33 +206,35 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
* Disable OSI(Linux) warnings on all "Acer, inc."
*
* _OSI(Linux) disables the latest Windows BIOS code:
* DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),
* DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"),
* DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
* DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"),
* DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"),
* _OSI(Linux) effect unknown:
* DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"),
*/
{
.callback = dmi_disable_osi_linux,
.ident = "Acer, inc.",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer, inc."),
},
},
/*
* note that dmi_check_system() uses strstr()
* to match sub-strings rather than !strcmp(),
* so "Acer" below matches "Acer, inc." above.
*/
/*
* Disable OSI(Linux) warnings on all "Acer"
*
* _OSI(Linux) effect unknown:
* DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
* DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
* DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"),
* DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"),
* DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"),
* DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"),
* DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"),
*
* _OSI(Linux) is a NOP:
* DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
*/
{
.callback = dmi_unknown_osi_linux,
.callback = dmi_disable_osi_linux,
.ident = "Acer",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
......@@ -242,21 +242,22 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
/*
* Disable OSI(Linux) warnings on all "Apple Computer, Inc."
* Disable OSI(Linux) warnings on all "Apple Inc."
*
* _OSI(Linux) confirmed to be a NOP:
* DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
* DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
* DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
* DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
* _OSI(Linux) effect unknown:
* DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"),
* DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
* DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
*/
{
.callback = dmi_disable_osi_linux,
.ident = "Apple",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
},
},
/*
......@@ -294,13 +295,13 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
* DMI_MATCH(DMI_BOARD_NAME, "IFL91"),
*/
{
.callback = dmi_unknown_osi_linux,
.callback = dmi_disable_osi_linux,
.ident = "Compal",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
},
},
{ /* OSI(Linux) touches USB, breaks suspend to disk */
{ /* OSI(Linux) touches USB, unknown side-effect */
.callback = dmi_disable_osi_linux,
.ident = "Dell Dimension 5150",
.matches = {
......@@ -310,7 +311,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
{ /* OSI(Linux) is a NOP */
.callback = dmi_disable_osi_linux,
.ident = "Dell",
.ident = "Dell i1501",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"),
......@@ -318,7 +319,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
{ /* OSI(Linux) effect unknown */
.callback = dmi_unknown_osi_linux,
.ident = "Dell",
.ident = "Dell Latitude D830",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"),
......@@ -326,7 +327,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
{ /* OSI(Linux) effect unknown */
.callback = dmi_unknown_osi_linux,
.ident = "Dell",
.ident = "Dell OP GX620",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"),
......@@ -334,15 +335,23 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
{ /* OSI(Linux) effect unknown */
.callback = dmi_unknown_osi_linux,
.ident = "Dell",
.ident = "Dell PE 1900",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"),
},
},
{ /* OSI(Linux) is a NOP */
.callback = dmi_disable_osi_linux,
.ident = "Dell PE R200",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R200"),
},
},
{ /* OSI(Linux) touches USB */
.callback = dmi_disable_osi_linux,
.ident = "Dell",
.ident = "Dell PR 390",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"),
......@@ -358,7 +367,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
{ /* OSI(Linux) effect unknown */
.callback = dmi_unknown_osi_linux,
.ident = "Dell",
.ident = "Dell PE SC440",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"),
......@@ -474,6 +483,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
*
* _OSI(Linux) confirmed to be a NOP:
* DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"),
* with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
*
* unknown:
* DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"),
* with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
*/
{
.callback = dmi_disable_osi_linux,
......@@ -516,7 +530,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
* DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"),
*/
{
.callback = dmi_unknown_osi_linux,
.callback = dmi_disable_osi_linux,
.ident = "Sony",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
......
......@@ -122,6 +122,31 @@ int acpi_bus_get_status(struct acpi_device *device)
EXPORT_SYMBOL(acpi_bus_get_status);
void acpi_bus_private_data_handler(acpi_handle handle,
u32 function, void *context)
{
return;
}
EXPORT_SYMBOL(acpi_bus_private_data_handler);
int acpi_bus_get_private_data(acpi_handle handle, void **data)
{
acpi_status status = AE_OK;
if (!*data)
return -EINVAL;
status = acpi_get_data(handle, acpi_bus_private_data_handler, data);
if (ACPI_FAILURE(status) || !*data) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
handle));
return -ENODEV;
}
return 0;
}
EXPORT_SYMBOL(acpi_bus_get_private_data);
/* --------------------------------------------------------------------------
Power Management
-------------------------------------------------------------------------- */
......@@ -366,7 +391,6 @@ int acpi_bus_receive_event(struct acpi_bus_event *event)
return 0;
}
EXPORT_SYMBOL(acpi_bus_receive_event);
#endif /* CONFIG_ACPI_PROC_EVENT */
/* --------------------------------------------------------------------------
......
......@@ -130,6 +130,63 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) {
module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644);
module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644);
static char trace_method_name[6];
module_param_string(trace_method_name, trace_method_name, 6, 0644);
static unsigned int trace_debug_layer;
module_param(trace_debug_layer, uint, 0644);
static unsigned int trace_debug_level;
module_param(trace_debug_level, uint, 0644);
static int param_set_trace_state(const char *val, struct kernel_param *kp)
{
int result = 0;
if (!strncmp(val, "enable", strlen("enable") - 1)) {
result = acpi_debug_trace(trace_method_name, trace_debug_level,
trace_debug_layer, 0);
if (result)
result = -EBUSY;
goto exit;
}
if (!strncmp(val, "disable", strlen("disable") - 1)) {
int name = 0;
result = acpi_debug_trace((char *)&name, trace_debug_level,
trace_debug_layer, 0);
if (result)
result = -EBUSY;
goto exit;
}
if (!strncmp(val, "1", 1)) {
result = acpi_debug_trace(trace_method_name, trace_debug_level,
trace_debug_layer, 1);
if (result)
result = -EBUSY;
goto exit;
}
result = -EINVAL;
exit:
return result;
}
static int param_get_trace_state(char *buffer, struct kernel_param *kp)
{
if (!acpi_gbl_trace_method_name)
return sprintf(buffer, "disable");
else {
if (acpi_gbl_trace_flags & 1)
return sprintf(buffer, "1");
else
return sprintf(buffer, "enable");
}
return 0;
}
module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
NULL, 0644);
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
......
......@@ -359,7 +359,9 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
status = acpi_os_validate_address(obj_desc->region.space_id,
obj_desc->region.address,
(acpi_size) obj_desc->region.length);
(acpi_size) obj_desc->region.length,
acpi_ut_get_node_name(node));
if (ACPI_FAILURE(status)) {
/*
* Invalid address/length. We will emit an error message and mark
......
......@@ -51,6 +51,12 @@ static struct atomic_notifier_head dock_notifier_list;
static struct platform_device *dock_device;
static char dock_device_name[] = "dock";
static const struct acpi_device_id dock_device_ids[] = {
{"LNXDOCK", 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, dock_device_ids);
struct dock_station {
acpi_handle handle;
unsigned long last_dock_time;
......@@ -680,7 +686,7 @@ static ssize_t show_docked(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
}
DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
/*
* show_flags - read method for flags file in sysfs
......@@ -691,7 +697,7 @@ static ssize_t show_flags(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
}
DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
/*
* write_undock - write method for "undock" file in sysfs
......@@ -707,7 +713,7 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
return ret ? ret: count;
}
DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
/*
* show_dock_uid - read method for "uid" file in sysfs
......@@ -723,7 +729,7 @@ static ssize_t show_dock_uid(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
}
DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
/**
* dock_add - add a new dock station
......
......@@ -573,7 +573,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
void *handler_context, void *region_context)
{
struct acpi_ec *ec = handler_context;
int result = 0, i = 0;
int result = 0, i;
u8 temp = 0;
if ((address > 0xFF) || !value || !handler_context)
......@@ -585,7 +585,18 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
if (bits != 8 && acpi_strict)
return AE_BAD_PARAMETER;
while (bits - i > 0) {
acpi_ec_burst_enable(ec);
if (function == ACPI_READ) {
result = acpi_ec_read(ec, address, &temp);
*value = temp;
} else {
temp = 0xff & (*value);
result = acpi_ec_write(ec, address, temp);
}
for (i = 8; unlikely(bits - i > 0); i += 8) {
++address;
if (function == ACPI_READ) {
result = acpi_ec_read(ec, address, &temp);
(*value) |= ((acpi_integer)temp) << i;
......@@ -593,10 +604,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
temp = 0xff & ((*value) >> i);
result = acpi_ec_write(ec, address, temp);
}
i += 8;
++address;
}
acpi_ec_burst_disable(ec);
switch (result) {
case -EINVAL:
return AE_BAD_PARAMETER;
......
......@@ -109,6 +109,34 @@ static const struct file_operations acpi_system_event_ops = {
};
#endif /* CONFIG_ACPI_PROC_EVENT */
/* ACPI notifier chain */
BLOCKING_NOTIFIER_HEAD(acpi_chain_head);
int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)
{
struct acpi_bus_event event;
strcpy(event.device_class, dev->pnp.device_class);
strcpy(event.bus_id, dev->pnp.bus_id);
event.type = type;
event.data = data;
return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event)
== NOTIFY_BAD) ? -EINVAL : 0;
}
EXPORT_SYMBOL(acpi_notifier_call_chain);
int register_acpi_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&acpi_chain_head, nb);
}
EXPORT_SYMBOL(register_acpi_notifier);
int unregister_acpi_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&acpi_chain_head, nb);
}
EXPORT_SYMBOL(unregister_acpi_notifier);
#ifdef CONFIG_NET
static unsigned int acpi_event_seqnum;
struct acpi_genl_event {
......
......@@ -259,7 +259,7 @@ u32 acpi_ev_fixed_event_detect(void)
enable_bit_mask)) {
/* Found an active (signalled) event */
acpi_os_fixed_event_count(i);
int_status |= acpi_ev_fixed_event_dispatch((u32) i);
}
}
......
......@@ -270,18 +270,18 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
case ACPI_GPE_TYPE_WAKE_RUN:
ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
/*lint -fallthrough */
/* fallthrough */
case ACPI_GPE_TYPE_RUNTIME:
/* Disable the requested runtime GPE */
ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
break;
/* fallthrough */
default:
return_ACPI_STATUS(AE_BAD_PARAMETER);
acpi_hw_write_gpe_enable_reg(gpe_event_info);
}
return_ACPI_STATUS(AE_OK);
......@@ -501,6 +501,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
* an interrupt handler.
*
******************************************************************************/
static void acpi_ev_asynch_enable_gpe(void *context);
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
{
......@@ -576,22 +577,30 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
method_node)));
}
}
/* Defer enabling of GPE until all notify handlers are done */
acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe,
gpe_event_info);
return_VOID;
}
if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
static void acpi_ev_asynch_enable_gpe(void *context)
{
struct acpi_gpe_event_info *gpe_event_info = context;
acpi_status status;
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
ACPI_GPE_LEVEL_TRIGGERED) {
/*
* GPE is level-triggered, we clear the GPE status bit after
* handling the event.
*/
status = acpi_hw_clear_gpe(&local_gpe_event_info);
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
return_VOID;
}
}
/* Enable this GPE */
(void)acpi_hw_write_gpe_enable_reg(&local_gpe_event_info);
(void)acpi_hw_write_gpe_enable_reg(gpe_event_info);
return_VOID;
}
......@@ -618,7 +627,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
acpi_gpe_count++;
acpi_os_gpe_count(gpe_number);
/*
* If edge-triggered, clear the GPE status bit now. Note that
......
......@@ -30,7 +30,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <linux/thermal.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
......@@ -68,9 +68,55 @@ static struct acpi_driver acpi_fan_driver = {
},
};
/* thermal cooling device callbacks */
static int fan_get_max_state(struct thermal_cooling_device *cdev, char *buf)
{
/* ACPI fan device only support two states: ON/OFF */
return sprintf(buf, "1\n");
}
static int fan_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
{
struct acpi_device *device = cdev->devdata;
int state;
int result;
if (!device)
return -EINVAL;
result = acpi_bus_get_power(device->handle, &state);
if (result)
return result;
return sprintf(buf, "%s\n", state == ACPI_STATE_D3 ? "0" :
(state == ACPI_STATE_D0 ? "1" : "unknown"));
}
static int
fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
{
struct acpi_device *device = cdev->devdata;
int result;
if (!device || (state != 0 && state != 1))
return -EINVAL;
result = acpi_bus_set_power(device->handle,
state ? ACPI_STATE_D0 : ACPI_STATE_D3);
return result;
}
static struct thermal_cooling_device_ops fan_cooling_ops = {
.get_max_state = fan_get_max_state,
.get_cur_state = fan_get_cur_state,
.set_cur_state = fan_set_cur_state,
};
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCFS
static struct proc_dir_entry *acpi_fan_dir;
......@@ -171,7 +217,17 @@ static int acpi_fan_remove_fs(struct acpi_device *device)
return 0;
}
#else
static int acpi_fan_add_fs(struct acpi_device *device)
{
return 0;
}
static int acpi_fan_remove_fs(struct acpi_device *device)
{
return 0;
}
#endif
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
......@@ -179,9 +235,8 @@ static int acpi_fan_remove_fs(struct acpi_device *device)
static int acpi_fan_add(struct acpi_device *device)
{
int result = 0;
struct acpi_fan *fan = NULL;
int state = 0;
struct thermal_cooling_device *cdev;
if (!device)
return -EINVAL;
......@@ -199,6 +254,25 @@ static int acpi_fan_add(struct acpi_device *device)
acpi_bus_set_power(device->handle, state);
device->flags.force_power_state = 0;
cdev = thermal_cooling_device_register("Fan", device,
&fan_cooling_ops);
if (cdev)
printk(KERN_INFO PREFIX
"%s is registered as cooling_device%d\n",
device->dev.bus_id, cdev->id);
else
goto end;
acpi_driver_data(device) = cdev;
result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj,
"thermal_cooling");
if (result)
return result;
result = sysfs_create_link(&cdev->device.kobj, &device->dev.kobj,
"device");
if (result)
return result;
result = acpi_fan_add_fs(device);
if (result)
goto end;
......@@ -208,18 +282,20 @@ static int acpi_fan_add(struct acpi_device *device)
!device->power.state ? "on" : "off");
end:
if (result)
kfree(fan);
return result;
}
static int acpi_fan_remove(struct acpi_device *device, int type)
{
if (!device || !acpi_driver_data(device))
struct thermal_cooling_device *cdev = acpi_driver_data(device);
if (!device || !cdev)
return -EINVAL;
acpi_fan_remove_fs(device);
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
sysfs_remove_link(&cdev->device.kobj, "device");
thermal_cooling_device_unregister(cdev);
return 0;
}
......@@ -261,10 +337,12 @@ static int __init acpi_fan_init(void)
int result = 0;
#ifdef CONFIG_ACPI_PROCFS
acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
if (!acpi_fan_dir)
return -ENODEV;
acpi_fan_dir->owner = THIS_MODULE;
#endif
result = acpi_bus_register_driver(&acpi_fan_driver);
if (result < 0) {
......
......@@ -36,8 +36,6 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
return -ENODEV;
}
EXPORT_SYMBOL(register_acpi_bus_type);
int unregister_acpi_bus_type(struct acpi_bus_type *type)
{
if (acpi_disabled)
......@@ -53,8 +51,6 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
return -ENODEV;
}
EXPORT_SYMBOL(unregister_acpi_bus_type);
static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
{
struct acpi_bus_type *tmp, *ret = NULL;
......
......@@ -286,13 +286,13 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
}
/*
* 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
*/
status = acpi_hw_disable_all_gpes();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = FALSE;
status = acpi_hw_enable_all_wakeup_gpes();
......
......@@ -443,6 +443,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
struct acpica_device_id hid;
struct acpi_compatible_id_list *cid;
acpi_native_uint i;
int found;
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
......@@ -496,16 +497,19 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
/* Walk the CID list */
found = 0;
for (i = 0; i < cid->count; i++) {
if (ACPI_STRNCMP(cid->id[i].value, info->hid,
sizeof(struct
acpi_compatible_id)) !=
acpi_compatible_id)) ==
0) {
ACPI_FREE(cid);
return (AE_OK);
found = 1;
break;
}
}
ACPI_FREE(cid);
if (!found)
return (AE_OK);
}
}
......
......@@ -78,6 +78,7 @@ int acpi_map_pxm_to_node(int pxm)
return node;
}
#if 0
void __cpuinit acpi_unmap_pxm_to_node(int node)
{
int pxm = node_to_pxm_map[node];
......@@ -85,6 +86,7 @@ void __cpuinit acpi_unmap_pxm_to_node(int node)
node_to_pxm_map[node] = PXM_INVAL;
node_clear(node, nodes_found_map);
}
#endif /* 0 */
static void __init
acpi_table_print_srat_entry(struct acpi_subtable_header *header)
......@@ -247,7 +249,6 @@ int acpi_get_pxm(acpi_handle h)
} while (ACPI_SUCCESS(status));
return -1;
}
EXPORT_SYMBOL(acpi_get_pxm);
int acpi_get_node(acpi_handle *handle)
{
......
......@@ -44,6 +44,8 @@
#include <asm/uaccess.h>
#include <linux/efi.h>
#include <linux/ioport.h>
#include <linux/list.h>
#define _COMPONENT ACPI_OS_SERVICES
ACPI_MODULE_NAME("osl");
......@@ -74,9 +76,25 @@ static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
static struct workqueue_struct *kacpi_notify_wq;
struct acpi_res_list {
resource_size_t start;
resource_size_t end;
acpi_adr_space_type resource_type; /* IO port, System memory, ...*/
char name[5]; /* only can have a length of 4 chars, make use of this
one instead of res->name, no need to kalloc then */
struct list_head resource_list;
};
static LIST_HEAD(resource_list_head);
static DEFINE_SPINLOCK(acpi_res_lock);
#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
static char osi_additional_string[OSI_STRING_LENGTH_MAX];
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
static int acpi_no_initrd_override;
#endif
/*
* "Ode to _OSI(Linux)"
*
......@@ -120,7 +138,7 @@ static char osi_additional_string[OSI_STRING_LENGTH_MAX];
*/
#define OSI_LINUX_ENABLE 0
struct osi_linux {
static struct osi_linux {
unsigned int enable:1;
unsigned int dmi:1;
unsigned int cmdline:1;
......@@ -219,8 +237,6 @@ void acpi_os_printf(const char *fmt, ...)
va_end(args);
}
EXPORT_SYMBOL(acpi_os_printf);
void acpi_os_vprintf(const char *fmt, va_list args)
{
static char buffer[512];
......@@ -250,11 +266,16 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
"System description tables not found\n");
return 0;
}
} else
return acpi_find_rsdp();
} else {
acpi_physical_address pa = 0;
acpi_find_root_pointer(&pa);
return pa;
}
}
void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
void __iomem *__init_refok
acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
{
if (phys > ULONG_MAX) {
printk(KERN_ERR PREFIX "Cannot map memory that high\n");
......@@ -312,6 +333,67 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
return AE_OK;
}
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
struct acpi_table_header *acpi_find_dsdt_initrd(void)
{
struct file *firmware_file;
mm_segment_t oldfs;
unsigned long len, len2;
struct acpi_table_header *dsdt_buffer, *ret = NULL;
struct kstat stat;
char *ramfs_dsdt_name = "/DSDT.aml";
printk(KERN_INFO PREFIX "Checking initramfs for custom DSDT");
/*
* Never do this at home, only the user-space is allowed to open a file.
* The clean way would be to use the firmware loader.
* But this code must be run before there is any userspace available.
* A static/init firmware infrastructure doesn't exist yet...
*/
if (vfs_stat(ramfs_dsdt_name, &stat) < 0)
return ret;
len = stat.size;
/* check especially against empty files */
if (len <= 4) {
printk(KERN_ERR PREFIX "Failed: DSDT only %lu bytes.\n", len);
return ret;
}
firmware_file = filp_open(ramfs_dsdt_name, O_RDONLY, 0);
if (IS_ERR(firmware_file)) {
printk(KERN_ERR PREFIX "Failed to open %s.\n", ramfs_dsdt_name);
return ret;
}
dsdt_buffer = kmalloc(len, GFP_ATOMIC);
if (!dsdt_buffer) {
printk(KERN_ERR PREFIX "Failed to allocate %lu bytes.\n", len);
goto err;
}
oldfs = get_fs();
set_fs(KERNEL_DS);
len2 = vfs_read(firmware_file, (char __user *)dsdt_buffer, len,
&firmware_file->f_pos);
set_fs(oldfs);
if (len2 < len) {
printk(KERN_ERR PREFIX "Failed to read %lu bytes from %s.\n",
len, ramfs_dsdt_name);
ACPI_FREE(dsdt_buffer);
goto err;
}
printk(KERN_INFO PREFIX "Found %lu byte DSDT in %s.\n",
len, ramfs_dsdt_name);
ret = dsdt_buffer;
err:
filp_close(firmware_file, NULL);
return ret;
}
#endif
acpi_status
acpi_os_table_override(struct acpi_table_header * existing_table,
struct acpi_table_header ** new_table)
......@@ -319,20 +401,52 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
if (!existing_table || !new_table)
return AE_BAD_PARAMETER;
*new_table = NULL;
#ifdef CONFIG_ACPI_CUSTOM_DSDT
if (strncmp(existing_table->signature, "DSDT", 4) == 0)
*new_table = (struct acpi_table_header *)AmlCode;
else
*new_table = NULL;
#else
*new_table = NULL;
#endif
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
if ((strncmp(existing_table->signature, "DSDT", 4) == 0) &&
!acpi_no_initrd_override) {
struct acpi_table_header *initrd_table;
initrd_table = acpi_find_dsdt_initrd();
if (initrd_table)
*new_table = initrd_table;
}
#endif
if (*new_table != NULL) {
printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
"this is unsafe: tainting kernel\n",
existing_table->signature,
existing_table->oem_table_id);
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
}
return AE_OK;
}
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
int __init acpi_no_initrd_override_setup(char *s)
{
acpi_no_initrd_override = 1;
return 1;
}
__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup);
#endif
static irqreturn_t acpi_irq(int irq, void *dev_id)
{
return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
u32 handled;
handled = (*acpi_irq_handler) (acpi_irq_context);
if (handled) {
acpi_irq_handled++;
return IRQ_HANDLED;
} else
return IRQ_NONE;
}
acpi_status
......@@ -341,6 +455,8 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
{
unsigned int irq;
acpi_irq_stats_init();
/*
* Ignore the GSI from the core, and use the value in our copy of the
* FADT. It may not be the same if an interrupt source override exists
......@@ -384,8 +500,6 @@ void acpi_os_sleep(acpi_integer ms)
schedule_timeout_interruptible(msecs_to_jiffies(ms));
}
EXPORT_SYMBOL(acpi_os_sleep);
void acpi_os_stall(u32 us)
{
while (us) {
......@@ -399,8 +513,6 @@ void acpi_os_stall(u32 us)
}
}
EXPORT_SYMBOL(acpi_os_stall);
/*
* Support ACPI 3.0 AML Timer operand
* Returns 64-bit free-running, monotonically increasing timer
......@@ -550,8 +662,6 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
return (result ? AE_ERROR : AE_OK);
}
EXPORT_SYMBOL(acpi_os_read_pci_configuration);
acpi_status
acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
acpi_integer value, u32 width)
......@@ -661,25 +771,6 @@ static void acpi_os_execute_deferred(struct work_struct *work)
dpc->function(dpc->context);
kfree(dpc);
/* Yield cpu to notify thread */
cond_resched();
return;
}
static void acpi_os_execute_notify(struct work_struct *work)
{
struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
if (!dpc) {
printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
return;
}
dpc->function(dpc->context);
kfree(dpc);
return;
}
......@@ -703,7 +794,7 @@ acpi_status acpi_os_execute(acpi_execute_type type,
{
acpi_status status = AE_OK;
struct acpi_os_dpc *dpc;
struct workqueue_struct *queue;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Scheduling function [%p(%p)] for deferred execution.\n",
function, context));
......@@ -727,20 +818,13 @@ acpi_status acpi_os_execute(acpi_execute_type type,
dpc->function = function;
dpc->context = context;
if (type == OSL_NOTIFY_HANDLER) {
INIT_WORK(&dpc->work, acpi_os_execute_notify);
if (!queue_work(kacpi_notify_wq, &dpc->work)) {
status = AE_ERROR;
kfree(dpc);
}
} else {
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
if (!queue_work(kacpid_wq, &dpc->work)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Call to queue_work() failed.\n"));
status = AE_ERROR;
kfree(dpc);
}
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq;
if (!queue_work(queue, &dpc->work)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Call to queue_work() failed.\n"));
status = AE_ERROR;
kfree(dpc);
}
return_ACPI_STATUS(status);
}
......@@ -793,8 +877,6 @@ acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
return AE_OK;
}
EXPORT_SYMBOL(acpi_os_create_semaphore);
/*
* TODO: A better way to delete semaphores? Linux doesn't have a
* 'delete_semaphore()' function -- may result in an invalid
......@@ -818,8 +900,6 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
return AE_OK;
}
EXPORT_SYMBOL(acpi_os_delete_semaphore);
/*
* TODO: The kernel doesn't have a 'down_timeout' function -- had to
* improvise. The process is to sleep for one scheduler quantum
......@@ -912,8 +992,6 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
return status;
}
EXPORT_SYMBOL(acpi_os_wait_semaphore);
/*
* TODO: Support for units > 1?
*/
......@@ -936,8 +1014,6 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
return AE_OK;
}
EXPORT_SYMBOL(acpi_os_signal_semaphore);
#ifdef ACPI_FUTURE_USAGE
u32 acpi_os_get_line(char *buffer)
{
......@@ -981,8 +1057,6 @@ acpi_status acpi_os_signal(u32 function, void *info)
return AE_OK;
}
EXPORT_SYMBOL(acpi_os_signal);
static int __init acpi_os_name_setup(char *str)
{
char *p = acpi_os_name;
......@@ -1102,6 +1176,128 @@ static int __init acpi_wake_gpes_always_on_setup(char *str)
__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
/* Check of resource interference between native drivers and ACPI
* OperationRegions (SystemIO and System Memory only).
* IO ports and memory declared in ACPI might be used by the ACPI subsystem
* in arbitrary AML code and can interfere with legacy drivers.
* acpi_enforce_resources= can be set to:
*
* - strict (2)
* -> further driver trying to access the resources will not load
* - lax (default) (1)
* -> further driver trying to access the resources will load, but you
* get a system message that something might go wrong...
*
* - no (0)
* -> ACPI Operation Region resources will not be registered
*
*/
#define ENFORCE_RESOURCES_STRICT 2
#define ENFORCE_RESOURCES_LAX 1
#define ENFORCE_RESOURCES_NO 0
static unsigned int acpi_enforce_resources = ENFORCE_RESOURCES_LAX;
static int __init acpi_enforce_resources_setup(char *str)
{
if (str == NULL || *str == '\0')
return 0;
if (!strcmp("strict", str))
acpi_enforce_resources = ENFORCE_RESOURCES_STRICT;
else if (!strcmp("lax", str))
acpi_enforce_resources = ENFORCE_RESOURCES_LAX;
else if (!strcmp("no", str))
acpi_enforce_resources = ENFORCE_RESOURCES_NO;
return 1;
}
__setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
/* Check for resource conflicts between ACPI OperationRegions and native
* drivers */
int acpi_check_resource_conflict(struct resource *res)
{
struct acpi_res_list *res_list_elem;
int ioport;
int clash = 0;
if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
return 0;
if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM))
return 0;
ioport = res->flags & IORESOURCE_IO;
spin_lock(&acpi_res_lock);
list_for_each_entry(res_list_elem, &resource_list_head,
resource_list) {
if (ioport && (res_list_elem->resource_type
!= ACPI_ADR_SPACE_SYSTEM_IO))
continue;
if (!ioport && (res_list_elem->resource_type
!= ACPI_ADR_SPACE_SYSTEM_MEMORY))
continue;
if (res->end < res_list_elem->start
|| res_list_elem->end < res->start)
continue;
clash = 1;
break;
}
spin_unlock(&acpi_res_lock);
if (clash) {
if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
printk(KERN_INFO "%sACPI: %s resource %s [0x%llx-0x%llx]"
" conflicts with ACPI region %s"
" [0x%llx-0x%llx]\n",
acpi_enforce_resources == ENFORCE_RESOURCES_LAX
? KERN_WARNING : KERN_ERR,
ioport ? "I/O" : "Memory", res->name,
(long long) res->start, (long long) res->end,
res_list_elem->name,
(long long) res_list_elem->start,
(long long) res_list_elem->end);
printk(KERN_INFO "ACPI: Device needs an ACPI driver\n");
}
if (acpi_enforce_resources == ENFORCE_RESOURCES_STRICT)
return -EBUSY;
}
return 0;
}
EXPORT_SYMBOL(acpi_check_resource_conflict);
int acpi_check_region(resource_size_t start, resource_size_t n,
const char *name)
{
struct resource res = {
.start = start,
.end = start + n - 1,
.name = name,
.flags = IORESOURCE_IO,
};
return acpi_check_resource_conflict(&res);
}
EXPORT_SYMBOL(acpi_check_region);
int acpi_check_mem_region(resource_size_t start, resource_size_t n,
const char *name)
{
struct resource res = {
.start = start,
.end = start + n - 1,
.name = name,
.flags = IORESOURCE_MEM,
};
return acpi_check_resource_conflict(&res);
}
EXPORT_SYMBOL(acpi_check_mem_region);
/*
* Acquire a spinlock.
*
......@@ -1213,24 +1409,24 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
*
* Returns 0 on success
*/
int acpi_dmi_dump(void)
static int acpi_dmi_dump(void)
{
if (!dmi_available)
return -1;
printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
dmi_get_slot(DMI_SYS_VENDOR));
dmi_get_system_info(DMI_SYS_VENDOR));
printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
dmi_get_slot(DMI_PRODUCT_NAME));
dmi_get_system_info(DMI_PRODUCT_NAME));
printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
dmi_get_slot(DMI_PRODUCT_VERSION));
dmi_get_system_info(DMI_PRODUCT_VERSION));
printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
dmi_get_slot(DMI_BOARD_NAME));
dmi_get_system_info(DMI_BOARD_NAME));
printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
dmi_get_slot(DMI_BIOS_VENDOR));
dmi_get_system_info(DMI_BIOS_VENDOR));
printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
dmi_get_slot(DMI_BIOS_DATE));
dmi_get_system_info(DMI_BIOS_DATE));
return 0;
}
......@@ -1303,10 +1499,46 @@ acpi_status
acpi_os_validate_address (
u8 space_id,
acpi_physical_address address,
acpi_size length)
acpi_size length,
char *name)
{
struct acpi_res_list *res;
if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
return AE_OK;
return AE_OK;
switch (space_id) {
case ACPI_ADR_SPACE_SYSTEM_IO:
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
/* Only interference checks against SystemIO and SytemMemory
are needed */
res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL);
if (!res)
return AE_OK;
/* ACPI names are fixed to 4 bytes, still better use strlcpy */
strlcpy(res->name, name, 5);
res->start = address;
res->end = address + length - 1;
res->resource_type = space_id;
spin_lock(&acpi_res_lock);
list_add(&res->resource_list, &resource_list_head);
spin_unlock(&acpi_res_lock);
pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, "
"name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
? "SystemIO" : "System Memory",
(unsigned long long)res->start,
(unsigned long long)res->end,
res->name);
break;
case ACPI_ADR_SPACE_PCI_CONFIG:
case ACPI_ADR_SPACE_EC:
case ACPI_ADR_SPACE_SMBUS:
case ACPI_ADR_SPACE_CMOS:
case ACPI_ADR_SPACE_PCI_BAR_TARGET:
case ACPI_ADR_SPACE_DATA_TABLE:
case ACPI_ADR_SPACE_FIXED_HARDWARE:
break;
}
return AE_OK;
}
#endif
......@@ -44,6 +44,8 @@ struct acpi_pci_data {
struct pci_dev *dev;
};
static int acpi_pci_unbind(struct acpi_device *device);
static void acpi_pci_data_handler(acpi_handle handle, u32 function,
void *context)
{
......@@ -267,7 +269,7 @@ int acpi_pci_bind(struct acpi_device *device)
return result;
}
int acpi_pci_unbind(struct acpi_device *device)
static int acpi_pci_unbind(struct acpi_device *device)
{
int result = 0;
acpi_status status = AE_OK;
......
......@@ -51,10 +51,8 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
int bus,
int device, int pin)
{
struct list_head *node = NULL;
struct acpi_prt_entry *entry = NULL;
if (!acpi_prt.count)
return NULL;
......@@ -64,8 +62,7 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
*
*/
spin_lock(&acpi_prt_lock);
list_for_each(node, &acpi_prt.entries) {
entry = list_entry(node, struct acpi_prt_entry, node);
list_for_each_entry(entry, &acpi_prt.entries, node) {
if ((segment == entry->id.segment)
&& (bus == entry->id.bus)
&& (device == entry->id.device)
......@@ -478,8 +475,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
return 0;
}
EXPORT_SYMBOL(acpi_pci_irq_enable);
/* FIXME: implement x86/x86_64 version */
void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
{
......
......@@ -95,7 +95,7 @@ static struct {
int count;
struct list_head entries;
} acpi_link;
DEFINE_MUTEX(acpi_link_lock);
static DEFINE_MUTEX(acpi_link_lock);
/* --------------------------------------------------------------------------
PCI Link Device Management
......
......@@ -458,11 +458,9 @@ int acpi_power_transition(struct acpi_device *device, int state)
}
end:
if (result) {
if (result)
device->power.state = ACPI_STATE_UNKNOWN;
printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n",
device->pnp.bus_id, state);
} else {
else {
/* We shouldn't change the state till all above operations succeed */
device->power.state = state;
}
......
......@@ -668,6 +668,24 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
acpi_processor_power_init(pr, device);
pr->cdev = thermal_cooling_device_register("Processor", device,
&processor_cooling_ops);
if (pr->cdev)
printk(KERN_INFO PREFIX
"%s is registered as cooling_device%d\n",
device->dev.bus_id, pr->cdev->id);
else
goto end;
result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj,
"thermal_cooling");
if (result)
return result;
result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj,
"device");
if (result)
return result;
if (pr->flags.throttling) {
printk(KERN_INFO PREFIX "%s [%s] (supports",
acpi_device_name(device), acpi_device_bid(device));
......@@ -791,6 +809,11 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
acpi_processor_remove_fs(device);
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
sysfs_remove_link(&pr->cdev->device.kobj, "device");
thermal_cooling_device_unregister(pr->cdev);
pr->cdev = NULL;
processors[pr->id] = NULL;
kfree(pr);
......@@ -812,11 +835,18 @@ static int is_processor_present(acpi_handle handle)
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) {
ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
return 0;
}
return 1;
/*
* if a processor object does not have an _STA object,
* OSPM assumes that the processor is present.
*/
if (status == AE_NOT_FOUND)
return 1;
if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
return 1;
ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
return 0;
}
static
......@@ -1061,6 +1091,8 @@ static int __init acpi_processor_init(void)
acpi_processor_ppc_init();
acpi_processor_throttling_init();
return 0;
out_cpuidle:
......
......@@ -98,6 +98,9 @@ module_param(bm_history, uint, 0644);
static int acpi_processor_set_power_policy(struct acpi_processor *pr);
#else /* CONFIG_CPU_IDLE */
static unsigned int latency_factor __read_mostly = 2;
module_param(latency_factor, uint, 0644);
#endif
/*
......@@ -201,6 +204,10 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2)
return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
}
/*
* Callers should disable interrupts before the call and enable
* interrupts after return.
*/
static void acpi_safe_halt(void)
{
current_thread_info()->status &= ~TS_POLLING;
......@@ -261,7 +268,7 @@ static atomic_t c3_cpu_count;
/* Common C-state entry for C2, C3, .. */
static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
{
if (cstate->space_id == ACPI_CSTATE_FFH) {
if (cstate->entry_method == ACPI_CSTATE_FFH) {
/* Call into architectural FFH based C-state */
acpi_processor_ffh_cstate_enter(cstate);
} else {
......@@ -413,6 +420,8 @@ static void acpi_processor_idle(void)
pm_idle_save();
else
acpi_safe_halt();
local_irq_enable();
return;
}
......@@ -521,6 +530,7 @@ static void acpi_processor_idle(void)
* skew otherwise.
*/
sleep_ticks = 0xFFFFFFFF;
local_irq_enable();
break;
case ACPI_STATE_C2:
......@@ -922,20 +932,20 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
cx.address = reg->address;
cx.index = current_count + 1;
cx.space_id = ACPI_CSTATE_SYSTEMIO;
cx.entry_method = ACPI_CSTATE_SYSTEMIO;
if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
if (acpi_processor_ffh_cstate_probe
(pr->id, &cx, reg) == 0) {
cx.space_id = ACPI_CSTATE_FFH;
} else if (cx.type != ACPI_STATE_C1) {
cx.entry_method = ACPI_CSTATE_FFH;
} else if (cx.type == ACPI_STATE_C1) {
/*
* C1 is a special case where FIXED_HARDWARE
* can be handled in non-MWAIT way as well.
* In that case, save this _CST entry info.
* That is, we retain space_id of SYSTEM_IO for
* halt based C1.
* Otherwise, ignore this info and continue.
*/
cx.entry_method = ACPI_CSTATE_HALT;
} else {
continue;
}
}
......@@ -1369,12 +1379,16 @@ static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr,
/**
* acpi_idle_do_entry - a helper function that does C2 and C3 type entry
* @cx: cstate data
*
* Caller disables interrupt before call and enables interrupt after return.
*/
static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
{
if (cx->space_id == ACPI_CSTATE_FFH) {
if (cx->entry_method == ACPI_CSTATE_FFH) {
/* Call into architectural FFH based C-state */
acpi_processor_ffh_cstate_enter(cx);
} else if (cx->entry_method == ACPI_CSTATE_HALT) {
acpi_safe_halt();
} else {
int unused;
/* IO port based C-state */
......@@ -1396,21 +1410,27 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
static int acpi_idle_enter_c1(struct cpuidle_device *dev,
struct cpuidle_state *state)
{
u32 t1, t2;
struct acpi_processor *pr;
struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
pr = processors[smp_processor_id()];
if (unlikely(!pr))
return 0;
local_irq_disable();
if (pr->flags.bm_check)
acpi_idle_update_bm_rld(pr, cx);
acpi_safe_halt();
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
acpi_idle_do_entry(cx);
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
local_irq_enable();
cx->usage++;
return 0;
return ticks_elapsed_in_us(t1, t2);
}
/**
......@@ -1517,7 +1537,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
if (dev->safe_state) {
return dev->safe_state->enter(dev, dev->safe_state);
} else {
local_irq_disable();
acpi_safe_halt();
local_irq_enable();
return 0;
}
}
......@@ -1609,7 +1631,7 @@ struct cpuidle_driver acpi_idle_driver = {
*/
static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
{
int i, count = 0;
int i, count = CPUIDLE_DRIVER_STATE_START;
struct acpi_processor_cx *cx;
struct cpuidle_state *state;
struct cpuidle_device *dev = &pr->power.dev;
......@@ -1638,13 +1660,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
state->exit_latency = cx->latency;
state->target_residency = cx->latency * 6;
state->target_residency = cx->latency * latency_factor;
state->power_usage = cx->power;
state->flags = 0;
switch (cx->type) {
case ACPI_STATE_C1:
state->flags |= CPUIDLE_FLAG_SHALLOW;
state->flags |= CPUIDLE_FLAG_TIME_VALID;
state->enter = acpi_idle_enter_c1;
dev->safe_state = state;
break;
......@@ -1667,6 +1690,8 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
}
count++;
if (count == CPUIDLE_STATE_MAX)
break;
}
dev->state_count = count;
......
......@@ -60,6 +60,11 @@ static DEFINE_MUTEX(performance_mutex);
* policy is adjusted accordingly.
*/
static unsigned int ignore_ppc = 0;
module_param(ignore_ppc, uint, 0644);
MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
"limited by BIOS, this should help");
#define PPC_REGISTERED 1
#define PPC_IN_USE 2
......@@ -72,6 +77,9 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
struct acpi_processor *pr;
unsigned int ppc = 0;
if (ignore_ppc)
return 0;
mutex_lock(&performance_mutex);
if (event != CPUFREQ_INCOMPATIBLE)
......@@ -130,7 +138,13 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
{
int ret = acpi_processor_get_platform_limit(pr);
int ret;
if (ignore_ppc)
return 0;
ret = acpi_processor_get_platform_limit(pr);
if (ret < 0)
return (ret);
else
......
......@@ -32,6 +32,7 @@
#include <linux/cpufreq.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/sysdev.h>
#include <asm/uaccess.h>
......@@ -93,6 +94,9 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr)
* _any_ cpufreq driver and not only the acpi-cpufreq driver.
*/
#define CPUFREQ_THERMAL_MIN_STEP 0
#define CPUFREQ_THERMAL_MAX_STEP 3
static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS];
static unsigned int acpi_thermal_cpufreq_is_init = 0;
......@@ -109,8 +113,9 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu)
if (!cpu_has_cpufreq(cpu))
return -ENODEV;
if (cpufreq_thermal_reduction_pctg[cpu] < 60) {
cpufreq_thermal_reduction_pctg[cpu] += 20;
if (cpufreq_thermal_reduction_pctg[cpu] <
CPUFREQ_THERMAL_MAX_STEP) {
cpufreq_thermal_reduction_pctg[cpu]++;
cpufreq_update_policy(cpu);
return 0;
}
......@@ -123,8 +128,9 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
if (!cpu_has_cpufreq(cpu))
return -ENODEV;
if (cpufreq_thermal_reduction_pctg[cpu] > 20)
cpufreq_thermal_reduction_pctg[cpu] -= 20;
if (cpufreq_thermal_reduction_pctg[cpu] >
(CPUFREQ_THERMAL_MIN_STEP + 1))
cpufreq_thermal_reduction_pctg[cpu]--;
else
cpufreq_thermal_reduction_pctg[cpu] = 0;
cpufreq_update_policy(cpu);
......@@ -143,7 +149,7 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
max_freq =
(policy->cpuinfo.max_freq *
(100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100;
(100 - cpufreq_thermal_reduction_pctg[policy->cpu] * 20)) / 100;
cpufreq_verify_within_limits(policy, 0, max_freq);
......@@ -155,6 +161,32 @@ static struct notifier_block acpi_thermal_cpufreq_notifier_block = {
.notifier_call = acpi_thermal_cpufreq_notifier,
};
static int cpufreq_get_max_state(unsigned int cpu)
{
if (!cpu_has_cpufreq(cpu))
return 0;
return CPUFREQ_THERMAL_MAX_STEP;
}
static int cpufreq_get_cur_state(unsigned int cpu)
{
if (!cpu_has_cpufreq(cpu))
return 0;
return cpufreq_thermal_reduction_pctg[cpu];
}
static int cpufreq_set_cur_state(unsigned int cpu, int state)
{
if (!cpu_has_cpufreq(cpu))
return 0;
cpufreq_thermal_reduction_pctg[cpu] = state;
cpufreq_update_policy(cpu);
return 0;
}
void acpi_thermal_cpufreq_init(void)
{
int i;
......@@ -179,6 +211,20 @@ void acpi_thermal_cpufreq_exit(void)
}
#else /* ! CONFIG_CPU_FREQ */
static int cpufreq_get_max_state(unsigned int cpu)
{
return 0;
}
static int cpufreq_get_cur_state(unsigned int cpu)
{
return 0;
}
static int cpufreq_set_cur_state(unsigned int cpu, int state)
{
return 0;
}
static int acpi_thermal_cpufreq_increase(unsigned int cpu)
{
......@@ -310,6 +356,84 @@ int acpi_processor_get_limit_info(struct acpi_processor *pr)
return 0;
}
/* thermal coolign device callbacks */
static int acpi_processor_max_state(struct acpi_processor *pr)
{
int max_state = 0;
/*
* There exists four states according to
* cpufreq_thermal_reduction_ptg. 0, 1, 2, 3
*/
max_state += cpufreq_get_max_state(pr->id);
if (pr->flags.throttling)
max_state += (pr->throttling.state_count -1);
return max_state;
}
static int
processor_get_max_state(struct thermal_cooling_device *cdev, char *buf)
{
struct acpi_device *device = cdev->devdata;
struct acpi_processor *pr = acpi_driver_data(device);
if (!device || !pr)
return -EINVAL;
return sprintf(buf, "%d\n", acpi_processor_max_state(pr));
}
static int
processor_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
{
struct acpi_device *device = cdev->devdata;
struct acpi_processor *pr = acpi_driver_data(device);
int cur_state;
if (!device || !pr)
return -EINVAL;
cur_state = cpufreq_get_cur_state(pr->id);
if (pr->flags.throttling)
cur_state += pr->throttling.state;
return sprintf(buf, "%d\n", cur_state);
}
static int
processor_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
{
struct acpi_device *device = cdev->devdata;
struct acpi_processor *pr = acpi_driver_data(device);
int result = 0;
int max_pstate;
if (!device || !pr)
return -EINVAL;
max_pstate = cpufreq_get_max_state(pr->id);
if (state > acpi_processor_max_state(pr))
return -EINVAL;
if (state <= max_pstate) {
if (pr->flags.throttling && pr->throttling.state)
result = acpi_processor_set_throttling(pr, 0);
cpufreq_set_cur_state(pr->id, state);
} else {
cpufreq_set_cur_state(pr->id, max_pstate);
result = acpi_processor_set_throttling(pr,
state - max_pstate);
}
return result;
}
struct thermal_cooling_device_ops processor_cooling_ops = {
.get_max_state = processor_get_max_state,
.get_cur_state = processor_get_cur_state,
.set_cur_state = processor_set_cur_state,
};
/* /proc interface */
static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
......
......@@ -45,9 +45,229 @@
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_throttling");
struct throttling_tstate {
unsigned int cpu; /* cpu nr */
int target_state; /* target T-state */
};
#define THROTTLING_PRECHANGE (1)
#define THROTTLING_POSTCHANGE (2)
static int acpi_processor_get_throttling(struct acpi_processor *pr);
int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
static int acpi_processor_update_tsd_coord(void)
{
int count, count_target;
int retval = 0;
unsigned int i, j;
cpumask_t covered_cpus;
struct acpi_processor *pr, *match_pr;
struct acpi_tsd_package *pdomain, *match_pdomain;
struct acpi_processor_throttling *pthrottling, *match_pthrottling;
/*
* Now that we have _TSD data from all CPUs, lets setup T-state
* coordination between all CPUs.
*/
for_each_possible_cpu(i) {
pr = processors[i];
if (!pr)
continue;
/* Basic validity check for domain info */
pthrottling = &(pr->throttling);
/*
* If tsd package for one cpu is invalid, the coordination
* among all CPUs is thought as invalid.
* Maybe it is ugly.
*/
if (!pthrottling->tsd_valid_flag) {
retval = -EINVAL;
break;
}
}
if (retval)
goto err_ret;
cpus_clear(covered_cpus);
for_each_possible_cpu(i) {
pr = processors[i];
if (!pr)
continue;
if (cpu_isset(i, covered_cpus))
continue;
pthrottling = &pr->throttling;
pdomain = &(pthrottling->domain_info);
cpu_set(i, pthrottling->shared_cpu_map);
cpu_set(i, covered_cpus);
/*
* If the number of processor in the TSD domain is 1, it is
* unnecessary to parse the coordination for this CPU.
*/
if (pdomain->num_processors <= 1)
continue;
/* Validate the Domain info */
count_target = pdomain->num_processors;
count = 1;
for_each_possible_cpu(j) {
if (i == j)
continue;
match_pr = processors[j];
if (!match_pr)
continue;
match_pthrottling = &(match_pr->throttling);
match_pdomain = &(match_pthrottling->domain_info);
if (match_pdomain->domain != pdomain->domain)
continue;
/* Here i and j are in the same domain.
* If two TSD packages have the same domain, they
* should have the same num_porcessors and
* coordination type. Otherwise it will be regarded
* as illegal.
*/
if (match_pdomain->num_processors != count_target) {
retval = -EINVAL;
goto err_ret;
}
if (pdomain->coord_type != match_pdomain->coord_type) {
retval = -EINVAL;
goto err_ret;
}
cpu_set(j, covered_cpus);
cpu_set(j, pthrottling->shared_cpu_map);
count++;
}
for_each_possible_cpu(j) {
if (i == j)
continue;
match_pr = processors[j];
if (!match_pr)
continue;
match_pthrottling = &(match_pr->throttling);
match_pdomain = &(match_pthrottling->domain_info);
if (match_pdomain->domain != pdomain->domain)
continue;
/*
* If some CPUS have the same domain, they
* will have the same shared_cpu_map.
*/
match_pthrottling->shared_cpu_map =
pthrottling->shared_cpu_map;
}
}
err_ret:
for_each_possible_cpu(i) {
pr = processors[i];
if (!pr)
continue;
/*
* Assume no coordination on any error parsing domain info.
* The coordination type will be forced as SW_ALL.
*/
if (retval) {
pthrottling = &(pr->throttling);
cpus_clear(pthrottling->shared_cpu_map);
cpu_set(i, pthrottling->shared_cpu_map);
pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
}
}
return retval;
}
/*
* Update the T-state coordination after the _TSD
* data for all cpus is obtained.
*/
void acpi_processor_throttling_init(void)
{
if (acpi_processor_update_tsd_coord())
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Assume no T-state coordination\n"));
return;
}
static int acpi_processor_throttling_notifier(unsigned long event, void *data)
{
struct throttling_tstate *p_tstate = data;
struct acpi_processor *pr;
unsigned int cpu ;
int target_state;
struct acpi_processor_limit *p_limit;
struct acpi_processor_throttling *p_throttling;
cpu = p_tstate->cpu;
pr = processors[cpu];
if (!pr) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n"));
return 0;
}
if (!pr->flags.throttling) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling control is "
"unsupported on CPU %d\n", cpu));
return 0;
}
target_state = p_tstate->target_state;
p_throttling = &(pr->throttling);
switch (event) {
case THROTTLING_PRECHANGE:
/*
* Prechange event is used to choose one proper t-state,
* which meets the limits of thermal, user and _TPC.
*/
p_limit = &pr->limit;
if (p_limit->thermal.tx > target_state)
target_state = p_limit->thermal.tx;
if (p_limit->user.tx > target_state)
target_state = p_limit->user.tx;
if (pr->throttling_platform_limit > target_state)
target_state = pr->throttling_platform_limit;
if (target_state >= p_throttling->state_count) {
printk(KERN_WARNING
"Exceed the limit of T-state \n");
target_state = p_throttling->state_count - 1;
}
p_tstate->target_state = target_state;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PreChange Event:"
"target T-state of CPU %d is T%d\n",
cpu, target_state));
break;
case THROTTLING_POSTCHANGE:
/*
* Postchange event is only used to update the
* T-state flag of acpi_processor_throttling.
*/
p_throttling->state = target_state;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PostChange Event:"
"CPU %d is switched to T%d\n",
cpu, target_state));
break;
default:
printk(KERN_WARNING
"Unsupported Throttling notifier event\n");
break;
}
return 0;
}
/*
* _TPC - Throttling Present Capabilities
*/
......@@ -293,6 +513,10 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
struct acpi_buffer state = { 0, NULL };
union acpi_object *tsd = NULL;
struct acpi_tsd_package *pdomain;
struct acpi_processor_throttling *pthrottling;
pthrottling = &pr->throttling;
pthrottling->tsd_valid_flag = 0;
status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer);
if (ACPI_FAILURE(status)) {
......@@ -340,6 +564,22 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
goto end;
}
pthrottling = &pr->throttling;
pthrottling->tsd_valid_flag = 1;
pthrottling->shared_type = pdomain->coord_type;
cpu_set(pr->id, pthrottling->shared_cpu_map);
/*
* If the coordination type is not defined in ACPI spec,
* the tsd_valid_flag will be clear and coordination type
* will be forecd as DOMAIN_COORD_TYPE_SW_ALL.
*/
if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
pthrottling->tsd_valid_flag = 0;
pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
}
end:
kfree(buffer.pointer);
return result;
......@@ -589,6 +829,11 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
cpumask_t saved_mask;
int ret;
if (!pr)
return -EINVAL;
if (!pr->flags.throttling)
return -ENODEV;
/*
* Migrate task to the cpu pointed by pr.
*/
......@@ -742,13 +987,92 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
{
cpumask_t saved_mask;
int ret;
int ret = 0;
unsigned int i;
struct acpi_processor *match_pr;
struct acpi_processor_throttling *p_throttling;
struct throttling_tstate t_state;
cpumask_t online_throttling_cpus;
if (!pr)
return -EINVAL;
if (!pr->flags.throttling)
return -ENODEV;
if ((state < 0) || (state > (pr->throttling.state_count - 1)))
return -EINVAL;
saved_mask = current->cpus_allowed;
t_state.target_state = state;
p_throttling = &(pr->throttling);
cpus_and(online_throttling_cpus, cpu_online_map,
p_throttling->shared_cpu_map);
/*
* Migrate task to the cpu pointed by pr.
* The throttling notifier will be called for every
* affected cpu in order to get one proper T-state.
* The notifier event is THROTTLING_PRECHANGE.
*/
saved_mask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(pr->id));
ret = pr->throttling.acpi_processor_set_throttling(pr, state);
for_each_cpu_mask(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
&t_state);
}
/*
* The function of acpi_processor_set_throttling will be called
* to switch T-state. If the coordination type is SW_ALL or HW_ALL,
* it is necessary to call it for every affected cpu. Otherwise
* it can be called only for the cpu pointed by pr.
*/
if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
set_cpus_allowed(current, cpumask_of_cpu(pr->id));
ret = p_throttling->acpi_processor_set_throttling(pr,
t_state.target_state);
} else {
/*
* When the T-state coordination is SW_ALL or HW_ALL,
* it is necessary to set T-state for every affected
* cpus.
*/
for_each_cpu_mask(i, online_throttling_cpus) {
match_pr = processors[i];
/*
* If the pointer is invalid, we will report the
* error message and continue.
*/
if (!match_pr) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Invalid Pointer for CPU %d\n", i));
continue;
}
/*
* If the throttling control is unsupported on CPU i,
* we will report the error message and continue.
*/
if (!match_pr->flags.throttling) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Throttling Controll is unsupported "
"on CPU %d\n", i));
continue;
}
t_state.cpu = i;
set_cpus_allowed(current, cpumask_of_cpu(i));
ret = match_pr->throttling.
acpi_processor_set_throttling(
match_pr, t_state.target_state);
}
}
/*
* After the set_throttling is called, the
* throttling notifier is called for every
* affected cpu to update the T-states.
* The notifier event is THROTTLING_POSTCHANGE
*/
for_each_cpu_mask(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
&t_state);
}
/* restore the previous state */
set_cpus_allowed(current, saved_mask);
return ret;
......@@ -757,6 +1081,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
int acpi_processor_get_throttling_info(struct acpi_processor *pr)
{
int result = 0;
struct acpi_processor_throttling *pthrottling;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
......@@ -788,7 +1113,16 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
&acpi_processor_set_throttling_ptc;
}
acpi_processor_get_tsd(pr);
/*
* If TSD package for one CPU can't be parsed successfully, it means
* that this CPU will have no coordination with other CPUs.
*/
if (acpi_processor_get_tsd(pr)) {
pthrottling = &pr->throttling;
pthrottling->tsd_valid_flag = 0;
cpu_set(pr->id, pthrottling->shared_cpu_map);
pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
}
/*
* PIIX4 Errata: We don't support throttling on the original PIIX4.
......
......@@ -888,7 +888,7 @@ static void acpi_charger_remove(struct acpi_sbs *sbs)
#endif
}
void acpi_sbs_callback(void *context)
static void acpi_sbs_callback(void *context)
{
int id;
struct acpi_sbs *sbs = context;
......
......@@ -111,8 +111,8 @@ static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
return -ETIME;
}
int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, u8 address,
u8 command, u8 *data, u8 length)
static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
u8 address, u8 command, u8 *data, u8 length)
{
int ret = -EFAULT, i;
u8 temp, sz = 0;
......
......@@ -59,7 +59,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
count = snprintf(&modalias[len], size, "%s:",
cid_list->id[i].value);
if (count < 0 || count >= size) {
printk(KERN_ERR "acpi: %s cid[%i] exceeds event buffer size",
printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size",
acpi_dev->pnp.device_name, i);
break;
}
......@@ -453,7 +453,7 @@ static int acpi_device_register(struct acpi_device *device,
device->dev.release = &acpi_device_release;
result = device_add(&device->dev);
if(result) {
printk("Error adding device %s", device->dev.bus_id);
printk(KERN_ERR PREFIX "Error adding device %s", device->dev.bus_id);
goto end;
}
......@@ -941,6 +941,15 @@ static int acpi_bay_match(struct acpi_device *device){
return -ENODEV;
}
/*
* acpi_dock_match - see if a device has a _DCK method
*/
static int acpi_dock_match(struct acpi_device *device)
{
acpi_handle tmp;
return acpi_get_handle(device->handle, "_DCK", &tmp);
}
static void acpi_device_set_id(struct acpi_device *device,
struct acpi_device *parent, acpi_handle handle,
int type)
......@@ -950,13 +959,14 @@ static void acpi_device_set_id(struct acpi_device *device,
char *hid = NULL;
char *uid = NULL;
struct acpi_compatible_id_list *cid_list = NULL;
const char *cid_add = NULL;
acpi_status status;
switch (type) {
case ACPI_BUS_TYPE_DEVICE:
status = acpi_get_object_info(handle, &buffer);
if (ACPI_FAILURE(status)) {
printk("%s: Error reading device info\n", __FUNCTION__);
printk(KERN_ERR PREFIX "%s: Error reading device info\n", __FUNCTION__);
return;
}
......@@ -972,15 +982,18 @@ static void acpi_device_set_id(struct acpi_device *device,
device->flags.bus_address = 1;
}
if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){
status = acpi_video_bus_match(device);
if(ACPI_SUCCESS(status))
hid = ACPI_VIDEO_HID;
/* If we have a video/bay/dock device, add our selfdefined
HID to the CID list. Like that the video/bay/dock drivers
will get autoloaded and the device might still match
against another driver.
*/
if (ACPI_SUCCESS(acpi_video_bus_match(device)))
cid_add = ACPI_VIDEO_HID;
else if (ACPI_SUCCESS(acpi_bay_match(device)))
cid_add = ACPI_BAY_HID;
else if (ACPI_SUCCESS(acpi_dock_match(device)))
cid_add = ACPI_DOCK_HID;
status = acpi_bay_match(device);
if (ACPI_SUCCESS(status))
hid = ACPI_BAY_HID;
}
break;
case ACPI_BUS_TYPE_POWER:
hid = ACPI_POWER_HID;
......@@ -1021,12 +1034,45 @@ static void acpi_device_set_id(struct acpi_device *device,
strcpy(device->pnp.unique_id, uid);
device->flags.unique_id = 1;
}
if (cid_list) {
device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL);
if (device->pnp.cid_list)
memcpy(device->pnp.cid_list, cid_list, cid_list->size);
else
printk(KERN_ERR "Memory allocation error\n");
if (cid_list || cid_add) {
struct acpi_compatible_id_list *list;
int size = 0;
int count = 0;
if (cid_list) {
size = cid_list->size;
} else if (cid_add) {
size = sizeof(struct acpi_compatible_id_list);
cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size);
if (!cid_list) {
printk(KERN_ERR "Memory allocation error\n");
kfree(buffer.pointer);
return;
} else {
cid_list->count = 0;
cid_list->size = size;
}
}
if (cid_add)
size += sizeof(struct acpi_compatible_id);
list = kmalloc(size, GFP_KERNEL);
if (list) {
if (cid_list) {
memcpy(list, cid_list, cid_list->size);
count = cid_list->count;
}
if (cid_add) {
strncpy(list->id[count].value, cid_add,
ACPI_MAX_CID_LENGTH);
count++;
device->flags.compatible_ids = 1;
}
list->size = size;
list->count = count;
device->pnp.cid_list = list;
} else
printk(KERN_ERR PREFIX "Memory allocation error\n");
}
kfree(buffer.pointer);
......@@ -1050,7 +1096,7 @@ static int acpi_device_set_context(struct acpi_device *device, int type)
acpi_bus_data_handler, device);
if (ACPI_FAILURE(status)) {
printk("Error attaching device data\n");
printk(KERN_ERR PREFIX "Error attaching device data\n");
result = -ENODEV;
}
}
......@@ -1080,6 +1126,20 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
return 0;
}
static int
acpi_is_child_device(struct acpi_device *device,
int (*matcher)(struct acpi_device *))
{
int result = -ENODEV;
do {
if (ACPI_SUCCESS(matcher(device)))
return AE_OK;
} while ((device = device->parent));
return result;
}
static int
acpi_add_single_object(struct acpi_device **child,
struct acpi_device *parent, acpi_handle handle, int type,
......@@ -1131,10 +1191,20 @@ acpi_add_single_object(struct acpi_device **child,
case ACPI_BUS_TYPE_PROCESSOR:
case ACPI_BUS_TYPE_DEVICE:
result = acpi_bus_get_status(device);
if (ACPI_FAILURE(result) || !device->status.present) {
result = -ENOENT;
if (ACPI_FAILURE(result)) {
result = -ENODEV;
goto end;
}
if (!device->status.present) {
/* Bay and dock should be handled even if absent */
if (!ACPI_SUCCESS(
acpi_is_child_device(device, acpi_bay_match)) &&
!ACPI_SUCCESS(
acpi_is_child_device(device, acpi_dock_match))) {
result = -ENODEV;
goto end;
}
}
break;
default:
STRUCT_TO_INT(device->status) =
......
......@@ -170,7 +170,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(acpi_state);
/* ACPI 3.0 specs (P62) says that it's the responsabilty
/* ACPI 3.0 specs (P62) says that it's the responsibility
* of the OSPM to clear the status bit [ implying that the
* POWER_BUTTON event should not reach userspace ]
*/
......@@ -472,11 +472,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
if (acpi_target_sleep_state == ACPI_STATE_S0 ||
(wake && adev->wakeup.state.enabled &&
adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
acpi_status status;
acpi_method[3] = 'W';
acpi_evaluate_integer(handle, acpi_method, NULL, &d_max);
/* Sanity check */
if (d_max < d_min)
status = acpi_evaluate_integer(handle, acpi_method, NULL,
&d_max);
if (ACPI_FAILURE(status)) {
d_max = d_min;
} else if (d_max < d_min) {
/* Warn the user of the broken DSDT */
printk(KERN_WARNING "ACPI: Wrong value from %s\n",
acpi_method);
/* Sanitize it */
d_min = d_max;
}
}
if (d_min_p)
......
......@@ -178,6 +178,9 @@ static int get_date_field(char **p, u32 * value)
* Try to find delimeter, only to insert null. The end of the
* string won't have one, but is still valid.
*/
if (*p == NULL)
return result;
next = strpbrk(*p, "- :");
if (next)
*next++ = '\0';
......@@ -190,6 +193,8 @@ static int get_date_field(char **p, u32 * value)
if (next)
*p = next;
else
*p = NULL;
return result;
}
......@@ -251,27 +256,6 @@ acpi_system_write_alarm(struct file *file,
if ((result = get_date_field(&p, &sec)))
goto end;
if (sec > 59) {
min += 1;
sec -= 60;
}
if (min > 59) {
hr += 1;
min -= 60;
}
if (hr > 23) {
day += 1;
hr -= 24;
}
if (day > 31) {
mo += 1;
day -= 31;
}
if (mo > 12) {
yr += 1;
mo -= 12;
}
spin_lock_irq(&rtc_lock);
rtc_control = CMOS_READ(RTC_CONTROL);
......@@ -288,24 +272,24 @@ acpi_system_write_alarm(struct file *file,
spin_unlock_irq(&rtc_lock);
if (sec > 59) {
min++;
sec -= 60;
min += sec/60;
sec = sec%60;
}
if (min > 59) {
hr++;
min -= 60;
hr += min/60;
min = min%60;
}
if (hr > 23) {
day++;
hr -= 24;
day += hr/24;
hr = hr%24;
}
if (day > 31) {
mo++;
day -= 31;
mo += day/32;
day = day%32;
}
if (mo > 12) {
yr++;
mo -= 12;
yr += mo/13;
mo = mo%13;
}
spin_lock_irq(&rtc_lock);
......
......@@ -40,6 +40,8 @@ ACPI_MODULE_NAME("system");
#define ACPI_SYSTEM_CLASS "system"
#define ACPI_SYSTEM_DEVICE_NAME "System"
u32 acpi_irq_handled;
/*
* Make ACPICA version work as module param
*/
......@@ -166,6 +168,212 @@ static int acpi_system_sysfs_init(void)
return 0;
}
/*
* Detailed ACPI IRQ counters in /sys/firmware/acpi/interrupts/
* See Documentation/ABI/testing/sysfs-firmware-acpi
*/
#define COUNT_GPE 0
#define COUNT_SCI 1 /* acpi_irq_handled */
#define COUNT_ERROR 2 /* other */
#define NUM_COUNTERS_EXTRA 3
static u32 *all_counters;
static u32 num_gpes;
static u32 num_counters;
static struct attribute **all_attrs;
static u32 acpi_gpe_count;
static struct attribute_group interrupt_stats_attr_group = {
.name = "interrupts",
};
static struct kobj_attribute *counter_attrs;
static int count_num_gpes(void)
{
int count = 0;
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
struct acpi_gpe_block_info *gpe_block;
acpi_cpu_flags flags;
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
while (gpe_xrupt_info) {
gpe_block = gpe_xrupt_info->gpe_block_list_head;
while (gpe_block) {
count += gpe_block->register_count *
ACPI_GPE_REGISTER_WIDTH;
gpe_block = gpe_block->next;
}
gpe_xrupt_info = gpe_xrupt_info->next;
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return count;
}
static void delete_gpe_attr_array(void)
{
u32 *tmp = all_counters;
all_counters = NULL;
kfree(tmp);
if (counter_attrs) {
int i;
for (i = 0; i < num_gpes; i++)
kfree(counter_attrs[i].attr.name);
kfree(counter_attrs);
}
kfree(all_attrs);
return;
}
void acpi_os_gpe_count(u32 gpe_number)
{
acpi_gpe_count++;
if (!all_counters)
return;
if (gpe_number < num_gpes)
all_counters[gpe_number]++;
else
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
return;
}
void acpi_os_fixed_event_count(u32 event_number)
{
if (!all_counters)
return;
if (event_number < ACPI_NUM_FIXED_EVENTS)
all_counters[num_gpes + event_number]++;
else
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
return;
}
static ssize_t counter_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI] =
acpi_irq_handled;
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE] =
acpi_gpe_count;
return sprintf(buf, "%d\n", all_counters[attr - counter_attrs]);
}
/*
* counter_set() sets the specified counter.
* setting the total "sci" file to any value clears all counters.
*/
static ssize_t counter_set(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t size)
{
int index = attr - counter_attrs;
if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
int i;
for (i = 0; i < num_counters; ++i)
all_counters[i] = 0;
acpi_gpe_count = 0;
acpi_irq_handled = 0;
} else
all_counters[index] = strtoul(buf, NULL, 0);
return size;
}
void acpi_irq_stats_init(void)
{
int i;
if (all_counters)
return;
num_gpes = count_num_gpes();
num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA;
all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1),
GFP_KERNEL);
if (all_attrs == NULL)
return;
all_counters = kzalloc(sizeof(u32) * (num_counters), GFP_KERNEL);
if (all_counters == NULL)
goto fail;
counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters),
GFP_KERNEL);
if (counter_attrs == NULL)
goto fail;
for (i = 0; i < num_counters; ++i) {
char buffer[10];
char *name;
if (i < num_gpes)
sprintf(buffer, "gpe%02X", i);
else if (i == num_gpes + ACPI_EVENT_PMTIMER)
sprintf(buffer, "ff_pmtimer");
else if (i == num_gpes + ACPI_EVENT_GLOBAL)
sprintf(buffer, "ff_gbl_lock");
else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON)
sprintf(buffer, "ff_pwr_btn");
else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON)
sprintf(buffer, "ff_slp_btn");
else if (i == num_gpes + ACPI_EVENT_RTC)
sprintf(buffer, "ff_rt_clk");
else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE)
sprintf(buffer, "gpe_all");
else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI)
sprintf(buffer, "sci");
else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR)
sprintf(buffer, "error");
else
sprintf(buffer, "bug%02X", i);
name = kzalloc(strlen(buffer) + 1, GFP_KERNEL);
if (name == NULL)
goto fail;
strncpy(name, buffer, strlen(buffer) + 1);
counter_attrs[i].attr.name = name;
counter_attrs[i].attr.mode = 0644;
counter_attrs[i].show = counter_show;
counter_attrs[i].store = counter_set;
all_attrs[i] = &counter_attrs[i].attr;
}
interrupt_stats_attr_group.attrs = all_attrs;
if (!sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group))
return;
fail:
delete_gpe_attr_array();
return;
}
static void __exit interrupt_stats_exit(void)
{
sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group);
delete_gpe_attr_array();
return;
}
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
......
......@@ -2,6 +2,6 @@
# Makefile for all Linux ACPI interpreter subdirectories
#
obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o
obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
EXTRA_CFLAGS += $(ACPI_CFLAGS)
......@@ -100,7 +100,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
/*******************************************************************************
*
* FUNCTION: acpi_tb_find_rsdp
* FUNCTION: acpi_find_root_pointer
*
* PARAMETERS: table_address - Where the table pointer is returned
*
......@@ -219,8 +219,6 @@ acpi_status acpi_find_root_pointer(acpi_native_uint * table_address)
return_ACPI_STATUS(AE_NOT_FOUND);
}
ACPI_EXPORT_SYMBOL(acpi_find_root_pointer)
/*******************************************************************************
*
* FUNCTION: acpi_tb_scan_memory_for_rsdp
......
此差异已折叠。
......@@ -671,7 +671,6 @@ void acpi_ut_init_globals(void)
/* GPE support */
acpi_gpe_count = 0;
acpi_gbl_gpe_xrupt_list_head = NULL;
acpi_gbl_gpe_fadt_blocks[0] = NULL;
acpi_gbl_gpe_fadt_blocks[1] = NULL;
......@@ -735,4 +734,3 @@ void acpi_ut_init_globals(void)
ACPI_EXPORT_SYMBOL(acpi_dbg_level)
ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
ACPI_EXPORT_SYMBOL(acpi_gpe_count)
此差异已折叠。
此差异已折叠。
config CPU_IDLE
bool "CPU idle PM support"
default ACPI
help
CPU idle is a generic framework for supporting software-controlled
idle processor power management. It includes modular cross-platform
governors that can be swapped during runtime.
If you're using a mobile platform that supports CPU idle PM (e.g.
an ACPI-capable notebook), you should say Y here.
If you're using an ACPI-enabled platform, you should say Y here.
config CPU_IDLE_GOV_LADDER
bool
......
......@@ -15,6 +15,7 @@
#include <linux/pm_qos_params.h>
#include <linux/cpu.h>
#include <linux/cpuidle.h>
#include <linux/ktime.h>
#include "cpuidle.h"
......@@ -180,6 +181,44 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
EXPORT_SYMBOL_GPL(cpuidle_disable_device);
#ifdef CONFIG_ARCH_HAS_CPU_RELAX
static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
{
ktime_t t1, t2;
s64 diff;
int ret;
t1 = ktime_get();
local_irq_enable();
while (!need_resched())
cpu_relax();
t2 = ktime_get();
diff = ktime_to_us(ktime_sub(t2, t1));
if (diff > INT_MAX)
diff = INT_MAX;
ret = (int) diff;
return ret;
}
static void poll_idle_init(struct cpuidle_device *dev)
{
struct cpuidle_state *state = &dev->states[0];
cpuidle_set_statedata(state, NULL);
snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)");
state->exit_latency = 0;
state->target_residency = 0;
state->power_usage = -1;
state->flags = CPUIDLE_FLAG_POLL | CPUIDLE_FLAG_TIME_VALID;
state->enter = poll_idle;
}
#else
static void poll_idle_init(struct cpuidle_device *dev) {}
#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
/**
* cpuidle_register_device - registers a CPU's idle PM feature
* @dev: the cpu
......@@ -198,6 +237,8 @@ int cpuidle_register_device(struct cpuidle_device *dev)
mutex_lock(&cpuidle_lock);
poll_idle_init(dev);
per_cpu(cpuidle_devices, dev->cpu) = dev;
list_add(&dev->device_list, &cpuidle_detected_devices);
if ((ret = cpuidle_add_sysfs(sys_dev))) {
......
......@@ -489,12 +489,3 @@ int dmi_get_year(int field)
return year;
}
/**
* dmi_get_slot - return dmi_ident[slot]
* @slot: index into dmi_ident[]
*/
char *dmi_get_slot(int slot)
{
return(dmi_ident[slot]);
}
......@@ -92,6 +92,22 @@ config TIFM_7XX1
To compile this driver as a module, choose M here: the module will
be called tifm_7xx1.
config ACER_WMI
tristate "Acer WMI Laptop Extras (EXPERIMENTAL)"
depends on X86
depends on EXPERIMENTAL
depends on ACPI
depends on ACPI_WMI
depends on LEDS_CLASS
depends on BACKLIGHT_CLASS_DEVICE
---help---
This is a driver for newer Acer (and Wistron) laptops. It adds
wireless radio and bluetooth control, and on some laptops,
exposes the mail LED and LCD backlight.
If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
here.
config ASUS_LAPTOP
tristate "Asus Laptop Extras (EXPERIMENTAL)"
depends on X86
......@@ -126,6 +142,15 @@ config FUJITSU_LAPTOP
If you have a Fujitsu laptop, say Y or M here.
config TC1100_WMI
tristate "HP Compaq TC1100 Tablet WMI Extras"
depends on X86 && !X86_64
depends on ACPI
depends on ACPI_WMI
---help---
This is a driver for the WMI extensions (wireless and bluetooth power
control) of the HP Compaq TC1100 tablet.
config MSI_LAPTOP
tristate "MSI Laptop Extras"
depends on X86
......@@ -219,6 +244,25 @@ config THINKPAD_ACPI_BAY
If you are not sure, say Y here.
config THINKPAD_ACPI_HOTKEY_POLL
bool "Suport NVRAM polling for hot keys"
depends on THINKPAD_ACPI
default y
---help---
Some thinkpad models benefit from NVRAM polling to detect a few of
the hot key press events. If you know your ThinkPad model does not
need to do NVRAM polling to support any of the hot keys you use,
unselecting this option will save about 1kB of memory.
ThinkPads T40 and newer, R52 and newer, and X31 and newer are
unlikely to need NVRAM polling in their latest BIOS versions.
NVRAM polling can detect at most the following keys: ThinkPad/Access
IBM, Zoom, Switch Display (fn+F7), ThinkLight, Volume up/down/mute,
Brightness up/down, Display Expand (fn+F8), Hibernate (fn+F12).
If you are not sure, say Y here. The driver enables polling only if
it is strictly necessary to do so.
config ATMEL_SSC
tristate "Device driver for Atmel SSC peripheral"
......@@ -232,4 +276,13 @@ config ATMEL_SSC
If unsure, say N.
config INTEL_MENLOW
tristate "Thermal Management driver for Intel menlow platform"
depends on ACPI_THERMAL
---help---
ACPI thermal management enhancement driver on
Intel Menlow platform.
If unsure, say N.
endif # MISC_DEVICES
......@@ -6,8 +6,10 @@ obj- := misc.o # Dummy rule to force built-in.o to be made
obj-$(CONFIG_IBM_ASM) += ibmasm/
obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
obj-$(CONFIG_ACER_WMI) += acer-wmi.o
obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
......@@ -17,3 +19,4 @@ obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
此差异已折叠。
......@@ -254,7 +254,7 @@ ASUS_LED(gled, "gaming");
* method is searched within the scope of the handle, can be NULL. The output
* of the method is written is output, which can also be NULL
*
* returns 1 if write is successful, 0 else.
* returns 0 if write is successful, -1 else.
*/
static int write_acpi_int(acpi_handle handle, const char *method, int val,
struct acpi_buffer *output)
......@@ -263,13 +263,19 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
union acpi_object in_obj; //the only param we use
acpi_status status;
if (!handle)
return 0;
params.count = 1;
params.pointer = &in_obj;
in_obj.type = ACPI_TYPE_INTEGER;
in_obj.integer.value = val;
status = acpi_evaluate_object(handle, (char *)method, &params, output);
return (status == AE_OK);
if (status == AE_OK)
return 0;
else
return -1;
}
static int read_wireless_status(int mask)
......@@ -321,7 +327,7 @@ static void write_status(acpi_handle handle, int out, int mask)
switch (mask) {
case MLED_ON:
out = !out & 0x1;
out = !(out & 0x1);
break;
case GLED_ON:
out = (out & 0x1) + 1;
......@@ -335,7 +341,7 @@ static void write_status(acpi_handle handle, int out, int mask)
break;
}
if (handle && !write_acpi_int(handle, NULL, out, NULL))
if (write_acpi_int(handle, NULL, out, NULL))
printk(ASUS_WARNING " write failed %x\n", mask);
}
......@@ -415,7 +421,7 @@ static int set_brightness(struct backlight_device *bd, int value)
value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
/* 0 <= value <= 15 */
if (!write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
printk(ASUS_WARNING "Error changing brightness\n");
ret = -EIO;
}
......@@ -545,7 +551,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
rv = parse_arg(buf, count, &value);
if (rv > 0) {
if (!write_acpi_int(ledd_set_handle, NULL, value, NULL))
if (write_acpi_int(ledd_set_handle, NULL, value, NULL))
printk(ASUS_WARNING "LED display write failed\n");
else
hotk->ledd_status = (u32) value;
......@@ -590,7 +596,7 @@ static ssize_t store_bluetooth(struct device *dev,
static void set_display(int value)
{
/* no sanity check needed for now */
if (!write_acpi_int(display_set_handle, NULL, value, NULL))
if (write_acpi_int(display_set_handle, NULL, value, NULL))
printk(ASUS_WARNING "Error setting display\n");
return;
}
......@@ -647,7 +653,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
*/
static void set_light_sens_switch(int value)
{
if (!write_acpi_int(ls_switch_handle, NULL, value, NULL))
if (write_acpi_int(ls_switch_handle, NULL, value, NULL))
printk(ASUS_WARNING "Error setting light sensor switch\n");
hotk->light_switch = value;
}
......@@ -672,7 +678,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
static void set_light_sens_level(int value)
{
if (!write_acpi_int(ls_level_handle, NULL, value, NULL))
if (write_acpi_int(ls_level_handle, NULL, value, NULL))
printk(ASUS_WARNING "Error setting light sensor level\n");
hotk->light_level = value;
}
......@@ -860,7 +866,7 @@ static int asus_hotk_get_info(void)
printk(ASUS_WARNING "Couldn't get the DSDT table header\n");
/* We have to write 0 on init this far for all ASUS models */
if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
printk(ASUS_ERR "Hotkey initialization failed\n");
return -ENODEV;
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -183,7 +183,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
if (ACPI_SUCCESS(status))
dev->capabilities |= PNP_CONFIGURABLE;
dev->capabilities |= PNP_READ;
if (device->flags.dynamic_status)
if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE))
dev->capabilities |= PNP_WRITE;
if (device->flags.removable)
dev->capabilities |= PNP_REMOVABLE;
......
......@@ -115,6 +115,7 @@ static struct device_attribute power_supply_attrs[] = {
/* Properties of type `const char *' */
POWER_SUPPLY_ATTR(model_name),
POWER_SUPPLY_ATTR(manufacturer),
POWER_SUPPLY_ATTR(serial_number),
};
static ssize_t power_supply_show_static_attrs(struct device *dev,
......
#
# Generic thermal sysfs drivers configuration
#
menuconfig THERMAL
bool "Generic Thermal sysfs driver"
default y
help
Generic Thermal Sysfs driver offers a generic mechanism for
thermal management. Usually it's made up of one or more thermal
zone and cooling device.
each thermal zone contains its own temperature, trip points,
cooling devices.
All platforms with ACPI thermal support can use this driver.
If you want this support, you should say Y here
#
# Makefile for sensor chip drivers.
#
obj-$(CONFIG_THERMAL) += thermal.o
此差异已折叠。
......@@ -117,10 +117,6 @@ extern u32 acpi_dbg_layer;
extern u32 acpi_gbl_nesting_level;
/* Event counters */
ACPI_EXTERN u32 acpi_gpe_count;
/* Support for dynamic control method tracing mechanism */
ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
......
......@@ -486,7 +486,7 @@
#define ACPI_FUNCTION_NAME(name)
#endif
#ifdef DEBUG_FUNC_TRACE
#ifdef CONFIG_ACPI_DEBUG_FUNC_TRACE
#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
......@@ -565,7 +565,7 @@
#endif /* ACPI_SIMPLE_RETURN_MACROS */
#else /* !DEBUG_FUNC_TRACE */
#else /* !CONFIG_ACPI_DEBUG_FUNC_TRACE */
#define ACPI_FUNCTION_TRACE(a)
#define ACPI_FUNCTION_TRACE_PTR(a,b)
......@@ -584,7 +584,7 @@
#define return_UINT32(s) return(s)
#define return_PTR(s) return(s)
#endif /* DEBUG_FUNC_TRACE */
#endif /* CONFIG_ACPI_DEBUG_FUNC_TRACE */
/* Conditional execution */
......
......@@ -321,6 +321,11 @@ struct acpi_bus_event {
extern struct kobject *acpi_kobj;
extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
void acpi_bus_private_data_handler(acpi_handle, u32, void *);
int acpi_bus_get_private_data(acpi_handle, void **);
extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
extern int register_acpi_notifier(struct notifier_block *);
extern int unregister_acpi_notifier(struct notifier_block *);
/*
* External Functions
*/
......
......@@ -48,6 +48,7 @@
#define ACPI_BUTTON_HID_SLEEPF "LNXSLPBN"
#define ACPI_VIDEO_HID "LNXVIDEO"
#define ACPI_BAY_HID "LNXIOBAY"
#define ACPI_DOCK_HID "LNXDOCK"
/* --------------------------------------------------------------------------
PCI
......@@ -73,7 +74,6 @@ struct pci_bus;
acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id);
int acpi_pci_bind(struct acpi_device *device);
int acpi_pci_unbind(struct acpi_device *device);
int acpi_pci_bind_root(struct acpi_device *device, struct acpi_pci_id *id,
struct pci_bus *bus);
......
......@@ -15,7 +15,6 @@ extern int pxm_to_node(int);
extern int node_to_pxm(int);
extern void __acpi_map_pxm_to_node(int, int);
extern int acpi_map_pxm_to_node(int);
extern void __cpuinit acpi_unmap_pxm_to_node(int);
#endif /* CONFIG_ACPI_NUMA */
#endif /* __ACP_NUMA_H */
......@@ -181,6 +181,9 @@ acpi_os_install_interrupt_handler(u32 gsi,
acpi_status
acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler service_routine);
void acpi_os_gpe_count(u32 gpe_number);
void acpi_os_fixed_event_count(u32 fixed_event_number);
/*
* Threads and Scheduling
*/
......@@ -239,8 +242,8 @@ acpi_status acpi_os_validate_interface(char *interface);
acpi_status acpi_osi_invalidate(char* interface);
acpi_status
acpi_os_validate_address(u8 space_id,
acpi_physical_address address, acpi_size length);
acpi_os_validate_address(u8 space_id, acpi_physical_address address,
acpi_size length, char *name);
u64 acpi_os_get_timer(void);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册