Commit 08acd4f8 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (179 commits)
  ACPI: Fix acpi_processor_idle and idle= boot parameters interaction
  acpi: fix section mismatch warning in pnpacpi
  intel_menlo: fix build warning
  ACPI: Cleanup: Remove unneeded, multiple local dummy variables
  ACPI: video - fix permissions on some proc entries
  ACPI: video - properly handle errors when registering proc elements
  ACPI: video - do not store invalid entries in attached_array list
  ACPI: re-name acpi_pm_ops to acpi_suspend_ops
  ACER_WMI/ASUS_LAPTOP: fix build bug
  thinkpad_acpi: fix possible NULL pointer dereference if kstrdup failed
  ACPI: check a return value correctly in acpi_power_get_context()
  #if 0 acpi/bay.c:eject_removable_drive()
  eeepc-laptop: add hwmon fan control
  eeepc-laptop: add backlight
  eeepc-laptop: add base driver
  ACPI: thinkpad-acpi: bump up version to 0.20
  ACPI: thinkpad-acpi: fix selects in Kconfig
  ACPI: thinkpad-acpi: use a private workqueue
  ACPI: thinkpad-acpi: fluff really minor fix
  ACPI: thinkpad-acpi: use uppercase for "LED" on user documentation
  ...

Fixed conflicts in drivers/acpi/video.c and drivers/misc/intel_menlow.c
manually.
parents ccf27795 008238b5
ThinkPad ACPI Extras Driver
Version 0.19
January 06th, 2008
Version 0.20
April 09th, 2008
Borislav Deianov <borislav@users.sf.net>
Henrique de Moraes Holschuh <hmh@hmh.eng.br>
......@@ -18,6 +18,11 @@ This driver used to be named ibm-acpi until kernel 2.6.21 and release
moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel
2.6.22, and release 0.14.
The driver is named "thinkpad-acpi". In some places, like module
names, "thinkpad_acpi" is used because of userspace issues.
"tpacpi" is used as a shorthand where "thinkpad-acpi" would be too
long due to length limitations on some Linux kernel versions.
Status
------
......@@ -571,6 +576,47 @@ netlink interface and the input layer interface, and don't bother at all
with hotkey_report_mode.
Brightness hotkey notes:
These are the current sane choices for brightness key mapping in
thinkpad-acpi:
For IBM and Lenovo models *without* ACPI backlight control (the ones on
which thinkpad-acpi will autoload its backlight interface by default,
and on which ACPI video does not export a backlight interface):
1. Don't enable or map the brightness hotkeys in thinkpad-acpi, as
these older firmware versions unfortunately won't respect the hotkey
mask for brightness keys anyway, and always reacts to them. This
usually work fine, unless X.org drivers are doing something to block
the BIOS. In that case, use (3) below. This is the default mode of
operation.
2. Enable the hotkeys, but map them to something else that is NOT
KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause
userspace to try to change the backlight level, and use that as an
on-screen-display hint.
3. IF AND ONLY IF X.org drivers find a way to block the firmware from
automatically changing the brightness, enable the hotkeys and map
them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to
something that calls xbacklight. thinkpad-acpi will not be able to
change brightness in that case either, so you should disable its
backlight interface.
For Lenovo models *with* ACPI backlight control:
1. Load up ACPI video and use that. ACPI video will report ACPI
events for brightness change keys. Do not mess with thinkpad-acpi
defaults in this case. thinkpad-acpi should not have anything to do
with backlight events in a scenario where ACPI video is loaded:
brightness hotkeys must be disabled, and the backlight interface is
to be kept disabled as well. This is the default mode of operation.
2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi,
and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process
these keys on userspace somehow (e.g. by calling xbacklight).
Bluetooth
---------
......@@ -647,16 +693,31 @@ while others are still having problems. For more information:
https://bugs.freedesktop.org/show_bug.cgi?id=2000
ThinkLight control -- /proc/acpi/ibm/light
------------------------------------------
ThinkLight control
------------------
procfs: /proc/acpi/ibm/light
sysfs attributes: as per LED class, for the "tpacpi::thinklight" LED
The current status of the ThinkLight can be found in this file. A few
models which do not make the status available will show it as
"unknown". The available commands are:
procfs notes:
The ThinkLight status can be read and set through the procfs interface. A
few models which do not make the status available will show the ThinkLight
status as "unknown". The available commands are:
echo on > /proc/acpi/ibm/light
echo off > /proc/acpi/ibm/light
sysfs notes:
The ThinkLight sysfs interface is documented by the LED class
documentation, in Documentation/leds-class.txt. The ThinkLight LED name
is "tpacpi::thinklight".
Due to limitations in the sysfs LED class, if the status of the thinklight
cannot be read or if it is unknown, thinkpad-acpi will report it as "off".
It is impossible to know if the status returned through sysfs is valid.
Docking / undocking -- /proc/acpi/ibm/dock
------------------------------------------
......@@ -815,28 +876,63 @@ The cmos command interface is prone to firmware split-brain problems, as
in newer ThinkPads it is just a compatibility layer. Do not use it, it is
exported just as a debug tool.
LED control -- /proc/acpi/ibm/led
---------------------------------
LED control
-----------
procfs: /proc/acpi/ibm/led
sysfs attributes: as per LED class, see below for names
Some of the LED indicators can be controlled through this feature. On
some older ThinkPad models, it is possible to query the status of the
LED indicators as well. Newer ThinkPads cannot query the real status
of the LED indicators.
Some of the LED indicators can be controlled through this feature. The
available commands are:
procfs notes:
The available commands are:
echo '<led number> on' >/proc/acpi/ibm/led
echo '<led number> off' >/proc/acpi/ibm/led
echo '<led number> blink' >/proc/acpi/ibm/led
echo '<LED number> on' >/proc/acpi/ibm/led
echo '<LED number> off' >/proc/acpi/ibm/led
echo '<LED number> blink' >/proc/acpi/ibm/led
The <led number> range is 0 to 7. The set of LEDs that can be
controlled varies from model to model. Here is the mapping on the X40:
The <LED number> range is 0 to 7. The set of LEDs that can be
controlled varies from model to model. Here is the common ThinkPad
mapping:
0 - power
1 - battery (orange)
2 - battery (green)
3 - UltraBase
3 - UltraBase/dock
4 - UltraBay
5 - UltraBase battery slot
6 - (unknown)
7 - standby
All of the above can be turned on and off and can be made to blink.
sysfs notes:
The ThinkPad LED sysfs interface is described in detail by the LED class
documentation, in Documentation/leds-class.txt.
The leds are named (in LED ID order, from 0 to 7):
"tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt",
"tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt",
"tpacpi::unknown_led", "tpacpi::standby".
Due to limitations in the sysfs LED class, if the status of the LED
indicators cannot be read due to an error, thinkpad-acpi will report it as
a brightness of zero (same as LED off).
If the thinkpad firmware doesn't support reading the current status,
trying to read the current LED brightness will just return whatever
brightness was last written to that attribute.
These LEDs can blink using hardware acceleration. To request that a
ThinkPad indicator LED should blink in hardware accelerated mode, use the
"timer" trigger, and leave the delay_on and delay_off parameters set to
zero (to request hardware acceleration autodetection).
ACPI sounds -- /proc/acpi/ibm/beep
----------------------------------
......@@ -1090,6 +1186,15 @@ it there will be the following attributes:
dim the display.
WARNING:
Whatever you do, do NOT ever call thinkpad-acpi backlight-level change
interface and the ACPI-based backlight level change interface
(available on newer BIOSes, and driven by the Linux ACPI video driver)
at the same time. The two will interact in bad ways, do funny things,
and maybe reduce the life of the backlight lamps by needlessly kicking
its level up and down at every change.
Volume control -- /proc/acpi/ibm/volume
---------------------------------------
......
......@@ -108,10 +108,12 @@ and throttle appropriate devices.
RO read only value
RW read/write value
All thermal sysfs attributes will be represented under /sys/class/thermal
Thermal sysfs attributes will be represented under /sys/class/thermal.
Hwmon sysfs I/F extension is also available under /sys/class/hwmon
if hwmon is compiled in or built as a module.
Thermal zone device sys I/F, created once it's registered:
|thermal_zone[0-*]:
/sys/class/thermal/thermal_zone[0-*]:
|-----type: Type of the thermal zone
|-----temp: Current temperature
|-----mode: Working mode of the thermal zone
......@@ -119,7 +121,7 @@ Thermal zone device sys I/F, created once it's registered:
|-----trip_point_[0-*]_type: Trip point type
Thermal cooling device sys I/F, created once it's registered:
|cooling_device[0-*]:
/sys/class/thermal/cooling_device[0-*]:
|-----type : Type of the cooling device(processor/fan/...)
|-----max_state: Maximum cooling state of the cooling device
|-----cur_state: Current cooling state of the cooling device
......@@ -130,10 +132,19 @@ They represent the relationship between a thermal zone and its associated coolin
They are created/removed for each
thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful execution.
|thermal_zone[0-*]
/sys/class/thermal/thermal_zone[0-*]
|-----cdev[0-*]: The [0-*]th cooling device in the current thermal zone
|-----cdev[0-*]_trip_point: Trip point that cdev[0-*] is associated with
Besides the thermal zone device sysfs I/F and cooling device sysfs I/F,
the generic thermal driver also creates a hwmon sysfs I/F for each _type_ of
thermal zone device. E.g. the generic thermal driver registers one hwmon class device
and build the associated hwmon sysfs I/F for all the registered ACPI thermal zones.
/sys/class/hwmon/hwmon[0-*]:
|-----name: The type of the thermal zone devices.
|-----temp[1-*]_input: The current temperature of thermal zone [1-*].
|-----temp[1-*]_critical: The critical trip point of thermal zone [1-*].
Please read Documentation/hwmon/sysfs-interface for additional information.
***************************
* Thermal zone attributes *
......@@ -141,7 +152,10 @@ thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful e
type Strings which represent the thermal zone type.
This is given by thermal zone driver as part of registration.
Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
Eg: "acpitz" indicates it's an ACPI thermal device.
In order to keep it consistent with hwmon sys attribute,
this should be a short, lowercase string,
not containing spaces nor dashes.
RO
Required
......@@ -218,7 +232,7 @@ the sys I/F structure will be built like this:
/sys/class/thermal:
|thermal_zone1:
|-----type: ACPI thermal zone
|-----type: acpitz
|-----temp: 37000
|-----mode: kernel
|-----trip_point_0_temp: 100000
......@@ -243,3 +257,10 @@ the sys I/F structure will be built like this:
|-----type: Fan
|-----max_state: 2
|-----cur_state: 0
/sys/class/hwmon:
|hwmon0:
|-----name: acpitz
|-----temp1_input: 37000
|-----temp1_crit: 100000
......@@ -1533,6 +1533,13 @@ L: bluesmoke-devel@lists.sourceforge.net
W: bluesmoke.sourceforge.net
S: Maintained
EEEPC LAPTOP EXTRAS DRIVER
P: Corentin Chary
M: corentincj@iksaif.net
L: acpi4asus-user@lists.sourceforge.net
W: http://sourceforge.net/projects/acpi4asus
S: Maintained
EEPRO100 NETWORK DRIVER
P: Andrey V. Savochkin
M: saw@saw.sw.com.sg
......
......@@ -163,14 +163,11 @@ static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp,
if ((mode != 1) && (mode != 5))
return -EINVAL;
retval = pm_send_all(PM_SUSPEND, (void *)3);
if (retval == 0) {
if (mode == 5)
retval = pm_do_bus_sleep();
else
retval = pm_do_suspend();
pm_send_all(PM_RESUME, (void *)0);
}
return retval;
......@@ -183,9 +180,6 @@ static int try_set_cmode(int new_cmode)
if (!(clock_cmodes_permitted & (1<<new_cmode)))
return -EINVAL;
/* tell all the drivers we're suspending */
pm_send_all(PM_SUSPEND, (void *)3);
/* now change cmode */
local_irq_disable();
frv_dma_pause_all();
......@@ -201,8 +195,6 @@ static int try_set_cmode(int new_cmode)
frv_dma_resume_all();
local_irq_enable();
/* tell all the drivers we're resuming */
pm_send_all(PM_RESUME, (void *)0);
return 0;
}
......
......@@ -251,7 +251,6 @@ int au_sleep(void)
static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
void __user *buffer, size_t * len, loff_t *ppos)
{
int retval = 0;
#ifdef SLEEP_TEST_TIMEOUT
#define TMPBUFLEN2 16
char buf[TMPBUFLEN2], *p;
......@@ -271,36 +270,12 @@ static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
p = buf;
sleep_ticks = simple_strtoul(p, &p, 0);
#endif
retval = pm_send_all(PM_SUSPEND, (void *) 2);
if (retval)
return retval;
au_sleep();
retval = pm_send_all(PM_RESUME, (void *) 0);
}
return retval;
}
static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,
void __user *buffer, size_t * len, loff_t *ppos)
{
int retval = 0;
if (!write) {
*len = 0;
} else {
retval = pm_send_all(PM_SUSPEND, (void *) 2);
if (retval)
return retval;
suspend_mode = 1;
retval = pm_send_all(PM_RESUME, (void *) 0);
}
return retval;
return 0;
}
static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
void __user *buffer, size_t * len, loff_t *ppos)
{
......@@ -413,14 +388,6 @@ static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
static struct ctl_table pm_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "suspend",
.data = NULL,
.maxlen = 0,
.mode = 0600,
.proc_handler = &pm_do_suspend
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "sleep",
......
......@@ -1192,19 +1192,6 @@ static int suspend(int vetoable)
int err;
struct apm_user *as;
if (pm_send_all(PM_SUSPEND, (void *)3)) {
/* Vetoed */
if (vetoable) {
if (apm_info.connection_version > 0x100)
set_system_power_state(APM_STATE_REJECT);
err = -EBUSY;
ignore_sys_suspend = 0;
printk(KERN_WARNING "apm: suspend was vetoed.\n");
goto out;
}
printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n");
}
device_suspend(PMSG_SUSPEND);
local_irq_disable();
device_power_down(PMSG_SUSPEND);
......@@ -1227,9 +1214,7 @@ static int suspend(int vetoable)
device_power_up();
local_irq_enable();
device_resume();
pm_send_all(PM_RESUME, (void *)0);
queue_event(APM_NORMAL_RESUME, NULL);
out:
spin_lock(&user_list_lock);
for (as = user_list; as != NULL; as = as->next) {
as->suspend_wait = 0;
......@@ -1340,7 +1325,6 @@ static void check_events(void)
if ((event != APM_NORMAL_RESUME)
|| (ignore_normal_resume == 0)) {
device_resume();
pm_send_all(PM_RESUME, (void *)0);
queue_event(event, NULL);
}
ignore_normal_resume = 0;
......
......@@ -140,6 +140,7 @@ config ACPI_VIDEO
tristate "Video"
depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL
depends on INPUT
select THERMAL
help
This driver implement the ACPI Extensions For Display Adapters
for integrated graphics devices on motherboard, as specified in
......@@ -151,6 +152,7 @@ config ACPI_VIDEO
config ACPI_FAN
tristate "Fan"
select THERMAL
default y
help
This driver adds support for ACPI fan devices, allowing user-mode
......@@ -172,6 +174,7 @@ config ACPI_BAY
config ACPI_PROCESSOR
tristate "Processor"
select THERMAL
default y
help
This driver installs ACPI as the idle handler for Linux, and uses
......
......@@ -201,6 +201,7 @@ static int is_ejectable_bay(acpi_handle handle)
return 0;
}
#if 0
/**
* eject_removable_drive - try to eject this drive
* @dev : the device structure of the drive
......@@ -225,6 +226,7 @@ int eject_removable_drive(struct device *dev)
return 0;
}
EXPORT_SYMBOL_GPL(eject_removable_drive);
#endif /* 0 */
static int acpi_bay_add_fs(struct bay *bay)
{
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
ACPI_FUNCTION_TRACE(ds_create_buffer_field);
/* Get the name_string argument */
/*
* Get the name_string argument (name of the new buffer_field)
*/
if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
/* For create_field, name is the 4th argument */
arg = acpi_ps_get_arg(op, 3);
} else {
/* Create Bit/Byte/Word/Dword field */
/* For all other create_xXXField operators, name is the 3rd argument */
arg = acpi_ps_get_arg(op, 2);
}
......@@ -107,26 +111,30 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
node = walk_state->deferred_node;
status = AE_OK;
} else {
/*
* During the load phase, we want to enter the name of the field into
* the namespace. During the execute phase (when we evaluate the size
* operand), we want to lookup the name
*/
if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
} else {
/* Execute flag should always be set when this function is entered */
if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* Creating new namespace node, should not already exist */
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) {
flags |= ACPI_NS_TEMPORARY;
}
/*
* Enter the name_string into the namespace
*/
/* Enter the name_string into the namespace */
status =
acpi_ns_lookup(walk_state->scope_info,
arg->common.value.string, ACPI_TYPE_ANY,
ACPI_IMODE_LOAD_PASS1, flags, walk_state,
&(node));
&node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
......@@ -136,7 +144,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
/*
* We could put the returned object (Node) on the object stack for later,
* but for now, we will put it in the "op" object that the parser uses,
* so we can get it again at the end of this scope
* so we can get it again at the end of this scope.
*/
op->common.node = node;
......@@ -164,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
}
/*
* Remember location in AML stream of the field unit
* opcode and operands -- since the buffer and index
* operands must be evaluated.
* Remember location in AML stream of the field unit opcode and operands --
* since the buffer and index operands must be evaluated.
*/
second_desc = obj_desc->common.next_object;
second_desc->extra.aml_start = op->named.data;
......@@ -261,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
case AML_INT_NAMEDFIELD_OP:
/* Lookup the name */
/* Lookup the name, it should already exist */
status = acpi_ns_lookup(walk_state->scope_info,
(char *)&arg->named.name,
......@@ -272,22 +279,25 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
status);
if (status != AE_ALREADY_EXISTS) {
return_ACPI_STATUS(status);
}
/* Already exists, ignore error */
} else {
arg->common.node = info->field_node;
info->field_bit_length = arg->common.value.size;
/* Create and initialize an object for the new Field Node */
/*
* If there is no object attached to the node, this node was
* just created and we need to create the field object.
* Otherwise, this was a lookup of an existing node and we
* don't want to create the field object again.
*/
if (!acpi_ns_get_attached_object
(info->field_node)) {
status = acpi_ex_prep_field_value(info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}
/* Keep track of bit position for the next field */
......@@ -399,9 +409,27 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
union acpi_parse_object *arg = NULL;
struct acpi_namespace_node *node;
u8 type = 0;
u32 flags;
ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
/* Execute flag should always be set when this function is entered */
if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
/* bank_field Op is deferred, just return OK */
return_ACPI_STATUS(AE_OK);
}
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
* Get the field_list argument for this opcode. This is the start of the
* list of field elements.
*/
switch (walk_state->opcode) {
case AML_FIELD_OP:
arg = acpi_ps_get_arg(op, 2);
......@@ -422,20 +450,33 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (!arg) {
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/* Creating new namespace node(s), should not already exist */
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) {
flags |= ACPI_NS_TEMPORARY;
}
/*
* Walk the list of entries in the field_list
*/
while (arg) {
/* Ignore OFFSET and ACCESSAS terms here */
/*
* Ignore OFFSET and ACCESSAS terms here; we are only interested in the
* field names in order to enter them into the namespace.
*/
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
status = acpi_ns_lookup(walk_state->scope_info,
(char *)&arg->named.name,
type, ACPI_IMODE_LOAD_PASS1,
ACPI_NS_NO_UPSEARCH |
ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND,
(char *)&arg->named.name, type,
ACPI_IMODE_LOAD_PASS1, flags,
walk_state, &node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
......@@ -452,7 +493,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
arg->common.node = node;
}
/* Move to next field in the list */
/* Get the next field element in the list */
arg = arg->common.next;
}
......@@ -466,7 +507,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
*
* PARAMETERS: Op - Op containing the Field definition and args
* region_node - Object for the containing Operation Region
* ` walk_state - Current method state
* walk_state - Current method state
*
* RETURN: Status
*
......@@ -513,36 +554,13 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
return_ACPI_STATUS(status);
}
/* Third arg is the bank_value */
/* TBD: This arg is a term_arg, not a constant, and must be evaluated */
/*
* Third arg is the bank_value
* This arg is a term_arg, not a constant
* It will be evaluated later, by acpi_ds_eval_bank_field_operands
*/
arg = arg->common.next;
/* Currently, only the following constants are supported */
switch (arg->common.aml_opcode) {
case AML_ZERO_OP:
info.bank_value = 0;
break;
case AML_ONE_OP:
info.bank_value = 1;
break;
case AML_BYTE_OP:
case AML_WORD_OP:
case AML_DWORD_OP:
case AML_QWORD_OP:
info.bank_value = (u32) arg->common.value.integer;
break;
default:
info.bank_value = 0;
ACPI_ERROR((AE_INFO,
"Non-constant BankValue for BankField is not implemented"));
}
/* Fourth arg is the field flags */
arg = arg->common.next;
......@@ -553,8 +571,17 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
info.region_node = region_node;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
/*
* Use Info.data_register_node to store bank_field Op
* It's safe because data_register_node will never be used when create bank field
* We store aml_start and aml_length in the bank_field Op for late evaluation
* Used in acpi_ex_prep_field_value(Info)
*
* TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"?
*/
info.data_register_node = (struct acpi_namespace_node *)op;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
return_ACPI_STATUS(status);
}
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -42,7 +42,6 @@
*/
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
......@@ -102,7 +101,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
walk_state->opcode,
walk_state->aml_offset,
NULL);
(void)acpi_ex_enter_interpreter();
acpi_ex_enter_interpreter();
}
#ifdef ACPI_DISASSEMBLER
if (ACPI_FAILURE(status)) {
......@@ -232,9 +231,9 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
* recursive call.
*/
if (!walk_state ||
!obj_desc->method.mutex->mutex.owner_thread ||
(walk_state->thread !=
obj_desc->method.mutex->mutex.owner_thread)) {
!obj_desc->method.mutex->mutex.thread_id ||
(walk_state->thread->thread_id !=
obj_desc->method.mutex->mutex.thread_id)) {
/*
* Acquire the method mutex. This releases the interpreter if we
* block (and reacquires it before it returns)
......@@ -254,8 +253,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
original_sync_level =
walk_state->thread->current_sync_level;
obj_desc->method.mutex->mutex.owner_thread =
walk_state->thread;
obj_desc->method.mutex->mutex.thread_id =
walk_state->thread->thread_id;
walk_state->thread->current_sync_level =
obj_desc->method.sync_level;
} else {
......@@ -535,8 +534,6 @@ void
acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
struct acpi_walk_state *walk_state)
{
struct acpi_namespace_node *method_node;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state);
......@@ -551,7 +548,6 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
/* Delete all arguments and locals */
acpi_ds_method_data_delete_all(walk_state);
}
/*
* If method is serialized, release the mutex and restore the
......@@ -567,19 +563,12 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
method_desc->method.mutex->mutex.
original_sync_level;
acpi_os_release_mutex(method_desc->method.mutex->mutex.
os_mutex);
method_desc->method.mutex->mutex.owner_thread = NULL;
acpi_os_release_mutex(method_desc->method.
mutex->mutex.os_mutex);
method_desc->method.mutex->mutex.thread_id = 0;
}
}
if (walk_state) {
/*
* Delete any objects created by this method during execution.
* The method Node is stored in the walk state
*/
method_node = walk_state->method_node;
/*
* Delete any namespace objects created anywhere within
* the namespace by the execution of this method
......@@ -620,7 +609,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
*/
if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED)
&& (!method_desc->method.mutex)) {
status = acpi_ds_create_method_mutex(method_desc);
(void)acpi_ds_create_method_mutex(method_desc);
}
/* No more threads, we can free the owner_id */
......
......@@ -5,7 +5,7 @@
******************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -157,7 +157,9 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
* will remain as named references. This behavior is not described
* in the ACPI spec, but it appears to be an oversight.
*/
obj_desc = (union acpi_operand_object *)op->common.node;
obj_desc =
ACPI_CAST_PTR(union acpi_operand_object,
op->common.node);
status =
acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
......@@ -172,7 +174,19 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
switch (op->common.node->type) {
/*
* For these types, we need the actual node, not the subobject.
* However, the subobject got an extra reference count above.
* However, the subobject did not get an extra reference count above.
*
* TBD: should ex_resolve_node_to_value be changed to fix this?
*/
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_THERMAL:
acpi_ut_add_reference(op->common.node->object);
/*lint -fallthrough */
/*
* For these types, we need the actual node, not the subobject.
* The subobject got an extra reference count in ex_resolve_node_to_value.
*/
case ACPI_TYPE_MUTEX:
case ACPI_TYPE_METHOD:
......@@ -180,25 +194,15 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_EVENT:
case ACPI_TYPE_REGION:
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_THERMAL:
obj_desc =
(union acpi_operand_object *)op->common.
node;
/* We will create a reference object for these types below */
break;
default:
break;
}
/*
* If above resolved to an operand object, we are done. Otherwise,
* we have a NS node, we must create the package entry as a named
* reference.
* All other types - the node was resolved to an actual
* object, we are done.
*/
if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
ACPI_DESC_TYPE_NAMED) {
goto exit;
}
}
......@@ -223,7 +227,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
exit:
*obj_desc_ptr = obj_desc;
return_ACPI_STATUS(AE_OK);
return_ACPI_STATUS(status);
}
/*******************************************************************************
......@@ -369,7 +373,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
union acpi_parse_object *parent;
union acpi_operand_object *obj_desc = NULL;
acpi_status status = AE_OK;
acpi_native_uint i;
unsigned i;
u16 index;
u16 reference_count;
ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
......@@ -447,13 +453,60 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
package.
elements[i]);
}
if (*obj_desc_ptr) {
/* Existing package, get existing reference count */
reference_count =
(*obj_desc_ptr)->common.reference_count;
if (reference_count > 1) {
/* Make new element ref count match original ref count */
for (index = 0; index < (reference_count - 1);
index++) {
acpi_ut_add_reference((obj_desc->
package.
elements[i]));
}
}
}
arg = arg->common.next;
}
/* Check for match between num_elements and actual length of package_list */
if (arg) {
/*
* num_elements was exhausted, but there are remaining elements in the
* package_list.
*
* 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.
*/
while (arg) {
/* Find out how many elements there really are */
i++;
arg = arg->common.next;
}
if (!arg) {
ACPI_ERROR((AE_INFO,
"Package List length (%X) larger than NumElements count (%X), truncated\n",
i, element_count));
} else if (i < element_count) {
/*
* Arg list (elements) was exhausted, but we did not reach num_elements count.
* Note: this is not an error, the package is padded out with NULLs.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Package List length larger than NumElements count (%X), truncated\n",
element_count));
"Package List length (%X) smaller than NumElements count (%X), padded with null elements\n",
i, element_count));
}
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
......@@ -721,6 +774,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
/* Node was saved in Op */
obj_desc->reference.node = op->common.node;
obj_desc->reference.object =
op->common.node->object;
}
obj_desc->reference.opcode = opcode;
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -49,6 +49,7 @@
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsopcode")
......@@ -217,6 +218,50 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_bank_field_arguments
*
* PARAMETERS: obj_desc - A valid bank_field object
*
* RETURN: Status.
*
* DESCRIPTION: Get bank_field bank_value. This implements the late
* evaluation of these field attributes.
*
******************************************************************************/
acpi_status
acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
{
union acpi_operand_object *extra_desc;
struct acpi_namespace_node *node;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
}
/* Get the AML pointer (method object) and bank_field node */
extra_desc = acpi_ns_get_secondary_object(obj_desc);
node = obj_desc->bank_field.node;
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
(ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
acpi_ut_get_node_name(node)));
/* Execute the AML code for the term_arg arguments */
status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_buffer_arguments
......@@ -770,7 +815,109 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
obj_desc,
ACPI_FORMAT_UINT64(obj_desc->region.address),
ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
obj_desc->region.length));
/* Now the address and length are valid for this opregion */
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_table_region_operands
*
* PARAMETERS: walk_state - Current walk
* Op - A valid region Op object
*
* RETURN: Status
*
* DESCRIPTION: Get region address and length
* Called from acpi_ds_exec_end_op during data_table_region parse tree walk
*
******************************************************************************/
acpi_status
acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_operand_object **operand;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
acpi_native_uint table_index;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
/*
* This is where we evaluate the signature_string and oem_iDString
* and oem_table_iDString of the data_table_region declaration
*/
node = op->common.node;
/* next_op points to signature_string op */
next_op = op->common.value.arg;
/*
* Evaluate/create the signature_string and oem_iDString
* and oem_table_iDString operands
*/
status = acpi_ds_create_operands(walk_state, next_op);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Resolve the signature_string and oem_iDString
* and oem_table_iDString operands
*/
status = acpi_ex_resolve_operands(op->common.aml_opcode,
ACPI_WALK_OPERANDS, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
acpi_ps_get_opcode_name(op->common.aml_opcode),
1, "after AcpiExResolveOperands");
operand = &walk_state->operands[0];
/* Find the ACPI table */
status = acpi_tb_find_table(operand[0]->string.pointer,
operand[1]->string.pointer,
operand[2]->string.pointer, &table_index);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_ut_remove_reference(operand[0]);
acpi_ut_remove_reference(operand[1]);
acpi_ut_remove_reference(operand[2]);
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
obj_desc->region.address =
(acpi_physical_address) ACPI_TO_INTEGER(table);
obj_desc->region.length = table->length;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
obj_desc,
ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
obj_desc->region.length));
/* Now the address and length are valid for this opregion */
......@@ -808,6 +955,12 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
/* The first operand (for all of these data objects) is the length */
/*
* Set proper index into operand stack for acpi_ds_obj_stack_push
* invoked inside acpi_ds_create_operand.
*/
walk_state->operand_index = walk_state->num_operands;
status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
......@@ -876,6 +1029,106 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_bank_field_operands
*
* PARAMETERS: walk_state - Current walk
* Op - A valid bank_field Op object
*
* RETURN: Status
*
* DESCRIPTION: Get bank_field bank_value
* Called from acpi_ds_exec_end_op during bank_field parse tree walk
*
******************************************************************************/
acpi_status
acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_operand_object *operand_desc;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
union acpi_parse_object *arg;
ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);
/*
* This is where we evaluate the bank_value field of the
* bank_field declaration
*/
/* next_op points to the op that holds the Region */
next_op = op->common.value.arg;
/* next_op points to the op that holds the Bank Register */
next_op = next_op->common.next;
/* next_op points to the op that holds the Bank Value */
next_op = next_op->common.next;
/*
* Set proper index into operand stack for acpi_ds_obj_stack_push
* invoked inside acpi_ds_create_operand.
*
* We use walk_state->Operands[0] to store the evaluated bank_value
*/
walk_state->operand_index = 0;
status = acpi_ds_create_operand(walk_state, next_op, 0);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
acpi_ps_get_opcode_name(op->common.aml_opcode),
1, "after AcpiExResolveOperands");
/*
* Get the bank_value operand and save it
* (at Top of stack)
*/
operand_desc = walk_state->operands[0];
/* Arg points to the start Bank Field */
arg = acpi_ps_get_arg(op, 4);
while (arg) {
/* Ignore OFFSET and ACCESSAS terms here */
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
node = arg->common.node;
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
obj_desc->bank_field.value =
(u32) operand_desc->integer.value;
}
/* Move to next field in the list */
arg = arg->common.next;
}
acpi_ut_remove_reference(operand_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_exec_begin_control_op
......@@ -1070,8 +1323,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
* is set to anything other than zero!
*/
walk_state->return_desc = walk_state->operands[0];
} else if ((walk_state->results) &&
(walk_state->results->results.num_results > 0)) {
} else if (walk_state->result_count) {
/* Since we have a real Return(), delete any implicit return */
......
......@@ -5,7 +5,7 @@
******************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -278,7 +278,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
AML_VAR_PACKAGE_OP)
|| (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
|| (op->common.parent->common.aml_opcode ==
AML_INT_EVAL_SUBTREE_OP)) {
AML_INT_EVAL_SUBTREE_OP)
|| (op->common.parent->common.aml_opcode ==
AML_BANK_FIELD_OP)) {
/*
* These opcodes allow term_arg(s) as operands and therefore
* the operands can be method calls. The result is used.
......@@ -472,7 +474,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
/* A valid name must be looked up in the namespace */
if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
(arg->common.value.string)) {
(arg->common.value.string) &&
!(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
arg));
......@@ -595,7 +598,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
} else {
/* Check for null name case */
if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) {
if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
!(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
/*
* If the name is null, this means that this is an
* optional result parameter that was not specified
......@@ -617,7 +621,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
if (op_info->flags & AML_HAS_RETVAL) {
if ((op_info->flags & AML_HAS_RETVAL)
|| (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Argument previously created, already stacked\n"));
......@@ -630,9 +635,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
* Use value that was already previously returned
* by the evaluation of this argument
*/
status =
acpi_ds_result_pop_from_bottom(&obj_desc,
walk_state);
status = acpi_ds_result_pop(&obj_desc, walk_state);
if (ACPI_FAILURE(status)) {
/*
* Only error is underflow, and this indicates
......@@ -698,27 +701,52 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
{
acpi_status status = AE_OK;
union acpi_parse_object *arg;
union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
u32 arg_count = 0;
u32 index = walk_state->num_operands;
u32 i;
ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
/* For all arguments in the list... */
/* Get all arguments in the list */
arg = first_arg;
while (arg) {
status = acpi_ds_create_operand(walk_state, arg, arg_count);
if (ACPI_FAILURE(status)) {
goto cleanup;
if (index >= ACPI_OBJ_NUM_OPERANDS) {
return_ACPI_STATUS(AE_BAD_DATA);
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Arg #%d (%p) done, Arg1=%p\n", arg_count,
arg, first_arg));
arguments[index] = arg;
walk_state->operands[index] = NULL;
/* Move on to next argument, if any */
arg = arg->common.next;
arg_count++;
index++;
}
index--;
/* It is the appropriate order to get objects from the Result stack */
for (i = 0; i < arg_count; i++) {
arg = arguments[index];
/* Force the filling of the operand stack in inverse order */
walk_state->operand_index = (u8) index;
status = acpi_ds_create_operand(walk_state, arg, index);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
index--;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Arg #%d (%p) done, Arg1=%p\n", index, arg,
first_arg));
}
return_ACPI_STATUS(status);
......@@ -729,9 +757,112 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
* pop everything off of the operand stack and delete those
* objects
*/
(void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index));
return_ACPI_STATUS(status);
}
/*****************************************************************************
*
* FUNCTION: acpi_ds_evaluate_name_path
*
* PARAMETERS: walk_state - Current state of the parse tree walk,
* the opcode of current operation should be
* AML_INT_NAMEPATH_OP
*
* RETURN: Status
*
* DESCRIPTION: Translate the -name_path- parse tree object to the equivalent
* interpreter object, convert it to value, if needed, duplicate
* it, if needed, and push it onto the current result stack.
*
****************************************************************************/
acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
union acpi_parse_object *op = walk_state->op;
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *new_obj_desc;
u8 type;
ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
if (!op->common.parent) {
/* This happens after certain exception processing */
goto exit;
}
if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
(op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
(op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
/* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
goto exit;
}
status = acpi_ds_create_operand(walk_state, op, 0);
if (ACPI_FAILURE(status)) {
goto exit;
}
if (op->common.flags & ACPI_PARSEOP_TARGET) {
new_obj_desc = *operand;
goto push_result;
}
type = ACPI_GET_OBJECT_TYPE(*operand);
status = acpi_ex_resolve_to_value(operand, walk_state);
if (ACPI_FAILURE(status)) {
goto exit;
}
if (type == ACPI_TYPE_INTEGER) {
/* It was incremented by acpi_ex_resolve_to_value */
acpi_ut_remove_reference(*operand);
status =
acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
walk_state);
if (ACPI_FAILURE(status)) {
goto exit;
}
} else {
/*
* The object either was anew created or is
* a Namespace node - don't decrement it.
*/
new_obj_desc = *operand;
}
/* Cleanup for name-path operand */
status = acpi_ds_obj_stack_pop(1, walk_state);
if (ACPI_FAILURE(status)) {
walk_state->result_obj = new_obj_desc;
goto exit;
}
push_result:
walk_state->result_obj = new_obj_desc;
status = acpi_ds_result_push(walk_state->result_obj, walk_state);
if (ACPI_SUCCESS(status)) {
/* Force to take it from stack */
op->common.flags |= ACPI_PARSEOP_IN_STACK;
}
exit:
ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d",
(arg_count + 1)));
return_ACPI_STATUS(status);
}
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -285,11 +285,6 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
switch (opcode_class) {
case AML_CLASS_CONTROL:
status = acpi_ds_result_stack_push(walk_state);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
status = acpi_ds_exec_begin_control_op(walk_state, op);
break;
......@@ -305,20 +300,11 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
status = acpi_ds_load2_begin_op(walk_state, NULL);
}
if (op->common.aml_opcode == AML_REGION_OP) {
status = acpi_ds_result_stack_push(walk_state);
}
break;
case AML_CLASS_EXECUTE:
case AML_CLASS_CREATE:
/*
* Most operators with arguments (except create_xxx_field operators)
* Start a new result/operand state
*/
if (walk_state->op_info->object_type != ACPI_TYPE_BUFFER_FIELD) {
status = acpi_ds_result_stack_push(walk_state);
}
break;
default:
......@@ -374,6 +360,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
/* Init the walk state */
walk_state->num_operands = 0;
walk_state->operand_index = 0;
walk_state->return_desc = NULL;
walk_state->result_obj = NULL;
......@@ -388,21 +375,21 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
/* Decode the Opcode Class */
switch (op_class) {
case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */
break;
case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */
case AML_CLASS_EXECUTE: /* most operators with arguments */
/* Build resolved operand stack */
status = acpi_ds_create_operands(walk_state, first_arg);
if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
status = acpi_ds_evaluate_name_path(walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
}
break;
/* Done with this result state (Now that operand stack is built) */
case AML_CLASS_EXECUTE: /* Most operators with arguments */
status = acpi_ds_result_stack_pop(walk_state);
/* Build resolved operand stack */
status = acpi_ds_create_operands(walk_state, first_arg);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
......@@ -487,16 +474,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
status = acpi_ds_exec_end_control_op(walk_state, op);
/* Make sure to properly pop the result stack */
if (ACPI_SUCCESS(status)) {
status = acpi_ds_result_stack_pop(walk_state);
} else if (status == AE_CTRL_PENDING) {
status = acpi_ds_result_stack_pop(walk_state);
if (ACPI_SUCCESS(status)) {
status = AE_CTRL_PENDING;
}
}
break;
case AML_TYPE_METHOD_CALL:
......@@ -516,7 +493,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
op->common.node =
(struct acpi_namespace_node *)op->asl.value.
arg->asl.node->object;
arg->asl.node;
acpi_ut_add_reference(op->asl.value.arg->asl.
node->object);
return_ACPI_STATUS(AE_OK);
......@@ -632,13 +609,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
break;
}
/* Done with result state (Now that operand stack is built) */
status = acpi_ds_result_stack_pop(walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/*
* If a result object was returned from above, push it on the
* current result stack
......@@ -671,8 +641,28 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
break;
}
} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing DataTableRegion Strings Op=%p\n",
op));
status =
acpi_ds_eval_table_region_operands
(walk_state, op);
if (ACPI_FAILURE(status)) {
break;
}
} else if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing BankField Op=%p\n",
op));
status = acpi_ds_result_stack_pop(walk_state);
status =
acpi_ds_eval_bank_field_operands(walk_state,
op);
if (ACPI_FAILURE(status)) {
break;
}
}
break;
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -443,6 +443,15 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
status =
acpi_ex_create_region(op->named.data,
op->named.length,
REGION_DATA_TABLE,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}
#endif
......@@ -767,6 +776,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
object_type, ACPI_IMODE_LOAD_PASS2, flags,
walk_state, &node);
if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"***New Node [%4.4s] %p is temporary\n",
acpi_ut_get_node_name(node), node));
}
break;
}
......@@ -823,6 +838,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
struct acpi_namespace_node *new_node;
#ifndef ACPI_NO_METHOD_EXECUTION
u32 i;
u8 region_space;
#endif
ACPI_FUNCTION_TRACE(ds_load2_end_op);
......@@ -1003,11 +1019,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
status = acpi_ex_create_event(walk_state);
break;
case AML_DATA_REGION_OP:
status = acpi_ex_create_table_region(walk_state);
break;
case AML_ALIAS_OP:
status = acpi_ex_create_alias(walk_state);
......@@ -1035,6 +1046,15 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
switch (op->common.aml_opcode) {
#ifndef ACPI_NO_METHOD_EXECUTION
case AML_REGION_OP:
case AML_DATA_REGION_OP:
if (op->common.aml_opcode == AML_REGION_OP) {
region_space = (acpi_adr_space_type)
((op->common.value.arg)->common.value.
integer);
} else {
region_space = REGION_DATA_TABLE;
}
/*
* If we are executing a method, initialize the region
......@@ -1043,10 +1063,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
status =
acpi_ex_create_region(op->named.data,
op->named.length,
(acpi_adr_space_type)
((op->common.value.
arg)->common.value.
integer),
region_space,
walk_state);
if (ACPI_FAILURE(status)) {
return (status);
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
This diff is collapsed.
This diff is collapsed.
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -248,10 +248,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
ACPI_FUNCTION_TRACE(ev_disable_gpe);
if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
return_ACPI_STATUS(AE_OK);
}
/* Make sure HW enable masks are updated */
status =
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -49,22 +49,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evmisc")
/* Names for Notify() values, used for debug output */
#ifdef ACPI_DEBUG_OUTPUT
static const char *acpi_notify_value_names[] = {
"Bus Check",
"Device Check",
"Device Wake",
"Eject Request",
"Device Check Light",
"Frequency Mismatch",
"Bus Mode Mismatch",
"Power Fault"
};
#endif
/* Pointer to FACS needed for the Global Lock */
static struct acpi_table_facs *facs = NULL;
/* Local prototypes */
......@@ -94,7 +79,6 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
switch (node->type) {
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_POWER:
case ACPI_TYPE_THERMAL:
/*
* These are the ONLY objects that can receive ACPI notifications
......@@ -139,17 +123,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
* initiate soft-off or sleep operation?
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Dispatching Notify(%X) on node %p\n", notify_value,
node));
if (notify_value <= 7) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notify value: %s\n",
acpi_notify_value_names[notify_value]));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Notify value: 0x%2.2X **Device Specific**\n",
notify_value));
}
"Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n",
acpi_ut_get_node_name(node), node, notify_value,
acpi_ut_get_notify_name(notify_value)));
/* Get the notify object attached to the NS Node */
......@@ -159,10 +135,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
/* We have the notify object, Get the right handler */
switch (node->type) {
/* Notify allowed only on these types */
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_THERMAL:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_POWER:
if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
handler_obj =
......@@ -179,8 +157,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
}
}
/* If there is any handler to run, schedule the dispatcher */
/*
* If there is any handler to run, schedule the dispatcher.
* Check for:
* 1) Global system notify handler
* 2) Global device notify handler
* 3) Per-device notify handler
*/
if ((acpi_gbl_system_notify.handler
&& (notify_value <= ACPI_MAX_SYS_NOTIFY))
|| (acpi_gbl_device_notify.handler
......@@ -190,6 +173,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
return (AE_NO_MEMORY);
}
if (!handler_obj) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Executing system notify handler for Notify (%4.4s, %X) node %p\n",
acpi_ut_get_node_name(node),
notify_value, node));
}
notify_info->common.descriptor_type =
ACPI_DESC_TYPE_STATE_NOTIFY;
notify_info->notify.node = node;
......@@ -202,15 +192,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
if (ACPI_FAILURE(status)) {
acpi_ut_delete_generic_state(notify_info);
}
}
if (!handler_obj) {
} else {
/*
* There is no per-device notify handler for this device.
* This may or may not be a problem.
* There is no notify handler (per-device or system) for this device.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No notify handler for Notify(%4.4s, %X) node %p\n",
"No notify handler for Notify (%4.4s, %X) node %p\n",
acpi_ut_get_node_name(node), notify_value,
node));
}
......@@ -349,9 +336,10 @@ acpi_status acpi_ev_init_global_lock_handler(void)
ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
status =
acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
(struct acpi_table_header **)&facs);
status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
ACPI_CAST_INDIRECT_PTR(struct
acpi_table_header,
&facs));
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
......@@ -439,7 +427,8 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
* Only one thread can acquire the GL at a time, the global_lock_mutex
* enforces this. This interface releases the interpreter if we must wait.
*/
status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0);
status = acpi_ex_system_wait_mutex(
acpi_gbl_global_lock_mutex->mutex.os_mutex, 0);
if (status == AE_TIME) {
if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {
acpi_ev_global_lock_acquired++;
......@@ -448,8 +437,8 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
}
if (ACPI_FAILURE(status)) {
status =
acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex,
status = acpi_ex_system_wait_mutex(
acpi_gbl_global_lock_mutex->mutex.os_mutex,
timeout);
}
if (ACPI_FAILURE(status)) {
......@@ -459,6 +448,19 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
acpi_ev_global_lock_thread_id = acpi_os_get_thread_id();
acpi_ev_global_lock_acquired++;
/*
* Update the global lock handle and check for wraparound. The handle is
* only used for the external global lock interfaces, but it is updated
* here to properly handle the case where a single thread may acquire the
* lock via both the AML and the acpi_acquire_global_lock interfaces. The
* handle is therefore updated on the first acquire from a given thread
* regardless of where the acquisition request originated.
*/
acpi_gbl_global_lock_handle++;
if (acpi_gbl_global_lock_handle == 0) {
acpi_gbl_global_lock_handle = 1;
}
/*
* Make sure that a global lock actually exists. If not, just treat
* the lock as a standard mutex.
......@@ -555,7 +557,7 @@ acpi_status acpi_ev_release_global_lock(void)
/* Release the local GL mutex */
acpi_ev_global_lock_thread_id = NULL;
acpi_ev_global_lock_acquired = 0;
acpi_os_release_mutex(acpi_gbl_global_lock_mutex);
acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex);
return_ACPI_STATUS(status);
}
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -394,7 +394,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
&region_obj->region.handler->address_space, handler,
ACPI_FORMAT_UINT64(address),
ACPI_FORMAT_NATIVE_UINT(address),
acpi_ut_get_region_name(region_obj->region.
space_id)));
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -6,7 +6,7 @@
******************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -758,6 +758,12 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
*
* DESCRIPTION: Acquire the ACPI Global Lock
*
* Note: Allows callers with the same thread ID to acquire the global lock
* multiple times. In other words, externally, the behavior of the global lock
* is identical to an AML mutex. On the first acquire, a new handle is
* returned. On any subsequent calls to acquire by the same thread, the same
* handle is returned.
*
******************************************************************************/
acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
{
......@@ -770,14 +776,19 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
/* Must lock interpreter to prevent race conditions */
acpi_ex_enter_interpreter();
status = acpi_ev_acquire_global_lock(timeout);
acpi_ex_exit_interpreter();
status = acpi_ex_acquire_mutex_object(timeout,
acpi_gbl_global_lock_mutex,
acpi_os_get_thread_id());
if (ACPI_SUCCESS(status)) {
acpi_gbl_global_lock_handle++;
/* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
*handle = acpi_gbl_global_lock_handle;
}
acpi_ex_exit_interpreter();
return (status);
}
......@@ -798,11 +809,11 @@ acpi_status acpi_release_global_lock(u32 handle)
{
acpi_status status;
if (handle != acpi_gbl_global_lock_handle) {
if (!handle || (handle != acpi_gbl_global_lock_handle)) {
return (AE_NOT_ACQUIRED);
}
status = acpi_ev_release_global_lock();
status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
return (status);
}
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -45,7 +45,6 @@
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
#include <acpi/actables.h>
#include <acpi/acdispat.h>
......@@ -138,6 +137,14 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
ACPI_FUNCTION_TRACE(ex_load_table_op);
/* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */
if ((operand[0]->string.length > ACPI_NAME_SIZE) ||
(operand[1]->string.length > ACPI_OEM_ID_SIZE) ||
(operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Find the ACPI table in the RSDT/XSDT */
status = acpi_tb_find_table(operand[0]->string.pointer,
......@@ -229,11 +236,18 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_SUCCESS(status)) {
ACPI_INFO((AE_INFO,
"Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]",
"Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]",
table->signature, table->oem_id,
table->oem_table_id));
}
/* Invoke table handler if present */
if (acpi_gbl_table_handler) {
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
acpi_gbl_table_handler_context);
}
*return_desc = ddb_handle;
return_ACPI_STATUS(status);
}
......@@ -268,6 +282,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
struct acpi_table_desc table_desc;
acpi_native_uint table_index;
acpi_status status;
u32 length;
ACPI_FUNCTION_TRACE(ex_load_op);
......@@ -278,16 +293,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_REGION:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
obj_desc,
acpi_ut_get_object_type_name(obj_desc)));
/* Region must be system_memory (from ACPI spec) */
if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
obj_desc,
acpi_ut_get_object_type_name(obj_desc)));
/*
* If the Region Address and Length have not been previously evaluated,
* evaluate them now and save the results.
......@@ -299,6 +314,11 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
}
}
/*
* We will simply map the memory region for the table. However, the
* memory region is technically not guaranteed to remain stable and
* we may eventually have to copy the table to a local buffer.
*/
table_desc.address = obj_desc->region.address;
table_desc.length = obj_desc->region.length;
table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED;
......@@ -306,18 +326,41 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
/* Simply extract the buffer from the buffer object */
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Load from Buffer or Field %p %s\n", obj_desc,
acpi_ut_get_object_type_name(obj_desc)));
table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header,
obj_desc->buffer.pointer);
table_desc.length = table_desc.pointer->length;
table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
length = obj_desc->buffer.length;
obj_desc->buffer.pointer = NULL;
/* Must have at least an ACPI table header */
if (length < sizeof(struct acpi_table_header)) {
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/* Validate checksum here. It won't get validated in tb_add_table */
status =
acpi_tb_verify_checksum(ACPI_CAST_PTR
(struct acpi_table_header,
obj_desc->buffer.pointer), length);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* We need to copy the buffer since the original buffer could be
* changed or deleted in the future
*/
table_desc.pointer = ACPI_ALLOCATE(length);
if (!table_desc.pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer,
length);
table_desc.length = length;
table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
break;
default:
......@@ -333,7 +376,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
}
status =
acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
acpi_ex_add_table(table_index, walk_state->scope_info->scope.node,
&ddb_handle);
if (ACPI_FAILURE(status)) {
/* On error, table_ptr was deallocated above */
......@@ -349,11 +393,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* table_ptr was deallocated above */
acpi_ut_remove_reference(ddb_handle);
return_ACPI_STATUS(status);
}
/* Invoke table handler if present */
if (acpi_gbl_table_handler) {
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD,
table_desc.pointer,
acpi_gbl_table_handler_context);
}
cleanup:
if (ACPI_FAILURE(status)) {
/* Delete allocated buffer or mapping */
acpi_tb_delete_table(&table_desc);
}
return_ACPI_STATUS(status);
......@@ -376,6 +432,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
acpi_status status = AE_OK;
union acpi_operand_object *table_desc = ddb_handle;
acpi_native_uint table_index;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE(ex_unload_table);
......@@ -395,17 +452,25 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
table_index = (acpi_native_uint) table_desc->reference.object;
/* Invoke table handler if present */
if (acpi_gbl_table_handler) {
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_SUCCESS(status)) {
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
table,
acpi_gbl_table_handler_context);
}
}
/*
* Delete the entire namespace under this table Node
* (Offset contains the table_id)
*/
acpi_tb_delete_namespace_by_owner(table_index);
acpi_tb_release_owner_id(table_index);
(void)acpi_tb_release_owner_id(table_index);
acpi_tb_set_table_loaded_flag(table_index, FALSE);
/* Delete the table descriptor (ddb_handle) */
acpi_ut_remove_reference(table_desc);
return_ACPI_STATUS(status);
return_ACPI_STATUS(AE_OK);
}
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -96,16 +96,28 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
* to the original Node.
*/
switch (target_node->type) {
/* For these types, the sub-object can change dynamically via a Store */
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_BUFFER_FIELD:
/*
* These types open a new scope, so we need the NS node in order to access
* any children.
*/
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL:
case ACPI_TYPE_LOCAL_SCOPE:
/*
* The new alias has the type ALIAS and points to the original
* NS node, not the object itself. This is because for these
* types, the object can change dynamically via a Store.
* NS node, not the object itself.
*/
alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
alias_node->object =
......@@ -115,9 +127,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
case ACPI_TYPE_METHOD:
/*
* The new alias has the type ALIAS and points to the original
* NS node, not the object itself. This is because for these
* types, the object can change dynamically via a Store.
* Control method aliases need to be differentiated
*/
alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
alias_node->object =
......@@ -340,101 +350,6 @@ acpi_ex_create_region(u8 * aml_start,
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_table_region
*
* PARAMETERS: walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Create a new data_table_region object
*
******************************************************************************/
acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
union acpi_operand_object *region_obj2;
acpi_native_uint table_index;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE(ex_create_table_region);
/* Get the Node from the object stack */
node = walk_state->op->common.node;
/*
* If the region object is already attached to this node,
* just return
*/
if (acpi_ns_get_attached_object(node)) {
return_ACPI_STATUS(AE_OK);
}
/* Find the ACPI table */
status = acpi_tb_find_table(operand[1]->string.pointer,
operand[2]->string.pointer,
operand[3]->string.pointer, &table_index);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Create the region descriptor */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
region_obj2 = obj_desc->common.next_object;
region_obj2->extra.region_context = NULL;
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Init the region from the operands */
obj_desc->region.space_id = REGION_DATA_TABLE;
obj_desc->region.address =
(acpi_physical_address) ACPI_TO_INTEGER(table);
obj_desc->region.length = table->length;
obj_desc->region.node = node;
obj_desc->region.flags = AOPOBJ_DATA_VALID;
/* Install the new region object in the parent Node */
status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
status = acpi_ev_initialize_region(obj_desc, FALSE);
if (ACPI_FAILURE(status)) {
if (status == AE_NOT_EXIST) {
status = AE_OK;
} else {
goto cleanup;
}
}
obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE;
cleanup:
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_processor
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -500,25 +500,28 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
acpi_os_printf("Reference: Debug\n");
break;
case AML_NAME_OP:
case AML_INDEX_OP:
ACPI_DUMP_PATHNAME(obj_desc->reference.object,
"Reference: Name: ", ACPI_LV_INFO,
_COMPONENT);
ACPI_DUMP_ENTRY(obj_desc->reference.object,
ACPI_LV_INFO);
acpi_os_printf("Reference: Index %p\n",
obj_desc->reference.object);
break;
case AML_INDEX_OP:
case AML_LOAD_OP:
acpi_os_printf("Reference: Index %p\n",
acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n",
obj_desc->reference.object);
break;
case AML_REF_OF_OP:
acpi_os_printf("Reference: (RefOf) %p\n",
obj_desc->reference.object);
acpi_os_printf("Reference: (RefOf) %p [%s]\n",
obj_desc->reference.object,
acpi_ut_get_type_name(((union
acpi_operand_object
*)obj_desc->
reference.
object)->common.
type));
break;
case AML_ARG_OP:
......@@ -559,8 +562,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
case AML_INT_NAMEPATH_OP:
acpi_os_printf("Reference.Node->Name %X\n",
obj_desc->reference.node->name.integer);
acpi_os_printf("Reference: Namepath %X [%4.4s]\n",
obj_desc->reference.node->name.integer,
obj_desc->reference.node->name.ascii);
break;
default:
......@@ -640,7 +644,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
acpi_os_printf("\n");
} else {
acpi_os_printf(" base %8.8X%8.8X Length %X\n",
ACPI_FORMAT_UINT64(obj_desc->region.
ACPI_FORMAT_NATIVE_UINT(obj_desc->region.
address),
obj_desc->region.length);
}
......@@ -877,21 +881,44 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) {
acpi_os_printf("Named Object %p ", obj_desc->reference.node);
acpi_os_printf(" Named Object %p ", obj_desc->reference.node);
status =
acpi_ns_handle_to_pathname(obj_desc->reference.node,
&ret_buf);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could not convert name to pathname\n");
acpi_os_printf(" Could not convert name to pathname\n");
} else {
acpi_os_printf("%s\n", (char *)ret_buf.pointer);
ACPI_FREE(ret_buf.pointer);
}
} else if (obj_desc->reference.object) {
acpi_os_printf("\nReferenced Object: %p\n",
if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
ACPI_DESC_TYPE_OPERAND) {
acpi_os_printf(" Target: %p",
obj_desc->reference.object);
if (obj_desc->reference.opcode == AML_LOAD_OP) {
/*
* For DDBHandle reference,
* obj_desc->Reference.Object is the table index
*/
acpi_os_printf(" [DDBHandle]\n");
} else {
acpi_os_printf(" [%s]\n",
acpi_ut_get_type_name(((union
acpi_operand_object
*)
obj_desc->
reference.
object)->
common.
type));
}
} else {
acpi_os_printf(" Target: %p\n",
obj_desc->reference.object);
}
}
}
/*******************************************************************************
......@@ -976,7 +1003,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
case ACPI_TYPE_LOCAL_REFERENCE:
acpi_os_printf("[Object Reference] ");
acpi_os_printf("[Object Reference] %s",
(acpi_ps_get_opcode_info
(obj_desc->reference.opcode))->name);
acpi_ex_dump_reference_obj(obj_desc);
break;
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -71,7 +71,6 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
union acpi_operand_object *buffer_desc;
acpi_size length;
void *buffer;
u8 locked;
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
......@@ -111,9 +110,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
/* Lock entire transaction if requested */
locked =
acpi_ex_acquire_global_lock(obj_desc->common_field.
field_flags);
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/*
* Perform the read.
......@@ -125,7 +122,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
buffer.pointer),
ACPI_READ | (obj_desc->field.
attribute << 16));
acpi_ex_release_global_lock(locked);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
goto exit;
}
......@@ -175,13 +172,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
/* Lock entire transaction if requested */
locked =
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Read from the field */
status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
acpi_ex_release_global_lock(locked);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
exit:
if (ACPI_FAILURE(status)) {
......@@ -214,10 +210,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
{
acpi_status status;
u32 length;
u32 required_length;
void *buffer;
void *new_buffer;
u8 locked;
union acpi_operand_object *buffer_desc;
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
......@@ -278,9 +271,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
/* Lock entire transaction if requested */
locked =
acpi_ex_acquire_global_lock(obj_desc->common_field.
field_flags);
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/*
* Perform the write (returns status and perhaps data in the
......@@ -291,7 +282,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
(acpi_integer *) buffer,
ACPI_WRITE | (obj_desc->field.
attribute << 16));
acpi_ex_release_global_lock(locked);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
*result_desc = buffer_desc;
return_ACPI_STATUS(status);
......@@ -319,35 +310,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
* We must have a buffer that is at least as long as the field
* we are writing to. This is because individual fields are
* indivisible and partial writes are not supported -- as per
* the ACPI specification.
*/
new_buffer = NULL;
required_length =
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
if (length < required_length) {
/* We need to create a new buffer */
new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
if (!new_buffer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Copy the original data to the new buffer, starting
* at Byte zero. All unused (upper) bytes of the
* buffer will be 0.
*/
ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length);
buffer = new_buffer;
length = required_length;
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
source_desc,
......@@ -366,19 +328,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
/* Lock entire transaction if requested */
locked =
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Write to the field */
status = acpi_ex_insert_into_field(obj_desc, buffer, length);
acpi_ex_release_global_lock(locked);
/* Free temporary buffer if we used one */
if (new_buffer) {
ACPI_FREE(new_buffer);
}
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
return_ACPI_STATUS(status);
}
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -263,7 +263,8 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
rgn_desc->region.space_id,
obj_desc->common_field.access_byte_width,
obj_desc->common_field.base_byte_offset,
field_datum_byte_offset, (void *)address));
field_datum_byte_offset, ACPI_CAST_PTR(void,
address)));
/* Invoke the appropriate address_space/op_region handler */
......@@ -805,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
u32 datum_count;
u32 field_datum_count;
u32 i;
u32 required_length;
void *new_buffer;
ACPI_FUNCTION_TRACE(ex_insert_into_field);
/* Validate input buffer */
if (buffer_length <
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
ACPI_ERROR((AE_INFO,
"Field size %X (bits) is too large for buffer (%X)",
obj_desc->common_field.bit_length, buffer_length));
new_buffer = NULL;
required_length =
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
/*
* We must have a buffer that is at least as long as the field
* we are writing to. This is because individual fields are
* indivisible and partial writes are not supported -- as per
* the ACPI specification.
*/
if (buffer_length < required_length) {
return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
/* We need to create a new buffer */
new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
if (!new_buffer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Copy the original data to the new buffer, starting
* at Byte zero. All unused (upper) bytes of the
* buffer will be 0.
*/
ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
buffer = new_buffer;
buffer_length = required_length;
}
/*
......@@ -866,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
merged_datum,
field_offset);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
goto exit;
}
field_offset += obj_desc->common_field.access_byte_width;
......@@ -924,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
mask, merged_datum,
field_offset);
exit:
/* Free temporary buffer if we used one */
if (new_buffer) {
ACPI_FREE(new_buffer);
}
return_ACPI_STATUS(status);
}
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
This diff is collapsed.
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -121,6 +121,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
if ((ACPI_FAILURE(status)) || walk_state->result_obj) {
acpi_ut_remove_reference(return_desc);
walk_state->result_obj = NULL;
} else {
/* Save the return value */
......@@ -739,26 +740,38 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
value = acpi_gbl_integer_byte_width;
break;
case ACPI_TYPE_BUFFER:
value = temp_desc->buffer.length;
break;
case ACPI_TYPE_STRING:
value = temp_desc->string.length;
break;
case ACPI_TYPE_BUFFER:
/* Buffer arguments may not be evaluated at this point */
status = acpi_ds_get_buffer_arguments(temp_desc);
value = temp_desc->buffer.length;
break;
case ACPI_TYPE_PACKAGE:
/* Package arguments may not be evaluated at this point */
status = acpi_ds_get_package_arguments(temp_desc);
value = temp_desc->package.count;
break;
default:
ACPI_ERROR((AE_INFO,
"Operand is not Buf/Int/Str/Pkg - found type %s",
"Operand must be Buffer/Integer/String/Package - found type %s",
acpi_ut_get_type_name(type)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/*
* Now that we have the size of the object, create a result
* object to hold the value
......
......@@ -5,7 +5,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -241,10 +241,6 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
goto cleanup;
}
/* Return the remainder */
walk_state->result_obj = return_desc1;
cleanup:
/*
* Since the remainder is not returned indirectly, remove a reference to
......@@ -259,6 +255,12 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
acpi_ut_remove_reference(return_desc1);
}
/* Save return object (the remainder) on success */
else {
walk_state->result_obj = return_desc1;
}
return_ACPI_STATUS(status);
}
......@@ -490,6 +492,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(return_desc);
walk_state->result_obj = NULL;
}
return_ACPI_STATUS(status);
......@@ -583,8 +586,6 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
return_desc->integer.value = ACPI_INTEGER_MAX;
}
walk_state->result_obj = return_desc;
cleanup:
/* Delete return object on error */
......@@ -593,5 +594,11 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
acpi_ut_remove_reference(return_desc);
}
/* Save return object on success */
else {
walk_state->result_obj = return_desc;
}
return_ACPI_STATUS(status);
}
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -260,6 +260,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status) || walk_state->result_obj) {
acpi_ut_remove_reference(return_desc);
walk_state->result_obj = NULL;
}
/* Set the return object and exit */
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -322,8 +322,6 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
goto cleanup;
}
walk_state->result_obj = return_desc;
cleanup:
/* Delete return object on error */
......@@ -332,5 +330,11 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
acpi_ut_remove_reference(return_desc);
}
/* Save return object on success */
else {
walk_state->result_obj = return_desc;
}
return_ACPI_STATUS(status);
}
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -412,6 +412,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *second_desc = NULL;
u32 type;
acpi_status status;
......@@ -494,6 +495,20 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
obj_desc->field.access_byte_width,
obj_desc->bank_field.region_obj,
obj_desc->bank_field.bank_obj));
/*
* Remember location in AML stream of the field unit
* opcode and operands -- since the bank_value
* operands must be evaluated.
*/
second_desc = obj_desc->common.next_object;
second_desc->extra.aml_start =
((union acpi_parse_object *)(info->data_register_node))->
named.data;
second_desc->extra.aml_length =
((union acpi_parse_object *)(info->data_register_node))->
named.length;
break;
case ACPI_TYPE_LOCAL_INDEX_FIELD:
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -160,7 +160,7 @@ acpi_ex_system_memory_space_handler(u32 function,
if (!mem_info->mapped_logical_address) {
ACPI_ERROR((AE_INFO,
"Could not map memory at %8.8X%8.8X, size %X",
ACPI_FORMAT_UINT64(address),
ACPI_FORMAT_NATIVE_UINT(address),
(u32) window_size));
mem_info->mapped_length = 0;
return_ACPI_STATUS(AE_NO_MEMORY);
......@@ -182,7 +182,8 @@ acpi_ex_system_memory_space_handler(u32 function,
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n",
bit_width, function, ACPI_FORMAT_UINT64(address)));
bit_width, function,
ACPI_FORMAT_NATIVE_UINT(address)));
/*
* Perform the memory read or write
......@@ -284,7 +285,8 @@ acpi_ex_system_io_space_handler(u32 function,
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"System-IO (width %d) R/W %d Address=%8.8X%8.8X\n",
bit_width, function, ACPI_FORMAT_UINT64(address)));
bit_width, function,
ACPI_FORMAT_NATIVE_UINT(address)));
/* Decode the function parameter */
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -116,9 +116,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
* Several object types require no further processing:
* 1) Device/Thermal objects don't have a "real" subobject, return the Node
* 2) Method locals and arguments have a pseudo-Node
* 3) 10/2007: Added method type to assist with Package construction.
*/
if ((entry_type == ACPI_TYPE_DEVICE) ||
(entry_type == ACPI_TYPE_THERMAL) ||
(entry_type == ACPI_TYPE_METHOD) ||
(node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
return_ACPI_STATUS(AE_OK);
}
......@@ -214,7 +216,6 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
/* For these objects, just return the object attached to the Node */
case ACPI_TYPE_MUTEX:
case ACPI_TYPE_METHOD:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_EVENT:
......@@ -238,13 +239,12 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
case ACPI_TYPE_LOCAL_REFERENCE:
switch (source_desc->reference.opcode) {
case AML_LOAD_OP:
case AML_LOAD_OP: /* This is a ddb_handle */
case AML_REF_OF_OP:
case AML_INDEX_OP:
/* This is a ddb_handle */
/* Return an additional reference to the object */
case AML_REF_OF_OP:
obj_desc = source_desc;
acpi_ut_add_reference(obj_desc);
break;
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -140,7 +140,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
{
acpi_status status = AE_OK;
union acpi_operand_object *stack_desc;
void *temp_node;
union acpi_operand_object *obj_desc = NULL;
u16 opcode;
......@@ -156,23 +155,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
opcode = stack_desc->reference.opcode;
switch (opcode) {
case AML_NAME_OP:
/*
* Convert name reference to a namespace node
* Then, acpi_ex_resolve_node_to_value can be used to get the value
*/
temp_node = stack_desc->reference.object;
/* Delete the Reference Object */
acpi_ut_remove_reference(stack_desc);
/* Return the namespace node */
(*stack_ptr) = temp_node;
break;
case AML_LOCAL_OP:
case AML_ARG_OP:
......@@ -207,15 +189,25 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
switch (stack_desc->reference.target_type) {
case ACPI_TYPE_BUFFER_FIELD:
/* Just return - leave the Reference on the stack */
/* Just return - do not dereference */
break;
case ACPI_TYPE_PACKAGE:
/* If method call or copy_object - do not dereference */
if ((walk_state->opcode ==
AML_INT_METHODCALL_OP)
|| (walk_state->opcode == AML_COPY_OP)) {
break;
}
/* Otherwise, dereference the package_index to a package element */
obj_desc = *stack_desc->reference.where;
if (obj_desc) {
/*
* Valid obj descriptor, copy pointer to return value
* Valid object descriptor, copy pointer to return value
* (i.e., dereference the package index)
* Delete the ref object, increment the returned object
*/
......@@ -224,11 +216,11 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
*stack_ptr = obj_desc;
} else {
/*
* A NULL object descriptor means an unitialized element of
* A NULL object descriptor means an uninitialized element of
* the package, can't dereference it
*/
ACPI_ERROR((AE_INFO,
"Attempt to deref an Index to NULL pkg element Idx=%p",
"Attempt to dereference an Index to NULL package element Idx=%p",
stack_desc));
status = AE_AML_UNINITIALIZED_ELEMENT;
}
......@@ -239,7 +231,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
/* Invalid reference object */
ACPI_ERROR((AE_INFO,
"Unknown TargetType %X in Index/Reference obj %p",
"Unknown TargetType %X in Index/Reference object %p",
stack_desc->reference.target_type,
stack_desc));
status = AE_AML_INTERNAL;
......@@ -251,7 +243,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
case AML_DEBUG_OP:
case AML_LOAD_OP:
/* Just leave the object as-is */
/* Just leave the object as-is, do not dereference */
break;
......@@ -390,10 +382,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
}
/*
* For reference objects created via the ref_of or Index operators,
* we need to get to the base object (as per the ACPI specification
* of the object_type and size_of operators). This means traversing
* the list of possibly many nested references.
* For reference objects created via the ref_of, Index, or Load/load_table
* operators, we need to get to the base object (as per the ACPI
* specification of the object_type and size_of operators). This means
* traversing the list of possibly many nested references.
*/
while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
switch (obj_desc->reference.opcode) {
......@@ -463,6 +455,11 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
}
break;
case AML_LOAD_OP:
type = ACPI_TYPE_DDB_HANDLE;
goto exit;
case AML_LOCAL_OP:
case AML_ARG_OP:
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -137,7 +137,6 @@ acpi_ex_resolve_operands(u16 opcode,
union acpi_operand_object *obj_desc;
acpi_status status = AE_OK;
u8 object_type;
void *temp_node;
u32 arg_types;
const struct acpi_opcode_info *op_info;
u32 this_arg_type;
......@@ -239,7 +238,6 @@ acpi_ex_resolve_operands(u16 opcode,
/*lint -fallthrough */
case AML_NAME_OP:
case AML_INDEX_OP:
case AML_REF_OF_OP:
case AML_ARG_OP:
......@@ -332,15 +330,6 @@ acpi_ex_resolve_operands(u16 opcode,
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (obj_desc->reference.opcode == AML_NAME_OP) {
/* Convert a named reference to the actual named object */
temp_node = obj_desc->reference.object;
acpi_ut_remove_reference(obj_desc);
(*stack_ptr) = temp_node;
}
goto next_operand;
case ARGI_DATAREFOBJ: /* Store operator only */
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -84,8 +84,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc);
/* Print line header as long as we are not in the middle of an object display */
if (!((level > 0) && index == 0)) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
level, " "));
}
/* Display index for package output only */
......@@ -95,12 +99,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
}
if (!source_desc) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n"));
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n"));
return_VOID;
}
if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ",
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ",
acpi_ut_get_object_type_name
(source_desc)));
......@@ -123,6 +127,8 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
return_VOID;
}
/* source_desc is of type ACPI_DESC_TYPE_OPERAND */
switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
case ACPI_TYPE_INTEGER:
......@@ -147,7 +153,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
(u32) source_desc->buffer.length));
ACPI_DUMP_BUFFER(source_desc->buffer.pointer,
(source_desc->buffer.length <
32) ? source_desc->buffer.length : 32);
256) ? source_desc->buffer.length : 256);
break;
case ACPI_TYPE_STRING:
......@@ -160,7 +166,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
case ACPI_TYPE_PACKAGE:
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
"[0x%.2X Elements]\n",
"[Contains 0x%.2X Elements]\n",
source_desc->package.count));
/* Output the entire contents of the package */
......@@ -180,12 +186,59 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
(source_desc->reference.opcode),
source_desc->reference.offset));
} else {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n",
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]",
acpi_ps_get_opcode_name
(source_desc->reference.opcode)));
}
if (source_desc->reference.object) {
if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
" Table OwnerId %p\n",
source_desc->reference.object));
break;
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " "));
/* Check for valid node first, then valid object */
if (source_desc->reference.node) {
if (ACPI_GET_DESCRIPTOR_TYPE
(source_desc->reference.node) !=
ACPI_DESC_TYPE_NAMED) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
" %p - Not a valid namespace node\n",
source_desc->reference.
node));
} else {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
"Node %p [%4.4s] ",
source_desc->reference.
node,
(source_desc->reference.
node)->name.ascii));
switch ((source_desc->reference.node)->type) {
/* These types have no attached object */
case ACPI_TYPE_DEVICE:
acpi_os_printf("Device\n");
break;
case ACPI_TYPE_THERMAL:
acpi_os_printf("Thermal Zone\n");
break;
default:
acpi_ex_do_debug_object((source_desc->
reference.
node)->object,
level + 4, 0);
break;
}
}
} else if (source_desc->reference.object) {
if (ACPI_GET_DESCRIPTOR_TYPE
(source_desc->reference.object) ==
ACPI_DESC_TYPE_NAMED) {
......@@ -198,18 +251,13 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
acpi_ex_do_debug_object(source_desc->reference.
object, level + 4, 0);
}
} else if (source_desc->reference.node) {
acpi_ex_do_debug_object((source_desc->reference.node)->
object, level + 4, 0);
}
break;
default:
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n",
source_desc,
acpi_ut_get_object_type_name
(source_desc)));
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n",
source_desc));
break;
}
......@@ -313,7 +361,6 @@ acpi_ex_store(union acpi_operand_object *source_desc,
* 4) Store to the debug object
*/
switch (ref_desc->reference.opcode) {
case AML_NAME_OP:
case AML_REF_OF_OP:
/* Storing an object into a Name "container" */
......@@ -415,12 +462,25 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
*/
obj_desc = *(index_desc->reference.where);
if (ACPI_GET_OBJECT_TYPE(source_desc) ==
ACPI_TYPE_LOCAL_REFERENCE
&& source_desc->reference.opcode == AML_LOAD_OP) {
/* This is a DDBHandle, just add a reference to it */
acpi_ut_add_reference(source_desc);
new_desc = source_desc;
} else {
/* Normal object, copy it */
status =
acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc,
acpi_ut_copy_iobject_to_iobject(source_desc,
&new_desc,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
if (obj_desc) {
......@@ -571,10 +631,17 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
/* If no implicit conversion, drop into the default case below */
if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) {
/* Force execution of default (no implicit conversion) */
if ((!implicit_conversion) ||
((walk_state->opcode == AML_COPY_OP) &&
(target_type != ACPI_TYPE_LOCAL_REGION_FIELD) &&
(target_type != ACPI_TYPE_LOCAL_BANK_FIELD) &&
(target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) {
/*
* Force execution of default (no implicit conversion). Note:
* copy_object does not perform an implicit conversion, as per the ACPI
* spec -- except in case of region/bank/index fields -- because these
* objects must retain their original type permanently.
*/
target_type = ACPI_TYPE_ANY;
}
......
......@@ -7,7 +7,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -44,7 +44,6 @@
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exsystem")
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -61,7 +61,6 @@
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exutils")
......@@ -217,9 +216,10 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
/*
* Object must be a valid number and we must be executing
* a control method
* a control method. NS node could be there for AML_INT_NAMEPATH_OP.
*/
if ((!obj_desc) ||
(ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) ||
(ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) {
return;
}
......@@ -240,72 +240,73 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
* PARAMETERS: field_flags - Flags with Lock rule:
* always_lock or never_lock
*
* RETURN: TRUE/FALSE indicating whether the lock was actually acquired
* RETURN: None
*
* DESCRIPTION: Obtain the global lock and keep track of this fact via two
* methods. A global variable keeps the state of the lock, and
* the state is returned to the caller.
* DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
* flags specifiy that it is to be obtained before field access.
*
******************************************************************************/
u8 acpi_ex_acquire_global_lock(u32 field_flags)
void acpi_ex_acquire_global_lock(u32 field_flags)
{
u8 locked = FALSE;
acpi_status status;
ACPI_FUNCTION_TRACE(ex_acquire_global_lock);
/* Only attempt lock if the always_lock bit is set */
/* Only use the lock if the always_lock bit is set */
if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) {
return_VOID;
}
if (field_flags & AML_FIELD_LOCK_RULE_MASK) {
/* Attempt to get the global lock, wait forever */
/* We should attempt to get the lock, wait forever */
status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER,
acpi_gbl_global_lock_mutex,
acpi_os_get_thread_id());
status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER);
if (ACPI_SUCCESS(status)) {
locked = TRUE;
} else {
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not acquire Global Lock"));
}
}
return_UINT8(locked);
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_global_lock
*
* PARAMETERS: locked_by_me - Return value from corresponding call to
* acquire_global_lock.
* PARAMETERS: field_flags - Flags with Lock rule:
* always_lock or never_lock
*
* RETURN: None
*
* DESCRIPTION: Release the global lock if it is locked.
* DESCRIPTION: Release the ACPI hardware Global Lock
*
******************************************************************************/
void acpi_ex_release_global_lock(u8 locked_by_me)
void acpi_ex_release_global_lock(u32 field_flags)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ex_release_global_lock);
/* Only attempt unlock if the caller locked it */
/* Only use the lock if the always_lock bit is set */
if (locked_by_me) {
if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) {
return_VOID;
}
/* OK, now release the lock */
/* Release the global lock */
status = acpi_ev_release_global_lock();
status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
if (ACPI_FAILURE(status)) {
/* Report the error, but there isn't much else we can do */
ACPI_EXCEPTION((AE_INFO, status,
"Could not release ACPI Global Lock"));
}
"Could not release Global Lock"));
}
return_VOID;
......
......@@ -256,7 +256,7 @@ static int acpi_fan_add(struct acpi_device *device)
result = PTR_ERR(cdev);
goto end;
}
if (cdev) {
printk(KERN_INFO PREFIX
"%s is registered as cooling_device%d\n",
device->dev.bus_id, cdev->id);
......@@ -266,14 +266,13 @@ static int acpi_fan_add(struct acpi_device *device)
&cdev->device.kobj,
"thermal_cooling");
if (result)
return result;
printk(KERN_ERR PREFIX "Create sysfs link\n");
result = sysfs_create_link(&cdev->device.kobj,
&device->dev.kobj,
"device");
if (result)
return result;
}
printk(KERN_ERR PREFIX "Create sysfs link\n");
result = acpi_fan_add_fs(device);
if (result)
......
......@@ -142,6 +142,7 @@ EXPORT_SYMBOL(acpi_get_physical_device);
static int acpi_bind_one(struct device *dev, acpi_handle handle)
{
struct acpi_device *acpi_dev;
acpi_status status;
if (dev->archdata.acpi_handle) {
......@@ -157,6 +158,16 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
}
dev->archdata.acpi_handle = handle;
status = acpi_bus_get_device(handle, &acpi_dev);
if (!ACPI_FAILURE(status)) {
int ret;
ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
"firmware_node");
ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
"physical_node");
}
return 0;
}
......@@ -165,8 +176,17 @@ static int acpi_unbind_one(struct device *dev)
if (!dev->archdata.acpi_handle)
return 0;
if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
struct acpi_device *acpi_dev;
/* acpi_get_physical_device increase refcnt by one */
put_device(dev);
if (!acpi_bus_get_device(dev->archdata.acpi_handle,
&acpi_dev)) {
sysfs_remove_link(&dev->kobj, "firmware_node");
sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node");
}
acpi_detach_data(dev->archdata.acpi_handle,
acpi_glue_data_handler);
dev->archdata.acpi_handle = NULL;
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -6,7 +6,7 @@
*****************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -7,7 +7,7 @@
******************************************************************************/
/*
* Copyright (C) 2000 - 2007, R. Byron Moore
* Copyright (C) 2000 - 2008, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment