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: (119 commits)
  ACPI: don't pass handle for fixed hardware notifications
  ACPI: remove null pointer checks in deferred execution path
  ACPI: simplify deferred execution path
  acerhdf: additional BIOS versions
  acerhdf: convert to dev_pm_ops
  acerhdf: fix fan control for AOA150 model
  thermal: add missing Kconfig dependency
  acpi: switch /proc/acpi/{debug_layer,debug_level} to seq_file
  hp-wmi: fix rfkill memory leak on unload
  ACPI: remove unnecessary #ifdef CONFIG_DMI
  ACPI: linux/acpi.h should not include linux/dmi.h
  hwmon driver for ACPI 4.0 power meters
  topstar-laptop: add new driver for hotkeys support on Topstar N01
  thinkpad_acpi: fix rfkill memory leak on unload
  thinkpad-acpi: report brightness events when required
  thinkpad-acpi: don't poll by default any of the reserved hotkeys
  thinkpad-acpi: Fix procfs hotkey reset command
  thinkpad-acpi: deprecate hotkey_bios_mask
  thinkpad-acpi: hotkey poll fixes
  thinkpad-acpi: be more strict when detecting a ThinkPad
  ...
This commit is contained in:
Linus Torvalds 2009-09-23 09:32:11 -07:00
commit c11f6c8258
130 changed files with 7306 additions and 3094 deletions

View File

@ -0,0 +1,36 @@
What: /sys/class/backlight/<backlight>/bl_power
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Control BACKLIGHT power, values are FB_BLANK_* from fb.h
- FB_BLANK_UNBLANK (0) : power on.
- FB_BLANK_POWERDOWN (4) : power off
Users: HAL
What: /sys/class/backlight/<backlight>/brightness
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Control the brightness for this <backlight>. Values
are between 0 and max_brightness. This file will also
show the brightness level stored in the driver, which
may not be the actual brightness (see actual_brightness).
Users: HAL
What: /sys/class/backlight/<backlight>/actual_brightness
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Show the actual brightness by querying the hardware.
Users: HAL
What: /sys/class/backlight/<backlight>/max_brightness
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Maximum brightness for <backlight>.
Users: HAL

View File

@ -0,0 +1,23 @@
What: /sys/class/lcd/<lcd>/lcd_power
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Control LCD power, values are FB_BLANK_* from fb.h
- FB_BLANK_UNBLANK (0) : power on.
- FB_BLANK_POWERDOWN (4) : power off
What: /sys/class/lcd/<lcd>/contrast
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Current contrast of this LCD device. Value is between 0 and
/sys/class/lcd/<lcd>/max_contrast.
What: /sys/class/lcd/<lcd>/max_contrast
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Maximum contrast for this LCD device.

View File

@ -0,0 +1,28 @@
What: /sys/class/leds/<led>/brightness
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Set the brightness of the LED. Most LEDs don't
have hardware brightness support so will just be turned on for
non-zero brightness settings. The value is between 0 and
/sys/class/leds/<led>/max_brightness.
What: /sys/class/leds/<led>/max_brightness
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Maximum brightness level for this led, default is 255 (LED_FULL).
What: /sys/class/leds/<led>/trigger
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Set the trigger for this LED. A trigger is a kernel based source
of led events.
You can change triggers in a similar manner to the way an IO
scheduler is chosen. Trigger specific parameters can appear in
/sys/class/leds/<led> once a given trigger is selected.

View File

@ -0,0 +1,52 @@
What: /sys/devices/platform/asus-laptop/display
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
This file allows display switching. The value
is composed by 4 bits and defined as follow:
4321
|||`- LCD
||`-- CRT
|`--- TV
`---- DVI
Ex: - 0 (0000b) means no display
- 3 (0011b) CRT+LCD.
What: /sys/devices/platform/asus-laptop/gps
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the gps device. 1 means on, 0 means off.
Users: Lapsus
What: /sys/devices/platform/asus-laptop/ledd
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Some models like the W1N have a LED display that can be
used to display several informations.
To control the LED display, use the following :
echo 0x0T000DDD > /sys/devices/platform/asus-laptop/
where T control the 3 letters display, and DDD the 3 digits display.
The DDD table can be found in Documentation/laptops/asus-laptop.txt
What: /sys/devices/platform/asus-laptop/bluetooth
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the bluetooth device. 1 means on, 0 means off.
This may control the led, the device or both.
Users: Lapsus
What: /sys/devices/platform/asus-laptop/wlan
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the bluetooth device. 1 means on, 0 means off.
This may control the led, the device or both.
Users: Lapsus

View File

@ -0,0 +1,50 @@
What: /sys/devices/platform/eeepc-laptop/disp
Date: May 2008
KernelVersion: 2.6.26
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
This file allows display switching.
- 1 = LCD
- 2 = CRT
- 3 = LCD+CRT
If you run X11, you should use xrandr instead.
What: /sys/devices/platform/eeepc-laptop/camera
Date: May 2008
KernelVersion: 2.6.26
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the camera. 1 means on, 0 means off.
What: /sys/devices/platform/eeepc-laptop/cardr
Date: May 2008
KernelVersion: 2.6.26
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the card reader. 1 means on, 0 means off.
What: /sys/devices/platform/eeepc-laptop/cpufv
Date: Jun 2009
KernelVersion: 2.6.31
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Change CPU clock configuration.
On the Eee PC 1000H there are three available clock configuration:
* 0 -> Super Performance Mode
* 1 -> High Performance Mode
* 2 -> Power Saving Mode
On Eee PC 701 there is only 2 available clock configurations.
Available configuration are listed in available_cpufv file.
Reading this file will show the raw hexadecimal value which
is defined as follow:
| 8 bit | 8 bit |
| `---- Current mode
`------------ Availables modes
For example, 0x301 means: mode 1 selected, 3 available modes.
What: /sys/devices/platform/eeepc-laptop/available_cpufv
Date: Jun 2009
KernelVersion: 2.6.31
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
List available cpufv modes.

View File

@ -0,0 +1,51 @@
Kernel driver power_meter
=========================
This driver talks to ACPI 4.0 power meters.
Supported systems:
* Any recent system with ACPI 4.0.
Prefix: 'power_meter'
Datasheet: http://acpi.info/, section 10.4.
Author: Darrick J. Wong
Description
-----------
This driver implements sensor reading support for the power meters exposed in
the ACPI 4.0 spec (Chapter 10.4). These devices have a simple set of
features--a power meter that returns average power use over a configurable
interval, an optional capping mechanism, and a couple of trip points. The
sysfs interface conforms with the specification outlined in the "Power" section
of Documentation/hwmon/sysfs-interface.
Special Features
----------------
The power[1-*]_is_battery knob indicates if the power supply is a battery.
Both power[1-*]_average_{min,max} must be set before the trip points will work.
When both of them are set, an ACPI event will be broadcast on the ACPI netlink
socket and a poll notification will be sent to the appropriate
power[1-*]_average sysfs file.
The power[1-*]_{model_number, serial_number, oem_info} fields display arbitrary
strings that ACPI provides with the meter. The measures/ directory contains
symlinks to the devices that this meter measures.
Some computers have the ability to enforce a power cap in hardware. If this is
the case, the power[1-*]_cap and related sysfs files will appear. When the
average power consumption exceeds the cap, an ACPI event will be broadcast on
the netlink event socket and a poll notification will be sent to the
appropriate power[1-*]_alarm file to indicate that capping has begun, and the
hardware has taken action to reduce power consumption. Most likely this will
result in reduced performance.
There are a few other ACPI notifications that can be sent by the firmware. In
all cases the ACPI event will be broadcast on the ACPI netlink event socket as
well as sent as a poll notification to a sysfs file. The events are as
follows:
power[1-*]_cap will be notified if the firmware changes the power cap.
power[1-*]_interval will be notified if the firmware changes the averaging
interval.

View File

@ -0,0 +1,258 @@
Asus Laptop Extras
Version 0.1
August 6, 2009
Corentin Chary <corentincj@iksaif.net>
http://acpi4asus.sf.net/
This driver provides support for extra features of ACPI-compatible ASUS laptops.
It may also support some MEDION, JVC or VICTOR laptops (such as MEDION 9675 or
VICTOR XP7210 for example). It makes all the extra buttons generate standard
ACPI events that go through /proc/acpi/events and input events (like keyboards).
On some models adds support for changing the display brightness and output,
switching the LCD backlight on and off, and most importantly, allows you to
blink those fancy LEDs intended for reporting mail and wireless status.
This driver supercedes the old asus_acpi driver.
Requirements
------------
Kernel 2.6.X sources, configured for your computer, with ACPI support.
You also need CONFIG_INPUT and CONFIG_ACPI.
Status
------
The features currently supported are the following (see below for
detailed description):
- Fn key combinations
- Bluetooth enable and disable
- Wlan enable and disable
- GPS enable and disable
- Video output switching
- Ambient Light Sensor on and off
- LED control
- LED Display control
- LCD brightness control
- LCD on and off
A compatibility table by model and feature is maintained on the web
site, http://acpi4asus.sf.net/.
Usage
-----
Try "modprobe asus_acpi". Check your dmesg (simply type dmesg). You should
see some lines like this :
Asus Laptop Extras version 0.42
L2D model detected.
If it is not the output you have on your laptop, send it (and the laptop's
DSDT) to me.
That's all, now, all the events generated by the hotkeys of your laptop
should be reported in your /proc/acpi/event entry. You can check with
"acpi_listen".
Hotkeys are also reported as input keys (like keyboards) you can check
which key are supported using "xev" under X11.
You can get informations on the version of your DSDT table by reading the
/sys/devices/platform/asus-laptop/infos entry. If you have a question or a
bug report to do, please include the output of this entry.
LEDs
----
You can modify LEDs be echoing values to /sys/class/leds/asus::*/brightness :
echo 1 > /sys/class/leds/asus::mail/brightness
will switch the mail LED on.
You can also know if they are on/off by reading their content and use
kernel triggers like ide-disk or heartbeat.
Backlight
---------
You can control lcd backlight power and brightness with
/sys/class/backlight/asus-laptop/. Brightness Values are between 0 and 15.
Wireless devices
---------------
You can turn the internal Bluetooth adapter on/off with the bluetooth entry
(only on models with Bluetooth). This usually controls the associated LED.
Same for Wlan adapter.
Display switching
-----------------
Note: the display switching code is currently considered EXPERIMENTAL.
Switching works for the following models:
L3800C
A2500H
L5800C
M5200N
W1000N (albeit with some glitches)
M6700R
A6JC
F3J
Switching doesn't work for the following:
M3700N
L2X00D (locks the laptop under certain conditions)
To switch the displays, echo values from 0 to 15 to
/sys/devices/platform/asus-laptop/display. The significance of those values
is as follows:
+-------+-----+-----+-----+-----+-----+
| Bin | Val | DVI | TV | CRT | LCD |
+-------+-----+-----+-----+-----+-----+
+ 0000 + 0 + + + + +
+-------+-----+-----+-----+-----+-----+
+ 0001 + 1 + + + + X +
+-------+-----+-----+-----+-----+-----+
+ 0010 + 2 + + + X + +
+-------+-----+-----+-----+-----+-----+
+ 0011 + 3 + + + X + X +
+-------+-----+-----+-----+-----+-----+
+ 0100 + 4 + + X + + +
+-------+-----+-----+-----+-----+-----+
+ 0101 + 5 + + X + + X +
+-------+-----+-----+-----+-----+-----+
+ 0110 + 6 + + X + X + +
+-------+-----+-----+-----+-----+-----+
+ 0111 + 7 + + X + X + X +
+-------+-----+-----+-----+-----+-----+
+ 1000 + 8 + X + + + +
+-------+-----+-----+-----+-----+-----+
+ 1001 + 9 + X + + + X +
+-------+-----+-----+-----+-----+-----+
+ 1010 + 10 + X + + X + +
+-------+-----+-----+-----+-----+-----+
+ 1011 + 11 + X + + X + X +
+-------+-----+-----+-----+-----+-----+
+ 1100 + 12 + X + X + + +
+-------+-----+-----+-----+-----+-----+
+ 1101 + 13 + X + X + + X +
+-------+-----+-----+-----+-----+-----+
+ 1110 + 14 + X + X + X + +
+-------+-----+-----+-----+-----+-----+
+ 1111 + 15 + X + X + X + X +
+-------+-----+-----+-----+-----+-----+
In most cases, the appropriate displays must be plugged in for the above
combinations to work. TV-Out may need to be initialized at boot time.
Debugging:
1) Check whether the Fn+F8 key:
a) does not lock the laptop (try disabling CONFIG_X86_UP_APIC or boot with
noapic / nolapic if it does)
b) generates events (0x6n, where n is the value corresponding to the
configuration above)
c) actually works
Record the disp value at every configuration.
2) Echo values from 0 to 15 to /sys/devices/platform/asus-laptop/display.
Record its value, note any change. If nothing changes, try a broader range,
up to 65535.
3) Send ANY output (both positive and negative reports are needed, unless your
machine is already listed above) to the acpi4asus-user mailing list.
Note: on some machines (e.g. L3C), after the module has been loaded, only 0x6n
events are generated and no actual switching occurs. In such a case, a line
like:
echo $((10#$arg-60)) > /sys/devices/platform/asus-laptop/display
will usually do the trick ($arg is the 0000006n-like event passed to acpid).
Note: there is currently no reliable way to read display status on xxN
(Centrino) models.
LED display
-----------
Some models like the W1N have a LED display that can be used to display
several informations.
LED display works for the following models:
W1000N
W1J
To control the LED display, use the following :
echo 0x0T000DDD > /sys/devices/platform/asus-laptop/
where T control the 3 letters display, and DDD the 3 digits display,
according to the tables below.
DDD (digits)
000 to 999 = display digits
AAA = ---
BBB to FFF = turn-off
T (type)
0 = off
1 = dvd
2 = vcd
3 = mp3
4 = cd
5 = tv
6 = cpu
7 = vol
For example "echo 0x01000001 >/sys/devices/platform/asus-laptop/ledd"
would display "DVD001".
Driver options:
---------------
Options can be passed to the asus-laptop driver using the standard
module argument syntax (<param>=<value> when passing the option to the
module or asus-laptop.<param>=<value> on the kernel boot line when
asus-laptop is statically linked into the kernel).
wapf: WAPF defines the behavior of the Fn+Fx wlan key
The significance of values is yet to be found, but
most of the time:
- 0x0 should do nothing
- 0x1 should allow to control the device with Fn+Fx key.
- 0x4 should send an ACPI event (0x88) while pressing the Fn+Fx key
- 0x5 like 0x1 or 0x4
The default value is 0x1.
Unsupported models
------------------
These models will never be supported by this module, as they use a completely
different mechanism to handle LEDs and extra stuff (meaning we have no clue
how it works):
- ASUS A1300 (A1B), A1370D
- ASUS L7300G
- ASUS L8400
Patches, Errors, Questions:
--------------------------
I appreciate any success or failure
reports, especially if they add to or correct the compatibility table.
Please include the following information in your report:
- Asus model name
- a copy of your ACPI tables, using the "acpidump" utility
- a copy of /sys/devices/platform/asus-laptop/infos
- which driver features work and which don't
- the observed behavior of non-working features
Any other comments or patches are also more than welcome.
acpi4asus-user@lists.sourceforge.net
http://sourceforge.net/projects/acpi4asus

View File

@ -219,7 +219,7 @@ The following commands can be written to the /proc/acpi/ibm/hotkey file:
echo 0xffffffff > /proc/acpi/ibm/hotkey -- enable all hot keys
echo 0 > /proc/acpi/ibm/hotkey -- disable all possible hot keys
... any other 8-hex-digit mask ...
echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
echo reset > /proc/acpi/ibm/hotkey -- restore the recommended mask
The following commands have been deprecated and will cause the kernel
to log a warning:
@ -240,9 +240,13 @@ sysfs notes:
Returns 0.
hotkey_bios_mask:
DEPRECATED, DON'T USE, WILL BE REMOVED IN THE FUTURE.
Returns the hot keys mask when thinkpad-acpi was loaded.
Upon module unload, the hot keys mask will be restored
to this value.
to this value. This is always 0x80c, because those are
the hotkeys that were supported by ancient firmware
without mask support.
hotkey_enable:
DEPRECATED, WILL BE REMOVED SOON.

View File

@ -1,3 +1,4 @@
LED handling under Linux
========================
@ -5,10 +6,10 @@ If you're reading this and thinking about keyboard leds, these are
handled by the input subsystem and the led class is *not* needed.
In its simplest form, the LED class just allows control of LEDs from
userspace. LEDs appear in /sys/class/leds/. The brightness file will
set the brightness of the LED (taking a value 0-255). Most LEDs don't
have hardware brightness support so will just be turned on for non-zero
brightness settings.
userspace. LEDs appear in /sys/class/leds/. The maximum brightness of the
LED is defined in max_brightness file. The brightness file will set the brightness
of the LED (taking a value 0-max_brightness). Most LEDs don't have hardware
brightness support so will just be turned on for non-zero brightness settings.
The class also introduces the optional concept of an LED trigger. A trigger
is a kernel based source of led events. Triggers can either be simple or

View File

@ -5069,6 +5069,11 @@ T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.2.x/tomoyo-lsm/patches
S: Maintained
F: security/tomoyo/
TOPSTAR LAPTOP EXTRAS DRIVER
M: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
S: Maintained
F: drivers/platform/x86/topstar-laptop.c
TOSHIBA ACPI EXTRAS DRIVER
S: Orphan
F: drivers/platform/x86/toshiba_acpi.c

View File

@ -2026,24 +2026,21 @@ acpi_sba_ioc_add(struct acpi_device *device)
struct ioc *ioc;
acpi_status status;
u64 hpa, length;
struct acpi_buffer buffer;
struct acpi_device_info *dev_info;
status = hp_acpi_csr_space(device->handle, &hpa, &length);
if (ACPI_FAILURE(status))
return 1;
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_get_object_info(device->handle, &buffer);
status = acpi_get_object_info(device->handle, &dev_info);
if (ACPI_FAILURE(status))
return 1;
dev_info = buffer.pointer;
/*
* For HWP0001, only SBA appears in ACPI namespace. It encloses the PCI
* root bridges, and its CSR space includes the IOC function.
*/
if (strncmp("HWP0001", dev_info->hardware_id.value, 7) == 0) {
if (strncmp("HWP0001", dev_info->hardware_id.string, 7) == 0) {
hpa += ZX1_IOC_OFFSET;
/* zx1 based systems default to kernel page size iommu pages */
if (!iovp_shift)

View File

@ -144,7 +144,6 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate)
#else /* !CONFIG_ACPI */
#define acpi_disabled 1
#define acpi_lapic 0
#define acpi_ioapic 0
static inline void acpi_noirq_set(void) { }

View File

@ -18,6 +18,8 @@
#include <asm/e820.h>
#include <asm/pci_x86.h>
#define PREFIX "PCI: "
/* aperture is up to 256MB but BIOS may reserve less */
#define MMCONFIG_APER_MIN (2 * 1024*1024)
#define MMCONFIG_APER_MAX (256 * 1024*1024)

View File

@ -60,7 +60,11 @@ config ACPI_PROCFS
/proc/acpi/fadt (/sys/firmware/acpi/tables/FACP)
/proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer)
/proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level)
/proc/acpi/processor/*/power (/sys/devices/system/cpu/*/cpuidle/*)
/proc/acpi/processor/*/performance (/sys/devices/system/cpu/*/
cpufreq/*)
/proc/acpi/processor/*/throttling (/sys/class/thermal/
cooling_device*/*)
This option has no effect on /proc/acpi/ files
and functions which do not yet exist in /sys.
@ -82,6 +86,17 @@ config ACPI_PROCFS_POWER
Say N to delete power /proc/acpi/ directories that have moved to /sys/
config ACPI_POWER_METER
tristate "ACPI 4.0 power meter"
depends on HWMON
help
This driver exposes ACPI 4.0 power meters as hardware monitoring
devices. Say Y (or M) if you have a computer with ACPI 4.0 firmware
and a power meter.
To compile this driver as a module, choose M here:
the module will be called power-meter.
config ACPI_SYSFS_POWER
bool "Future power /sys interface"
select POWER_SUPPLY

View File

@ -56,6 +56,7 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_SBS) += sbshc.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o
# processor has its own "processor." module_param namespace
processor-y := processor_core.o processor_throttling.o

View File

@ -37,6 +37,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_AC_DEVICE_NAME "AC Adapter"
#define ACPI_AC_FILE_STATE "state"

View File

@ -53,7 +53,6 @@ MODULE_LICENSE("GPL");
static int acpi_memory_device_add(struct acpi_device *device);
static int acpi_memory_device_remove(struct acpi_device *device, int type);
static int acpi_memory_device_start(struct acpi_device *device);
static const struct acpi_device_id memory_device_ids[] = {
{ACPI_MEMORY_DEVICE_HID, 0},
@ -68,7 +67,6 @@ static struct acpi_driver acpi_memory_device_driver = {
.ops = {
.add = acpi_memory_device_add,
.remove = acpi_memory_device_remove,
.start = acpi_memory_device_start,
},
};
@ -431,6 +429,22 @@ static int acpi_memory_device_add(struct acpi_device *device)
printk(KERN_DEBUG "%s \n", acpi_device_name(device));
/*
* Early boot code has recognized memory area by EFI/E820.
* If DSDT shows these memory devices on boot, hotplug is not necessary
* for them. So, it just returns until completion of this driver's
* start up.
*/
if (!acpi_hotmem_initialized)
return 0;
if (!acpi_memory_check_device(mem_device)) {
/* call add_memory func */
result = acpi_memory_enable_device(mem_device);
if (result)
printk(KERN_ERR PREFIX
"Error in acpi_memory_enable_device\n");
}
return result;
}
@ -448,32 +462,6 @@ static int acpi_memory_device_remove(struct acpi_device *device, int type)
return 0;
}
static int acpi_memory_device_start (struct acpi_device *device)
{
struct acpi_memory_device *mem_device;
int result = 0;
/*
* Early boot code has recognized memory area by EFI/E820.
* If DSDT shows these memory devices on boot, hotplug is not necessary
* for them. So, it just returns until completion of this driver's
* start up.
*/
if (!acpi_hotmem_initialized)
return 0;
mem_device = acpi_driver_data(device);
if (!acpi_memory_check_device(mem_device)) {
/* call add_memory func */
result = acpi_memory_enable_device(mem_device);
if (result)
printk(KERN_ERR PREFIX
"Error in acpi_memory_enable_device\n");
}
return result;
}
/*
* Helper function to check for memory device
*/
@ -481,26 +469,23 @@ static acpi_status is_memory_device(acpi_handle handle)
{
char *hardware_id;
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_device_info *info;
status = acpi_get_object_info(handle, &buffer);
status = acpi_get_object_info(handle, &info);
if (ACPI_FAILURE(status))
return status;
info = buffer.pointer;
if (!(info->valid & ACPI_VALID_HID)) {
kfree(buffer.pointer);
kfree(info);
return AE_ERROR;
}
hardware_id = info->hardware_id.value;
hardware_id = info->hardware_id.string;
if ((hardware_id == NULL) ||
(strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
status = AE_ERROR;
kfree(buffer.pointer);
kfree(info);
return status;
}

View File

@ -28,7 +28,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \
nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
nsparse.o nspredef.o
nsparse.o nspredef.o nsrepair.o
acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
@ -44,4 +44,4 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
utstate.o utmutex.o utobject.o utresrc.o utlock.o
utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o

View File

@ -183,7 +183,7 @@
/* Operation regions */
#define ACPI_NUM_PREDEFINED_REGIONS 8
#define ACPI_NUM_PREDEFINED_REGIONS 9
#define ACPI_USER_REGION_BEGIN 0x80
/* Maximum space_ids for Operation Regions */
@ -199,9 +199,15 @@
#define ACPI_RSDP_CHECKSUM_LENGTH 20
#define ACPI_RSDP_XCHECKSUM_LENGTH 36
/* SMBus bidirectional buffer size */
/* SMBus and IPMI bidirectional buffer size */
#define ACPI_SMBUS_BUFFER_SIZE 34
#define ACPI_IPMI_BUFFER_SIZE 66
/* _sx_d and _sx_w control methods */
#define ACPI_NUM_sx_d_METHODS 4
#define ACPI_NUM_sx_w_METHODS 5
/******************************************************************************
*

View File

@ -154,10 +154,6 @@ void
acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
void acpi_db_check_predefined_names(void);
void acpi_db_batch_execute(void);
/*
* dbexec - debugger control method execution
*/

View File

@ -58,6 +58,10 @@
#define ACPI_INIT_GLOBAL(a,b) a
#endif
#ifdef DEFINE_ACPI_GLOBALS
/* Public globals, available from outside ACPICA subsystem */
/*****************************************************************************
*
* Runtime configuration (static defaults that can be overriden at runtime)
@ -78,7 +82,7 @@
* 5) Allow unresolved references (invalid target name) in package objects
* 6) Enable warning messages for behavior that is not ACPI spec compliant
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
/*
* Automatically serialize ALL control methods? Default is FALSE, meaning
@ -86,27 +90,36 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
* Only change this if the ASL code is poorly written and cannot handle
* reentrancy even though methods are marked "NotSerialized".
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE);
/*
* Create the predefined _OSI method in the namespace? Default is TRUE
* because ACPI CA is fully compatible with other ACPI implementations.
* Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE);
/*
* Disable wakeup GPEs during runtime? Default is TRUE because WAKE and
* RUNTIME GPEs should never be shared, and WAKE GPEs should typically only
* be enabled just before going to sleep.
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE);
/*
* Optionally use default values for the ACPI register widths. Set this to
* TRUE to use the defaults, if an FADT contains incorrect widths/lengths.
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
struct acpi_table_fadt acpi_gbl_FADT;
u32 acpi_current_gpe_count;
u32 acpi_gbl_trace_flags;
acpi_name acpi_gbl_trace_method_name;
#endif
/*****************************************************************************
*
@ -114,11 +127,6 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
*
****************************************************************************/
/* Runtime configuration of debug print levels */
extern u32 acpi_dbg_level;
extern u32 acpi_dbg_layer;
/* Procedure nesting level for debug output */
extern u32 acpi_gbl_nesting_level;
@ -127,10 +135,8 @@ extern u32 acpi_gbl_nesting_level;
ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
ACPI_EXTERN u32 acpi_gbl_original_dbg_layer;
ACPI_EXTERN acpi_name acpi_gbl_trace_method_name;
ACPI_EXTERN u32 acpi_gbl_trace_dbg_level;
ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
ACPI_EXTERN u32 acpi_gbl_trace_flags;
/*****************************************************************************
*
@ -142,10 +148,8 @@ ACPI_EXTERN u32 acpi_gbl_trace_flags;
* acpi_gbl_root_table_list is the master list of ACPI tables found in the
* RSDT/XSDT.
*
* acpi_gbl_FADT is a local copy of the FADT, converted to a common format.
*/
ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list;
ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT;
ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS;
/* These addresses are calculated from the FADT Event Block addresses */
@ -261,7 +265,8 @@ ACPI_EXTERN u8 acpi_gbl_osi_data;
extern u8 acpi_gbl_shutdown;
extern u32 acpi_gbl_startup_flags;
extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT];
extern const char *acpi_gbl_highest_dstate_names[4];
extern const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS];
extern const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS];
extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
@ -290,6 +295,7 @@ extern char const *acpi_gbl_exception_names_ctrl[];
ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct;
ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node;
ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device;
ACPI_EXTERN union acpi_operand_object *acpi_gbl_module_code_list;
extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES];
extern const struct acpi_predefined_names
@ -340,7 +346,6 @@ ACPI_EXTERN struct acpi_fixed_event_handler
ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
ACPI_EXTERN struct acpi_gpe_block_info
*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
ACPI_EXTERN u32 acpi_current_gpe_count;
/*****************************************************************************
*

View File

@ -62,6 +62,14 @@ u32 acpi_hw_get_mode(void);
/*
* hwregs - ACPI Register I/O
*/
acpi_status
acpi_hw_validate_register(struct acpi_generic_address *reg,
u8 max_bit_width, u64 *address);
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg);
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg);
struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id);
acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control);

View File

@ -461,9 +461,9 @@ void acpi_ex_acquire_global_lock(u32 rule);
void acpi_ex_release_global_lock(u32 rule);
void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string);
void acpi_ex_eisa_id_to_string(char *dest, acpi_integer compressed_id);
void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string);
void acpi_ex_integer_to_string(char *dest, acpi_integer value);
/*
* exregion - default op_region handlers

View File

@ -369,6 +369,19 @@ union acpi_predefined_info {
struct acpi_package_info3 ret_info3;
};
/* Data block used during object validation */
struct acpi_predefined_data {
char *pathname;
const union acpi_predefined_info *predefined;
u32 flags;
u8 node_flags;
};
/* Defines for Flags field above */
#define ACPI_OBJECT_REPAIRED 1
/*
* Bitmapped return value types
* Note: the actual data types must be contiguous, a loop in nspredef.c
@ -885,6 +898,9 @@ struct acpi_bit_register_info {
#define ACPI_OSI_WIN_XP_SP2 0x05
#define ACPI_OSI_WINSRV_2003_SP1 0x06
#define ACPI_OSI_WIN_VISTA 0x07
#define ACPI_OSI_WINSRV_2008 0x08
#define ACPI_OSI_WIN_VISTA_SP1 0x09
#define ACPI_OSI_WIN_7 0x0A
#define ACPI_ALWAYS_ILLEGAL 0x00

View File

@ -340,6 +340,7 @@
*/
#define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e);
#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e);
#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist
#else
@ -347,6 +348,7 @@
#define ACPI_ERROR_NAMESPACE(s, e)
#define ACPI_ERROR_METHOD(s, n, p, e)
#define ACPI_WARN_PREDEFINED(plist)
#endif /* ACPI_NO_ERROR_MESSAGES */
/*

View File

@ -73,6 +73,14 @@
#define ACPI_NS_WALK_UNLOCK 0x01
#define ACPI_NS_WALK_TEMP_NODES 0x02
/* Object is not a package element */
#define ACPI_NOT_PACKAGE_ELEMENT ACPI_UINT32_MAX
/* Always emit warning message, not dependent on node flags */
#define ACPI_WARN_ALWAYS 0
/*
* nsinit - Namespace initialization
*/
@ -144,6 +152,8 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name);
void acpi_ns_delete_node(struct acpi_namespace_node *node);
void acpi_ns_remove_node(struct acpi_namespace_node *node);
void
acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_handle);
@ -186,6 +196,8 @@ acpi_ns_dump_objects(acpi_object_type type,
*/
acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
void acpi_ns_exec_module_code_list(void);
/*
* nspredef - Support for predefined/reserved names
*/
@ -259,6 +271,19 @@ acpi_status
acpi_ns_get_attached_data(struct acpi_namespace_node *node,
acpi_object_handler handler, void **data);
/*
* nsrepair - return object repair for predefined methods/objects
*/
acpi_status
acpi_ns_repair_object(struct acpi_predefined_data *data,
u32 expected_btypes,
u32 package_index,
union acpi_operand_object **return_object_ptr);
acpi_status
acpi_ns_repair_package_list(struct acpi_predefined_data *data,
union acpi_operand_object **obj_desc_ptr);
/*
* nssearch - Namespace searching and entry
*/

View File

@ -98,6 +98,7 @@
#define AOPOBJ_SETUP_COMPLETE 0x10
#define AOPOBJ_SINGLE_DATUM 0x20
#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */
#define AOPOBJ_MODULE_LEVEL 0x80
/******************************************************************************
*

View File

@ -62,6 +62,8 @@
#define ACPI_PARSE_DEFERRED_OP 0x0100
#define ACPI_PARSE_DISASSEMBLE 0x0200
#define ACPI_PARSE_MODULE_LEVEL 0x0400
/******************************************************************************
*
* Parser interfaces

View File

@ -64,8 +64,8 @@
* (Used for _PRW)
*
*
* 2) PTYPE2 packages contain a variable number of sub-packages. Each of the
* different types describe the contents of each of the sub-packages.
* 2) PTYPE2 packages contain a Variable-length number of sub-packages. Each
* of the different types describe the contents of each of the sub-packages.
*
* ACPI_PTYPE2: Each subpackage contains 1 or 2 object types:
* object type
@ -91,6 +91,9 @@
* ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length
* (Used for _HPX)
*
* ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length
* (Used for _ART, _FPS)
*
*****************************************************************************/
enum acpi_return_package_types {
@ -101,9 +104,11 @@ enum acpi_return_package_types {
ACPI_PTYPE2_COUNT = 5,
ACPI_PTYPE2_PKG_COUNT = 6,
ACPI_PTYPE2_FIXED = 7,
ACPI_PTYPE2_MIN = 8
ACPI_PTYPE2_MIN = 8,
ACPI_PTYPE2_REV_FIXED = 9
};
#ifdef ACPI_CREATE_PREDEFINED_TABLE
/*
* Predefined method/object information table.
*
@ -136,239 +141,384 @@ enum acpi_return_package_types {
* is saved here (rather than in a separate table) in order to minimize the
* overall size of the stored data.
*/
static const union acpi_predefined_info predefined_names[] = {
{.info = {"_AC0", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AC1", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AC2", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AC3", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AC4", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AC5", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AC6", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AC7", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AC8", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AC9", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_ADR", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_AL0", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_AL1", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_AL2", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_AL3", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_AL4", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_AL5", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_AL6", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_AL7", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_AL8", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_AL9", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_ALC", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_ALI", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_ALP", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_ALR", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2, 0, 0, 0}}, /* variable (Pkgs) each 2 (Ints) */
{.info = {"_ALT", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_BBN", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_BCL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Ints) */
{.info = {"_BCM", 1, 0}},
{.info = {"_BDN", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_BFS", 1, 0}},
{.info = {"_BIF", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER,
9,
ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 4, 0}}, /* fixed (9 Int),(4 Str) */
{.info = {"_BLT", 3, 0}},
{.info = {"_BMC", 1, 0}},
{.info = {"_BMD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* fixed (5 Int) */
{.info = {"_BQC", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_BST", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0}}, /* fixed (4 Int) */
{.info = {"_BTM", 1, ACPI_RTYPE_INTEGER}},
{.info = {"_BTP", 1, 0}},
{.info = {"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* see PCI firmware spec 3.0 */
{.info = {"_CID", 0,
ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}},
{.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0, 0, 0, 0}}, /* variable (Ints/Strs) */
{.info = {"_CRS", 0, ACPI_RTYPE_BUFFER}},
{.info = {"_CRT", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_CSD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (1 Int(n), n-1 Int) */
{.info = {"_CST", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_PKG_COUNT,
ACPI_RTYPE_BUFFER, 1,
ACPI_RTYPE_INTEGER, 3, 0}}, /* variable (1 Int(n), n Pkg (1 Buf/3 Int) */
{.info = {"_DCK", 1, ACPI_RTYPE_INTEGER}},
{.info = {"_DCS", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}},
{.info = {"_DDN", 0, ACPI_RTYPE_STRING}},
{.info = {"_DGS", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_DIS", 0, 0}},
{.info = {"_DMA", 0, ACPI_RTYPE_BUFFER}},
{.info = {"_DOD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Ints) */
{.info = {"_DOS", 1, 0}},
{.info = {"_DSM", 4, ACPI_RTYPE_ALL}}, /* Must return a type, but it can be of any type */
{.info = {"_DSS", 1, 0}},
{.info = {"_DSW", 3, 0}},
{.info = {"_EC_", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_EDL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_EJ0", 1, 0}},
{.info = {"_EJ1", 1, 0}},
{.info = {"_EJ2", 1, 0}},
{.info = {"_EJ3", 1, 0}},
{.info = {"_EJ4", 1, 0}},
{.info = {"_EJD", 0, ACPI_RTYPE_STRING}},
{.info = {"_FDE", 0, ACPI_RTYPE_BUFFER}},
{.info = {"_FDI", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, 0, 0, 0}}, /* fixed (16 Int) */
{.info = {"_FDM", 1, 0}},
{.info = {"_FIX", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Ints) */
{.info = {"_GLK", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_GPD", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */
{.info = {"_GSB", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_GTF", 0, ACPI_RTYPE_BUFFER}},
{.info = {"_GTM", 0, ACPI_RTYPE_BUFFER}},
{.info = {"_GTS", 1, 0}},
{.info = {"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}},
{.info = {"_HOT", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_HPP", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0}}, /* fixed (4 Int) */
static const union acpi_predefined_info predefined_names[] =
{
{{"_AC0", 0, ACPI_RTYPE_INTEGER}},
{{"_AC1", 0, ACPI_RTYPE_INTEGER}},
{{"_AC2", 0, ACPI_RTYPE_INTEGER}},
{{"_AC3", 0, ACPI_RTYPE_INTEGER}},
{{"_AC4", 0, ACPI_RTYPE_INTEGER}},
{{"_AC5", 0, ACPI_RTYPE_INTEGER}},
{{"_AC6", 0, ACPI_RTYPE_INTEGER}},
{{"_AC7", 0, ACPI_RTYPE_INTEGER}},
{{"_AC8", 0, ACPI_RTYPE_INTEGER}},
{{"_AC9", 0, ACPI_RTYPE_INTEGER}},
{{"_ADR", 0, ACPI_RTYPE_INTEGER}},
{{"_AL0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_AL1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_AL2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_AL3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_AL4", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_AL5", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_AL6", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_AL7", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_AL8", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_AL9", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_ALC", 0, ACPI_RTYPE_INTEGER}},
{{"_ALI", 0, ACPI_RTYPE_INTEGER}},
{{"_ALP", 0, ACPI_RTYPE_INTEGER}},
{{"_ALR", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2 (Ints) */
{{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2,0}, 0,0}},
{{"_ALT", 0, ACPI_RTYPE_INTEGER}},
{{"_ART", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (2 Ref/11 Int) */
{{{ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER},
11, 0}},
{{"_BBN", 0, ACPI_RTYPE_INTEGER}},
{{"_BCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}},
{{"_BCM", 1, 0}},
{{"_BCT", 1, ACPI_RTYPE_INTEGER}},
{{"_BDN", 0, ACPI_RTYPE_INTEGER}},
{{"_BFS", 1, 0}},
{{"_BIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (9 Int),(4 Str) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, ACPI_RTYPE_STRING}, 4,0}},
{{"_BIX", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int),(4 Str) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, ACPI_RTYPE_STRING}, 4,
0}},
{{"_BLT", 3, 0}},
{{"_BMA", 1, ACPI_RTYPE_INTEGER}},
{{"_BMC", 1, 0}},
{{"_BMD", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (5 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5,0}, 0,0}},
{{"_BMS", 1, ACPI_RTYPE_INTEGER}},
{{"_BQC", 0, ACPI_RTYPE_INTEGER}},
{{"_BST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}},
{{"_BTM", 1, ACPI_RTYPE_INTEGER}},
{{"_BTP", 1, 0}},
{{"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* See PCI firmware spec 3.0 */
{{"_CDM", 0, ACPI_RTYPE_INTEGER}},
{{"_CID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Strs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0}, 0,0}},
{{"_CRS", 0, ACPI_RTYPE_BUFFER}},
{{"_CRT", 0, ACPI_RTYPE_INTEGER}},
{{"_CSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n-1 Int) */
{{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0,0}, 0,0}},
{{"_CST", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */
{{{ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3,0}},
{{"_DCK", 1, ACPI_RTYPE_INTEGER}},
{{"_DCS", 0, ACPI_RTYPE_INTEGER}},
{{"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}},
{{"_DDN", 0, ACPI_RTYPE_STRING}},
{{"_DGS", 0, ACPI_RTYPE_INTEGER}},
{{"_DIS", 0, 0}},
{{"_DMA", 0, ACPI_RTYPE_BUFFER}},
{{"_DOD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}},
{{"_DOS", 1, 0}},
{{"_DSM", 4, ACPI_RTYPE_ALL}}, /* Must return a type, but it can be of any type */
{{"_DSS", 1, 0}},
{{"_DSW", 3, 0}},
{{"_DTI", 1, 0}},
{{"_EC_", 0, ACPI_RTYPE_INTEGER}},
{{"_EDL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs)*/
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_EJ0", 1, 0}},
{{"_EJ1", 1, 0}},
{{"_EJ2", 1, 0}},
{{"_EJ3", 1, 0}},
{{"_EJ4", 1, 0}},
{{"_EJD", 0, ACPI_RTYPE_STRING}},
{{"_FDE", 0, ACPI_RTYPE_BUFFER}},
{{"_FDI", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,0}, 0,0}},
{{"_FDM", 1, 0}},
{{"_FIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0}, 0, 0}},
{{"_FIX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}},
{{"_FPS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (5 Int) */
{{{ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_INTEGER, 5, 0}, 0, 0}},
{{"_FSL", 1, 0}},
{{"_FST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}},
{{"_GAI", 0, ACPI_RTYPE_INTEGER}},
{{"_GHL", 0, ACPI_RTYPE_INTEGER}},
{{"_GLK", 0, ACPI_RTYPE_INTEGER}},
{{"_GPD", 0, ACPI_RTYPE_INTEGER}},
{{"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */
{{"_GSB", 0, ACPI_RTYPE_INTEGER}},
{{"_GTF", 0, ACPI_RTYPE_BUFFER}},
{{"_GTM", 0, ACPI_RTYPE_BUFFER}},
{{"_GTS", 1, 0}},
{{"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}},
{{"_HOT", 0, ACPI_RTYPE_INTEGER}},
{{"_HPP", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}},
/*
* For _HPX, a single package is returned, containing a variable number of sub-packages.
* Each sub-package contains a PCI record setting. There are several different type of
* record settings, of different lengths, but all elements of all settings are Integers.
* For _HPX, a single package is returned, containing a Variable-length number
* of sub-packages. Each sub-package contains a PCI record setting.
* There are several different type of record settings, of different
* lengths, but all elements of all settings are Integers.
*/
{.info = {"_HPX", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* variable (Pkgs) each (var Ints) */
{.info = {"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* see IPMI spec */
{.info = {"_INI", 0, 0}},
{.info = {"_IRC", 0, 0}},
{.info = {"_LCK", 1, 0}},
{.info = {"_LID", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_MAT", 0, ACPI_RTYPE_BUFFER}},
{.info = {"_MLS", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_STRING, 2, 0, 0, 0}}, /* variable (Pkgs) each (2 Str) */
{.info = {"_MSG", 1, 0}},
{.info = {"_OFF", 0, 0}},
{.info = {"_ON_", 0, 0}},
{.info = {"_OS_", 0, ACPI_RTYPE_STRING}},
{.info = {"_OSC", 4, ACPI_RTYPE_BUFFER}},
{.info = {"_OST", 3, 0}},
{.info = {"_PCL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_PCT", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2, 0, 0, 0}}, /* fixed (2 Buf) */
{.info = {"_PDC", 1, 0}},
{.info = {"_PIC", 1, 0}},
{.info = {"_PLD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0, 0, 0, 0}}, /* variable (Bufs) */
{.info = {"_PPC", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_PPE", 0, ACPI_RTYPE_INTEGER}}, /* see dig64 spec */
{.info = {"_PR0", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_PR1", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_PR2", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_PRS", 0, ACPI_RTYPE_BUFFER}},
{{"_HPX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (var Ints) */
{{{ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5,0}, 0,0}},
{{"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */
{{"_INI", 0, 0}},
{{"_IRC", 0, 0}},
{{"_LCK", 1, 0}},
{{"_LID", 0, ACPI_RTYPE_INTEGER}},
{{"_MAT", 0, ACPI_RTYPE_BUFFER}},
{{"_MBM", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (8 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8, 0}, 0, 0}},
{{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (2 Str) */
{{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 2,0}, 0,0}},
{{"_MSG", 1, 0}},
{{"_MSM", 4, ACPI_RTYPE_INTEGER}},
{{"_NTT", 0, ACPI_RTYPE_INTEGER}},
{{"_OFF", 0, 0}},
{{"_ON_", 0, 0}},
{{"_OS_", 0, ACPI_RTYPE_STRING}},
{{"_OSC", 4, ACPI_RTYPE_BUFFER}},
{{"_OST", 3, 0}},
{{"_PAI", 1, ACPI_RTYPE_INTEGER}},
{{"_PCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_PCT", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}},
{{"_PDC", 1, 0}},
{{"_PDL", 0, ACPI_RTYPE_INTEGER}},
{{"_PIC", 1, 0}},
{{"_PIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int),(3 Str) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, ACPI_RTYPE_STRING}, 3, 0}},
{{"_PLD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Bufs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0,0}, 0,0}},
{{"_PMC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (11 Int),(3 Str) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 11, ACPI_RTYPE_STRING}, 3,
0}},
{{"_PMD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
{{"_PMM", 0, ACPI_RTYPE_INTEGER}},
{{"_PPC", 0, ACPI_RTYPE_INTEGER}},
{{"_PPE", 0, ACPI_RTYPE_INTEGER}}, /* See dig64 spec */
{{"_PR0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_PR1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_PR2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_PR3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
{{"_PRL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
{{"_PRS", 0, ACPI_RTYPE_BUFFER}},
/*
* For _PRT, many BIOSs reverse the 2nd and 3rd Package elements. This bug is so prevalent that there
* is code in the ACPICA Resource Manager to detect this and switch them back. For now, do not allow
* and issue a warning. To allow this and eliminate the warning, add the ACPI_RTYPE_REFERENCE
* type to the 2nd element (index 1) in the statement below.
* For _PRT, many BIOSs reverse the 3rd and 4th Package elements (Source
* and source_index). This bug is so prevalent that there is code in the
* ACPICA Resource Manager to detect this and switch them back. For now,
* do not allow and issue a warning. To allow this and eliminate the
* warning, add the ACPI_RTYPE_REFERENCE type to the 4th element (index 3)
* in the statement below.
*/
{.info = {"_PRT", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_FIXED, 4,
ACPI_RTYPE_INTEGER,
ACPI_RTYPE_INTEGER,
ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE, ACPI_RTYPE_INTEGER}}, /* variable (Pkgs) each (4): Int,Int,Int/Ref,Int */
{{"_PRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (4): Int,Int,Int/Ref,Int */
{{{ACPI_PTYPE2_FIXED, 4, ACPI_RTYPE_INTEGER,ACPI_RTYPE_INTEGER},
ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE,
ACPI_RTYPE_INTEGER}},
{.info = {"_PRW", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_OPTION, 2,
ACPI_RTYPE_INTEGER |
ACPI_RTYPE_PACKAGE,
ACPI_RTYPE_INTEGER, ACPI_RTYPE_REFERENCE, 0}}, /* variable (Pkgs) each: Pkg/Int,Int,[variable Refs] (Pkg is Ref/Int) */
{{"_PRW", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each: Pkg/Int,Int,[Variable-length Refs] (Pkg is Ref/Int) */
{{{ACPI_PTYPE1_OPTION, 2, ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE,
ACPI_RTYPE_INTEGER}, ACPI_RTYPE_REFERENCE,0}},
{.info = {"_PS0", 0, 0}},
{.info = {"_PS1", 0, 0}},
{.info = {"_PS2", 0, 0}},
{.info = {"_PS3", 0, 0}},
{.info = {"_PSC", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_PSD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Pkgs) each (5 Int) with count */
{.info = {"_PSL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_PSR", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_PSS", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6, 0, 0, 0}}, /* variable (Pkgs) each (6 Int) */
{.info = {"_PSV", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_PSW", 1, 0}},
{.info = {"_PTC", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2, 0, 0, 0}}, /* fixed (2 Buf) */
{.info = {"_PTS", 1, 0}},
{.info = {"_PXM", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_REG", 2, 0}},
{.info = {"_REV", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_RMV", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_ROM", 2, ACPI_RTYPE_BUFFER}},
{.info = {"_RTV", 0, ACPI_RTYPE_INTEGER}},
{{"_PS0", 0, 0}},
{{"_PS1", 0, 0}},
{{"_PS2", 0, 0}},
{{"_PS3", 0, 0}},
{{"_PSC", 0, ACPI_RTYPE_INTEGER}},
{{"_PSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (5 Int) with count */
{{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER,0,0}, 0,0}},
{{"_PSL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_PSR", 0, ACPI_RTYPE_INTEGER}},
{{"_PSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (6 Int) */
{{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6,0}, 0,0}},
{{"_PSV", 0, ACPI_RTYPE_INTEGER}},
{{"_PSW", 1, 0}},
{{"_PTC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}},
{{"_PTP", 2, ACPI_RTYPE_INTEGER}},
{{"_PTS", 1, 0}},
{{"_PUR", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0}, 0, 0}},
{{"_PXM", 0, ACPI_RTYPE_INTEGER}},
{{"_REG", 2, 0}},
{{"_REV", 0, ACPI_RTYPE_INTEGER}},
{{"_RMV", 0, ACPI_RTYPE_INTEGER}},
{{"_ROM", 2, ACPI_RTYPE_BUFFER}},
{{"_RTV", 0, ACPI_RTYPE_INTEGER}},
/*
* For _S0_ through _S5_, the ACPI spec defines a return Package containing 1 Integer,
* but most DSDTs have it wrong - 2,3, or 4 integers. Allow this by making the objects "variable length",
* but all elements must be Integers.
* For _S0_ through _S5_, the ACPI spec defines a return Package
* containing 1 Integer, but most DSDTs have it wrong - 2,3, or 4 integers.
* Allow this by making the objects "Variable-length length", but all elements
* must be Integers.
*/
{.info = {"_S0_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */
{.info = {"_S1_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */
{.info = {"_S2_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */
{.info = {"_S3_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */
{.info = {"_S4_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */
{.info = {"_S5_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */
{{"_S0_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}},
{.info = {"_S1D", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_S2D", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_S3D", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_S4D", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_S0W", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_S1W", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_S2W", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_S3W", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_S4W", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_SBS", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_SCP", 0x13, 0}}, /* Acpi 1.0 allowed 1 arg. Acpi 3.0 expanded to 3 args. Allow both. */
/* Note: the 3-arg definition may be removed for ACPI 4.0 */
{.info = {"_SDD", 1, 0}},
{.info = {"_SEG", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_SLI", 0, ACPI_RTYPE_BUFFER}},
{.info = {"_SPD", 1, ACPI_RTYPE_INTEGER}},
{.info = {"_SRS", 1, 0}},
{.info = {"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* see IPMI spec */
{.info = {"_SST", 1, 0}},
{.info = {"_STA", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_STM", 3, 0}},
{.info = {"_STR", 0, ACPI_RTYPE_BUFFER}},
{.info = {"_SUN", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_SWS", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_TC1", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_TC2", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_TMP", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_TPC", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_TPT", 1, 0}},
{.info = {"_TRT", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2,
ACPI_RTYPE_INTEGER, 6, 0}}, /* variable (Pkgs) each 2_ref/6_int */
{.info = {"_TSD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* variable (Pkgs) each 5_int with count */
{.info = {"_TSP", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_TSS", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* variable (Pkgs) each 5_int */
{.info = {"_TST", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_TTS", 1, 0}},
{.info = {"_TZD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */
{.info = {"_TZM", 0, ACPI_RTYPE_REFERENCE}},
{.info = {"_TZP", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_UID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}},
{.info = {"_UPC", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0}}, /* fixed (4 Int) */
{.info = {"_UPD", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_UPP", 0, ACPI_RTYPE_INTEGER}},
{.info = {"_VPO", 0, ACPI_RTYPE_INTEGER}},
{{"_S1_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}},
{{"_S2_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}},
{{"_S3_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}},
{{"_S4_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}},
{{"_S5_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}},
{{"_S1D", 0, ACPI_RTYPE_INTEGER}},
{{"_S2D", 0, ACPI_RTYPE_INTEGER}},
{{"_S3D", 0, ACPI_RTYPE_INTEGER}},
{{"_S4D", 0, ACPI_RTYPE_INTEGER}},
{{"_S0W", 0, ACPI_RTYPE_INTEGER}},
{{"_S1W", 0, ACPI_RTYPE_INTEGER}},
{{"_S2W", 0, ACPI_RTYPE_INTEGER}},
{{"_S3W", 0, ACPI_RTYPE_INTEGER}},
{{"_S4W", 0, ACPI_RTYPE_INTEGER}},
{{"_SBS", 0, ACPI_RTYPE_INTEGER}},
{{"_SCP", 0x13, 0}}, /* Acpi 1.0 allowed 1 arg. Acpi 3.0 expanded to 3 args. Allow both. */
/* Note: the 3-arg definition may be removed for ACPI 4.0 */
{{"_SDD", 1, 0}},
{{"_SEG", 0, ACPI_RTYPE_INTEGER}},
{{"_SHL", 1, ACPI_RTYPE_INTEGER}},
{{"_SLI", 0, ACPI_RTYPE_BUFFER}},
{{"_SPD", 1, ACPI_RTYPE_INTEGER}},
{{"_SRS", 1, 0}},
{{"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */
{{"_SST", 1, 0}},
{{"_STA", 0, ACPI_RTYPE_INTEGER}},
{{"_STM", 3, 0}},
{{"_STP", 2, ACPI_RTYPE_INTEGER}},
{{"_STR", 0, ACPI_RTYPE_BUFFER}},
{{"_STV", 2, ACPI_RTYPE_INTEGER}},
{{"_SUN", 0, ACPI_RTYPE_INTEGER}},
{{"_SWS", 0, ACPI_RTYPE_INTEGER}},
{{"_TC1", 0, ACPI_RTYPE_INTEGER}},
{{"_TC2", 0, ACPI_RTYPE_INTEGER}},
{{"_TIP", 1, ACPI_RTYPE_INTEGER}},
{{"_TIV", 1, ACPI_RTYPE_INTEGER}},
{{"_TMP", 0, ACPI_RTYPE_INTEGER}},
{{"_TPC", 0, ACPI_RTYPE_INTEGER}},
{{"_TPT", 1, 0}},
{{"_TRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2_ref/6_int */
{{{ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER}, 6, 0}},
{{"_TSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5_int with count */
{{{ACPI_PTYPE2_COUNT,ACPI_RTYPE_INTEGER, 5,0}, 0,0}},
{{"_TSP", 0, ACPI_RTYPE_INTEGER}},
{{"_TSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5_int */
{{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5,0}, 0,0}},
{{"_TST", 0, ACPI_RTYPE_INTEGER}},
{{"_TTS", 1, 0}},
{{"_TZD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
{{"_TZM", 0, ACPI_RTYPE_REFERENCE}},
{{"_TZP", 0, ACPI_RTYPE_INTEGER}},
{{"_UID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}},
{{"_UPC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}},
{{"_UPD", 0, ACPI_RTYPE_INTEGER}},
{{"_UPP", 0, ACPI_RTYPE_INTEGER}},
{{"_VPO", 0, ACPI_RTYPE_INTEGER}},
/* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */
{.info = {"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
{.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0}}, /* fixed (2 Int), but is optional */
{.ret_info = {0, 0, 0, 0, 0, 0}} /* Table terminator */
{{"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, /* Fixed-length (2 Int), but is optional */
{{{0,0,0,0}, 0,0}} /* Table terminator */
};
#if 0
/* Not implemented */
{
"_WDG", 0, ACPI_RTYPE_BUFFER}, /* MS Extension */
{{"_WDG", 0, ACPI_RTYPE_BUFFER}}, /* MS Extension */
{{"_WED", 1, ACPI_RTYPE_PACKAGE}}, /* MS Extension */
{
"_WED", 1, ACPI_RTYPE_PACKAGE}, /* MS Extension */
/* This is an internally implemented control method, no need to check */
{{"_OSI", 1, ACPI_RTYPE_INTEGER}},
/* This is an internally implemented control method, no need to check */
{
"_OSI", 1, ACPI_RTYPE_INTEGER},
/* TBD: */
_PRT - currently ignore reversed entries. attempt to fix here?
think about possibly fixing package elements like _BIF, etc.
#endif
/* TBD: */
_PRT - currently ignore reversed entries.attempt to fix here ?
think about code that attempts to fix package elements like _BIF, etc.
#endif
#endif

View File

@ -324,26 +324,30 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
acpi_status
acpi_ut_evaluate_numeric_object(char *object_name,
struct acpi_namespace_node *device_node,
acpi_integer * address);
acpi_integer *value);
acpi_status
acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 *status_flags);
acpi_status
acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
const char **method_names,
u8 method_count, u8 *out_values);
/*
* utids - device ID support
*/
acpi_status
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
struct acpica_device_id *hid);
acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
struct acpi_compatible_id_list **return_cid_list);
acpi_status
acpi_ut_execute_STA(struct acpi_namespace_node *device_node,
u32 * status_flags);
struct acpica_device_id **return_id);
acpi_status
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
struct acpica_device_id *uid);
struct acpica_device_id **return_id);
acpi_status
acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest);
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
struct acpica_device_id_list **return_cid_list);
/*
* utlock - reader/writer locks
@ -445,6 +449,8 @@ acpi_ut_short_divide(acpi_integer in_dividend,
*/
const char *acpi_ut_validate_exception(acpi_status status);
u8 acpi_ut_is_pci_root_bridge(char *id);
u8 acpi_ut_is_aml_table(struct acpi_table_header *table);
acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id);
@ -469,6 +475,12 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position);
acpi_status
acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer);
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_warning(const char *module_name,
u32 line_number,
char *pathname,
u8 node_flags, const char *format, ...);
/* Values for Base above (16=Hex, 10=Decimal) */
#define ACPI_ANY_BASE 0

View File

@ -404,6 +404,7 @@ typedef enum {
REGION_SMBUS,
REGION_CMOS,
REGION_PCI_BAR,
REGION_IPMI,
REGION_DATA_TABLE, /* Internal use only */
REGION_FIXED_HW = 0x7F
} AML_REGION_TYPES;

View File

@ -123,9 +123,12 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
/* Mark node temporary if we are executing a method */
if (walk_state->method_node) {
/*
* Mark node temporary if we are executing a normal control
* method. (Don't mark if this is a module-level code method)
*/
if (walk_state->method_node &&
!(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}
@ -456,9 +459,12 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
/* Mark node(s) temporary if we are executing a method */
if (walk_state->method_node) {
/*
* Mark node(s) temporary if we are executing a normal control
* method. (Don't mark if this is a module-level code method)
*/
if (walk_state->method_node &&
!(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}

View File

@ -578,10 +578,15 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
}
/*
* Delete any namespace objects created anywhere within
* the namespace by the execution of this method
* Delete any namespace objects created anywhere within the
* namespace by the execution of this method. Unless this method
* is a module-level executable code method, in which case we
* want make the objects permanent.
*/
acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id);
if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
acpi_ns_delete_namespace_by_owner(method_desc->method.
owner_id);
}
}
/* Decrement the thread count on the method */
@ -622,7 +627,9 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
/* No more threads, we can free the owner_id */
acpi_ut_release_owner_id(&method_desc->method.owner_id);
if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
acpi_ut_release_owner_id(&method_desc->method.owner_id);
}
}
return_VOID;

View File

@ -433,10 +433,10 @@ acpi_ds_method_data_get_value(u8 type,
case ACPI_REFCLASS_LOCAL:
ACPI_ERROR((AE_INFO,
"Uninitialized Local[%d] at node %p",
index, node));
/*
* No error message for this case, will be trapped again later to
* detect and ignore cases of Store(local_x,local_x)
*/
return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
default:

View File

@ -482,14 +482,27 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
if (arg) {
/*
* num_elements was exhausted, but there are remaining elements in the
* package_list.
* package_list. Truncate the package to num_elements.
*
* Note: technically, this is an error, from ACPI spec: "It is an error
* for NumElements to be less than the number of elements in the
* PackageList". However, for now, we just print an error message and
* no exception is returned.
* PackageList". However, we just print an error message and
* no exception is returned. This provides Windows compatibility. Some
* BIOSs will alter the num_elements on the fly, creating this type
* of ill-formed package object.
*/
while (arg) {
/*
* We must delete any package elements that were created earlier
* and are not going to be used because of the package truncation.
*/
if (arg->common.node) {
acpi_ut_remove_reference(ACPI_CAST_PTR
(union
acpi_operand_object,
arg->common.node));
arg->common.node = NULL;
}
/* Find out how many elements there really are */
@ -498,7 +511,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
}
ACPI_WARNING((AE_INFO,
"Package List length (%X) larger than NumElements count (%X), truncated\n",
"Package List length (0x%X) larger than NumElements count (0x%X), truncated\n",
i, element_count));
} else if (i < element_count) {
/*
@ -506,7 +519,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
* Note: this is not an error, the package is padded out with NULLs.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Package List length (%X) smaller than NumElements count (%X), padded with null elements\n",
"Package List length (0x%X) smaller than NumElements count (0x%X), padded with null elements\n",
i, element_count));
}

View File

@ -581,21 +581,6 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
(walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
(!(walk_state->op_info->flags & AML_NAMED))) {
#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
(walk_state->op_info->class == AML_CLASS_CONTROL)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Begin/EXEC: %s (fl %8.8X)\n",
walk_state->op_info->name,
walk_state->op_info->flags));
/* Executing a type1 or type2 opcode outside of a method */
status =
acpi_ds_exec_begin_op(walk_state, out_op);
return_ACPI_STATUS(status);
}
#endif
return_ACPI_STATUS(AE_OK);
}
@ -768,7 +753,13 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
/* Execution mode, node cannot already exist, node is temporary */
flags |= (ACPI_NS_ERROR_IF_FOUND | ACPI_NS_TEMPORARY);
flags |= ACPI_NS_ERROR_IF_FOUND;
if (!
(walk_state->
parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}
}
/* Add new entry or lookup existing entry */
@ -851,24 +842,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
/* Check if opcode had an associated namespace object */
if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
#ifndef ACPI_NO_METHOD_EXECUTION
#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
/* No namespace object. Executable opcode? */
if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
(walk_state->op_info->class == AML_CLASS_CONTROL)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"End/EXEC: %s (fl %8.8X)\n",
walk_state->op_info->name,
walk_state->op_info->flags));
/* Executing a type1 or type2 opcode outside of a method */
status = acpi_ds_exec_end_op(walk_state);
return_ACPI_STATUS(status);
}
#endif
#endif
return_ACPI_STATUS(AE_OK);
}

View File

@ -424,8 +424,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
/* Read the Status Register */
status =
acpi_read(&status_reg,
&gpe_register_info->status_address);
acpi_hw_read(&status_reg,
&gpe_register_info->status_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@ -433,8 +433,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
/* Read the Enable Register */
status =
acpi_read(&enable_reg,
&gpe_register_info->enable_address);
acpi_hw_read(&enable_reg,
&gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}

View File

@ -843,14 +843,14 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
/* Disable all GPEs within this register */
status = acpi_write(0x00, &this_register->enable_address);
status = acpi_hw_write(0x00, &this_register->enable_address);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
/* Clear any pending GPE events within this register */
status = acpi_write(0xFF, &this_register->status_address);
status = acpi_hw_write(0xFF, &this_register->status_address);
if (ACPI_FAILURE(status)) {
goto error_exit;
}

View File

@ -50,8 +50,6 @@
ACPI_MODULE_NAME("evrgnini")
/* Local prototypes */
static u8 acpi_ev_match_pci_root_bridge(char *id);
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node);
/*******************************************************************************
@ -330,37 +328,6 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_match_pci_root_bridge
*
* PARAMETERS: Id - The HID/CID in string format
*
* RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge
*
* DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID.
*
******************************************************************************/
static u8 acpi_ev_match_pci_root_bridge(char *id)
{
/*
* Check if this is a PCI root.
* ACPI 3.0+: check for a PCI Express root also.
*/
if (!(ACPI_STRNCMP(id,
PCI_ROOT_HID_STRING,
sizeof(PCI_ROOT_HID_STRING))) ||
!(ACPI_STRNCMP(id,
PCI_EXPRESS_ROOT_HID_STRING,
sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) {
return (TRUE);
}
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_is_pci_root_bridge
@ -377,9 +344,10 @@ static u8 acpi_ev_match_pci_root_bridge(char *id)
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
{
acpi_status status;
struct acpica_device_id hid;
struct acpi_compatible_id_list *cid;
struct acpica_device_id *hid;
struct acpica_device_id_list *cid;
u32 i;
u8 match;
/* Get the _HID and check for a PCI Root Bridge */
@ -388,7 +356,10 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
return (FALSE);
}
if (acpi_ev_match_pci_root_bridge(hid.value)) {
match = acpi_ut_is_pci_root_bridge(hid->string);
ACPI_FREE(hid);
if (match) {
return (TRUE);
}
@ -402,7 +373,7 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
/* Check all _CIDs in the returned list */
for (i = 0; i < cid->count; i++) {
if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) {
if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) {
ACPI_FREE(cid);
return (TRUE);
}

View File

@ -110,8 +110,15 @@ acpi_ex_add_table(u32 table_index,
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(obj_desc);
*ddb_handle = NULL;
return_ACPI_STATUS(status);
}
/* Execute any module-level code that was found in the table */
acpi_ex_exit_interpreter();
acpi_ns_exec_module_code_list();
acpi_ex_enter_interpreter();
return_ACPI_STATUS(status);
}

View File

@ -418,9 +418,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
case ACPI_EXD_REFERENCE:
acpi_ex_out_string("Class Name",
(char *)
acpi_ut_get_reference_name
(obj_desc));
ACPI_CAST_PTR(char,
acpi_ut_get_reference_name
(obj_desc)));
acpi_ex_dump_reference_obj(obj_desc);
break;

View File

@ -72,6 +72,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
union acpi_operand_object *buffer_desc;
acpi_size length;
void *buffer;
u32 function;
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
@ -97,13 +98,27 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
}
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS)) {
ACPI_ADR_SPACE_SMBUS
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
* This is an SMBus read. We must create a buffer to hold the data
* and directly access the region handler.
* This is an SMBus or IPMI read. We must create a buffer to hold
* the data and then directly access the region handler.
*
* Note: Smbus protocol value is passed in upper 16-bits of Function
*/
buffer_desc =
acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS) {
length = ACPI_SMBUS_BUFFER_SIZE;
function =
ACPI_READ | (obj_desc->field.attribute << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
function = ACPI_READ;
}
buffer_desc = acpi_ut_create_buffer_object(length);
if (!buffer_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@ -112,16 +127,13 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/*
* Perform the read.
* Note: Smbus protocol value is passed in upper 16-bits of Function
*/
/* Call the region handler for the read */
status = acpi_ex_access_region(obj_desc, 0,
ACPI_CAST_PTR(acpi_integer,
buffer_desc->
buffer.pointer),
ACPI_READ | (obj_desc->field.
attribute << 16));
function);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
goto exit;
}
@ -212,6 +224,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
u32 length;
void *buffer;
union acpi_operand_object *buffer_desc;
u32 function;
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
@ -234,39 +247,56 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
}
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS)) {
ACPI_ADR_SPACE_SMBUS
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
* This is an SMBus write. We will bypass the entire field mechanism
* and handoff the buffer directly to the handler.
* This is an SMBus or IPMI write. We will bypass the entire field
* mechanism and handoff the buffer directly to the handler. For
* these address spaces, the buffer is bi-directional; on a write,
* return data is returned in the same buffer.
*
* Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
* Source must be a buffer of sufficient size:
* ACPI_SMBUS_BUFFER_SIZE or ACPI_IPMI_BUFFER_SIZE.
*
* Note: SMBus protocol type is passed in upper 16-bits of Function
*/
if (source_desc->common.type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO,
"SMBus write requires Buffer, found type %s",
"SMBus or IPMI write requires Buffer, found type %s",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS) {
length = ACPI_SMBUS_BUFFER_SIZE;
function =
ACPI_WRITE | (obj_desc->field.attribute << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
function = ACPI_WRITE;
}
if (source_desc->buffer.length < length) {
ACPI_ERROR((AE_INFO,
"SMBus write requires Buffer of length %X, found length %X",
ACPI_SMBUS_BUFFER_SIZE,
source_desc->buffer.length));
"SMBus or IPMI write requires Buffer of length %X, found length %X",
length, source_desc->buffer.length));
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
buffer_desc =
acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
/* Create the bi-directional buffer */
buffer_desc = acpi_ut_create_buffer_object(length);
if (!buffer_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
buffer = buffer_desc->buffer.pointer;
ACPI_MEMCPY(buffer, source_desc->buffer.pointer,
ACPI_SMBUS_BUFFER_SIZE);
ACPI_MEMCPY(buffer, source_desc->buffer.pointer, length);
/* Lock entire transaction if requested */
@ -275,12 +305,10 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
/*
* Perform the write (returns status and perhaps data in the
* same buffer)
* Note: SMBus protocol type is passed in upper 16-bits of Function.
*/
status = acpi_ex_access_region(obj_desc, 0,
(acpi_integer *) buffer,
ACPI_WRITE | (obj_desc->field.
attribute << 16));
function);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
*result_desc = buffer_desc;

View File

@ -120,12 +120,13 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
}
/*
* Exit now for SMBus address space, it has a non-linear address space
* Exit now for SMBus or IPMI address space, it has a non-linear address space
* and the request cannot be directly validated
*/
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
/* SMBus has a non-linear address space */
/* SMBus or IPMI has a non-linear address space */
return_ACPI_STATUS(AE_OK);
}

View File

@ -358,50 +358,67 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base)
*
* FUNCTION: acpi_ex_eisa_id_to_string
*
* PARAMETERS: numeric_id - EISA ID to be converted
* PARAMETERS: compressed_id - EISAID to be converted
* out_string - Where to put the converted string (8 bytes)
*
* RETURN: None
*
* DESCRIPTION: Convert a numeric EISA ID to string representation
* DESCRIPTION: Convert a numeric EISAID to string representation. Return
* buffer must be large enough to hold the string. The string
* returned is always exactly of length ACPI_EISAID_STRING_SIZE
* (includes null terminator). The EISAID is always 32 bits.
*
******************************************************************************/
void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string)
void acpi_ex_eisa_id_to_string(char *out_string, acpi_integer compressed_id)
{
u32 eisa_id;
u32 swapped_id;
ACPI_FUNCTION_ENTRY();
/* The EISAID should be a 32-bit integer */
if (compressed_id > ACPI_UINT32_MAX) {
ACPI_WARNING((AE_INFO,
"Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating",
ACPI_FORMAT_UINT64(compressed_id)));
}
/* Swap ID to big-endian to get contiguous bits */
eisa_id = acpi_ut_dword_byte_swap(numeric_id);
swapped_id = acpi_ut_dword_byte_swap((u32)compressed_id);
out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f));
out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f));
out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f));
out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12);
out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8);
out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4);
out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0);
/* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */
out_string[0] =
(char)(0x40 + (((unsigned long)swapped_id >> 26) & 0x1F));
out_string[1] = (char)(0x40 + ((swapped_id >> 21) & 0x1F));
out_string[2] = (char)(0x40 + ((swapped_id >> 16) & 0x1F));
out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 12);
out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 8);
out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 4);
out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 0);
out_string[7] = 0;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_unsigned_integer_to_string
* FUNCTION: acpi_ex_integer_to_string
*
* PARAMETERS: Value - Value to be converted
* out_string - Where to put the converted string (8 bytes)
* PARAMETERS: out_string - Where to put the converted string. At least
* 21 bytes are needed to hold the largest
* possible 64-bit integer.
* Value - Value to be converted
*
* RETURN: None, string
*
* DESCRIPTION: Convert a number to string representation. Assumes string
* buffer is large enough to hold the string.
* DESCRIPTION: Convert a 64-bit integer to decimal string representation.
* Assumes string buffer is large enough to hold the string. The
* largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1).
*
******************************************************************************/
void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string)
void acpi_ex_integer_to_string(char *out_string, acpi_integer value)
{
u32 count;
u32 digits_needed;

View File

@ -82,7 +82,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
/* Get current value of the enable register that contains this GPE */
status = acpi_read(&enable_mask, &gpe_register_info->enable_address);
status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
@ -95,7 +95,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
/* Write the updated enable mask */
status = acpi_write(enable_mask, &gpe_register_info->enable_address);
status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
return (status);
}
@ -130,8 +130,8 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
/* Write the entire GPE (runtime) enable register */
status = acpi_write(gpe_register_info->enable_for_run,
&gpe_register_info->enable_address);
status = acpi_hw_write(gpe_register_info->enable_for_run,
&gpe_register_info->enable_address);
return (status);
}
@ -163,8 +163,8 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
status = acpi_write(register_bit,
&gpe_event_info->register_info->status_address);
status = acpi_hw_write(register_bit,
&gpe_event_info->register_info->status_address);
return (status);
}
@ -222,7 +222,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
/* GPE currently active (status bit == 1)? */
status = acpi_read(&in_byte, &gpe_register_info->status_address);
status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@ -266,8 +266,8 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Disable all GPEs in this register */
status =
acpi_write(0x00,
&gpe_block->register_info[i].enable_address);
acpi_hw_write(0x00,
&gpe_block->register_info[i].enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
@ -303,8 +303,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Clear status on all GPEs in this register */
status =
acpi_write(0xFF,
&gpe_block->register_info[i].status_address);
acpi_hw_write(0xFF,
&gpe_block->register_info[i].status_address);
if (ACPI_FAILURE(status)) {
return (status);
}
@ -345,9 +345,9 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Enable all "runtime" GPEs in this register */
status = acpi_write(gpe_block->register_info[i].enable_for_run,
&gpe_block->register_info[i].
enable_address);
status =
acpi_hw_write(gpe_block->register_info[i].enable_for_run,
&gpe_block->register_info[i].enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
@ -387,9 +387,9 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Enable all "wake" GPEs in this register */
status = acpi_write(gpe_block->register_info[i].enable_for_wake,
&gpe_block->register_info[i].
enable_address);
status =
acpi_hw_write(gpe_block->register_info[i].enable_for_wake,
&gpe_block->register_info[i].enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}

View File

@ -62,6 +62,184 @@ acpi_hw_write_multiple(u32 value,
struct acpi_generic_address *register_a,
struct acpi_generic_address *register_b);
/******************************************************************************
*
* FUNCTION: acpi_hw_validate_register
*
* PARAMETERS: Reg - GAS register structure
* max_bit_width - Max bit_width supported (32 or 64)
* Address - Pointer to where the gas->address
* is returned
*
* RETURN: Status
*
* DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
* pointer, Address, space_id, bit_width, and bit_offset.
*
******************************************************************************/
acpi_status
acpi_hw_validate_register(struct acpi_generic_address *reg,
u8 max_bit_width, u64 *address)
{
/* Must have a valid pointer to a GAS structure */
if (!reg) {
return (AE_BAD_PARAMETER);
}
/*
* Copy the target address. This handles possible alignment issues.
* Address must not be null. A null address also indicates an optional
* ACPI register that is not supported, so no error message.
*/
ACPI_MOVE_64_TO_64(address, &reg->address);
if (!(*address)) {
return (AE_BAD_ADDRESS);
}
/* Validate the space_iD */
if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
(reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
ACPI_ERROR((AE_INFO,
"Unsupported address space: 0x%X", reg->space_id));
return (AE_SUPPORT);
}
/* Validate the bit_width */
if ((reg->bit_width != 8) &&
(reg->bit_width != 16) &&
(reg->bit_width != 32) && (reg->bit_width != max_bit_width)) {
ACPI_ERROR((AE_INFO,
"Unsupported register bit width: 0x%X",
reg->bit_width));
return (AE_SUPPORT);
}
/* Validate the bit_offset. Just a warning for now. */
if (reg->bit_offset != 0) {
ACPI_WARNING((AE_INFO,
"Unsupported register bit offset: 0x%X",
reg->bit_offset));
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_read
*
* PARAMETERS: Value - Where the value is returned
* Reg - GAS register structure
*
* RETURN: Status
*
* DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
* version of acpi_read, used internally since the overhead of
* 64-bit values is not needed.
*
* LIMITATIONS: <These limitations also apply to acpi_hw_write>
* bit_width must be exactly 8, 16, or 32.
* space_iD must be system_memory or system_iO.
* bit_offset and access_width are currently ignored, as there has
* not been a need to implement these.
*
******************************************************************************/
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
{
u64 address;
acpi_status status;
ACPI_FUNCTION_NAME(hw_read);
/* Validate contents of the GAS register */
status = acpi_hw_validate_register(reg, 32, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Initialize entire 32-bit return value to zero */
*value = 0;
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_read_memory((acpi_physical_address)
address, value, reg->bit_width);
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_read_port((acpi_io_address)
address, value, reg->bit_width);
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
*value, reg->bit_width, ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_write
*
* PARAMETERS: Value - Value to be written
* Reg - GAS register structure
*
* RETURN: Status
*
* DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
* version of acpi_write, used internally since the overhead of
* 64-bit values is not needed.
*
******************************************************************************/
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
{
u64 address;
acpi_status status;
ACPI_FUNCTION_NAME(hw_write);
/* Validate contents of the GAS register */
status = acpi_hw_validate_register(reg, 32, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_write_memory((acpi_physical_address)
address, value, reg->bit_width);
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_write_port((acpi_io_address)
address, value, reg->bit_width);
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
value, reg->bit_width, ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_clear_acpi_status
@ -152,15 +330,16 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control)
ACPI_FUNCTION_TRACE(hw_write_pm1_control);
status = acpi_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
status =
acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (acpi_gbl_FADT.xpm1b_control_block.address) {
status =
acpi_write(pm1b_control,
&acpi_gbl_FADT.xpm1b_control_block);
acpi_hw_write(pm1b_control,
&acpi_gbl_FADT.xpm1b_control_block);
}
return_ACPI_STATUS(status);
}
@ -218,12 +397,13 @@ acpi_hw_register_read(u32 register_id, u32 * return_value)
case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
status = acpi_read(&value, &acpi_gbl_FADT.xpm2_control_block);
status =
acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block);
break;
case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
status = acpi_read(&value, &acpi_gbl_FADT.xpm_timer_block);
status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block);
break;
case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
@ -340,7 +520,8 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value)
* as per the ACPI spec.
*/
status =
acpi_read(&read_value, &acpi_gbl_FADT.xpm2_control_block);
acpi_hw_read(&read_value,
&acpi_gbl_FADT.xpm2_control_block);
if (ACPI_FAILURE(status)) {
goto exit;
}
@ -350,12 +531,13 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value)
ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS,
read_value);
status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block);
status =
acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block);
break;
case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block);
status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block);
break;
case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
@ -401,7 +583,7 @@ acpi_hw_read_multiple(u32 *value,
/* The first register is always required */
status = acpi_read(&value_a, register_a);
status = acpi_hw_read(&value_a, register_a);
if (ACPI_FAILURE(status)) {
return (status);
}
@ -409,7 +591,7 @@ acpi_hw_read_multiple(u32 *value,
/* Second register is optional */
if (register_b->address) {
status = acpi_read(&value_b, register_b);
status = acpi_hw_read(&value_b, register_b);
if (ACPI_FAILURE(status)) {
return (status);
}
@ -452,7 +634,7 @@ acpi_hw_write_multiple(u32 value,
/* The first register is always required */
status = acpi_write(value, register_a);
status = acpi_hw_write(value, register_a);
if (ACPI_FAILURE(status)) {
return (status);
}
@ -470,7 +652,7 @@ acpi_hw_write_multiple(u32 value,
* and writes have no side effects"
*/
if (register_b->address) {
status = acpi_write(value, register_b);
status = acpi_hw_write(value, register_b);
}
return (status);

View File

@ -100,7 +100,7 @@ acpi_status acpi_get_timer(u32 * ticks)
}
status =
acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block);
acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
return_ACPI_STATUS(status);
}

View File

@ -78,9 +78,22 @@ acpi_status acpi_reset(void)
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Write the reset value to the reset register */
if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
/*
* For I/O space, write directly to the OSL. This bypasses the port
* validation mechanism, which may block a valid write to the reset
* register.
*/
status =
acpi_os_write_port((acpi_io_address) reset_reg->address,
acpi_gbl_FADT.reset_value,
reset_reg->bit_width);
} else {
/* Write the reset value to the reset register */
status = acpi_hw_write(acpi_gbl_FADT.reset_value, reset_reg);
}
status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg);
return_ACPI_STATUS(status);
}
@ -97,67 +110,92 @@ ACPI_EXPORT_SYMBOL(acpi_reset)
*
* DESCRIPTION: Read from either memory or IO space.
*
* LIMITATIONS: <These limitations also apply to acpi_write>
* bit_width must be exactly 8, 16, 32, or 64.
* space_iD must be system_memory or system_iO.
* bit_offset and access_width are currently ignored, as there has
* not been a need to implement these.
*
******************************************************************************/
acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg)
acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
{
u32 value;
u32 width;
u64 address;
acpi_status status;
ACPI_FUNCTION_NAME(acpi_read);
/*
* Must have a valid pointer to a GAS structure, and a non-zero address
* within.
*/
if (!reg) {
if (!return_value) {
return (AE_BAD_PARAMETER);
}
/* Get a local copy of the address. Handles possible alignment issues */
/* Validate contents of the GAS register. Allow 64-bit transfers */
ACPI_MOVE_64_TO_64(&address, &reg->address);
if (!address) {
return (AE_BAD_ADDRESS);
status = acpi_hw_validate_register(reg, 64, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Supported widths are 8/16/32 */
width = reg->bit_width;
if ((width != 8) && (width != 16) && (width != 32)) {
return (AE_SUPPORT);
if (width == 64) {
width = 32; /* Break into two 32-bit transfers */
}
/* Initialize entire 32-bit return value to zero */
/* Initialize entire 64-bit return value to zero */
*value = 0;
*return_value = 0;
value = 0;
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_read_memory((acpi_physical_address)
address, &value, width);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value = value;
status = acpi_os_read_memory((acpi_physical_address) address,
value, width);
break;
if (reg->bit_width == 64) {
case ACPI_ADR_SPACE_SYSTEM_IO:
/* Read the top 32 bits */
status =
acpi_hw_read_port((acpi_io_address) address, value, width);
break;
status = acpi_os_read_memory((acpi_physical_address)
(address + 4), &value, 32);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value |= ((u64)value << 32);
}
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
default:
ACPI_ERROR((AE_INFO,
"Unsupported address space: %X", reg->space_id));
return (AE_BAD_PARAMETER);
status = acpi_hw_read_port((acpi_io_address)
address, &value, width);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value = value;
if (reg->bit_width == 64) {
/* Read the top 32 bits */
status = acpi_hw_read_port((acpi_io_address)
(address + 4), &value, 32);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value |= ((u64)value << 32);
}
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
*value, width, ACPI_FORMAT_UINT64(address),
"Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
ACPI_FORMAT_UINT64(*return_value), reg->bit_width,
ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
@ -169,7 +207,7 @@ ACPI_EXPORT_SYMBOL(acpi_read)
*
* FUNCTION: acpi_write
*
* PARAMETERS: Value - To be written
* PARAMETERS: Value - Value to be written
* Reg - GAS register structure
*
* RETURN: Status
@ -177,7 +215,7 @@ ACPI_EXPORT_SYMBOL(acpi_read)
* DESCRIPTION: Write to either memory or IO space.
*
******************************************************************************/
acpi_status acpi_write(u32 value, struct acpi_generic_address *reg)
acpi_status acpi_write(u64 value, struct acpi_generic_address *reg)
{
u32 width;
u64 address;
@ -185,54 +223,61 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg)
ACPI_FUNCTION_NAME(acpi_write);
/*
* Must have a valid pointer to a GAS structure, and a non-zero address
* within.
*/
if (!reg) {
return (AE_BAD_PARAMETER);
/* Validate contents of the GAS register. Allow 64-bit transfers */
status = acpi_hw_validate_register(reg, 64, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Get a local copy of the address. Handles possible alignment issues */
ACPI_MOVE_64_TO_64(&address, &reg->address);
if (!address) {
return (AE_BAD_ADDRESS);
}
/* Supported widths are 8/16/32 */
width = reg->bit_width;
if ((width != 8) && (width != 16) && (width != 32)) {
return (AE_SUPPORT);
if (width == 64) {
width = 32; /* Break into two 32-bit transfers */
}
/*
* Two address spaces supported: Memory or IO.
* PCI_Config is not supported here because the GAS struct is insufficient
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_write_memory((acpi_physical_address)
address, ACPI_LODWORD(value),
width);
if (ACPI_FAILURE(status)) {
return (status);
}
status = acpi_os_write_memory((acpi_physical_address) address,
value, width);
break;
if (reg->bit_width == 64) {
status = acpi_os_write_memory((acpi_physical_address)
(address + 4),
ACPI_HIDWORD(value), 32);
if (ACPI_FAILURE(status)) {
return (status);
}
}
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
case ACPI_ADR_SPACE_SYSTEM_IO:
status = acpi_hw_write_port((acpi_io_address) address, value,
status = acpi_hw_write_port((acpi_io_address)
address, ACPI_LODWORD(value),
width);
break;
if (ACPI_FAILURE(status)) {
return (status);
}
default:
ACPI_ERROR((AE_INFO,
"Unsupported address space: %X", reg->space_id));
return (AE_BAD_PARAMETER);
if (reg->bit_width == 64) {
status = acpi_hw_write_port((acpi_io_address)
(address + 4),
ACPI_HIDWORD(value), 32);
if (ACPI_FAILURE(status)) {
return (status);
}
}
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
value, width, ACPI_FORMAT_UINT64(address),
"Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n",
ACPI_FORMAT_UINT64(value), reg->bit_width,
ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);

View File

@ -96,17 +96,68 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name)
*
* RETURN: None
*
* DESCRIPTION: Delete a namespace node
* DESCRIPTION: Delete a namespace node. All node deletions must come through
* here. Detaches any attached objects, including any attached
* data. If a handler is associated with attached data, it is
* invoked before the node is deleted.
*
******************************************************************************/
void acpi_ns_delete_node(struct acpi_namespace_node *node)
{
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_NAME(ns_delete_node);
/* Detach an object if there is one */
acpi_ns_detach_object(node);
/*
* Delete an attached data object if present (an object that was created
* and attached via acpi_attach_data). Note: After any normal object is
* detached above, the only possible remaining object is a data object.
*/
obj_desc = node->object;
if (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
/* Invoke the attached data deletion handler if present */
if (obj_desc->data.handler) {
obj_desc->data.handler(node, obj_desc->data.pointer);
}
acpi_ut_remove_reference(obj_desc);
}
/* Now we can delete the node */
(void)acpi_os_release_object(acpi_gbl_namespace_cache, node);
ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n",
node, acpi_gbl_current_node_count));
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_remove_node
*
* PARAMETERS: Node - Node to be removed/deleted
*
* RETURN: None
*
* DESCRIPTION: Remove (unlink) and delete a namespace node
*
******************************************************************************/
void acpi_ns_remove_node(struct acpi_namespace_node *node)
{
struct acpi_namespace_node *parent_node;
struct acpi_namespace_node *prev_node;
struct acpi_namespace_node *next_node;
ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node);
ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node);
parent_node = acpi_ns_get_parent_node(node);
@ -142,12 +193,9 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
}
}
ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
/* Delete the node and any attached objects */
/* Detach an object if there is one, then delete the node */
acpi_ns_detach_object(node);
(void)acpi_os_release_object(acpi_gbl_namespace_cache, node);
acpi_ns_delete_node(node);
return_VOID;
}
@ -273,25 +321,11 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
parent_node, child_node));
}
/* Now we can free this child object */
ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
"Object %p, Remaining %X\n", child_node,
acpi_gbl_current_node_count));
/* Detach an object if there is one, then free the child node */
acpi_ns_detach_object(child_node);
/* Now we can delete the node */
(void)acpi_os_release_object(acpi_gbl_namespace_cache,
child_node);
/* And move on to the next child in the list */
/*
* Delete this child node and move on to the next child in the list.
* No need to unlink the node since we are deleting the entire branch.
*/
acpi_ns_delete_node(child_node);
child_node = next_node;
} while (!(flags & ANOBJ_END_OF_PEER_LIST));
@ -433,7 +467,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
if (deletion_node) {
acpi_ns_delete_children(deletion_node);
acpi_ns_delete_node(deletion_node);
acpi_ns_remove_node(deletion_node);
deletion_node = NULL;
}

View File

@ -70,7 +70,6 @@ static acpi_status
acpi_ns_dump_one_device(acpi_handle obj_handle,
u32 level, void *context, void **return_value)
{
struct acpi_buffer buffer;
struct acpi_device_info *info;
acpi_status status;
u32 i;
@ -80,17 +79,15 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
status =
acpi_ns_dump_one_object(obj_handle, level, context, return_value);
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_get_object_info(obj_handle, &buffer);
status = acpi_get_object_info(obj_handle, &info);
if (ACPI_SUCCESS(status)) {
info = buffer.pointer;
for (i = 0; i < level; i++) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " "));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES,
" HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
info->hardware_id.value,
info->hardware_id.string,
ACPI_FORMAT_UINT64(info->address),
info->current_status));
ACPI_FREE(info);

View File

@ -50,6 +50,11 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nseval")
/* Local prototypes */
static void
acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
struct acpi_evaluate_info *info);
/*******************************************************************************
*
* FUNCTION: acpi_ns_evaluate
@ -76,6 +81,7 @@ ACPI_MODULE_NAME("nseval")
* MUTEX: Locks interpreter
*
******************************************************************************/
acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
{
acpi_status status;
@ -276,3 +282,134 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
*/
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_exec_module_code_list
*
* PARAMETERS: None
*
* RETURN: None. Exceptions during method execution are ignored, since
* we cannot abort a table load.
*
* DESCRIPTION: Execute all elements of the global module-level code list.
* Each element is executed as a single control method.
*
******************************************************************************/
void acpi_ns_exec_module_code_list(void)
{
union acpi_operand_object *prev;
union acpi_operand_object *next;
struct acpi_evaluate_info *info;
u32 method_count = 0;
ACPI_FUNCTION_TRACE(ns_exec_module_code_list);
/* Exit now if the list is empty */
next = acpi_gbl_module_code_list;
if (!next) {
return_VOID;
}
/* Allocate the evaluation information block */
info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info));
if (!info) {
return_VOID;
}
/* Walk the list, executing each "method" */
while (next) {
prev = next;
next = next->method.mutex;
/* Clear the link field and execute the method */
prev->method.mutex = NULL;
acpi_ns_exec_module_code(prev, info);
method_count++;
/* Delete the (temporary) method object */
acpi_ut_remove_reference(prev);
}
ACPI_INFO((AE_INFO,
"Executed %u blocks of module-level executable AML code",
method_count));
ACPI_FREE(info);
acpi_gbl_module_code_list = NULL;
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_exec_module_code
*
* PARAMETERS: method_obj - Object container for the module-level code
* Info - Info block for method evaluation
*
* RETURN: None. Exceptions during method execution are ignored, since
* we cannot abort a table load.
*
* DESCRIPTION: Execute a control method containing a block of module-level
* executable AML code. The control method is temporarily
* installed to the root node, then evaluated.
*
******************************************************************************/
static void
acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
struct acpi_evaluate_info *info)
{
union acpi_operand_object *root_obj;
acpi_status status;
ACPI_FUNCTION_TRACE(ns_exec_module_code);
/* Initialize the evaluation information block */
ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
info->prefix_node = acpi_gbl_root_node;
/*
* Get the currently attached root object. Add a reference, because the
* ref count will be decreased when the method object is installed to
* the root node.
*/
root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
acpi_ut_add_reference(root_obj);
/* Install the method (module-level code) in the root node */
status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
ACPI_TYPE_METHOD);
if (ACPI_FAILURE(status)) {
goto exit;
}
/* Execute the root node as a control method */
status = acpi_ns_evaluate(info);
ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n",
method_obj->method.aml_start));
/* Detach the temporary method object */
acpi_ns_detach_object(acpi_gbl_root_node);
/* Restore the original root object */
status =
acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
ACPI_TYPE_DEVICE);
exit:
acpi_ut_remove_reference(root_obj);
return_VOID;
}

View File

@ -170,6 +170,21 @@ acpi_status acpi_ns_initialize_devices(void)
goto error_exit;
}
/*
* Execute the "global" _INI method that may appear at the root. This
* support is provided for Windows compatibility (Vista+) and is not
* part of the ACPI specification.
*/
info.evaluate_info->prefix_node = acpi_gbl_root_node;
info.evaluate_info->pathname = METHOD_NAME__INI;
info.evaluate_info->parameters = NULL;
info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
status = acpi_ns_evaluate(info.evaluate_info);
if (ACPI_SUCCESS(status)) {
info.num_INI++;
}
/* Walk namespace to execute all _INIs on present devices */
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,

View File

@ -270,8 +270,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
/* Now delete the starting object, and we are done */
acpi_ns_delete_node(child_handle);
acpi_ns_remove_node(child_handle);
return_ACPI_STATUS(AE_OK);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,203 @@
/******************************************************************************
*
* Module Name: nsrepair - Repair for objects returned by predefined methods
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2009, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
#include "acpredef.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsrepair")
/*******************************************************************************
*
* FUNCTION: acpi_ns_repair_object
*
* PARAMETERS: Data - Pointer to validation data structure
* expected_btypes - Object types expected
* package_index - Index of object within parent package (if
* applicable - ACPI_NOT_PACKAGE_ELEMENT
* otherwise)
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN: Status. AE_OK if repair was successful.
*
* DESCRIPTION: Attempt to repair/convert a return object of a type that was
* not expected.
*
******************************************************************************/
acpi_status
acpi_ns_repair_object(struct acpi_predefined_data *data,
u32 expected_btypes,
u32 package_index,
union acpi_operand_object **return_object_ptr)
{
union acpi_operand_object *return_object = *return_object_ptr;
union acpi_operand_object *new_object;
acpi_size length;
switch (return_object->common.type) {
case ACPI_TYPE_BUFFER:
/* Does the method/object legally return a string? */
if (!(expected_btypes & ACPI_RTYPE_STRING)) {
return (AE_AML_OPERAND_TYPE);
}
/*
* Have a Buffer, expected a String, convert. Use a to_string
* conversion, no transform performed on the buffer data. The best
* example of this is the _BIF method, where the string data from
* the battery is often (incorrectly) returned as buffer object(s).
*/
length = 0;
while ((length < return_object->buffer.length) &&
(return_object->buffer.pointer[length])) {
length++;
}
/* Allocate a new string object */
new_object = acpi_ut_create_string_object(length);
if (!new_object) {
return (AE_NO_MEMORY);
}
/*
* Copy the raw buffer data with no transform. String is already NULL
* terminated at Length+1.
*/
ACPI_MEMCPY(new_object->string.pointer,
return_object->buffer.pointer, length);
/*
* If the original object is a package element, we need to:
* 1. Set the reference count of the new object to match the
* reference count of the old object.
* 2. Decrement the reference count of the original object.
*/
if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
new_object->common.reference_count =
return_object->common.reference_count;
if (return_object->common.reference_count > 1) {
return_object->common.reference_count--;
}
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
data->node_flags,
"Converted Buffer to expected String at index %u",
package_index));
} else {
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
data->node_flags,
"Converted Buffer to expected String"));
}
/* Delete old object, install the new return object */
acpi_ut_remove_reference(return_object);
*return_object_ptr = new_object;
data->flags |= ACPI_OBJECT_REPAIRED;
return (AE_OK);
default:
break;
}
return (AE_AML_OPERAND_TYPE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_repair_package_list
*
* PARAMETERS: Data - Pointer to validation data structure
* obj_desc_ptr - Pointer to the object to repair. The new
* package object is returned here,
* overwriting the old object.
*
* RETURN: Status, new object in *obj_desc_ptr
*
* DESCRIPTION: Repair a common problem with objects that are defined to return
* a variable-length Package of Packages. If the variable-length
* is one, some BIOS code mistakenly simply declares a single
* Package instead of a Package with one sub-Package. This
* function attempts to repair this error by wrapping a Package
* object around the original Package, creating the correct
* Package with one sub-Package.
*
* Names that can be repaired in this manner include:
* _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
*
******************************************************************************/
acpi_status
acpi_ns_repair_package_list(struct acpi_predefined_data *data,
union acpi_operand_object **obj_desc_ptr)
{
union acpi_operand_object *pkg_obj_desc;
/*
* Create the new outer package and populate it. The new package will
* have a single element, the lone subpackage.
*/
pkg_obj_desc = acpi_ut_create_package_object(1);
if (!pkg_obj_desc) {
return (AE_NO_MEMORY);
}
pkg_obj_desc->package.elements[0] = *obj_desc_ptr;
/* Return the new object in the object pointer */
*obj_desc_ptr = pkg_obj_desc;
data->flags |= ACPI_OBJECT_REPAIRED;
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
"Incorrectly formed Package, attempting repair"));
return (AE_OK);
}

View File

@ -88,7 +88,8 @@ acpi_ns_report_error(const char *module_name,
/* There is a non-ascii character in the name */
ACPI_MOVE_32_TO_32(&bad_name, internal_name);
ACPI_MOVE_32_TO_32(&bad_name,
ACPI_CAST_PTR(u32, internal_name));
acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
} else {
/* Convert path to external format */
@ -836,7 +837,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
acpi_status status;
char *internal_path;
ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname);
ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
if (!pathname) {
*return_node = prefix_node;

View File

@ -535,10 +535,11 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
acpi_status status;
struct acpi_namespace_node *node;
u32 flags;
struct acpica_device_id hid;
struct acpi_compatible_id_list *cid;
struct acpica_device_id *hid;
struct acpica_device_id_list *cid;
u32 i;
int found;
u8 found;
int no_match;
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
@ -582,10 +583,14 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
return (AE_CTRL_DEPTH);
}
if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) {
/* Get the list of Compatible IDs */
no_match = ACPI_STRCMP(hid->string, info->hid);
ACPI_FREE(hid);
if (no_match) {
/*
* HID does not match, attempt match within the
* list of Compatible IDs (CIDs)
*/
status = acpi_ut_execute_CID(node, &cid);
if (status == AE_NOT_FOUND) {
return (AE_OK);
@ -597,10 +602,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
found = 0;
for (i = 0; i < cid->count; i++) {
if (ACPI_STRNCMP(cid->id[i].value, info->hid,
sizeof(struct
acpi_compatible_id)) ==
0) {
if (ACPI_STRCMP(cid->ids[i].string, info->hid)
== 0) {
found = 1;
break;
}

View File

@ -51,6 +51,11 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsxfname")
/* Local prototypes */
static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
struct acpica_device_id *source,
char *string_area);
/******************************************************************************
*
* FUNCTION: acpi_get_handle
@ -68,6 +73,7 @@ ACPI_MODULE_NAME("nsxfname")
* namespace handle.
*
******************************************************************************/
acpi_status
acpi_get_handle(acpi_handle parent,
acpi_string pathname, acpi_handle * ret_handle)
@ -208,12 +214,40 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
ACPI_EXPORT_SYMBOL(acpi_get_name)
/******************************************************************************
*
* FUNCTION: acpi_ns_copy_device_id
*
* PARAMETERS: Dest - Pointer to the destination DEVICE_ID
* Source - Pointer to the source DEVICE_ID
* string_area - Pointer to where to copy the dest string
*
* RETURN: Pointer to the next string area
*
* DESCRIPTION: Copy a single DEVICE_ID, including the string data.
*
******************************************************************************/
static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
struct acpica_device_id *source,
char *string_area)
{
/* Create the destination DEVICE_ID */
dest->string = string_area;
dest->length = source->length;
/* Copy actual string and return a pointer to the next string area */
ACPI_MEMCPY(string_area, source->string, source->length);
return (string_area + source->length);
}
/******************************************************************************
*
* FUNCTION: acpi_get_object_info
*
* PARAMETERS: Handle - Object Handle
* Buffer - Where the info is returned
* PARAMETERS: Handle - Object Handle
* return_buffer - Where the info is returned
*
* RETURN: Status
*
@ -221,33 +255,37 @@ ACPI_EXPORT_SYMBOL(acpi_get_name)
* namespace node and possibly by running several standard
* control methods (Such as in the case of a device.)
*
* For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
* _ADR, _sx_w, and _sx_d methods.
*
* Note: Allocates the return buffer, must be freed by the caller.
*
******************************************************************************/
acpi_status
acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
acpi_get_object_info(acpi_handle handle,
struct acpi_device_info **return_buffer)
{
acpi_status status;
struct acpi_namespace_node *node;
struct acpi_device_info *info;
struct acpi_device_info *return_info;
struct acpi_compatible_id_list *cid_list = NULL;
acpi_size size;
struct acpica_device_id_list *cid_list = NULL;
struct acpica_device_id *hid = NULL;
struct acpica_device_id *uid = NULL;
char *next_id_string;
acpi_object_type type;
acpi_name name;
u8 param_count = 0;
u8 valid = 0;
u32 info_size;
u32 i;
acpi_status status;
/* Parameter validation */
if (!handle || !buffer) {
if (!handle || !return_buffer) {
return (AE_BAD_PARAMETER);
}
status = acpi_ut_validate_buffer(buffer);
if (ACPI_FAILURE(status)) {
return (status);
}
info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info));
if (!info) {
return (AE_NO_MEMORY);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto cleanup;
@ -256,66 +294,91 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
node = acpi_ns_map_handle_to_node(handle);
if (!node) {
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
status = AE_BAD_PARAMETER;
goto cleanup;
return (AE_BAD_PARAMETER);
}
/* Init return structure */
/* Get the namespace node data while the namespace is locked */
size = sizeof(struct acpi_device_info);
info->type = node->type;
info->name = node->name.integer;
info->valid = 0;
info_size = sizeof(struct acpi_device_info);
type = node->type;
name = node->name.integer;
if (node->type == ACPI_TYPE_METHOD) {
info->param_count = node->object->method.param_count;
param_count = node->object->method.param_count;
}
status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto cleanup;
return (status);
}
/* If not a device, we are all done */
if (info->type == ACPI_TYPE_DEVICE) {
if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
/*
* Get extra info for ACPI Devices objects only:
* Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
* Get extra info for ACPI Device/Processor objects only:
* Run the Device _HID, _UID, and _CID methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info->Valid bitfield is used
* to indicate which methods were found and ran successfully.
* not be present for this device. The Info->Valid bitfield is used
* to indicate which methods were found and run successfully.
*/
/* Execute the Device._HID method */
status = acpi_ut_execute_HID(node, &info->hardware_id);
status = acpi_ut_execute_HID(node, &hid);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_HID;
info_size += hid->length;
valid |= ACPI_VALID_HID;
}
/* Execute the Device._UID method */
status = acpi_ut_execute_UID(node, &info->unique_id);
status = acpi_ut_execute_UID(node, &uid);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_UID;
info_size += uid->length;
valid |= ACPI_VALID_UID;
}
/* Execute the Device._CID method */
status = acpi_ut_execute_CID(node, &cid_list);
if (ACPI_SUCCESS(status)) {
size += cid_list->size;
info->valid |= ACPI_VALID_CID;
/* Add size of CID strings and CID pointer array */
info_size +=
(cid_list->list_size -
sizeof(struct acpica_device_id_list));
valid |= ACPI_VALID_CID;
}
}
/*
* Now that we have the variable-length data, we can allocate the
* return buffer
*/
info = ACPI_ALLOCATE_ZEROED(info_size);
if (!info) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Get the fixed-length data */
if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
/*
* Get extra info for ACPI Device/Processor objects only:
* Run the _STA, _ADR and, sx_w, and _sx_d methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info->Valid bitfield is used
* to indicate which methods were found and run successfully.
*/
/* Execute the Device._STA method */
status = acpi_ut_execute_STA(node, &info->current_status);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_STA;
valid |= ACPI_VALID_STA;
}
/* Execute the Device._ADR method */
@ -323,36 +386,100 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
&info->address);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_ADR;
valid |= ACPI_VALID_ADR;
}
/* Execute the Device._sx_w methods */
status = acpi_ut_execute_power_methods(node,
acpi_gbl_lowest_dstate_names,
ACPI_NUM_sx_w_METHODS,
info->lowest_dstates);
if (ACPI_SUCCESS(status)) {
valid |= ACPI_VALID_SXWS;
}
/* Execute the Device._sx_d methods */
status = acpi_ut_execute_sxds(node, info->highest_dstates);
status = acpi_ut_execute_power_methods(node,
acpi_gbl_highest_dstate_names,
ACPI_NUM_sx_d_METHODS,
info->highest_dstates);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_SXDS;
valid |= ACPI_VALID_SXDS;
}
}
/* Validate/Allocate/Clear caller buffer */
/*
* Create a pointer to the string area of the return buffer.
* Point to the end of the base struct acpi_device_info structure.
*/
next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids);
if (cid_list) {
status = acpi_ut_initialize_buffer(buffer, size);
if (ACPI_FAILURE(status)) {
goto cleanup;
/* Point past the CID DEVICE_ID array */
next_id_string +=
((acpi_size) cid_list->count *
sizeof(struct acpica_device_id));
}
/* Populate the return buffer */
/*
* Copy the HID, UID, and CIDs to the return buffer. The variable-length
* strings are copied to the reserved area at the end of the buffer.
*
* For HID and CID, check if the ID is a PCI Root Bridge.
*/
if (hid) {
next_id_string = acpi_ns_copy_device_id(&info->hardware_id,
hid, next_id_string);
return_info = buffer->pointer;
ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info));
if (acpi_ut_is_pci_root_bridge(hid->string)) {
info->flags |= ACPI_PCI_ROOT_BRIDGE;
}
}
if (uid) {
next_id_string = acpi_ns_copy_device_id(&info->unique_id,
uid, next_id_string);
}
if (cid_list) {
ACPI_MEMCPY(&return_info->compatibility_id, cid_list,
cid_list->size);
info->compatible_id_list.count = cid_list->count;
info->compatible_id_list.list_size = cid_list->list_size;
/* Copy each CID */
for (i = 0; i < cid_list->count; i++) {
next_id_string =
acpi_ns_copy_device_id(&info->compatible_id_list.
ids[i], &cid_list->ids[i],
next_id_string);
if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) {
info->flags |= ACPI_PCI_ROOT_BRIDGE;
}
}
}
/* Copy the fixed-length data */
info->info_size = info_size;
info->type = type;
info->name = name;
info->param_count = param_count;
info->valid = valid;
*return_buffer = info;
status = AE_OK;
cleanup:
ACPI_FREE(info);
if (hid) {
ACPI_FREE(hid);
}
if (uid) {
ACPI_FREE(uid);
}
if (cid_list) {
ACPI_FREE(cid_list);
}

View File

@ -86,6 +86,9 @@ static acpi_status
acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op, acpi_status status);
static void
acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_aml_opcode
@ -390,6 +393,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
{
acpi_status status = AE_OK;
union acpi_parse_object *arg = NULL;
const struct acpi_opcode_info *op_info;
ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
@ -449,13 +453,11 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
INCREMENT_ARG_LIST(walk_state->arg_types);
}
/* Special processing for certain opcodes */
/* TBD (remove): Temporary mechanism to disable this code if needed */
#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) &&
/*
* Handle executable code at "module-level". This refers to
* executable opcodes that appear outside of any control method.
*/
if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
/*
* We want to skip If/Else/While constructs during Pass1 because we
@ -469,6 +471,23 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
case AML_ELSE_OP:
case AML_WHILE_OP:
/*
* Currently supported module-level opcodes are:
* IF/ELSE/WHILE. These appear to be the most common,
* and easiest to support since they open an AML
* package.
*/
if (walk_state->pass_number ==
ACPI_IMODE_LOAD_PASS1) {
acpi_ps_link_module_code(aml_op_start,
walk_state->
parser_state.
pkg_end -
aml_op_start,
walk_state->
owner_id);
}
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"Pass1: Skipping an If/Else/While body\n"));
@ -480,10 +499,34 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
break;
default:
/*
* Check for an unsupported executable opcode at module
* level. We must be in PASS1, the parent must be a SCOPE,
* The opcode class must be EXECUTE, and the opcode must
* not be an argument to another opcode.
*/
if ((walk_state->pass_number ==
ACPI_IMODE_LOAD_PASS1)
&& (op->common.parent->common.aml_opcode ==
AML_SCOPE_OP)) {
op_info =
acpi_ps_get_opcode_info(op->common.
aml_opcode);
if ((op_info->class ==
AML_CLASS_EXECUTE) && (!arg)) {
ACPI_WARNING((AE_INFO,
"Detected an unsupported executable opcode "
"at module-level: [0x%.4X] at table offset 0x%.4X",
op->common.aml_opcode,
(u32)((aml_op_start - walk_state->parser_state.aml_start)
+ sizeof(struct acpi_table_header))));
}
}
break;
}
}
#endif
/* Special processing for certain opcodes */
switch (op->common.aml_opcode) {
case AML_METHOD_OP:
@ -551,6 +594,66 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ps_link_module_code
*
* PARAMETERS: aml_start - Pointer to the AML
* aml_length - Length of executable AML
* owner_id - owner_id of module level code
*
* RETURN: None.
*
* DESCRIPTION: Wrap the module-level code with a method object and link the
* object to the global list. Note, the mutex field of the method
* object is used to link multiple module-level code objects.
*
******************************************************************************/
static void
acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
{
union acpi_operand_object *prev;
union acpi_operand_object *next;
union acpi_operand_object *method_obj;
/* Get the tail of the list */
prev = next = acpi_gbl_module_code_list;
while (next) {
prev = next;
next = next->method.mutex;
}
/*
* Insert the module level code into the list. Merge it if it is
* adjacent to the previous element.
*/
if (!prev ||
((prev->method.aml_start + prev->method.aml_length) != aml_start)) {
/* Create, initialize, and link a new temporary method object */
method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
if (!method_obj) {
return;
}
method_obj->method.aml_start = aml_start;
method_obj->method.aml_length = aml_length;
method_obj->method.owner_id = owner_id;
method_obj->method.flags |= AOPOBJ_MODULE_LEVEL;
if (!prev) {
acpi_gbl_module_code_list = method_obj;
} else {
prev->method.mutex = method_obj;
}
} else {
prev->method.aml_length += aml_length;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ps_complete_op

View File

@ -280,6 +280,10 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
goto cleanup;
}
if (info->obj_desc->method.flags & AOPOBJ_MODULE_LEVEL) {
walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
}
/* Invoke an internal method if necessary */
if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {

View File

@ -49,6 +49,12 @@
ACPI_MODULE_NAME("tbutils")
/* Local prototypes */
static void acpi_tb_fix_string(char *string, acpi_size length);
static void
acpi_tb_cleanup_table_header(struct acpi_table_header *out_header,
struct acpi_table_header *header);
static acpi_physical_address
acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
@ -159,6 +165,59 @@ u8 acpi_tb_tables_loaded(void)
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_fix_string
*
* PARAMETERS: String - String to be repaired
* Length - Maximum length
*
* RETURN: None
*
* DESCRIPTION: Replace every non-printable or non-ascii byte in the string
* with a question mark '?'.
*
******************************************************************************/
static void acpi_tb_fix_string(char *string, acpi_size length)
{
while (length && *string) {
if (!ACPI_IS_PRINT(*string)) {
*string = '?';
}
string++;
length--;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_cleanup_table_header
*
* PARAMETERS: out_header - Where the cleaned header is returned
* Header - Input ACPI table header
*
* RETURN: Returns the cleaned header in out_header
*
* DESCRIPTION: Copy the table header and ensure that all "string" fields in
* the header consist of printable characters.
*
******************************************************************************/
static void
acpi_tb_cleanup_table_header(struct acpi_table_header *out_header,
struct acpi_table_header *header)
{
ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header));
acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE);
acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE);
acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_print_table_header
@ -176,6 +235,7 @@ void
acpi_tb_print_table_header(acpi_physical_address address,
struct acpi_table_header *header)
{
struct acpi_table_header local_header;
/*
* The reason that the Address is cast to a void pointer is so that we
@ -192,6 +252,11 @@ acpi_tb_print_table_header(acpi_physical_address address,
/* RSDP has no common fields */
ACPI_MEMCPY(local_header.oem_id,
ACPI_CAST_PTR(struct acpi_table_rsdp,
header)->oem_id, ACPI_OEM_ID_SIZE);
acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)",
ACPI_CAST_PTR (void, address),
(ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
@ -200,18 +265,21 @@ acpi_tb_print_table_header(acpi_physical_address address,
header)->length : 20,
ACPI_CAST_PTR(struct acpi_table_rsdp,
header)->revision,
ACPI_CAST_PTR(struct acpi_table_rsdp,
header)->oem_id));
local_header.oem_id));
} else {
/* Standard ACPI table with full common header */
acpi_tb_cleanup_table_header(&local_header, header);
ACPI_INFO((AE_INFO,
"%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)",
header->signature, ACPI_CAST_PTR (void, address),
header->length, header->revision, header->oem_id,
header->oem_table_id, header->oem_revision,
header->asl_compiler_id,
header->asl_compiler_revision));
local_header.signature, ACPI_CAST_PTR(void, address),
local_header.length, local_header.revision,
local_header.oem_id, local_header.oem_table_id,
local_header.oem_revision,
local_header.asl_compiler_id,
local_header.asl_compiler_revision));
}
}

View File

@ -215,6 +215,12 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
"***** Region %p\n", object));
/* Invalidate the region address/length via the host OS */
acpi_os_invalidate_address(object->region.space_id,
object->region.address,
(acpi_size) object->region.length);
second_desc = acpi_ns_get_secondary_object(object);
if (second_desc) {
/*

View File

@ -44,19 +44,10 @@
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
#include "acinterp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("uteval")
/* Local prototypes */
static void
acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length);
static acpi_status
acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
struct acpi_compatible_id *one_cid);
/*
* Strings supported by the _OSI predefined (internal) method.
*
@ -78,6 +69,9 @@ static struct acpi_interface_info acpi_interfaces_supported[] = {
{"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */
{"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */
{"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */
{"Windows 2006.1", ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */
{"Windows 2006 SP1", ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */
{"Windows 2009", ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */
/* Feature Group Strings */
@ -213,7 +207,7 @@ acpi_status acpi_osi_invalidate(char *interface)
* RETURN: Status
*
* DESCRIPTION: Evaluates a namespace object and verifies the type of the
* return object. Common code that simplifies accessing objects
* return object. Common code that simplifies accessing objects
* that have required return objects of fixed types.
*
* NOTE: Internal function, no parameter validation
@ -298,7 +292,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) {
/*
* We received a return object, but one was not expected. This can
* We received a return object, but one was not expected. This can
* happen frequently if the "implicit return" feature is enabled.
* Just delete the return object and return AE_OK.
*/
@ -340,12 +334,12 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
*
* PARAMETERS: object_name - Object name to be evaluated
* device_node - Node for the device
* Address - Where the value is returned
* Value - Where the value is returned
*
* RETURN: Status
*
* DESCRIPTION: Evaluates a numeric namespace object for a selected device
* and stores result in *Address.
* and stores result in *Value.
*
* NOTE: Internal function, no parameter validation
*
@ -354,7 +348,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
acpi_status
acpi_ut_evaluate_numeric_object(char *object_name,
struct acpi_namespace_node *device_node,
acpi_integer * address)
acpi_integer *value)
{
union acpi_operand_object *obj_desc;
acpi_status status;
@ -369,295 +363,7 @@ acpi_ut_evaluate_numeric_object(char *object_name,
/* Get the returned Integer */
*address = obj_desc->integer.value;
/* On exit, we must delete the return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_id_string
*
* PARAMETERS: Destination - Where to copy the string
* Source - Source string
* max_length - Length of the destination buffer
*
* RETURN: None
*
* DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
* Performs removal of a leading asterisk if present -- workaround
* for a known issue on a bunch of machines.
*
******************************************************************************/
static void
acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length)
{
/*
* Workaround for ID strings that have a leading asterisk. This construct
* is not allowed by the ACPI specification (ID strings must be
* alphanumeric), but enough existing machines have this embedded in their
* ID strings that the following code is useful.
*/
if (*source == '*') {
source++;
}
/* Do the actual copy */
ACPI_STRNCPY(destination, source, max_length);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_HID
*
* PARAMETERS: device_node - Node for the device
* Hid - Where the HID is returned
*
* RETURN: Status
*
* DESCRIPTION: Executes the _HID control method that returns the hardware
* ID of the device.
*
* NOTE: Internal function, no parameter validation
*
******************************************************************************/
acpi_status
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
struct acpica_device_id *hid)
{
union acpi_operand_object *obj_desc;
acpi_status status;
ACPI_FUNCTION_TRACE(ut_execute_HID);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
&obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
/* Convert the Numeric HID to string */
acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
hid->value);
} else {
/* Copy the String HID from the returned object */
acpi_ut_copy_id_string(hid->value, obj_desc->string.pointer,
sizeof(hid->value));
}
/* On exit, we must delete the return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_translate_one_cid
*
* PARAMETERS: obj_desc - _CID object, must be integer or string
* one_cid - Where the CID string is returned
*
* RETURN: Status
*
* DESCRIPTION: Return a numeric or string _CID value as a string.
* (Compatible ID)
*
* NOTE: Assumes a maximum _CID string length of
* ACPI_MAX_CID_LENGTH.
*
******************************************************************************/
static acpi_status
acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
struct acpi_compatible_id *one_cid)
{
switch (obj_desc->common.type) {
case ACPI_TYPE_INTEGER:
/* Convert the Numeric CID to string */
acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
one_cid->value);
return (AE_OK);
case ACPI_TYPE_STRING:
if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) {
return (AE_AML_STRING_LIMIT);
}
/* Copy the String CID from the returned object */
acpi_ut_copy_id_string(one_cid->value, obj_desc->string.pointer,
ACPI_MAX_CID_LENGTH);
return (AE_OK);
default:
return (AE_TYPE);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_CID
*
* PARAMETERS: device_node - Node for the device
* return_cid_list - Where the CID list is returned
*
* RETURN: Status
*
* DESCRIPTION: Executes the _CID control method that returns one or more
* compatible hardware IDs for the device.
*
* NOTE: Internal function, no parameter validation
*
******************************************************************************/
acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
struct acpi_compatible_id_list ** return_cid_list)
{
union acpi_operand_object *obj_desc;
acpi_status status;
u32 count;
u32 size;
struct acpi_compatible_id_list *cid_list;
u32 i;
ACPI_FUNCTION_TRACE(ut_execute_CID);
/* Evaluate the _CID method for this device */
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
| ACPI_BTYPE_PACKAGE, &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the number of _CIDs returned */
count = 1;
if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
count = obj_desc->package.count;
}
/* Allocate a worst-case buffer for the _CIDs */
size = (((count - 1) * sizeof(struct acpi_compatible_id)) +
sizeof(struct acpi_compatible_id_list));
cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size);
if (!cid_list) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Init CID list */
cid_list->count = count;
cid_list->size = size;
/*
* A _CID can return either a single compatible ID or a package of
* compatible IDs. Each compatible ID can be one of the following:
* 1) Integer (32 bit compressed EISA ID) or
* 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
*/
/* The _CID object can be either a single CID or a package (list) of CIDs */
if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
/* Translate each package element */
for (i = 0; i < count; i++) {
status =
acpi_ut_translate_one_cid(obj_desc->package.
elements[i],
&cid_list->id[i]);
if (ACPI_FAILURE(status)) {
break;
}
}
} else {
/* Only one CID, translate to a string */
status = acpi_ut_translate_one_cid(obj_desc, cid_list->id);
}
/* Cleanup on error */
if (ACPI_FAILURE(status)) {
ACPI_FREE(cid_list);
} else {
*return_cid_list = cid_list;
}
/* On exit, we must delete the _CID return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_UID
*
* PARAMETERS: device_node - Node for the device
* Uid - Where the UID is returned
*
* RETURN: Status
*
* DESCRIPTION: Executes the _UID control method that returns the hardware
* ID of the device.
*
* NOTE: Internal function, no parameter validation
*
******************************************************************************/
acpi_status
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
struct acpica_device_id *uid)
{
union acpi_operand_object *obj_desc;
acpi_status status;
ACPI_FUNCTION_TRACE(ut_execute_UID);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
&obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
/* Convert the Numeric UID to string */
acpi_ex_unsigned_integer_to_string(obj_desc->integer.value,
uid->value);
} else {
/* Copy the String UID from the returned object */
acpi_ut_copy_id_string(uid->value, obj_desc->string.pointer,
sizeof(uid->value));
}
*value = obj_desc->integer.value;
/* On exit, we must delete the return object */
@ -716,60 +422,64 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_Sxds
* FUNCTION: acpi_ut_execute_power_methods
*
* PARAMETERS: device_node - Node for the device
* Flags - Where the status flags are returned
* method_names - Array of power method names
* method_count - Number of methods to execute
* out_values - Where the power method values are returned
*
* RETURN: Status
* RETURN: Status, out_values
*
* DESCRIPTION: Executes _STA for selected device and stores results in
* *Flags.
* DESCRIPTION: Executes the specified power methods for the device and returns
* the result(s).
*
* NOTE: Internal function, no parameter validation
*
******************************************************************************/
******************************************************************************/
acpi_status
acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest)
acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
const char **method_names,
u8 method_count, u8 *out_values)
{
union acpi_operand_object *obj_desc;
acpi_status status;
acpi_status final_status = AE_NOT_FOUND;
u32 i;
ACPI_FUNCTION_TRACE(ut_execute_sxds);
ACPI_FUNCTION_TRACE(ut_execute_power_methods);
for (i = 0; i < 4; i++) {
highest[i] = 0xFF;
for (i = 0; i < method_count; i++) {
/*
* Execute the power method (_sx_d or _sx_w). The only allowable
* return type is an Integer.
*/
status = acpi_ut_evaluate_object(device_node,
ACPI_CAST_PTR(char,
acpi_gbl_highest_dstate_names
[i]),
method_names[i]),
ACPI_BTYPE_INTEGER, &obj_desc);
if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"%s on Device %4.4s, %s\n",
ACPI_CAST_PTR(char,
acpi_gbl_highest_dstate_names
[i]),
acpi_ut_get_node_name
(device_node),
acpi_format_exception
(status)));
return_ACPI_STATUS(status);
}
} else {
/* Extract the Dstate value */
highest[i] = (u8) obj_desc->integer.value;
if (ACPI_SUCCESS(status)) {
out_values[i] = (u8)obj_desc->integer.value;
/* Delete the return object */
acpi_ut_remove_reference(obj_desc);
final_status = AE_OK; /* At least one value is valid */
continue;
}
out_values[i] = ACPI_UINT8_MAX;
if (status == AE_NOT_FOUND) {
continue; /* Ignore if not found */
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Failed %s on Device %4.4s, %s\n",
ACPI_CAST_PTR(char, method_names[i]),
acpi_ut_get_node_name(device_node),
acpi_format_exception(status)));
}
return_ACPI_STATUS(AE_OK);
return_ACPI_STATUS(final_status);
}

View File

@ -90,7 +90,15 @@ const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
"\\_S5_"
};
const char *acpi_gbl_highest_dstate_names[4] = {
const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS] = {
"_S0W",
"_S1W",
"_S2W",
"_S3W",
"_S4W"
};
const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS] = {
"_S1D",
"_S2D",
"_S3D",
@ -351,6 +359,7 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
"SMBus",
"SystemCMOS",
"PCIBARTarget",
"IPMI",
"DataTable"
};
@ -798,6 +807,7 @@ acpi_status acpi_ut_init_globals(void)
/* Namespace */
acpi_gbl_module_code_list = NULL;
acpi_gbl_root_node = NULL;
acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED;

382
drivers/acpi/acpica/utids.c Normal file
View File

@ -0,0 +1,382 @@
/******************************************************************************
*
* Module Name: utids - support for device IDs - HID, UID, CID
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2009, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utids")
/* Local prototypes */
static void acpi_ut_copy_id_string(char *destination, char *source);
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_id_string
*
* PARAMETERS: Destination - Where to copy the string
* Source - Source string
*
* RETURN: None
*
* DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
* Performs removal of a leading asterisk if present -- workaround
* for a known issue on a bunch of machines.
*
******************************************************************************/
static void acpi_ut_copy_id_string(char *destination, char *source)
{
/*
* Workaround for ID strings that have a leading asterisk. This construct
* is not allowed by the ACPI specification (ID strings must be
* alphanumeric), but enough existing machines have this embedded in their
* ID strings that the following code is useful.
*/
if (*source == '*') {
source++;
}
/* Do the actual copy */
ACPI_STRCPY(destination, source);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_HID
*
* PARAMETERS: device_node - Node for the device
* return_id - Where the string HID is returned
*
* RETURN: Status
*
* DESCRIPTION: Executes the _HID control method that returns the hardware
* ID of the device. The HID is either an 32-bit encoded EISAID
* Integer or a String. A string is always returned. An EISAID
* is converted to a string.
*
* NOTE: Internal function, no parameter validation
*
******************************************************************************/
acpi_status
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
struct acpica_device_id **return_id)
{
union acpi_operand_object *obj_desc;
struct acpica_device_id *hid;
u32 length;
acpi_status status;
ACPI_FUNCTION_TRACE(ut_execute_HID);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
&obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the size of the String to be returned, includes null terminator */
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
length = ACPI_EISAID_STRING_SIZE;
} else {
length = obj_desc->string.length + 1;
}
/* Allocate a buffer for the HID */
hid =
ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
(acpi_size) length);
if (!hid) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Area for the string starts after DEVICE_ID struct */
hid->string = ACPI_ADD_PTR(char, hid, sizeof(struct acpica_device_id));
/* Convert EISAID to a string or simply copy existing string */
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value);
} else {
acpi_ut_copy_id_string(hid->string, obj_desc->string.pointer);
}
hid->length = length;
*return_id = hid;
cleanup:
/* On exit, we must delete the return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_UID
*
* PARAMETERS: device_node - Node for the device
* return_id - Where the string UID is returned
*
* RETURN: Status
*
* DESCRIPTION: Executes the _UID control method that returns the unique
* ID of the device. The UID is either a 64-bit Integer (NOT an
* EISAID) or a string. Always returns a string. A 64-bit integer
* is converted to a decimal string.
*
* NOTE: Internal function, no parameter validation
*
******************************************************************************/
acpi_status
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
struct acpica_device_id **return_id)
{
union acpi_operand_object *obj_desc;
struct acpica_device_id *uid;
u32 length;
acpi_status status;
ACPI_FUNCTION_TRACE(ut_execute_UID);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
&obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the size of the String to be returned, includes null terminator */
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
length = ACPI_MAX64_DECIMAL_DIGITS + 1;
} else {
length = obj_desc->string.length + 1;
}
/* Allocate a buffer for the UID */
uid =
ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
(acpi_size) length);
if (!uid) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Area for the string starts after DEVICE_ID struct */
uid->string = ACPI_ADD_PTR(char, uid, sizeof(struct acpica_device_id));
/* Convert an Integer to string, or just copy an existing string */
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
acpi_ex_integer_to_string(uid->string, obj_desc->integer.value);
} else {
acpi_ut_copy_id_string(uid->string, obj_desc->string.pointer);
}
uid->length = length;
*return_id = uid;
cleanup:
/* On exit, we must delete the return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_CID
*
* PARAMETERS: device_node - Node for the device
* return_cid_list - Where the CID list is returned
*
* RETURN: Status, list of CID strings
*
* DESCRIPTION: Executes the _CID control method that returns one or more
* compatible hardware IDs for the device.
*
* NOTE: Internal function, no parameter validation
*
* A _CID method can return either a single compatible ID or a package of
* compatible IDs. Each compatible ID can be one of the following:
* 1) Integer (32 bit compressed EISA ID) or
* 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
*
* The Integer CIDs are converted to string format by this function.
*
******************************************************************************/
acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
struct acpica_device_id_list **return_cid_list)
{
union acpi_operand_object **cid_objects;
union acpi_operand_object *obj_desc;
struct acpica_device_id_list *cid_list;
char *next_id_string;
u32 string_area_size;
u32 length;
u32 cid_list_size;
acpi_status status;
u32 count;
u32 i;
ACPI_FUNCTION_TRACE(ut_execute_CID);
/* Evaluate the _CID method for this device */
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
| ACPI_BTYPE_PACKAGE, &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Get the count and size of the returned _CIDs. _CID can return either
* a Package of Integers/Strings or a single Integer or String.
* Note: This section also validates that all CID elements are of the
* correct type (Integer or String).
*/
if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
count = obj_desc->package.count;
cid_objects = obj_desc->package.elements;
} else { /* Single Integer or String CID */
count = 1;
cid_objects = &obj_desc;
}
string_area_size = 0;
for (i = 0; i < count; i++) {
/* String lengths include null terminator */
switch (cid_objects[i]->common.type) {
case ACPI_TYPE_INTEGER:
string_area_size += ACPI_EISAID_STRING_SIZE;
break;
case ACPI_TYPE_STRING:
string_area_size += cid_objects[i]->string.length + 1;
break;
default:
status = AE_TYPE;
goto cleanup;
}
}
/*
* Now that we know the length of the CIDs, allocate return buffer:
* 1) Size of the base structure +
* 2) Size of the CID DEVICE_ID array +
* 3) Size of the actual CID strings
*/
cid_list_size = sizeof(struct acpica_device_id_list) +
((count - 1) * sizeof(struct acpica_device_id)) + string_area_size;
cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
if (!cid_list) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Area for CID strings starts after the CID DEVICE_ID array */
next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
((acpi_size) count * sizeof(struct acpica_device_id));
/* Copy/convert the CIDs to the return buffer */
for (i = 0; i < count; i++) {
if (cid_objects[i]->common.type == ACPI_TYPE_INTEGER) {
/* Convert the Integer (EISAID) CID to a string */
acpi_ex_eisa_id_to_string(next_id_string,
cid_objects[i]->integer.
value);
length = ACPI_EISAID_STRING_SIZE;
} else { /* ACPI_TYPE_STRING */
/* Copy the String CID from the returned object */
acpi_ut_copy_id_string(next_id_string,
cid_objects[i]->string.pointer);
length = cid_objects[i]->string.length + 1;
}
cid_list->ids[i].string = next_id_string;
cid_list->ids[i].length = length;
next_id_string += length;
}
/* Finish the CID list */
cid_list->count = count;
cid_list->list_size = cid_list_size;
*return_cid_list = cid_list;
cleanup:
/* On exit, we must delete the _CID return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}

View File

@ -99,33 +99,19 @@ static void acpi_ut_terminate(void)
*
* FUNCTION: acpi_ut_subsystem_shutdown
*
* PARAMETERS: none
* PARAMETERS: None
*
* RETURN: none
* RETURN: None
*
* DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex
* objects here -- because the AML debugger may be still running.
* DESCRIPTION: Shutdown the various components. Do not delete the mutex
* objects here, because the AML debugger may be still running.
*
******************************************************************************/
void acpi_ut_subsystem_shutdown(void)
{
ACPI_FUNCTION_TRACE(ut_subsystem_shutdown);
/* Just exit if subsystem is already shutdown */
if (acpi_gbl_shutdown) {
ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated"));
return_VOID;
}
/* Subsystem appears active, go ahead and shut it down */
acpi_gbl_shutdown = TRUE;
acpi_gbl_startup_flags = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
#ifndef ACPI_ASL_COMPILER
/* Close the acpi_event Handling */

View File

@ -50,6 +50,11 @@
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utmisc")
/*
* Common suffix for messages
*/
#define ACPI_COMMON_MSG_SUFFIX \
acpi_os_printf(" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number)
/*******************************************************************************
*
* FUNCTION: acpi_ut_validate_exception
@ -118,6 +123,34 @@ const char *acpi_ut_validate_exception(acpi_status status)
return (ACPI_CAST_PTR(const char, exception));
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_is_pci_root_bridge
*
* PARAMETERS: Id - The HID/CID in string format
*
* RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge
*
* DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID.
*
******************************************************************************/
u8 acpi_ut_is_pci_root_bridge(char *id)
{
/*
* Check if this is a PCI root bridge.
* ACPI 3.0+: check for a PCI Express root also.
*/
if (!(ACPI_STRCMP(id,
PCI_ROOT_HID_STRING)) ||
!(ACPI_STRCMP(id, PCI_EXPRESS_ROOT_HID_STRING))) {
return (TRUE);
}
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_is_aml_table
@ -1037,8 +1070,7 @@ acpi_error(const char *module_name, u32 line_number, const char *format, ...)
va_start(args, format);
acpi_os_vprintf(format, args);
acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name,
line_number);
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}
@ -1052,8 +1084,7 @@ acpi_exception(const char *module_name,
va_start(args, format);
acpi_os_vprintf(format, args);
acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name,
line_number);
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}
@ -1066,8 +1097,7 @@ acpi_warning(const char *module_name, u32 line_number, const char *format, ...)
va_start(args, format);
acpi_os_vprintf(format, args);
acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name,
line_number);
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}
@ -1088,3 +1118,46 @@ ACPI_EXPORT_SYMBOL(acpi_error)
ACPI_EXPORT_SYMBOL(acpi_exception)
ACPI_EXPORT_SYMBOL(acpi_warning)
ACPI_EXPORT_SYMBOL(acpi_info)
/*******************************************************************************
*
* FUNCTION: acpi_ut_predefined_warning
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Pathname - Full pathname to the node
* node_flags - From Namespace node for the method/object
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Warnings for the predefined validation module. Messages are
* only emitted the first time a problem with a particular
* method/object is detected. This prevents a flood of error
* messages for methods that are repeatedly evaluated.
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_warning(const char *module_name,
u32 line_number,
char *pathname,
u8 node_flags, const char *format, ...)
{
va_list args;
/*
* Warning messages for this method/object will be disabled after the
* first time a validation fails or an object is successfully repaired.
*/
if (node_flags & ANOBJ_EVALUATED) {
return;
}
acpi_os_printf("ACPI Warning for %s: ", pathname);
va_start(args, format);
acpi_os_vprintf(format, args);
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}

View File

@ -250,6 +250,16 @@ acpi_status acpi_initialize_objects(u32 flags)
}
}
/*
* Execute any module-level code that was detected during the table load
* phase. Although illegal since ACPI 2.0, there are many machines that
* contain this type of code. Each block of detected executable AML code
* outside of any control method is wrapped with a temporary control
* method object and placed on a global list. The methods on this list
* are executed below.
*/
acpi_ns_exec_module_code_list();
/*
* Initialize the objects that remain uninitialized. This runs the
* executable AML that may be part of the declaration of these objects:
@ -318,7 +328,7 @@ ACPI_EXPORT_SYMBOL(acpi_initialize_objects)
*
* RETURN: Status
*
* DESCRIPTION: Shutdown the ACPI subsystem. Release all resources.
* DESCRIPTION: Shutdown the ACPICA subsystem and release all resources.
*
******************************************************************************/
acpi_status acpi_terminate(void)
@ -327,6 +337,19 @@ acpi_status acpi_terminate(void)
ACPI_FUNCTION_TRACE(acpi_terminate);
/* Just exit if subsystem is already shutdown */
if (acpi_gbl_shutdown) {
ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated"));
return_ACPI_STATUS(AE_OK);
}
/* Subsystem appears active, go ahead and shut it down */
acpi_gbl_shutdown = TRUE;
acpi_gbl_startup_flags = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
/* Terminate the AML Debugger if present */
ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE);
@ -353,6 +376,7 @@ acpi_status acpi_terminate(void)
}
ACPI_EXPORT_SYMBOL(acpi_terminate)
#ifndef ACPI_ASL_COMPILER
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************

View File

@ -31,6 +31,7 @@
#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/async.h>
#include <linux/dmi.h>
#ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h>
@ -45,6 +46,8 @@
#include <linux/power_supply.h>
#endif
#define PREFIX "ACPI: "
#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
#define ACPI_BATTERY_CLASS "battery"
@ -85,6 +88,10 @@ static const struct acpi_device_id battery_device_ids[] = {
MODULE_DEVICE_TABLE(acpi, battery_device_ids);
/* For buggy DSDTs that report negative 16-bit values for either charging
* or discharging current and/or report 0 as 65536 due to bad math.
*/
#define QUIRK_SIGNED16_CURRENT 0x0001
struct acpi_battery {
struct mutex lock;
@ -112,6 +119,7 @@ struct acpi_battery {
int state;
int power_unit;
u8 alarm_present;
long quirks;
};
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
@ -390,6 +398,11 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
state_offsets, ARRAY_SIZE(state_offsets));
battery->update_time = jiffies;
kfree(buffer.pointer);
if ((battery->quirks & QUIRK_SIGNED16_CURRENT) &&
battery->rate_now != -1)
battery->rate_now = abs((s16)battery->rate_now);
return result;
}
@ -495,6 +508,14 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
}
#endif
static void acpi_battery_quirks(struct acpi_battery *battery)
{
battery->quirks = 0;
if (dmi_name_in_vendors("Acer") && battery->power_unit) {
battery->quirks |= QUIRK_SIGNED16_CURRENT;
}
}
static int acpi_battery_update(struct acpi_battery *battery)
{
int result, old_present = acpi_battery_present(battery);
@ -513,6 +534,7 @@ static int acpi_battery_update(struct acpi_battery *battery)
result = acpi_battery_get_info(battery);
if (result)
return result;
acpi_battery_quirks(battery);
acpi_battery_init_alarm(battery);
}
#ifdef CONFIG_ACPI_SYSFS_POWER

View File

@ -34,6 +34,8 @@
#include <acpi/acpi_bus.h>
#include <linux/dmi.h>
#include "internal.h"
enum acpi_blacklist_predicates {
all_versions,
less_than_or_equal,

View File

@ -38,6 +38,7 @@
#include <linux/pci.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/dmi.h>
#include "internal.h"
@ -141,7 +142,7 @@ 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)
void *context)
{
return;
}

View File

@ -33,6 +33,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
#define ACPI_BUTTON_CLASS "button"
#define ACPI_BUTTON_FILE_INFO "info"
#define ACPI_BUTTON_FILE_STATE "state"

View File

@ -28,6 +28,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
ACPI_MODULE_NAME("cm_sbs");
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_BATTERY_CLASS "battery"

View File

@ -35,6 +35,8 @@
#include <acpi/acpi_drivers.h>
#include <acpi/container.h>
#define PREFIX "ACPI: "
#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device"
#define ACPI_CONTAINER_CLASS "container"
@ -200,20 +202,17 @@ container_walk_namespace_cb(acpi_handle handle,
u32 lvl, void *context, void **rv)
{
char *hid = NULL;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_device_info *info;
acpi_status status;
int *action = context;
status = acpi_get_object_info(handle, &buffer);
if (ACPI_FAILURE(status) || !buffer.pointer) {
status = acpi_get_object_info(handle, &info);
if (ACPI_FAILURE(status)) {
return AE_OK;
}
info = buffer.pointer;
if (info->valid & ACPI_VALID_HID)
hid = info->hardware_id.value;
hid = info->hardware_id.string;
if (hid == NULL) {
goto end;
@ -240,7 +239,7 @@ container_walk_namespace_cb(acpi_handle handle,
}
end:
kfree(buffer.pointer);
kfree(info);
return AE_OK;
}

View File

@ -3,6 +3,7 @@
*/
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
@ -201,72 +202,54 @@ module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
static int
acpi_system_read_debug(char *page,
char **start, off_t off, int count, int *eof, void *data)
static int acpi_system_debug_proc_show(struct seq_file *m, void *v)
{
char *p = page;
int size = 0;
unsigned int i;
if (off != 0)
goto end;
seq_printf(m, "%-25s\tHex SET\n", "Description");
p += sprintf(p, "%-25s\tHex SET\n", "Description");
switch ((unsigned long)data) {
switch ((unsigned long)m->private) {
case 0:
for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
seq_printf(m, "%-25s\t0x%08lX [%c]\n",
acpi_debug_layers[i].name,
acpi_debug_layers[i].value,
(acpi_dbg_layer & acpi_debug_layers[i].
value) ? '*' : ' ');
}
p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
seq_printf(m, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
ACPI_ALL_DRIVERS,
(acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
ACPI_ALL_DRIVERS) ==
0 ? ' ' : '-');
p += sprintf(p,
seq_printf(m,
"--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
acpi_dbg_layer);
break;
case 1:
for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
seq_printf(m, "%-25s\t0x%08lX [%c]\n",
acpi_debug_levels[i].name,
acpi_debug_levels[i].value,
(acpi_dbg_level & acpi_debug_levels[i].
value) ? '*' : ' ');
}
p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
seq_printf(m, "--\ndebug_level = 0x%08X (* = enabled)\n",
acpi_dbg_level);
break;
default:
p += sprintf(p, "Invalid debug option\n");
break;
}
end:
size = (p - page);
if (size <= off + count)
*eof = 1;
*start = page + off;
size -= off;
if (size > count)
size = count;
if (size < 0)
size = 0;
return size;
return 0;
}
static int
acpi_system_write_debug(struct file *file,
static int acpi_system_debug_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, acpi_system_debug_proc_show, PDE(inode)->data);
}
static ssize_t acpi_system_debug_proc_write(struct file *file,
const char __user * buffer,
unsigned long count, void *data)
size_t count, loff_t *pos)
{
char debug_string[12] = { '\0' };
@ -279,7 +262,7 @@ acpi_system_write_debug(struct file *file,
debug_string[count] = '\0';
switch ((unsigned long)data) {
switch ((unsigned long)PDE(file->f_path.dentry->d_inode)->data) {
case 0:
acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0);
break;
@ -292,6 +275,15 @@ acpi_system_write_debug(struct file *file,
return count;
}
static const struct file_operations acpi_system_debug_proc_fops = {
.owner = THIS_MODULE,
.open = acpi_system_debug_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = acpi_system_debug_proc_write,
};
#endif
int __init acpi_debug_init(void)
@ -303,24 +295,18 @@ int __init acpi_debug_init(void)
/* 'debug_layer' [R/W] */
name = ACPI_SYSTEM_FILE_DEBUG_LAYER;
entry =
create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
acpi_root_dir, acpi_system_read_debug,
(void *)0);
if (entry)
entry->write_proc = acpi_system_write_debug;
else
entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR,
acpi_root_dir, &acpi_system_debug_proc_fops,
(void *)0);
if (!entry)
goto Error;
/* 'debug_level' [R/W] */
name = ACPI_SYSTEM_FILE_DEBUG_LEVEL;
entry =
create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
acpi_root_dir, acpi_system_read_debug,
(void *)1);
if (entry)
entry->write_proc = acpi_system_write_debug;
else
entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR,
acpi_root_dir, &acpi_system_debug_proc_fops,
(void *)1);
if (!entry)
goto Error;
Done:

View File

@ -33,6 +33,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
#define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver"
ACPI_MODULE_NAME("dock");
@ -231,18 +233,16 @@ static int is_ata(acpi_handle handle)
static int is_battery(acpi_handle handle)
{
struct acpi_device_info *info;
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
int ret = 1;
if (!ACPI_SUCCESS(acpi_get_object_info(handle, &buffer)))
if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info)))
return 0;
info = buffer.pointer;
if (!(info->valid & ACPI_VALID_HID))
ret = 0;
else
ret = !strcmp("PNP0C0A", info->hardware_id.value);
ret = !strcmp("PNP0C0A", info->hardware_id.string);
kfree(buffer.pointer);
kfree(info);
return ret;
}

View File

@ -42,12 +42,12 @@
#include <asm/io.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/dmi.h>
#define ACPI_EC_CLASS "embedded_controller"
#define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info"
#undef PREFIX
#define PREFIX "ACPI: EC: "
/* EC status register */
@ -68,15 +68,13 @@ enum ec_command {
#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
#define ACPI_EC_CDELAY 10 /* Wait 10us before polling EC */
#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */
#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts
per one transaction */
enum {
EC_FLAGS_QUERY_PENDING, /* Query is pending */
EC_FLAGS_GPE_MODE, /* Expect GPE to be sent
* for status change */
EC_FLAGS_NO_GPE, /* Don't use GPE mode */
EC_FLAGS_GPE_STORM, /* GPE storm detected */
EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and
* OpReg are installed */
@ -170,7 +168,7 @@ static void start_transaction(struct acpi_ec *ec)
acpi_ec_write_cmd(ec, ec->curr->command);
}
static void gpe_transaction(struct acpi_ec *ec, u8 status)
static void advance_transaction(struct acpi_ec *ec, u8 status)
{
unsigned long flags;
spin_lock_irqsave(&ec->curr_lock, flags);
@ -201,29 +199,6 @@ static void gpe_transaction(struct acpi_ec *ec, u8 status)
spin_unlock_irqrestore(&ec->curr_lock, flags);
}
static int acpi_ec_wait(struct acpi_ec *ec)
{
if (wait_event_timeout(ec->wait, ec_transaction_done(ec),
msecs_to_jiffies(ACPI_EC_DELAY)))
return 0;
/* try restart command if we get any false interrupts */
if (ec->curr->irq_count &&
(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
pr_debug(PREFIX "controller reset, restart transaction\n");
start_transaction(ec);
if (wait_event_timeout(ec->wait, ec_transaction_done(ec),
msecs_to_jiffies(ACPI_EC_DELAY)))
return 0;
}
/* missing GPEs, switch back to poll mode */
if (printk_ratelimit())
pr_info(PREFIX "missing confirmations, "
"switch off interrupt mode.\n");
set_bit(EC_FLAGS_NO_GPE, &ec->flags);
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
return 1;
}
static void acpi_ec_gpe_query(void *ec_cxt);
static int ec_check_sci(struct acpi_ec *ec, u8 state)
@ -236,43 +211,51 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
return 0;
}
static void ec_delay(void)
{
/* EC in MSI notebooks don't tolerate delays other than 550 usec */
if (EC_FLAGS_MSI)
udelay(ACPI_EC_DELAY);
else
/* Use shortest sleep available */
msleep(1);
}
static int ec_poll(struct acpi_ec *ec)
{
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
udelay(ACPI_EC_CDELAY);
while (time_before(jiffies, delay)) {
gpe_transaction(ec, acpi_ec_read_status(ec));
ec_delay();
if (ec_transaction_done(ec))
return 0;
unsigned long flags;
int repeat = 2; /* number of command restarts */
while (repeat--) {
unsigned long delay = jiffies +
msecs_to_jiffies(ACPI_EC_DELAY);
do {
/* don't sleep with disabled interrupts */
if (EC_FLAGS_MSI || irqs_disabled()) {
udelay(ACPI_EC_MSI_UDELAY);
if (ec_transaction_done(ec))
return 0;
} else {
if (wait_event_timeout(ec->wait,
ec_transaction_done(ec),
msecs_to_jiffies(1)))
return 0;
}
advance_transaction(ec, acpi_ec_read_status(ec));
} while (time_before(jiffies, delay));
if (!ec->curr->irq_count ||
(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF))
break;
/* try restart command if we get any false interrupts */
pr_debug(PREFIX "controller reset, restart transaction\n");
spin_lock_irqsave(&ec->curr_lock, flags);
start_transaction(ec);
spin_unlock_irqrestore(&ec->curr_lock, flags);
}
return -ETIME;
}
static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
struct transaction *t,
int force_poll)
struct transaction *t)
{
unsigned long tmp;
int ret = 0;
pr_debug(PREFIX "transaction start\n");
/* disable GPE during transaction if storm is detected */
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
acpi_disable_gpe(NULL, ec->gpe);
}
if (EC_FLAGS_MSI)
udelay(ACPI_EC_DELAY);
udelay(ACPI_EC_MSI_UDELAY);
/* start transaction */
spin_lock_irqsave(&ec->curr_lock, tmp);
/* following two actions should be kept atomic */
@ -281,11 +264,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
spin_unlock_irqrestore(&ec->curr_lock, tmp);
/* if we selected poll mode or failed in GPE-mode do a poll loop */
if (force_poll ||
!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ||
acpi_ec_wait(ec))
ret = ec_poll(ec);
ret = ec_poll(ec);
pr_debug(PREFIX "transaction end\n");
spin_lock_irqsave(&ec->curr_lock, tmp);
ec->curr = NULL;
@ -295,8 +274,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
ec_check_sci(ec, acpi_ec_read_status(ec));
/* it is safe to enable GPE outside of transaction */
acpi_enable_gpe(NULL, ec->gpe);
} else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
t->irq_count > ACPI_EC_STORM_THRESHOLD) {
} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
pr_info(PREFIX "GPE storm detected, "
"transactions will use polling mode\n");
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
@ -314,16 +292,14 @@ static int ec_wait_ibf0(struct acpi_ec *ec)
{
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
/* interrupt wait manually if GPE mode is not active */
unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ?
msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1);
while (time_before(jiffies, delay))
if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout))
if (wait_event_timeout(ec->wait, ec_check_ibf0(ec),
msecs_to_jiffies(1)))
return 0;
return -ETIME;
}
static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t,
int force_poll)
static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
{
int status;
u32 glk;
@ -345,7 +321,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t,
status = -ETIME;
goto end;
}
status = acpi_ec_transaction_unlocked(ec, t, force_poll);
status = acpi_ec_transaction_unlocked(ec, t);
end:
if (ec->global_lock)
acpi_release_global_lock(glk);
@ -354,10 +330,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t,
return status;
}
/*
* Note: samsung nv5000 doesn't work with ec burst mode.
* http://bugzilla.kernel.org/show_bug.cgi?id=4980
*/
static int acpi_ec_burst_enable(struct acpi_ec *ec)
{
u8 d;
@ -365,7 +337,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec)
.wdata = NULL, .rdata = &d,
.wlen = 0, .rlen = 1};
return acpi_ec_transaction(ec, &t, 0);
return acpi_ec_transaction(ec, &t);
}
static int acpi_ec_burst_disable(struct acpi_ec *ec)
@ -375,7 +347,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
.wlen = 0, .rlen = 0};
return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
acpi_ec_transaction(ec, &t, 0) : 0;
acpi_ec_transaction(ec, &t) : 0;
}
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
@ -386,7 +358,7 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
.wdata = &address, .rdata = &d,
.wlen = 1, .rlen = 1};
result = acpi_ec_transaction(ec, &t, 0);
result = acpi_ec_transaction(ec, &t);
*data = d;
return result;
}
@ -398,7 +370,7 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
.wdata = wdata, .rdata = NULL,
.wlen = 2, .rlen = 0};
return acpi_ec_transaction(ec, &t, 0);
return acpi_ec_transaction(ec, &t);
}
/*
@ -466,7 +438,7 @@ int ec_transaction(u8 command,
if (!first_ec)
return -ENODEV;
return acpi_ec_transaction(first_ec, &t, force_poll);
return acpi_ec_transaction(first_ec, &t);
}
EXPORT_SYMBOL(ec_transaction);
@ -487,7 +459,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
* bit to be cleared (and thus clearing the interrupt source).
*/
result = acpi_ec_transaction(ec, &t, 0);
result = acpi_ec_transaction(ec, &t);
if (result)
return result;
@ -570,28 +542,10 @@ static u32 acpi_ec_gpe_handler(void *data)
pr_debug(PREFIX "~~~> interrupt\n");
status = acpi_ec_read_status(ec);
if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) {
gpe_transaction(ec, status);
if (ec_transaction_done(ec) &&
(status & ACPI_EC_FLAG_IBF) == 0)
wake_up(&ec->wait);
}
advance_transaction(ec, status);
if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0)
wake_up(&ec->wait);
ec_check_sci(ec, status);
if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
!test_bit(EC_FLAGS_NO_GPE, &ec->flags)) {
/* this is non-query, must be confirmation */
if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
if (printk_ratelimit())
pr_info(PREFIX "non-query interrupt received,"
" switching to interrupt mode\n");
} else {
/* hush, STORM switches the mode every transaction */
pr_debug(PREFIX "non-query interrupt received,"
" switching to interrupt mode\n");
}
set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
}
return ACPI_INTERRUPT_HANDLED;
}
@ -617,7 +571,8 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
if (bits != 8 && acpi_strict)
return AE_BAD_PARAMETER;
acpi_ec_burst_enable(ec);
if (EC_FLAGS_MSI)
acpi_ec_burst_enable(ec);
if (function == ACPI_READ) {
result = acpi_ec_read(ec, address, &temp);
@ -638,7 +593,8 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
}
}
acpi_ec_burst_disable(ec);
if (EC_FLAGS_MSI)
acpi_ec_burst_disable(ec);
switch (result) {
case -EINVAL:
@ -788,106 +744,6 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
return AE_CTRL_TERMINATE;
}
static void ec_remove_handlers(struct acpi_ec *ec)
{
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
pr_err(PREFIX "failed to remove space handler\n");
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
pr_err(PREFIX "failed to remove gpe handler\n");
clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
}
static int acpi_ec_add(struct acpi_device *device)
{
struct acpi_ec *ec = NULL;
if (!device)
return -EINVAL;
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
/* Check for boot EC */
if (boot_ec &&
(boot_ec->handle == device->handle ||
boot_ec->handle == ACPI_ROOT_OBJECT)) {
ec = boot_ec;
boot_ec = NULL;
} else {
ec = make_acpi_ec();
if (!ec)
return -ENOMEM;
}
if (ec_parse_device(device->handle, 0, ec, NULL) !=
AE_CTRL_TERMINATE) {
kfree(ec);
return -EINVAL;
}
ec->handle = device->handle;
/* Find and register all query methods */
acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1,
acpi_ec_register_query_methods, ec, NULL);
if (!first_ec)
first_ec = ec;
device->driver_data = ec;
acpi_ec_add_fs(device);
pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);
pr_info(PREFIX "driver started in %s mode\n",
(test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll");
return 0;
}
static int acpi_ec_remove(struct acpi_device *device, int type)
{
struct acpi_ec *ec;
struct acpi_ec_query_handler *handler, *tmp;
if (!device)
return -EINVAL;
ec = acpi_driver_data(device);
mutex_lock(&ec->lock);
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
list_del(&handler->node);
kfree(handler);
}
mutex_unlock(&ec->lock);
acpi_ec_remove_fs(device);
device->driver_data = NULL;
if (ec == first_ec)
first_ec = NULL;
kfree(ec);
return 0;
}
static acpi_status
ec_parse_io_ports(struct acpi_resource *resource, void *context)
{
struct acpi_ec *ec = context;
if (resource->type != ACPI_RESOURCE_TYPE_IO)
return AE_OK;
/*
* The first address region returned is the data port, and
* the second address region returned is the status/command
* port.
*/
if (ec->data_addr == 0)
ec->data_addr = resource->data.io.minimum;
else if (ec->command_addr == 0)
ec->command_addr = resource->data.io.minimum;
else
return AE_CTRL_TERMINATE;
return AE_OK;
}
static int ec_install_handlers(struct acpi_ec *ec)
{
acpi_status status;
@ -924,18 +780,54 @@ static int ec_install_handlers(struct acpi_ec *ec)
return 0;
}
static int acpi_ec_start(struct acpi_device *device)
static void ec_remove_handlers(struct acpi_ec *ec)
{
struct acpi_ec *ec;
int ret = 0;
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
pr_err(PREFIX "failed to remove space handler\n");
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
pr_err(PREFIX "failed to remove gpe handler\n");
clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
}
if (!device)
return -EINVAL;
static int acpi_ec_add(struct acpi_device *device)
{
struct acpi_ec *ec = NULL;
int ret;
ec = acpi_driver_data(device);
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
if (!ec)
return -EINVAL;
/* Check for boot EC */
if (boot_ec &&
(boot_ec->handle == device->handle ||
boot_ec->handle == ACPI_ROOT_OBJECT)) {
ec = boot_ec;
boot_ec = NULL;
} else {
ec = make_acpi_ec();
if (!ec)
return -ENOMEM;
}
if (ec_parse_device(device->handle, 0, ec, NULL) !=
AE_CTRL_TERMINATE) {
kfree(ec);
return -EINVAL;
}
ec->handle = device->handle;
/* Find and register all query methods */
acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1,
acpi_ec_register_query_methods, ec, NULL);
if (!first_ec)
first_ec = ec;
device->driver_data = ec;
acpi_ec_add_fs(device);
pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);
ret = ec_install_handlers(ec);
@ -944,19 +836,53 @@ static int acpi_ec_start(struct acpi_device *device)
return ret;
}
static int acpi_ec_stop(struct acpi_device *device, int type)
static int acpi_ec_remove(struct acpi_device *device, int type)
{
struct acpi_ec *ec;
struct acpi_ec_query_handler *handler, *tmp;
if (!device)
return -EINVAL;
ec = acpi_driver_data(device);
if (!ec)
return -EINVAL;
ec_remove_handlers(ec);
ec = acpi_driver_data(device);
ec_remove_handlers(ec);
mutex_lock(&ec->lock);
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
list_del(&handler->node);
kfree(handler);
}
mutex_unlock(&ec->lock);
acpi_ec_remove_fs(device);
device->driver_data = NULL;
if (ec == first_ec)
first_ec = NULL;
kfree(ec);
return 0;
}
static acpi_status
ec_parse_io_ports(struct acpi_resource *resource, void *context)
{
struct acpi_ec *ec = context;
if (resource->type != ACPI_RESOURCE_TYPE_IO)
return AE_OK;
/*
* The first address region returned is the data port, and
* the second address region returned is the status/command
* port.
*/
if (ec->data_addr == 0)
ec->data_addr = resource->data.io.minimum;
else if (ec->command_addr == 0)
ec->command_addr = resource->data.io.minimum;
else
return AE_CTRL_TERMINATE;
return AE_OK;
}
int __init acpi_boot_ec_enable(void)
{
if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags))
@ -1054,8 +980,6 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
{
struct acpi_ec *ec = acpi_driver_data(device);
/* Stop using GPE */
set_bit(EC_FLAGS_NO_GPE, &ec->flags);
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
acpi_disable_gpe(NULL, ec->gpe);
return 0;
}
@ -1064,8 +988,6 @@ static int acpi_ec_resume(struct acpi_device *device)
{
struct acpi_ec *ec = acpi_driver_data(device);
/* Enable use of GPE back */
clear_bit(EC_FLAGS_NO_GPE, &ec->flags);
set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
acpi_enable_gpe(NULL, ec->gpe);
return 0;
}
@ -1077,8 +999,6 @@ static struct acpi_driver acpi_ec_driver = {
.ops = {
.add = acpi_ec_add,
.remove = acpi_ec_remove,
.start = acpi_ec_start,
.stop = acpi_ec_stop,
.suspend = acpi_ec_suspend,
.resume = acpi_ec_resume,
},

View File

@ -14,6 +14,8 @@
#include <net/netlink.h>
#include <net/genetlink.h>
#include "internal.h"
#define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("event");

View File

@ -34,6 +34,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
#define ACPI_FAN_CLASS "fan"
#define ACPI_FAN_FILE_STATE "state"

View File

@ -12,6 +12,8 @@
#include <linux/rwsem.h>
#include <linux/acpi.h>
#include "internal.h"
#define ACPI_GLUE_DEBUG 0
#if ACPI_GLUE_DEBUG
#define DBG(x...) printk(PREFIX x)
@ -93,15 +95,13 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
struct acpi_device_info *info;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_find_child *find = context;
status = acpi_get_object_info(handle, &buffer);
status = acpi_get_object_info(handle, &info);
if (ACPI_SUCCESS(status)) {
info = buffer.pointer;
if (info->address == find->address)
find->handle = handle;
kfree(buffer.pointer);
kfree(info);
}
return AE_OK;
}
@ -121,7 +121,7 @@ EXPORT_SYMBOL(acpi_get_child);
/* Link ACPI devices with physical devices */
static void acpi_glue_data_handler(acpi_handle handle,
u32 function, void *context)
void *context)
{
/* we provide an empty handler */
}

View File

@ -1,4 +1,24 @@
/* For use by Linux/ACPI infrastructure, not drivers */
/*
* acpi/internal.h
* For use by Linux/ACPI infrastructure, not drivers
*
* Copyright (c) 2009, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define PREFIX "ACPI: "
int init_acpi_device_notify(void);
int acpi_scan_init(void);

View File

@ -30,6 +30,8 @@
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#define PREFIX "ACPI: "
#define ACPI_NUMA 0x80000000
#define _COMPONENT ACPI_NUMA
ACPI_MODULE_NAME("numa");

View File

@ -58,6 +58,7 @@ struct acpi_os_dpc {
acpi_osd_exec_callback function;
void *context;
struct work_struct work;
int wait;
};
#ifdef CONFIG_ACPI_CUSTOM_DSDT
@ -88,6 +89,7 @@ struct acpi_res_list {
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;
int count;
};
static LIST_HEAD(resource_list_head);
@ -697,31 +699,12 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
static void acpi_os_execute_deferred(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;
}
if (dpc->wait)
acpi_os_wait_events_complete(NULL);
dpc->function(dpc->context);
kfree(dpc);
return;
}
static void acpi_os_execute_hp_deferred(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;
}
acpi_os_wait_events_complete(NULL);
dpc->function(dpc->context);
kfree(dpc);
return;
}
/*******************************************************************************
@ -745,15 +728,11 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
acpi_status status = AE_OK;
struct acpi_os_dpc *dpc;
struct workqueue_struct *queue;
work_func_t func;
int ret;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Scheduling function [%p(%p)] for deferred execution.\n",
function, context));
if (!function)
return AE_BAD_PARAMETER;
/*
* Allocate/initialize DPC structure. Note that this memory will be
* freed by the callee. The kernel handles the work_struct list in a
@ -778,8 +757,8 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
*/
queue = hp ? kacpi_hotplug_wq :
(type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq);
func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred;
INIT_WORK(&dpc->work, func);
dpc->wait = hp ? 1 : 0;
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
ret = queue_work(queue, &dpc->work);
if (!ret) {
@ -1358,6 +1337,89 @@ acpi_os_validate_interface (char *interface)
return AE_SUPPORT;
}
static inline int acpi_res_list_add(struct acpi_res_list *res)
{
struct acpi_res_list *res_list_elem;
list_for_each_entry(res_list_elem, &resource_list_head,
resource_list) {
if (res->resource_type == res_list_elem->resource_type &&
res->start == res_list_elem->start &&
res->end == res_list_elem->end) {
/*
* The Region(addr,len) already exist in the list,
* just increase the count
*/
res_list_elem->count++;
return 0;
}
}
res->count = 1;
list_add(&res->resource_list, &resource_list_head);
return 1;
}
static inline void acpi_res_list_del(struct acpi_res_list *res)
{
struct acpi_res_list *res_list_elem;
list_for_each_entry(res_list_elem, &resource_list_head,
resource_list) {
if (res->resource_type == res_list_elem->resource_type &&
res->start == res_list_elem->start &&
res->end == res_list_elem->end) {
/*
* If the res count is decreased to 0,
* remove and free it
*/
if (--res_list_elem->count == 0) {
list_del(&res_list_elem->resource_list);
kfree(res_list_elem);
}
return;
}
}
}
acpi_status
acpi_os_invalidate_address(
u8 space_id,
acpi_physical_address address,
acpi_size length)
{
struct acpi_res_list res;
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.start = address;
res.end = address + length - 1;
res.resource_type = space_id;
spin_lock(&acpi_res_lock);
acpi_res_list_del(&res);
spin_unlock(&acpi_res_lock);
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;
}
/******************************************************************************
*
* FUNCTION: acpi_os_validate_address
@ -1382,6 +1444,7 @@ acpi_os_validate_address (
char *name)
{
struct acpi_res_list *res;
int added;
if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
return AE_OK;
@ -1399,14 +1462,17 @@ acpi_os_validate_address (
res->end = address + length - 1;
res->resource_type = space_id;
spin_lock(&acpi_res_lock);
list_add(&res->resource_list, &resource_list_head);
added = acpi_res_list_add(res);
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)
pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, "
"name: %s\n", added ? "Added" : "Already exist",
(space_id == ACPI_ADR_SPACE_SYSTEM_IO)
? "SystemIO" : "System Memory",
(unsigned long long)res->start,
(unsigned long long)res->end,
res->name);
if (!added)
kfree(res);
break;
case ACPI_ADR_SPACE_PCI_CONFIG:
case ACPI_ADR_SPACE_EC:

View File

@ -40,6 +40,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME("pci_irq");

View File

@ -43,6 +43,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME("pci_link");
#define ACPI_PCI_LINK_CLASS "pci_irq_routing"

View File

@ -36,6 +36,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME("pci_root");
#define ACPI_PCI_ROOT_CLASS "pci_bridge"

View File

@ -31,6 +31,7 @@
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/dmi.h>
static int debug;
static int check_sta_before_sun;
@ -57,7 +58,7 @@ ACPI_MODULE_NAME("pci_slot");
MY_NAME , ## arg); \
} while (0)
#define SLOT_NAME_SIZE 20 /* Inspired by #define in acpiphp.h */
#define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */
struct acpi_pci_slot {
acpi_handle root_handle; /* handle of the root bridge */
@ -149,7 +150,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK;
}
snprintf(name, sizeof(name), "%u", (u32)sun);
snprintf(name, sizeof(name), "%llu", sun);
pci_slot = pci_create_slot(pci_bus, device, name, NULL);
if (IS_ERR(pci_slot)) {
err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot));

View File

@ -43,9 +43,10 @@
#include <linux/seq_file.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include "sleep.h"
#define PREFIX "ACPI: "
#define _COMPONENT ACPI_POWER_COMPONENT
ACPI_MODULE_NAME("power");
#define ACPI_POWER_CLASS "power_resource"

1018
drivers/acpi/power_meter.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -59,6 +59,8 @@
#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
#define ACPI_PROCESSOR_FILE_INFO "info"
@ -79,9 +81,10 @@ MODULE_DESCRIPTION("ACPI Processor Driver");
MODULE_LICENSE("GPL");
static int acpi_processor_add(struct acpi_device *device);
static int acpi_processor_start(struct acpi_device *device);
static int acpi_processor_remove(struct acpi_device *device, int type);
#ifdef CONFIG_ACPI_PROCFS
static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
#endif
static void acpi_processor_notify(struct acpi_device *device, u32 event);
static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
static int acpi_processor_handle_eject(struct acpi_processor *pr);
@ -101,7 +104,6 @@ static struct acpi_driver acpi_processor_driver = {
.ops = {
.add = acpi_processor_add,
.remove = acpi_processor_remove,
.start = acpi_processor_start,
.suspend = acpi_processor_suspend,
.resume = acpi_processor_resume,
.notify = acpi_processor_notify,
@ -110,7 +112,7 @@ static struct acpi_driver acpi_processor_driver = {
#define INSTALL_NOTIFY_HANDLER 1
#define UNINSTALL_NOTIFY_HANDLER 2
#ifdef CONFIG_ACPI_PROCFS
static const struct file_operations acpi_processor_info_fops = {
.owner = THIS_MODULE,
.open = acpi_processor_info_open_fs,
@ -118,6 +120,7 @@ static const struct file_operations acpi_processor_info_fops = {
.llseek = seq_lseek,
.release = single_release,
};
#endif
DEFINE_PER_CPU(struct acpi_processor *, processors);
struct acpi_processor_errata errata __read_mostly;
@ -316,6 +319,7 @@ static int acpi_processor_set_pdc(struct acpi_processor *pr)
FS Interface (/proc)
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCFS
static struct proc_dir_entry *acpi_processor_dir = NULL;
static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
@ -388,7 +392,6 @@ static int acpi_processor_add_fs(struct acpi_device *device)
return -EIO;
return 0;
}
static int acpi_processor_remove_fs(struct acpi_device *device)
{
@ -405,6 +408,16 @@ static int acpi_processor_remove_fs(struct acpi_device *device)
return 0;
}
#else
static inline int acpi_processor_add_fs(struct acpi_device *device)
{
return 0;
}
static inline int acpi_processor_remove_fs(struct acpi_device *device)
{
return 0;
}
#endif
/* Use the acpiid in MADT to map cpus in case of SMP */
@ -698,92 +711,6 @@ static int acpi_processor_get_info(struct acpi_device *device)
static DEFINE_PER_CPU(void *, processor_device_array);
static int __cpuinit acpi_processor_start(struct acpi_device *device)
{
int result = 0;
struct acpi_processor *pr;
struct sys_device *sysdev;
pr = acpi_driver_data(device);
result = acpi_processor_get_info(device);
if (result) {
/* Processor is physically not present */
return 0;
}
BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
/*
* Buggy BIOS check
* ACPI id of processors can be reported wrongly by the BIOS.
* Don't trust it blindly
*/
if (per_cpu(processor_device_array, pr->id) != NULL &&
per_cpu(processor_device_array, pr->id) != device) {
printk(KERN_WARNING "BIOS reported wrong ACPI id "
"for the processor\n");
return -ENODEV;
}
per_cpu(processor_device_array, pr->id) = device;
per_cpu(processors, pr->id) = pr;
result = acpi_processor_add_fs(device);
if (result)
goto end;
sysdev = get_cpu_sysdev(pr->id);
if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev"))
return -EFAULT;
/* _PDC call should be done before doing anything else (if reqd.). */
arch_acpi_processor_init_pdc(pr);
acpi_processor_set_pdc(pr);
arch_acpi_processor_cleanup_pdc(pr);
#ifdef CONFIG_CPU_FREQ
acpi_processor_ppc_has_changed(pr);
#endif
acpi_processor_get_throttling_info(pr);
acpi_processor_get_limit_info(pr);
acpi_processor_power_init(pr, device);
pr->cdev = thermal_cooling_device_register("Processor", device,
&processor_cooling_ops);
if (IS_ERR(pr->cdev)) {
result = PTR_ERR(pr->cdev);
goto end;
}
dev_info(&device->dev, "registered as cooling_device%d\n",
pr->cdev->id);
result = sysfs_create_link(&device->dev.kobj,
&pr->cdev->device.kobj,
"thermal_cooling");
if (result)
printk(KERN_ERR PREFIX "Create sysfs link\n");
result = sysfs_create_link(&pr->cdev->device.kobj,
&device->dev.kobj,
"device");
if (result)
printk(KERN_ERR PREFIX "Create sysfs link\n");
if (pr->flags.throttling) {
printk(KERN_INFO PREFIX "%s [%s] (supports",
acpi_device_name(device), acpi_device_bid(device));
printk(" %d throttling states", pr->throttling.state_count);
printk(")\n");
}
end:
return result;
}
static void acpi_processor_notify(struct acpi_device *device, u32 event)
{
struct acpi_processor *pr = acpi_driver_data(device);
@ -846,10 +773,8 @@ static struct notifier_block acpi_cpu_notifier =
static int acpi_processor_add(struct acpi_device *device)
{
struct acpi_processor *pr = NULL;
if (!device)
return -EINVAL;
int result = 0;
struct sys_device *sysdev;
pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
if (!pr)
@ -865,7 +790,100 @@ static int acpi_processor_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
device->driver_data = pr;
result = acpi_processor_get_info(device);
if (result) {
/* Processor is physically not present */
return 0;
}
BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
/*
* Buggy BIOS check
* ACPI id of processors can be reported wrongly by the BIOS.
* Don't trust it blindly
*/
if (per_cpu(processor_device_array, pr->id) != NULL &&
per_cpu(processor_device_array, pr->id) != device) {
printk(KERN_WARNING "BIOS reported wrong ACPI id "
"for the processor\n");
result = -ENODEV;
goto err_free_cpumask;
}
per_cpu(processor_device_array, pr->id) = device;
per_cpu(processors, pr->id) = pr;
result = acpi_processor_add_fs(device);
if (result)
goto err_free_cpumask;
sysdev = get_cpu_sysdev(pr->id);
if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
result = -EFAULT;
goto err_remove_fs;
}
/* _PDC call should be done before doing anything else (if reqd.). */
arch_acpi_processor_init_pdc(pr);
acpi_processor_set_pdc(pr);
arch_acpi_processor_cleanup_pdc(pr);
#ifdef CONFIG_CPU_FREQ
acpi_processor_ppc_has_changed(pr);
#endif
acpi_processor_get_throttling_info(pr);
acpi_processor_get_limit_info(pr);
acpi_processor_power_init(pr, device);
pr->cdev = thermal_cooling_device_register("Processor", device,
&processor_cooling_ops);
if (IS_ERR(pr->cdev)) {
result = PTR_ERR(pr->cdev);
goto err_power_exit;
}
dev_info(&device->dev, "registered as cooling_device%d\n",
pr->cdev->id);
result = sysfs_create_link(&device->dev.kobj,
&pr->cdev->device.kobj,
"thermal_cooling");
if (result) {
printk(KERN_ERR PREFIX "Create sysfs link\n");
goto err_thermal_unregister;
}
result = sysfs_create_link(&pr->cdev->device.kobj,
&device->dev.kobj,
"device");
if (result) {
printk(KERN_ERR PREFIX "Create sysfs link\n");
goto err_remove_sysfs;
}
if (pr->flags.throttling) {
printk(KERN_INFO PREFIX "%s [%s] (supports",
acpi_device_name(device), acpi_device_bid(device));
printk(" %d throttling states", pr->throttling.state_count);
printk(")\n");
}
return 0;
err_remove_sysfs:
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
err_thermal_unregister:
thermal_cooling_device_unregister(pr->cdev);
err_power_exit:
acpi_processor_power_exit(pr, device);
err_remove_fs:
acpi_processor_remove_fs(device);
err_free_cpumask:
free_cpumask_var(pr->throttling.shared_cpu_map);
return result;
}
static int acpi_processor_remove(struct acpi_device *device, int type)
@ -942,7 +960,6 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
{
acpi_handle phandle;
struct acpi_device *pdev;
struct acpi_processor *pr;
if (acpi_get_parent(handle, &phandle)) {
@ -957,15 +974,6 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
return -ENODEV;
}
acpi_bus_start(*device);
pr = acpi_driver_data(*device);
if (!pr)
return -ENODEV;
if ((pr->id >= 0) && (pr->id < nr_cpu_ids)) {
kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE);
}
return 0;
}
@ -995,25 +1003,6 @@ static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
"Unable to add the device\n");
break;
}
pr = acpi_driver_data(device);
if (!pr) {
printk(KERN_ERR PREFIX "Driver data is NULL\n");
break;
}
if (pr->id >= 0 && (pr->id < nr_cpu_ids)) {
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
break;
}
result = acpi_processor_start(device);
if ((!result) && ((pr->id >= 0) && (pr->id < nr_cpu_ids))) {
kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
} else {
printk(KERN_ERR PREFIX "Device [%s] failed to start\n",
acpi_device_bid(device));
}
break;
case ACPI_NOTIFY_EJECT_REQUEST:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@ -1030,9 +1019,6 @@ static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
"Driver data is NULL, dropping EJECT\n");
return;
}
if ((pr->id < nr_cpu_ids) && (cpu_present(pr->id)))
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@ -1161,11 +1147,11 @@ static int __init acpi_processor_init(void)
(struct acpi_table_header **)&madt)))
madt = NULL;
#endif
#ifdef CONFIG_ACPI_PROCFS
acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
if (!acpi_processor_dir)
return -ENOMEM;
#endif
/*
* Check whether the system is DMI table. If yes, OSPM
* should not use mwait for CPU-states.
@ -1193,7 +1179,9 @@ static int __init acpi_processor_init(void)
cpuidle_unregister_driver(&acpi_idle_driver);
out_proc:
#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
#endif
return result;
}
@ -1213,7 +1201,9 @@ static void __exit acpi_processor_exit(void)
cpuidle_unregister_driver(&acpi_idle_driver);
#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
#endif
return;
}

View File

@ -60,6 +60,8 @@
#include <acpi/processor.h>
#include <asm/processor.h>
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_idle");
@ -680,6 +682,7 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
return 0;
}
#ifdef CONFIG_ACPI_PROCFS
static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_processor *pr = seq->private;
@ -759,7 +762,7 @@ static const struct file_operations acpi_processor_power_fops = {
.llseek = seq_lseek,
.release = single_release,
};
#endif
/**
* acpi_idle_bm_check - checks if bus master activity was detected
@ -1160,7 +1163,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
{
acpi_status status = 0;
static int first_run;
#ifdef CONFIG_ACPI_PROCFS
struct proc_dir_entry *entry = NULL;
#endif
unsigned int i;
if (boot_option_idle_override)
@ -1217,7 +1222,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
pr->power.states[i].type);
printk(")\n");
}
#ifdef CONFIG_ACPI_PROCFS
/* 'power' [R] */
entry = proc_create_data(ACPI_PROCESSOR_FILE_POWER,
S_IRUGO, acpi_device_dir(device),
@ -1225,6 +1230,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
acpi_driver_data(device));
if (!entry)
return -EIO;
#endif
return 0;
}
@ -1237,9 +1243,11 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
cpuidle_unregister_device(&pr->power.dev);
pr->flags.power_setup_done = 0;
#ifdef CONFIG_ACPI_PROCFS
if (acpi_device_dir(device))
remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
acpi_device_dir(device));
#endif
return 0;
}

View File

@ -39,6 +39,8 @@
#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT

View File

@ -40,6 +40,8 @@
#include <acpi/processor.h>
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_thermal");
@ -438,7 +440,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = {
};
/* /proc interface */
#ifdef CONFIG_ACPI_PROCFS
static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_processor *pr = (struct acpi_processor *)seq->private;
@ -517,3 +519,4 @@ const struct file_operations acpi_processor_limit_fops = {
.llseek = seq_lseek,
.release = single_release,
};
#endif

View File

@ -41,6 +41,8 @@
#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_throttling");
@ -1216,7 +1218,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
}
/* proc interface */
#ifdef CONFIG_ACPI_PROCFS
static int acpi_processor_throttling_seq_show(struct seq_file *seq,
void *offset)
{
@ -1324,3 +1326,4 @@ const struct file_operations acpi_processor_throttling_fops = {
.llseek = seq_lseek,
.release = single_release,
};
#endif

View File

@ -46,6 +46,8 @@
#include "sbshc.h"
#define PREFIX "ACPI: "
#define ACPI_SBS_CLASS "sbs"
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_BATTERY_CLASS "battery"

View File

@ -15,6 +15,8 @@
#include <linux/interrupt.h>
#include "sbshc.h"
#define PREFIX "ACPI: "
#define ACPI_SMB_HC_CLASS "smbus_host_controller"
#define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC"

View File

@ -60,13 +60,13 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
}
if (acpi_dev->flags.compatible_ids) {
struct acpi_compatible_id_list *cid_list;
struct acpica_device_id_list *cid_list;
int i;
cid_list = acpi_dev->pnp.cid_list;
for (i = 0; i < cid_list->count; i++) {
count = snprintf(&modalias[len], size, "%s:",
cid_list->id[i].value);
cid_list->ids[i].string);
if (count < 0 || count >= size) {
printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size",
acpi_dev->pnp.device_name, i);
@ -287,14 +287,14 @@ int acpi_match_device_ids(struct acpi_device *device,
}
if (device->flags.compatible_ids) {
struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
struct acpica_device_id_list *cid_list = device->pnp.cid_list;
int i;
for (id = ids; id->id[0]; id++) {
/* compare multiple _CID entries against driver ids */
for (i = 0; i < cid_list->count; i++) {
if (!strcmp((char*)id->id,
cid_list->id[i].value))
cid_list->ids[i].string))
return 0;
}
}
@ -309,6 +309,10 @@ static void acpi_device_release(struct device *dev)
struct acpi_device *acpi_dev = to_acpi_device(dev);
kfree(acpi_dev->pnp.cid_list);
if (acpi_dev->flags.hardware_id)
kfree(acpi_dev->pnp.hardware_id);
if (acpi_dev->flags.unique_id)
kfree(acpi_dev->pnp.unique_id);
kfree(acpi_dev);
}
@ -366,7 +370,8 @@ static acpi_status acpi_device_notify_fixed(void *data)
{
struct acpi_device *device = data;
acpi_device_notify(device->handle, ACPI_FIXED_HARDWARE_EVENT, device);
/* Fixed hardware devices have no handles */
acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
return AE_OK;
}
@ -426,9 +431,6 @@ static int acpi_device_probe(struct device * dev)
if (acpi_drv->ops.notify) {
ret = acpi_device_install_notify_handler(acpi_dev);
if (ret) {
if (acpi_drv->ops.stop)
acpi_drv->ops.stop(acpi_dev,
acpi_dev->removal_type);
if (acpi_drv->ops.remove)
acpi_drv->ops.remove(acpi_dev,
acpi_dev->removal_type);
@ -452,8 +454,6 @@ static int acpi_device_remove(struct device * dev)
if (acpi_drv) {
if (acpi_drv->ops.notify)
acpi_device_remove_notify_handler(acpi_dev);
if (acpi_drv->ops.stop)
acpi_drv->ops.stop(acpi_dev, acpi_dev->removal_type);
if (acpi_drv->ops.remove)
acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
}
@ -687,7 +687,7 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
}
EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);
void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context)
void acpi_bus_data_handler(acpi_handle handle, void *context)
{
/* TBD */
@ -1000,33 +1000,89 @@ static int acpi_dock_match(struct acpi_device *device)
return acpi_get_handle(device->handle, "_DCK", &tmp);
}
static struct acpica_device_id_list*
acpi_add_cid(
struct acpi_device_info *info,
struct acpica_device_id *new_cid)
{
struct acpica_device_id_list *cid;
char *next_id_string;
acpi_size cid_length;
acpi_size new_cid_length;
u32 i;
/* Allocate new CID list with room for the new CID */
if (!new_cid)
new_cid_length = info->compatible_id_list.list_size;
else if (info->compatible_id_list.list_size)
new_cid_length = info->compatible_id_list.list_size +
new_cid->length + sizeof(struct acpica_device_id);
else
new_cid_length = sizeof(struct acpica_device_id_list) + new_cid->length;
cid = ACPI_ALLOCATE_ZEROED(new_cid_length);
if (!cid) {
return NULL;
}
cid->list_size = new_cid_length;
cid->count = info->compatible_id_list.count;
if (new_cid)
cid->count++;
next_id_string = (char *) cid->ids + (cid->count * sizeof(struct acpica_device_id));
/* Copy all existing CIDs */
for (i = 0; i < info->compatible_id_list.count; i++) {
cid_length = info->compatible_id_list.ids[i].length;
cid->ids[i].string = next_id_string;
cid->ids[i].length = cid_length;
ACPI_MEMCPY(next_id_string, info->compatible_id_list.ids[i].string,
cid_length);
next_id_string += cid_length;
}
/* Append the new CID */
if (new_cid) {
cid->ids[i].string = next_id_string;
cid->ids[i].length = new_cid->length;
ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length);
}
return cid;
}
static void acpi_device_set_id(struct acpi_device *device,
struct acpi_device *parent, acpi_handle handle,
int type)
{
struct acpi_device_info *info;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_device_info *info = NULL;
char *hid = NULL;
char *uid = NULL;
struct acpi_compatible_id_list *cid_list = NULL;
const char *cid_add = NULL;
struct acpica_device_id_list *cid_list = NULL;
char *cid_add = NULL;
acpi_status status;
switch (type) {
case ACPI_BUS_TYPE_DEVICE:
status = acpi_get_object_info(handle, &buffer);
status = acpi_get_object_info(handle, &info);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
return;
}
info = buffer.pointer;
if (info->valid & ACPI_VALID_HID)
hid = info->hardware_id.value;
hid = info->hardware_id.string;
if (info->valid & ACPI_VALID_UID)
uid = info->unique_id.value;
uid = info->unique_id.string;
if (info->valid & ACPI_VALID_CID)
cid_list = &info->compatibility_id;
cid_list = &info->compatible_id_list;
if (info->valid & ACPI_VALID_ADR) {
device->pnp.bus_address = info->address;
device->flags.bus_address = 1;
@ -1077,55 +1133,46 @@ static void acpi_device_set_id(struct acpi_device *device,
}
if (hid) {
strcpy(device->pnp.hardware_id, hid);
device->flags.hardware_id = 1;
}
if (uid) {
strcpy(device->pnp.unique_id, uid);
device->flags.unique_id = 1;
}
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;
}
device->pnp.hardware_id = ACPI_ALLOCATE_ZEROED(strlen (hid) + 1);
if (device->pnp.hardware_id) {
strcpy(device->pnp.hardware_id, hid);
device->flags.hardware_id = 1;
}
}
if (!device->flags.hardware_id)
device->pnp.hardware_id = "";
if (uid) {
device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1);
if (device->pnp.unique_id) {
strcpy(device->pnp.unique_id, uid);
device->flags.unique_id = 1;
}
}
if (!device->flags.unique_id)
device->pnp.unique_id = "";
if (cid_list || cid_add) {
struct acpica_device_id_list *list;
if (cid_add) {
struct acpica_device_id cid;
cid.length = strlen (cid_add) + 1;
cid.string = cid_add;
list = acpi_add_cid(info, &cid);
} else {
list = acpi_add_cid(info, NULL);
}
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");
if (cid_add)
device->flags.compatible_ids = 1;
}
}
kfree(buffer.pointer);
kfree(info);
}
static int acpi_device_set_context(struct acpi_device *device, int type)
@ -1264,16 +1311,6 @@ acpi_add_single_object(struct acpi_device **child,
*/
acpi_device_set_id(device, parent, handle, type);
/*
* The ACPI device is attached to acpi handle before getting
* the power/wakeup/peformance flags. Otherwise OS can't get
* the corresponding ACPI device by the acpi handle in the course
* of getting the power/wakeup/performance flags.
*/
result = acpi_device_set_context(device, type);
if (result)
goto end;
/*
* Power Management
* ----------------
@ -1304,6 +1341,8 @@ acpi_add_single_object(struct acpi_device **child,
goto end;
}
if ((result = acpi_device_set_context(device, type)))
goto end;
result = acpi_device_register(device, parent);
@ -1318,10 +1357,8 @@ acpi_add_single_object(struct acpi_device **child,
end:
if (!result)
*child = device;
else {
kfree(device->pnp.cid_list);
kfree(device);
}
else
acpi_device_release(&device->dev);
return result;
}

View File

@ -405,6 +405,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
},
},
{
.callback = init_set_sci_en_on_resume,
.ident = "Hewlett-Packard HP Pavilion dv3 Notebook PC",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv3 Notebook PC"),
},
},
{
.callback = init_old_suspend_ordering,
.ident = "Panasonic CF51-2L",
.matches = {

View File

@ -31,6 +31,8 @@
#include <acpi/acpi_drivers.h>
#define PREFIX "ACPI: "
#define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("system");

View File

@ -213,6 +213,9 @@ acpi_table_parse_entries(char *id,
unsigned long table_end;
acpi_size tbl_size;
if (acpi_disabled)
return -ENODEV;
if (!handler)
return -EINVAL;
@ -277,6 +280,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
struct acpi_table_header *table = NULL;
acpi_size tbl_size;
if (acpi_disabled)
return -ENODEV;
if (!handler)
return -EINVAL;

Some files were not shown because too many files have changed in this diff Show More