mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
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: (123 commits) dock: make dock driver not a module ACPI: fix ia64 build warning ACPI: hack around sysfs warning with link order ACPI suspend: fix build warning when CONFIG_ACPI_SLEEP=n intel_menlo: fix build warning panasonic-laptop: fix build ACPICA: Update version to 20080926 ACPICA: Add support for zero-length buffer-to-string conversions ACPICA: New: Validation for predefined ACPI methods/objects ACPICA: Fix for implicit return compatibility ACPICA: Fixed a couple memory leaks associated with "implicit return" ACPICA: Optimize buffer allocation procedure ACPICA: Fix possible memory leak, error exit path ACPICA: Fix fault after mem allocation failure in AML parser ACPICA: Remove unused ACPI register bit definition ACPICA: Update version to 20080829 ACPICA: Fix possible memory leak in acpi_ns_get_external_pathname ACPICA: Cleanup for internal Reference Object ACPICA: Update comments - no functional changes ACPICA: Update for Reference ACPI_OPERAND_OBJECT ...
This commit is contained in:
commit
765426e8ee
145 changed files with 5917 additions and 2212 deletions
|
|
@ -42,7 +42,7 @@ if ACPI
|
|||
|
||||
config ACPI_SLEEP
|
||||
bool
|
||||
depends on PM_SLEEP
|
||||
depends on SUSPEND || HIBERNATION
|
||||
default y
|
||||
|
||||
config ACPI_PROCFS
|
||||
|
|
@ -157,18 +157,11 @@ config ACPI_FAN
|
|||
applications to perform basic fan control (on, off, status).
|
||||
|
||||
config ACPI_DOCK
|
||||
tristate "Dock"
|
||||
bool "Dock"
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
This driver adds support for ACPI controlled docking stations
|
||||
|
||||
config ACPI_BAY
|
||||
tristate "Removable Drive Bay (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
depends on ACPI_DOCK
|
||||
help
|
||||
This driver adds support for ACPI controlled removable drive
|
||||
bays such as the IBM ultrabay or the Dell Module Bay.
|
||||
This driver adds support for ACPI controlled docking stations and removable
|
||||
drive bays such as the IBM ultrabay or the Dell Module Bay.
|
||||
|
||||
config ACPI_PROCESSOR
|
||||
tristate "Processor"
|
||||
|
|
|
|||
|
|
@ -45,14 +45,13 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o
|
|||
obj-$(CONFIG_ACPI_BUTTON) += button.o
|
||||
obj-$(CONFIG_ACPI_FAN) += fan.o
|
||||
obj-$(CONFIG_ACPI_DOCK) += dock.o
|
||||
obj-$(CONFIG_ACPI_BAY) += bay.o
|
||||
obj-$(CONFIG_ACPI_VIDEO) += video.o
|
||||
obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
|
||||
obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
|
||||
obj-$(CONFIG_ACPI_POWER) += power.o
|
||||
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
|
||||
obj-$(CONFIG_ACPI_CONTAINER) += container.o
|
||||
obj-$(CONFIG_ACPI_THERMAL) += thermal.o
|
||||
obj-$(CONFIG_ACPI_POWER) += power.o
|
||||
obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
|
||||
obj-$(CONFIG_ACPI_DEBUG) += debug.o
|
||||
obj-$(CONFIG_ACPI_NUMA) += numa.o
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ struct acpi_ac {
|
|||
struct power_supply charger;
|
||||
#endif
|
||||
struct acpi_device * device;
|
||||
unsigned long state;
|
||||
unsigned long long state;
|
||||
};
|
||||
|
||||
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
|
||||
|
|
@ -269,7 +269,7 @@ static int acpi_ac_add(struct acpi_device *device)
|
|||
ac->device = device;
|
||||
strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_AC_CLASS);
|
||||
acpi_driver_data(device) = ac;
|
||||
device->driver_data = ac;
|
||||
|
||||
result = acpi_ac_get_state(ac);
|
||||
if (result)
|
||||
|
|
|
|||
|
|
@ -194,8 +194,7 @@ acpi_memory_get_device(acpi_handle handle,
|
|||
|
||||
static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
|
||||
{
|
||||
unsigned long current_status;
|
||||
|
||||
unsigned long long current_status;
|
||||
|
||||
/* Get device present/absent information from the _STA */
|
||||
if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA",
|
||||
|
|
@ -264,7 +263,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
|
|||
acpi_status status;
|
||||
struct acpi_object_list arg_list;
|
||||
union acpi_object arg;
|
||||
unsigned long current_status;
|
||||
unsigned long long current_status;
|
||||
|
||||
|
||||
/* Issue the _EJ0 command */
|
||||
|
|
@ -403,7 +402,7 @@ static int acpi_memory_device_add(struct acpi_device *device)
|
|||
mem_device->device = device;
|
||||
sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
|
||||
sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
|
||||
acpi_driver_data(device) = mem_device;
|
||||
device->driver_data = mem_device;
|
||||
|
||||
/* Get the range from the _CRS */
|
||||
result = acpi_memory_get_device_resources(mem_device);
|
||||
|
|
@ -454,8 +453,8 @@ static int acpi_memory_device_start (struct acpi_device *device)
|
|||
/* call add_memory func */
|
||||
result = acpi_memory_enable_device(mem_device);
|
||||
if (result)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Error in acpi_memory_enable_device\n"));
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error in acpi_memory_enable_device\n");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
#define ASUS_ACPI_VERSION "0.30"
|
||||
|
||||
#define PROC_ASUS "asus" //the directory
|
||||
#define PROC_ASUS "asus" /* The directory */
|
||||
#define PROC_MLED "mled"
|
||||
#define PROC_WLED "wled"
|
||||
#define PROC_TLED "tled"
|
||||
|
|
@ -66,10 +66,10 @@
|
|||
/*
|
||||
* Flags for hotk status
|
||||
*/
|
||||
#define MLED_ON 0x01 //mail LED
|
||||
#define WLED_ON 0x02 //wireless LED
|
||||
#define TLED_ON 0x04 //touchpad LED
|
||||
#define BT_ON 0x08 //internal Bluetooth
|
||||
#define MLED_ON 0x01 /* Mail LED */
|
||||
#define WLED_ON 0x02 /* Wireless LED */
|
||||
#define TLED_ON 0x04 /* Touchpad LED */
|
||||
#define BT_ON 0x08 /* Internal Bluetooth */
|
||||
|
||||
MODULE_AUTHOR("Julien Lerouge, Karol Kozimor");
|
||||
MODULE_DESCRIPTION(ACPI_HOTK_NAME);
|
||||
|
|
@ -82,28 +82,28 @@ MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus");
|
|||
module_param(asus_gid, uint, 0);
|
||||
MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus");
|
||||
|
||||
/* For each model, all features implemented,
|
||||
/* For each model, all features implemented,
|
||||
* those marked with R are relative to HOTK, A for absolute */
|
||||
struct model_data {
|
||||
char *name; //name of the laptop________________A
|
||||
char *mt_mled; //method to handle mled_____________R
|
||||
char *mled_status; //node to handle mled reading_______A
|
||||
char *mt_wled; //method to handle wled_____________R
|
||||
char *wled_status; //node to handle wled reading_______A
|
||||
char *mt_tled; //method to handle tled_____________R
|
||||
char *tled_status; //node to handle tled reading_______A
|
||||
char *mt_ledd; //method to handle LED display______R
|
||||
char *mt_bt_switch; //method to switch Bluetooth on/off_R
|
||||
char *bt_status; //no model currently supports this__?
|
||||
char *mt_lcd_switch; //method to turn LCD on/off_________A
|
||||
char *lcd_status; //node to read LCD panel state______A
|
||||
char *brightness_up; //method to set brightness up_______A
|
||||
char *brightness_down; //guess what ?______________________A
|
||||
char *brightness_set; //method to set absolute brightness_R
|
||||
char *brightness_get; //method to get absolute brightness_R
|
||||
char *brightness_status; //node to get brightness____________A
|
||||
char *display_set; //method to set video output________R
|
||||
char *display_get; //method to get video output________R
|
||||
char *name; /* name of the laptop________________A */
|
||||
char *mt_mled; /* method to handle mled_____________R */
|
||||
char *mled_status; /* node to handle mled reading_______A */
|
||||
char *mt_wled; /* method to handle wled_____________R */
|
||||
char *wled_status; /* node to handle wled reading_______A */
|
||||
char *mt_tled; /* method to handle tled_____________R */
|
||||
char *tled_status; /* node to handle tled reading_______A */
|
||||
char *mt_ledd; /* method to handle LED display______R */
|
||||
char *mt_bt_switch; /* method to switch Bluetooth on/off_R */
|
||||
char *bt_status; /* no model currently supports this__? */
|
||||
char *mt_lcd_switch; /* method to turn LCD on/off_________A */
|
||||
char *lcd_status; /* node to read LCD panel state______A */
|
||||
char *brightness_up; /* method to set brightness up_______A */
|
||||
char *brightness_down; /* method to set brightness down ____A */
|
||||
char *brightness_set; /* method to set absolute brightness_R */
|
||||
char *brightness_get; /* method to get absolute brightness_R */
|
||||
char *brightness_status;/* node to get brightness____________A */
|
||||
char *display_set; /* method to set video output________R */
|
||||
char *display_get; /* method to get video output________R */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -111,41 +111,41 @@ struct model_data {
|
|||
* about the hotk device
|
||||
*/
|
||||
struct asus_hotk {
|
||||
struct acpi_device *device; //the device we are in
|
||||
acpi_handle handle; //the handle of the hotk device
|
||||
char status; //status of the hotk, for LEDs, ...
|
||||
u32 ledd_status; //status of the LED display
|
||||
struct model_data *methods; //methods available on the laptop
|
||||
u8 brightness; //brightness level
|
||||
struct acpi_device *device; /* the device we are in */
|
||||
acpi_handle handle; /* the handle of the hotk device */
|
||||
char status; /* status of the hotk, for LEDs */
|
||||
u32 ledd_status; /* status of the LED display */
|
||||
struct model_data *methods; /* methods available on the laptop */
|
||||
u8 brightness; /* brightness level */
|
||||
enum {
|
||||
A1x = 0, //A1340D, A1300F
|
||||
A2x, //A2500H
|
||||
A4G, //A4700G
|
||||
D1x, //D1
|
||||
L2D, //L2000D
|
||||
L3C, //L3800C
|
||||
L3D, //L3400D
|
||||
L3H, //L3H, L2000E, L5D
|
||||
L4R, //L4500R
|
||||
L5x, //L5800C
|
||||
L8L, //L8400L
|
||||
M1A, //M1300A
|
||||
M2E, //M2400E, L4400L
|
||||
M6N, //M6800N, W3400N
|
||||
M6R, //M6700R, A3000G
|
||||
P30, //Samsung P30
|
||||
S1x, //S1300A, but also L1400B and M2400A (L84F)
|
||||
S2x, //S200 (J1 reported), Victor MP-XP7210
|
||||
W1N, //W1000N
|
||||
W5A, //W5A
|
||||
W3V, //W3030V
|
||||
xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
|
||||
A4S, //Z81sp
|
||||
//(Centrino)
|
||||
F3Sa,
|
||||
A1x = 0, /* A1340D, A1300F */
|
||||
A2x, /* A2500H */
|
||||
A4G, /* A4700G */
|
||||
D1x, /* D1 */
|
||||
L2D, /* L2000D */
|
||||
L3C, /* L3800C */
|
||||
L3D, /* L3400D */
|
||||
L3H, /* L3H, L2000E, L5D */
|
||||
L4R, /* L4500R */
|
||||
L5x, /* L5800C */
|
||||
L8L, /* L8400L */
|
||||
M1A, /* M1300A */
|
||||
M2E, /* M2400E, L4400L */
|
||||
M6N, /* M6800N, W3400N */
|
||||
M6R, /* M6700R, A3000G */
|
||||
P30, /* Samsung P30 */
|
||||
S1x, /* S1300A, but also L1400B and M2400A (L84F) */
|
||||
S2x, /* S200 (J1 reported), Victor MP-XP7210 */
|
||||
W1N, /* W1000N */
|
||||
W5A, /* W5A */
|
||||
W3V, /* W3030V */
|
||||
xxN, /* M2400N, M3700N, M5200N, M6800N,
|
||||
S1300N, S5200N*/
|
||||
A4S, /* Z81sp */
|
||||
F3Sa, /* (Centrino) */
|
||||
END_MODEL
|
||||
} model; //Models currently supported
|
||||
u16 event_count[128]; //count for each event TODO make this better
|
||||
} model; /* Models currently supported */
|
||||
u16 event_count[128]; /* Count for each event TODO make this better */
|
||||
};
|
||||
|
||||
/* Here we go */
|
||||
|
|
@ -459,18 +459,18 @@ static struct acpi_driver asus_hotk_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
/*
|
||||
/*
|
||||
* This function evaluates an ACPI method, given an int as parameter, the
|
||||
* method is searched within the scope of the handle, can be NULL. The output
|
||||
* of the method is written is output, which can also be NULL
|
||||
*
|
||||
* returns 1 if write is successful, 0 else.
|
||||
* returns 1 if write is successful, 0 else.
|
||||
*/
|
||||
static int write_acpi_int(acpi_handle handle, const char *method, int val,
|
||||
struct acpi_buffer *output)
|
||||
{
|
||||
struct acpi_object_list params; //list of input parameters (an int here)
|
||||
union acpi_object in_obj; //the only param we use
|
||||
struct acpi_object_list params; /* list of input parameters (int) */
|
||||
union acpi_object in_obj; /* the only param we use */
|
||||
acpi_status status;
|
||||
|
||||
params.count = 1;
|
||||
|
|
@ -507,18 +507,18 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
|
|||
{
|
||||
int len = 0;
|
||||
int temp;
|
||||
char buf[16]; //enough for all info
|
||||
char buf[16]; /* enough for all info */
|
||||
/*
|
||||
* We use the easy way, we don't care of off and count, so we don't set eof
|
||||
* to 1
|
||||
* We use the easy way, we don't care of off and count,
|
||||
* so we don't set eof to 1
|
||||
*/
|
||||
|
||||
len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
|
||||
len += sprintf(page + len, "Model reference : %s\n",
|
||||
hotk->methods->name);
|
||||
/*
|
||||
* The SFUN method probably allows the original driver to get the list
|
||||
* of features supported by a given model. For now, 0x0100 or 0x0800
|
||||
/*
|
||||
* The SFUN method probably allows the original driver to get the list
|
||||
* of features supported by a given model. For now, 0x0100 or 0x0800
|
||||
* bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
|
||||
* The significance of others is yet to be found.
|
||||
*/
|
||||
|
|
@ -528,7 +528,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
|
|||
/*
|
||||
* Another value for userspace: the ASYM method returns 0x02 for
|
||||
* battery low and 0x04 for battery critical, its readings tend to be
|
||||
* more accurate than those provided by _BST.
|
||||
* more accurate than those provided by _BST.
|
||||
* Note: since not all the laptops provide this method, errors are
|
||||
* silently ignored.
|
||||
*/
|
||||
|
|
@ -579,7 +579,7 @@ static int read_led(const char *ledname, int ledmask)
|
|||
return (hotk->status & ledmask) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int parse_arg(const char __user * buf, unsigned long count, int *val)
|
||||
static int parse_arg(const char __user *buf, unsigned long count, int *val)
|
||||
{
|
||||
char s[32];
|
||||
if (!count)
|
||||
|
|
@ -596,7 +596,7 @@ static int parse_arg(const char __user * buf, unsigned long count, int *val)
|
|||
|
||||
/* FIXME: kill extraneous args so it can be called independently */
|
||||
static int
|
||||
write_led(const char __user * buffer, unsigned long count,
|
||||
write_led(const char __user *buffer, unsigned long count,
|
||||
char *ledname, int ledmask, int invert)
|
||||
{
|
||||
int rv, value;
|
||||
|
|
@ -631,7 +631,7 @@ proc_read_mled(char *page, char **start, off_t off, int count, int *eof,
|
|||
}
|
||||
|
||||
static int
|
||||
proc_write_mled(struct file *file, const char __user * buffer,
|
||||
proc_write_mled(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
|
||||
|
|
@ -648,7 +648,7 @@ proc_read_ledd(char *page, char **start, off_t off, int count, int *eof,
|
|||
}
|
||||
|
||||
static int
|
||||
proc_write_ledd(struct file *file, const char __user * buffer,
|
||||
proc_write_ledd(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
int rv, value;
|
||||
|
|
@ -677,7 +677,7 @@ proc_read_wled(char *page, char **start, off_t off, int count, int *eof,
|
|||
}
|
||||
|
||||
static int
|
||||
proc_write_wled(struct file *file, const char __user * buffer,
|
||||
proc_write_wled(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
|
||||
|
|
@ -694,10 +694,10 @@ proc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof,
|
|||
}
|
||||
|
||||
static int
|
||||
proc_write_bluetooth(struct file *file, const char __user * buffer,
|
||||
proc_write_bluetooth(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
/* Note: mt_bt_switch controls both internal Bluetooth adapter's
|
||||
/* Note: mt_bt_switch controls both internal Bluetooth adapter's
|
||||
presence and its LED */
|
||||
return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0);
|
||||
}
|
||||
|
|
@ -714,7 +714,7 @@ proc_read_tled(char *page, char **start, off_t off, int count, int *eof,
|
|||
}
|
||||
|
||||
static int
|
||||
proc_write_tled(struct file *file, const char __user * buffer,
|
||||
proc_write_tled(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
|
||||
|
|
@ -734,7 +734,7 @@ static int get_lcd_state(void)
|
|||
|
||||
input.count = 2;
|
||||
input.pointer = mt_params;
|
||||
/* Note: the following values are partly guessed up, but
|
||||
/* Note: the following values are partly guessed up, but
|
||||
otherwise they seem to work */
|
||||
mt_params[0].type = ACPI_TYPE_INTEGER;
|
||||
mt_params[0].integer.value = 0x02;
|
||||
|
|
@ -753,7 +753,7 @@ static int get_lcd_state(void)
|
|||
/* That's what the AML code does */
|
||||
lcd = out_obj.integer.value >> 8;
|
||||
} else if (hotk->model == F3Sa) {
|
||||
unsigned long tmp;
|
||||
unsigned long long tmp;
|
||||
union acpi_object param;
|
||||
struct acpi_object_list input;
|
||||
acpi_status status;
|
||||
|
|
@ -796,12 +796,13 @@ static int set_lcd_state(int value)
|
|||
acpi_evaluate_object(NULL,
|
||||
hotk->methods->mt_lcd_switch,
|
||||
NULL, NULL);
|
||||
} else { /* L3H and the like have to be handled differently */
|
||||
} else {
|
||||
/* L3H and the like must be handled differently */
|
||||
if (!write_acpi_int
|
||||
(hotk->handle, hotk->methods->mt_lcd_switch, 0x07,
|
||||
NULL))
|
||||
status = AE_ERROR;
|
||||
/* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
|
||||
/* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
|
||||
the exact behaviour is simulated here */
|
||||
}
|
||||
if (ACPI_FAILURE(status))
|
||||
|
|
@ -819,7 +820,7 @@ proc_read_lcd(char *page, char **start, off_t off, int count, int *eof,
|
|||
}
|
||||
|
||||
static int
|
||||
proc_write_lcd(struct file *file, const char __user * buffer,
|
||||
proc_write_lcd(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
int rv, value;
|
||||
|
|
@ -897,7 +898,7 @@ proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
|
|||
}
|
||||
|
||||
static int
|
||||
proc_write_brn(struct file *file, const char __user * buffer,
|
||||
proc_write_brn(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
int rv, value;
|
||||
|
|
@ -921,7 +922,7 @@ static void set_display(int value)
|
|||
}
|
||||
|
||||
/*
|
||||
* Now, *this* one could be more user-friendly, but so far, no-one has
|
||||
* Now, *this* one could be more user-friendly, but so far, no-one has
|
||||
* complained. The significance of bits is the same as in proc_write_disp()
|
||||
*/
|
||||
static int
|
||||
|
|
@ -933,18 +934,18 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
|
|||
if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
|
||||
printk(KERN_WARNING
|
||||
"Asus ACPI: Error reading display status\n");
|
||||
value &= 0x07; /* needed for some models, shouldn't hurt others */
|
||||
value &= 0x07; /* needed for some models, shouldn't hurt others */
|
||||
return sprintf(page, "%d\n", value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Experimental support for display switching. As of now: 1 should activate
|
||||
* the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination
|
||||
* (bitwise) of these will suffice. I never actually tested 3 displays hooked up
|
||||
* simultaneously, so be warned. See the acpi4asus README for more info.
|
||||
* Experimental support for display switching. As of now: 1 should activate
|
||||
* the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination
|
||||
* (bitwise) of these will suffice. I never actually tested 3 displays hooked
|
||||
* up simultaneously, so be warned. See the acpi4asus README for more info.
|
||||
*/
|
||||
static int
|
||||
proc_write_disp(struct file *file, const char __user * buffer,
|
||||
proc_write_disp(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
int rv, value;
|
||||
|
|
@ -957,12 +958,12 @@ proc_write_disp(struct file *file, const char __user * buffer,
|
|||
|
||||
typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data);
|
||||
typedef int (proc_writefunc) (struct file * file, const char __user * buffer,
|
||||
typedef int (proc_writefunc) (struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data);
|
||||
|
||||
static int
|
||||
asus_proc_add(char *name, proc_writefunc * writefunc,
|
||||
proc_readfunc * readfunc, mode_t mode,
|
||||
asus_proc_add(char *name, proc_writefunc *writefunc,
|
||||
proc_readfunc *readfunc, mode_t mode,
|
||||
struct acpi_device *device)
|
||||
{
|
||||
struct proc_dir_entry *proc =
|
||||
|
|
@ -1040,9 +1041,9 @@ static int asus_hotk_add_fs(struct acpi_device *device)
|
|||
&proc_read_bluetooth, mode, device);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need both read node and write method as LCD switch is also accessible
|
||||
* from keyboard
|
||||
/*
|
||||
* We need both read node and write method as LCD switch is also
|
||||
* accessible from the keyboard
|
||||
*/
|
||||
if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) {
|
||||
asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode,
|
||||
|
|
@ -1096,11 +1097,10 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
|
|||
if (!hotk)
|
||||
return;
|
||||
|
||||
if ((event & ~((u32) BR_UP)) < 16) {
|
||||
if ((event & ~((u32) BR_UP)) < 16)
|
||||
hotk->brightness = (event & ~((u32) BR_UP));
|
||||
} else if ((event & ~((u32) BR_DOWN)) < 16) {
|
||||
else if ((event & ~((u32) BR_DOWN)) < 16)
|
||||
hotk->brightness = (event & ~((u32) BR_DOWN));
|
||||
}
|
||||
|
||||
acpi_bus_generate_proc_event(hotk->device, event,
|
||||
hotk->event_count[event % 128]++);
|
||||
|
|
@ -1186,8 +1186,8 @@ static int asus_hotk_get_info(void)
|
|||
acpi_status status;
|
||||
|
||||
/*
|
||||
* Get DSDT headers early enough to allow for differentiating between
|
||||
* models, but late enough to allow acpi_bus_register_driver() to fail
|
||||
* Get DSDT headers early enough to allow for differentiating between
|
||||
* models, but late enough to allow acpi_bus_register_driver() to fail
|
||||
* before doing anything ACPI-specific. Should we encounter a machine,
|
||||
* which needs special handling (i.e. its hotkey device has a different
|
||||
* HID), this bit will be moved. A global variable asus_info contains
|
||||
|
|
@ -1212,8 +1212,8 @@ static int asus_hotk_get_info(void)
|
|||
|
||||
/*
|
||||
* Try to match the object returned by INIT to the specific model.
|
||||
* Handle every possible object (or the lack of thereof) the DSDT
|
||||
* writers might throw at us. When in trouble, we pass NULL to
|
||||
* Handle every possible object (or the lack of thereof) the DSDT
|
||||
* writers might throw at us. When in trouble, we pass NULL to
|
||||
* asus_model_match() and try something completely different.
|
||||
*/
|
||||
if (buffer.pointer) {
|
||||
|
|
@ -1244,6 +1244,8 @@ static int asus_hotk_get_info(void)
|
|||
"default values\n", string);
|
||||
printk(KERN_NOTICE
|
||||
" send /proc/acpi/dsdt to the developers\n");
|
||||
kfree(model);
|
||||
return -ENODEV;
|
||||
}
|
||||
hotk->methods = &model_conf[hotk->model];
|
||||
return AE_OK;
|
||||
|
|
@ -1254,7 +1256,7 @@ static int asus_hotk_get_info(void)
|
|||
/* Sort of per-model blacklist */
|
||||
if (strncmp(string, "L2B", 3) == 0)
|
||||
hotk->methods->lcd_status = NULL;
|
||||
/* L2B is similar enough to L3C to use its settings, with this only
|
||||
/* L2B is similar enough to L3C to use its settings, with this only
|
||||
exception */
|
||||
else if (strncmp(string, "A3G", 3) == 0)
|
||||
hotk->methods->lcd_status = "\\BLFG";
|
||||
|
|
@ -1321,7 +1323,7 @@ static int asus_hotk_add(struct acpi_device *device)
|
|||
hotk->handle = device->handle;
|
||||
strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_HOTK_CLASS);
|
||||
acpi_driver_data(device) = hotk;
|
||||
device->driver_data = hotk;
|
||||
hotk->device = device;
|
||||
|
||||
result = asus_hotk_check();
|
||||
|
|
@ -1366,10 +1368,9 @@ static int asus_hotk_add(struct acpi_device *device)
|
|||
/* LED display is off by default */
|
||||
hotk->ledd_status = 0xFFF;
|
||||
|
||||
end:
|
||||
if (result) {
|
||||
end:
|
||||
if (result)
|
||||
kfree(hotk);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1394,8 +1395,8 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
|
|||
}
|
||||
|
||||
static struct backlight_ops asus_backlight_data = {
|
||||
.get_brightness = read_brightness,
|
||||
.update_status = set_brightness_status,
|
||||
.get_brightness = read_brightness,
|
||||
.update_status = set_brightness_status,
|
||||
};
|
||||
|
||||
static void asus_acpi_exit(void)
|
||||
|
|
@ -1442,15 +1443,15 @@ static int __init asus_acpi_init(void)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
asus_backlight_device = backlight_device_register("asus",NULL,NULL,
|
||||
asus_backlight_device = backlight_device_register("asus", NULL, NULL,
|
||||
&asus_backlight_data);
|
||||
if (IS_ERR(asus_backlight_device)) {
|
||||
if (IS_ERR(asus_backlight_device)) {
|
||||
printk(KERN_ERR "Could not register asus backlight device\n");
|
||||
asus_backlight_device = NULL;
|
||||
asus_acpi_exit();
|
||||
return -ENODEV;
|
||||
}
|
||||
asus_backlight_device->props.max_brightness = 15;
|
||||
asus_backlight_device->props.max_brightness = 15;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -804,7 +804,7 @@ static int acpi_battery_add(struct acpi_device *device)
|
|||
battery->device = device;
|
||||
strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
|
||||
acpi_driver_data(device) = battery;
|
||||
device->driver_data = battery;
|
||||
mutex_init(&battery->lock);
|
||||
acpi_battery_update(battery);
|
||||
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||
|
|
|
|||
|
|
@ -1,411 +0,0 @@
|
|||
/*
|
||||
* bay.c - ACPI removable drive bay driver
|
||||
*
|
||||
* Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
ACPI_MODULE_NAME("bay");
|
||||
MODULE_AUTHOR("Kristen Carlson Accardi");
|
||||
MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
#define ACPI_BAY_CLASS "bay"
|
||||
#define ACPI_BAY_COMPONENT 0x10000000
|
||||
#define _COMPONENT ACPI_BAY_COMPONENT
|
||||
#define bay_dprintk(h,s) {\
|
||||
char prefix[80] = {'\0'};\
|
||||
struct acpi_buffer buffer = {sizeof(prefix), prefix};\
|
||||
acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
|
||||
printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
|
||||
static void bay_notify(acpi_handle handle, u32 event, void *data);
|
||||
|
||||
static const struct acpi_device_id bay_device_ids[] = {
|
||||
{"LNXIOBAY", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, bay_device_ids);
|
||||
|
||||
struct bay {
|
||||
acpi_handle handle;
|
||||
char *name;
|
||||
struct list_head list;
|
||||
struct platform_device *pdev;
|
||||
};
|
||||
|
||||
static LIST_HEAD(drive_bays);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Drive Bay functions *
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* is_ejectable - see if a device is ejectable
|
||||
* @handle: acpi handle of the device
|
||||
*
|
||||
* If an acpi object has a _EJ0 method, then it is ejectable
|
||||
*/
|
||||
static int is_ejectable(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle tmp;
|
||||
|
||||
status = acpi_get_handle(handle, "_EJ0", &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* bay_present - see if the bay device is present
|
||||
* @bay: the drive bay
|
||||
*
|
||||
* execute the _STA method.
|
||||
*/
|
||||
static int bay_present(struct bay *bay)
|
||||
{
|
||||
unsigned long sta;
|
||||
acpi_status status;
|
||||
|
||||
if (bay) {
|
||||
status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta);
|
||||
if (ACPI_SUCCESS(status) && sta)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* eject_device - respond to an eject request
|
||||
* @handle - the device to eject
|
||||
*
|
||||
* Call this devices _EJ0 method.
|
||||
*/
|
||||
static void eject_device(acpi_handle handle)
|
||||
{
|
||||
struct acpi_object_list arg_list;
|
||||
union acpi_object arg;
|
||||
|
||||
bay_dprintk(handle, "Ejecting device");
|
||||
|
||||
arg_list.count = 1;
|
||||
arg_list.pointer = &arg;
|
||||
arg.type = ACPI_TYPE_INTEGER;
|
||||
arg.integer.value = 1;
|
||||
|
||||
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
|
||||
&arg_list, NULL)))
|
||||
pr_debug("Failed to evaluate _EJ0!\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* show_present - read method for "present" file in sysfs
|
||||
*/
|
||||
static ssize_t show_present(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct bay *bay = dev_get_drvdata(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay));
|
||||
|
||||
}
|
||||
static DEVICE_ATTR(present, S_IRUGO, show_present, NULL);
|
||||
|
||||
/*
|
||||
* write_eject - write method for "eject" file in sysfs
|
||||
*/
|
||||
static ssize_t write_eject(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct bay *bay = dev_get_drvdata(dev);
|
||||
|
||||
if (!count)
|
||||
return -EINVAL;
|
||||
|
||||
eject_device(bay->handle);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject);
|
||||
|
||||
/**
|
||||
* is_ata - see if a device is an ata device
|
||||
* @handle: acpi handle of the device
|
||||
*
|
||||
* If an acpi object has one of 4 ATA ACPI methods defined,
|
||||
* then it is an ATA device
|
||||
*/
|
||||
static int is_ata(acpi_handle handle)
|
||||
{
|
||||
acpi_handle tmp;
|
||||
|
||||
if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
|
||||
(ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
|
||||
(ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
|
||||
(ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* parent_is_ata(acpi_handle handle)
|
||||
*
|
||||
*/
|
||||
static int parent_is_ata(acpi_handle handle)
|
||||
{
|
||||
acpi_handle phandle;
|
||||
|
||||
if (acpi_get_parent(handle, &phandle))
|
||||
return 0;
|
||||
|
||||
return is_ata(phandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_ejectable_bay - see if a device is an ejectable drive bay
|
||||
* @handle: acpi handle of the device
|
||||
*
|
||||
* If an acpi object is ejectable and has one of the ACPI ATA
|
||||
* methods defined, then we can safely call it an ejectable
|
||||
* drive bay
|
||||
*/
|
||||
static int is_ejectable_bay(acpi_handle handle)
|
||||
{
|
||||
if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* eject_removable_drive - try to eject this drive
|
||||
* @dev : the device structure of the drive
|
||||
*
|
||||
* If a device is a removable drive that requires an _EJ0 method
|
||||
* to be executed in order to safely remove from the system, do
|
||||
* it. ATM - always returns success
|
||||
*/
|
||||
int eject_removable_drive(struct device *dev)
|
||||
{
|
||||
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
|
||||
|
||||
if (handle) {
|
||||
bay_dprintk(handle, "Got device handle");
|
||||
if (is_ejectable_bay(handle))
|
||||
eject_device(handle);
|
||||
} else {
|
||||
printk("No acpi handle for device\n");
|
||||
}
|
||||
|
||||
/* should I return an error code? */
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(eject_removable_drive);
|
||||
#endif /* 0 */
|
||||
|
||||
static int acpi_bay_add_fs(struct bay *bay)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = &bay->pdev->dev;
|
||||
|
||||
ret = device_create_file(dev, &dev_attr_present);
|
||||
if (ret)
|
||||
goto add_fs_err;
|
||||
ret = device_create_file(dev, &dev_attr_eject);
|
||||
if (ret) {
|
||||
device_remove_file(dev, &dev_attr_present);
|
||||
goto add_fs_err;
|
||||
}
|
||||
return 0;
|
||||
|
||||
add_fs_err:
|
||||
bay_dprintk(bay->handle, "Error adding sysfs files\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void acpi_bay_remove_fs(struct bay *bay)
|
||||
{
|
||||
struct device *dev = &bay->pdev->dev;
|
||||
|
||||
/* cleanup sysfs */
|
||||
device_remove_file(dev, &dev_attr_present);
|
||||
device_remove_file(dev, &dev_attr_eject);
|
||||
}
|
||||
|
||||
static int bay_is_dock_device(acpi_handle handle)
|
||||
{
|
||||
acpi_handle parent;
|
||||
|
||||
acpi_get_parent(handle, &parent);
|
||||
|
||||
/* if the device or it's parent is dependent on the
|
||||
* dock, then we are a dock device
|
||||
*/
|
||||
return (is_dock_device(handle) || is_dock_device(parent));
|
||||
}
|
||||
|
||||
static int bay_add(acpi_handle handle, int id)
|
||||
{
|
||||
acpi_status status;
|
||||
struct bay *new_bay;
|
||||
struct platform_device *pdev;
|
||||
struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer);
|
||||
|
||||
bay_dprintk(handle, "Adding notify handler");
|
||||
|
||||
/*
|
||||
* Initialize bay device structure
|
||||
*/
|
||||
new_bay = kzalloc(sizeof(*new_bay), GFP_ATOMIC);
|
||||
INIT_LIST_HEAD(&new_bay->list);
|
||||
new_bay->handle = handle;
|
||||
new_bay->name = (char *)nbuffer.pointer;
|
||||
|
||||
/* initialize platform device stuff */
|
||||
pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0);
|
||||
if (IS_ERR(pdev)) {
|
||||
printk(KERN_ERR PREFIX "Error registering bay device\n");
|
||||
goto bay_add_err;
|
||||
}
|
||||
new_bay->pdev = pdev;
|
||||
platform_set_drvdata(pdev, new_bay);
|
||||
|
||||
/*
|
||||
* we want the bay driver to be able to send uevents
|
||||
*/
|
||||
pdev->dev.uevent_suppress = 0;
|
||||
|
||||
/* register for events on this device */
|
||||
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
bay_notify, new_bay);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_INFO PREFIX "Error installing bay notify handler\n");
|
||||
platform_device_unregister(new_bay->pdev);
|
||||
goto bay_add_err;
|
||||
}
|
||||
|
||||
if (acpi_bay_add_fs(new_bay)) {
|
||||
acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
bay_notify);
|
||||
platform_device_unregister(new_bay->pdev);
|
||||
goto bay_add_err;
|
||||
}
|
||||
|
||||
/* if we are on a dock station, we should register for dock
|
||||
* notifications.
|
||||
*/
|
||||
if (bay_is_dock_device(handle)) {
|
||||
bay_dprintk(handle, "Is dependent on dock\n");
|
||||
register_hotplug_dock_device(handle, bay_notify, new_bay);
|
||||
}
|
||||
list_add(&new_bay->list, &drive_bays);
|
||||
printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name);
|
||||
return 0;
|
||||
|
||||
bay_add_err:
|
||||
kfree(new_bay->name);
|
||||
kfree(new_bay);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* bay_notify - act upon an acpi bay notification
|
||||
* @handle: the bay handle
|
||||
* @event: the acpi event
|
||||
* @data: our driver data struct
|
||||
*
|
||||
*/
|
||||
static void bay_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct bay *bay_dev = (struct bay *)data;
|
||||
struct device *dev = &bay_dev->pdev->dev;
|
||||
char event_string[12];
|
||||
char *envp[] = { event_string, NULL };
|
||||
|
||||
bay_dprintk(handle, "Bay event");
|
||||
sprintf(event_string, "BAY_EVENT=%d", event);
|
||||
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
int *count = (int *)context;
|
||||
|
||||
/*
|
||||
* there could be more than one ejectable bay.
|
||||
* so, just return AE_OK always so that every object
|
||||
* will be checked.
|
||||
*/
|
||||
if (is_ejectable_bay(handle)) {
|
||||
bay_dprintk(handle, "found ejectable bay");
|
||||
if (!bay_add(handle, *count))
|
||||
(*count)++;
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int __init bay_init(void)
|
||||
{
|
||||
int bays = 0;
|
||||
|
||||
INIT_LIST_HEAD(&drive_bays);
|
||||
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
|
||||
/* look for dockable drive bays */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_bay, &bays, NULL);
|
||||
|
||||
if (!bays)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit bay_exit(void)
|
||||
{
|
||||
struct bay *bay, *tmp;
|
||||
|
||||
list_for_each_entry_safe(bay, tmp, &drive_bays, list) {
|
||||
if (is_dock_device(bay->handle))
|
||||
unregister_hotplug_dock_device(bay->handle);
|
||||
acpi_bay_remove_fs(bay);
|
||||
acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY,
|
||||
bay_notify);
|
||||
platform_device_unregister(bay->pdev);
|
||||
kfree(bay->name);
|
||||
kfree(bay);
|
||||
}
|
||||
}
|
||||
|
||||
postcore_initcall(bay_init);
|
||||
module_exit(bay_exit);
|
||||
|
||||
|
|
@ -48,6 +48,23 @@ EXPORT_SYMBOL(acpi_root_dir);
|
|||
|
||||
#define STRUCT_TO_INT(s) (*((int*)&s))
|
||||
|
||||
static int set_power_nocheck(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_NOTICE PREFIX "%s detected - "
|
||||
"disable power check in power transistion\n", id->ident);
|
||||
acpi_power_nocheck = 1;
|
||||
return 0;
|
||||
}
|
||||
static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = {
|
||||
{
|
||||
set_power_nocheck, "HP Pavilion 05", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Device Management
|
||||
-------------------------------------------------------------------------- */
|
||||
|
|
@ -77,7 +94,7 @@ EXPORT_SYMBOL(acpi_bus_get_device);
|
|||
int acpi_bus_get_status(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
unsigned long sta = 0;
|
||||
unsigned long long sta = 0;
|
||||
|
||||
|
||||
if (!device)
|
||||
|
|
@ -95,21 +112,21 @@ int acpi_bus_get_status(struct acpi_device *device)
|
|||
}
|
||||
|
||||
/*
|
||||
* Otherwise we assume the status of our parent (unless we don't
|
||||
* have one, in which case status is implied).
|
||||
* According to ACPI spec some device can be present and functional
|
||||
* even if the parent is not present but functional.
|
||||
* In such conditions the child device should not inherit the status
|
||||
* from the parent.
|
||||
*/
|
||||
else if (device->parent)
|
||||
device->status = device->parent->status;
|
||||
else
|
||||
STRUCT_TO_INT(device->status) =
|
||||
ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
|
||||
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
|
||||
|
||||
if (device->status.functional && !device->status.present) {
|
||||
printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
|
||||
"functional but not present; setting present\n",
|
||||
device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status));
|
||||
device->status.present = 1;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
|
||||
"functional but not present;\n",
|
||||
device->pnp.bus_id,
|
||||
(u32) STRUCT_TO_INT(device->status)));
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
|
||||
|
|
@ -155,7 +172,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
|
|||
int result = 0;
|
||||
acpi_status status = 0;
|
||||
struct acpi_device *device = NULL;
|
||||
unsigned long psc = 0;
|
||||
unsigned long long psc = 0;
|
||||
|
||||
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
|
|
@ -223,7 +240,19 @@ int acpi_bus_set_power(acpi_handle handle, int state)
|
|||
/*
|
||||
* Get device's current power state
|
||||
*/
|
||||
acpi_bus_get_power(device->handle, &device->power.state);
|
||||
if (!acpi_power_nocheck) {
|
||||
/*
|
||||
* Maybe the incorrect power state is returned on the bogus
|
||||
* bios, which is different with the real power state.
|
||||
* For example: the bios returns D0 state and the real power
|
||||
* state is D3. OS expects to set the device to D0 state. In
|
||||
* such case if OS uses the power state returned by the BIOS,
|
||||
* the device can't be transisted to the correct power state.
|
||||
* So if the acpi_power_nocheck is set, it is unnecessary to
|
||||
* get the power state by calling acpi_bus_get_power.
|
||||
*/
|
||||
acpi_bus_get_power(device->handle, &device->power.state);
|
||||
}
|
||||
if ((state == device->power.state) && !device->flags.force_power_state) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
|
||||
state));
|
||||
|
|
@ -496,6 +525,19 @@ static int acpi_bus_check_scope(struct acpi_device *device)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
|
||||
int register_acpi_bus_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&acpi_bus_notify_list, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_acpi_bus_notifier);
|
||||
|
||||
void unregister_acpi_bus_notifier(struct notifier_block *nb)
|
||||
{
|
||||
blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier);
|
||||
|
||||
/**
|
||||
* acpi_bus_notify
|
||||
* ---------------
|
||||
|
|
@ -506,6 +548,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
|
|||
int result = 0;
|
||||
struct acpi_device *device = NULL;
|
||||
|
||||
blocking_notifier_call_chain(&acpi_bus_notify_list,
|
||||
type, (void *)handle);
|
||||
|
||||
if (acpi_bus_get_device(handle, &device))
|
||||
return;
|
||||
|
|
@ -749,6 +793,12 @@ static int __init acpi_bus_init(void)
|
|||
goto error1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Maybe EC region is required at bus_scan/acpi_get_devices. So it
|
||||
* is necessary to enable it as early as possible.
|
||||
*/
|
||||
acpi_boot_ec_enable();
|
||||
|
||||
printk(KERN_INFO PREFIX "Interpreter enabled\n");
|
||||
|
||||
/* Initialize sleep structures */
|
||||
|
|
@ -818,7 +868,11 @@ static int __init acpi_init(void)
|
|||
}
|
||||
} else
|
||||
disable_acpi();
|
||||
|
||||
/*
|
||||
* If the laptop falls into the DMI check table, the power state check
|
||||
* will be disabled in the course of device power transistion.
|
||||
*/
|
||||
dmi_check_system(power_nocheck_dmi_table);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
|
|||
{
|
||||
struct acpi_button *button = seq->private;
|
||||
acpi_status status;
|
||||
unsigned long state;
|
||||
unsigned long long state;
|
||||
|
||||
if (!button || !button->device)
|
||||
return 0;
|
||||
|
|
@ -253,7 +253,7 @@ static int acpi_button_remove_fs(struct acpi_device *device)
|
|||
-------------------------------------------------------------------------- */
|
||||
static int acpi_lid_send_state(struct acpi_button *button)
|
||||
{
|
||||
unsigned long state;
|
||||
unsigned long long state;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(button->device->handle, "_LID", NULL,
|
||||
|
|
@ -384,7 +384,7 @@ static int acpi_button_add(struct acpi_device *device)
|
|||
return -ENOMEM;
|
||||
|
||||
button->device = device;
|
||||
acpi_driver_data(device) = button;
|
||||
device->driver_data = button;
|
||||
|
||||
button->input = input = input_allocate_device();
|
||||
if (!input) {
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ struct proc_dir_entry *acpi_lock_ac_dir(void)
|
|||
if (acpi_ac_dir) {
|
||||
lock_ac_dir_cnt++;
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Cannot create %s\n", ACPI_AC_CLASS));
|
||||
printk(KERN_ERR PREFIX
|
||||
"Cannot create %s\n", ACPI_AC_CLASS);
|
||||
}
|
||||
mutex_unlock(&cm_sbs_mutex);
|
||||
return acpi_ac_dir;
|
||||
|
|
@ -83,8 +83,8 @@ struct proc_dir_entry *acpi_lock_battery_dir(void)
|
|||
if (acpi_battery_dir) {
|
||||
lock_battery_dir_cnt++;
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Cannot create %s\n", ACPI_BATTERY_CLASS));
|
||||
printk(KERN_ERR PREFIX
|
||||
"Cannot create %s\n", ACPI_BATTERY_CLASS);
|
||||
}
|
||||
mutex_unlock(&cm_sbs_mutex);
|
||||
return acpi_battery_dir;
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ static int is_device_present(acpi_handle handle)
|
|||
{
|
||||
acpi_handle temp;
|
||||
acpi_status status;
|
||||
unsigned long sta;
|
||||
unsigned long long sta;
|
||||
|
||||
|
||||
status = acpi_get_handle(handle, "_STA", &temp);
|
||||
|
|
@ -108,7 +108,7 @@ static int acpi_container_add(struct acpi_device *device)
|
|||
container->handle = device->handle;
|
||||
strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
|
||||
acpi_driver_data(device) = container;
|
||||
device->driver_data = container;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
|
||||
acpi_device_name(device), acpi_device_bid(device)));
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ static const struct acpi_dlayer acpi_debug_layers[] = {
|
|||
};
|
||||
|
||||
static const struct acpi_dlevel acpi_debug_levels[] = {
|
||||
ACPI_DEBUG_INIT(ACPI_LV_ERROR),
|
||||
ACPI_DEBUG_INIT(ACPI_LV_WARN),
|
||||
ACPI_DEBUG_INIT(ACPI_LV_INIT),
|
||||
ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
|
||||
ACPI_DEBUG_INIT(ACPI_LV_INFO),
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
|
|||
NULL);
|
||||
acpi_ex_enter_interpreter();
|
||||
}
|
||||
|
||||
acpi_ds_clear_implicit_return(walk_state);
|
||||
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acdispat.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acinterp.h>
|
||||
|
||||
|
|
@ -52,11 +51,11 @@ ACPI_MODULE_NAME("dsmthdat")
|
|||
|
||||
/* Local prototypes */
|
||||
static void
|
||||
acpi_ds_method_data_delete_value(u16 opcode,
|
||||
acpi_ds_method_data_delete_value(u8 type,
|
||||
u32 index, struct acpi_walk_state *walk_state);
|
||||
|
||||
static acpi_status
|
||||
acpi_ds_method_data_set_value(u16 opcode,
|
||||
acpi_ds_method_data_set_value(u8 type,
|
||||
u32 index,
|
||||
union acpi_operand_object *object,
|
||||
struct acpi_walk_state *walk_state);
|
||||
|
|
@ -216,7 +215,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params,
|
|||
* Store the argument in the method/walk descriptor.
|
||||
* Do not copy the arg in order to implement call by reference
|
||||
*/
|
||||
status = acpi_ds_method_data_set_value(AML_ARG_OP, index,
|
||||
status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
|
||||
params[index],
|
||||
walk_state);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
|
@ -234,7 +233,8 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params,
|
|||
*
|
||||
* FUNCTION: acpi_ds_method_data_get_node
|
||||
*
|
||||
* PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
|
||||
* PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
|
||||
* ACPI_REFCLASS_ARG
|
||||
* Index - Which Local or Arg whose type to get
|
||||
* walk_state - Current walk state object
|
||||
* Node - Where the node is returned.
|
||||
|
|
@ -246,7 +246,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params,
|
|||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_method_data_get_node(u16 opcode,
|
||||
acpi_ds_method_data_get_node(u8 type,
|
||||
u32 index,
|
||||
struct acpi_walk_state *walk_state,
|
||||
struct acpi_namespace_node **node)
|
||||
|
|
@ -256,8 +256,8 @@ acpi_ds_method_data_get_node(u16 opcode,
|
|||
/*
|
||||
* Method Locals and Arguments are supported
|
||||
*/
|
||||
switch (opcode) {
|
||||
case AML_LOCAL_OP:
|
||||
switch (type) {
|
||||
case ACPI_REFCLASS_LOCAL:
|
||||
|
||||
if (index > ACPI_METHOD_MAX_LOCAL) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
|
|
@ -271,7 +271,7 @@ acpi_ds_method_data_get_node(u16 opcode,
|
|||
*node = &walk_state->local_variables[index];
|
||||
break;
|
||||
|
||||
case AML_ARG_OP:
|
||||
case ACPI_REFCLASS_ARG:
|
||||
|
||||
if (index > ACPI_METHOD_MAX_ARG) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
|
|
@ -286,8 +286,8 @@ acpi_ds_method_data_get_node(u16 opcode,
|
|||
break;
|
||||
|
||||
default:
|
||||
ACPI_ERROR((AE_INFO, "Opcode %d is invalid", opcode));
|
||||
return_ACPI_STATUS(AE_AML_BAD_OPCODE);
|
||||
ACPI_ERROR((AE_INFO, "Type %d is invalid", type));
|
||||
return_ACPI_STATUS(AE_TYPE);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
|
|
@ -297,7 +297,8 @@ acpi_ds_method_data_get_node(u16 opcode,
|
|||
*
|
||||
* FUNCTION: acpi_ds_method_data_set_value
|
||||
*
|
||||
* PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
|
||||
* PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
|
||||
* ACPI_REFCLASS_ARG
|
||||
* Index - Which Local or Arg to get
|
||||
* Object - Object to be inserted into the stack entry
|
||||
* walk_state - Current walk state object
|
||||
|
|
@ -310,7 +311,7 @@ acpi_ds_method_data_get_node(u16 opcode,
|
|||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ds_method_data_set_value(u16 opcode,
|
||||
acpi_ds_method_data_set_value(u8 type,
|
||||
u32 index,
|
||||
union acpi_operand_object *object,
|
||||
struct acpi_walk_state *walk_state)
|
||||
|
|
@ -321,13 +322,13 @@ acpi_ds_method_data_set_value(u16 opcode,
|
|||
ACPI_FUNCTION_TRACE(ds_method_data_set_value);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"NewObj %p Opcode %X, Refs=%d [%s]\n", object,
|
||||
opcode, object->common.reference_count,
|
||||
"NewObj %p Type %2.2X, Refs=%d [%s]\n", object,
|
||||
type, object->common.reference_count,
|
||||
acpi_ut_get_type_name(object->common.type)));
|
||||
|
||||
/* Get the namespace node for the arg/local */
|
||||
|
||||
status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
|
||||
status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
|
@ -350,7 +351,8 @@ acpi_ds_method_data_set_value(u16 opcode,
|
|||
*
|
||||
* FUNCTION: acpi_ds_method_data_get_value
|
||||
*
|
||||
* PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
|
||||
* PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
|
||||
* ACPI_REFCLASS_ARG
|
||||
* Index - Which local_var or argument to get
|
||||
* walk_state - Current walk state object
|
||||
* dest_desc - Where Arg or Local value is returned
|
||||
|
|
@ -363,7 +365,7 @@ acpi_ds_method_data_set_value(u16 opcode,
|
|||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_method_data_get_value(u16 opcode,
|
||||
acpi_ds_method_data_get_value(u8 type,
|
||||
u32 index,
|
||||
struct acpi_walk_state *walk_state,
|
||||
union acpi_operand_object **dest_desc)
|
||||
|
|
@ -383,7 +385,7 @@ acpi_ds_method_data_get_value(u16 opcode,
|
|||
|
||||
/* Get the namespace node for the arg/local */
|
||||
|
||||
status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
|
||||
status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
|
@ -419,8 +421,8 @@ acpi_ds_method_data_get_value(u16 opcode,
|
|||
/* Otherwise, return the error */
|
||||
|
||||
else
|
||||
switch (opcode) {
|
||||
case AML_ARG_OP:
|
||||
switch (type) {
|
||||
case ACPI_REFCLASS_ARG:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Uninitialized Arg[%d] at node %p",
|
||||
|
|
@ -428,7 +430,7 @@ acpi_ds_method_data_get_value(u16 opcode,
|
|||
|
||||
return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
|
||||
|
||||
case AML_LOCAL_OP:
|
||||
case ACPI_REFCLASS_LOCAL:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Uninitialized Local[%d] at node %p",
|
||||
|
|
@ -437,9 +439,10 @@ acpi_ds_method_data_get_value(u16 opcode,
|
|||
return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Not a Arg/Local opcode: %X",
|
||||
opcode));
|
||||
type));
|
||||
return_ACPI_STATUS(AE_AML_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
|
@ -458,7 +461,8 @@ acpi_ds_method_data_get_value(u16 opcode,
|
|||
*
|
||||
* FUNCTION: acpi_ds_method_data_delete_value
|
||||
*
|
||||
* PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
|
||||
* PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
|
||||
* ACPI_REFCLASS_ARG
|
||||
* Index - Which local_var or argument to delete
|
||||
* walk_state - Current walk state object
|
||||
*
|
||||
|
|
@ -470,7 +474,7 @@ acpi_ds_method_data_get_value(u16 opcode,
|
|||
******************************************************************************/
|
||||
|
||||
static void
|
||||
acpi_ds_method_data_delete_value(u16 opcode,
|
||||
acpi_ds_method_data_delete_value(u8 type,
|
||||
u32 index, struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
|
|
@ -481,7 +485,7 @@ acpi_ds_method_data_delete_value(u16 opcode,
|
|||
|
||||
/* Get the namespace node for the arg/local */
|
||||
|
||||
status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
|
||||
status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_VOID;
|
||||
}
|
||||
|
|
@ -514,7 +518,8 @@ acpi_ds_method_data_delete_value(u16 opcode,
|
|||
*
|
||||
* FUNCTION: acpi_ds_store_object_to_local
|
||||
*
|
||||
* PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
|
||||
* PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
|
||||
* ACPI_REFCLASS_ARG
|
||||
* Index - Which Local or Arg to set
|
||||
* obj_desc - Value to be stored
|
||||
* walk_state - Current walk state
|
||||
|
|
@ -528,7 +533,7 @@ acpi_ds_method_data_delete_value(u16 opcode,
|
|||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_store_object_to_local(u16 opcode,
|
||||
acpi_ds_store_object_to_local(u8 type,
|
||||
u32 index,
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
|
|
@ -539,8 +544,8 @@ acpi_ds_store_object_to_local(u16 opcode,
|
|||
union acpi_operand_object *new_obj_desc;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ds_store_object_to_local);
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
|
||||
opcode, index, obj_desc));
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%d Obj=%p\n",
|
||||
type, index, obj_desc));
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
|
|
@ -550,7 +555,7 @@ acpi_ds_store_object_to_local(u16 opcode,
|
|||
|
||||
/* Get the namespace node for the arg/local */
|
||||
|
||||
status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
|
||||
status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
|
@ -602,7 +607,7 @@ acpi_ds_store_object_to_local(u16 opcode,
|
|||
*
|
||||
* Weird, but true.
|
||||
*/
|
||||
if (opcode == AML_ARG_OP) {
|
||||
if (type == ACPI_REFCLASS_ARG) {
|
||||
/*
|
||||
* If we have a valid reference object that came from ref_of(),
|
||||
* do the indirect store
|
||||
|
|
@ -611,8 +616,8 @@ acpi_ds_store_object_to_local(u16 opcode,
|
|||
ACPI_DESC_TYPE_OPERAND)
|
||||
&& (current_obj_desc->common.type ==
|
||||
ACPI_TYPE_LOCAL_REFERENCE)
|
||||
&& (current_obj_desc->reference.opcode ==
|
||||
AML_REF_OF_OP)) {
|
||||
&& (current_obj_desc->reference.class ==
|
||||
ACPI_REFCLASS_REFOF)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"Arg (%p) is an ObjRef(Node), storing in node %p\n",
|
||||
new_obj_desc,
|
||||
|
|
@ -640,11 +645,9 @@ acpi_ds_store_object_to_local(u16 opcode,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the existing object
|
||||
* before storing the new one
|
||||
*/
|
||||
acpi_ds_method_data_delete_value(opcode, index, walk_state);
|
||||
/* Delete the existing object before storing the new one */
|
||||
|
||||
acpi_ds_method_data_delete_value(type, index, walk_state);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -653,7 +656,7 @@ acpi_ds_store_object_to_local(u16 opcode,
|
|||
* (increments the object reference count by one)
|
||||
*/
|
||||
status =
|
||||
acpi_ds_method_data_set_value(opcode, index, new_obj_desc,
|
||||
acpi_ds_method_data_set_value(type, index, new_obj_desc,
|
||||
walk_state);
|
||||
|
||||
/* Remove local reference if we copied the object above */
|
||||
|
|
|
|||
|
|
@ -731,54 +731,70 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
|
|||
switch (op_info->type) {
|
||||
case AML_TYPE_LOCAL_VARIABLE:
|
||||
|
||||
/* Split the opcode into a base opcode + offset */
|
||||
/* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */
|
||||
|
||||
obj_desc->reference.opcode = AML_LOCAL_OP;
|
||||
obj_desc->reference.offset = opcode - AML_LOCAL_OP;
|
||||
obj_desc->reference.value = opcode - AML_LOCAL_OP;
|
||||
obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
|
||||
|
||||
#ifndef ACPI_NO_METHOD_EXECUTION
|
||||
status = acpi_ds_method_data_get_node(AML_LOCAL_OP,
|
||||
obj_desc->
|
||||
reference.offset,
|
||||
walk_state,
|
||||
(struct
|
||||
acpi_namespace_node
|
||||
**)&obj_desc->
|
||||
reference.object);
|
||||
status =
|
||||
acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL,
|
||||
obj_desc->reference.
|
||||
value, walk_state,
|
||||
ACPI_CAST_INDIRECT_PTR
|
||||
(struct
|
||||
acpi_namespace_node,
|
||||
&obj_desc->reference.
|
||||
object));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AML_TYPE_METHOD_ARGUMENT:
|
||||
|
||||
/* Split the opcode into a base opcode + offset */
|
||||
/* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */
|
||||
|
||||
obj_desc->reference.opcode = AML_ARG_OP;
|
||||
obj_desc->reference.offset = opcode - AML_ARG_OP;
|
||||
obj_desc->reference.value = opcode - AML_ARG_OP;
|
||||
obj_desc->reference.class = ACPI_REFCLASS_ARG;
|
||||
|
||||
#ifndef ACPI_NO_METHOD_EXECUTION
|
||||
status = acpi_ds_method_data_get_node(AML_ARG_OP,
|
||||
status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG,
|
||||
obj_desc->
|
||||
reference.offset,
|
||||
reference.value,
|
||||
walk_state,
|
||||
ACPI_CAST_INDIRECT_PTR
|
||||
(struct
|
||||
acpi_namespace_node
|
||||
**)&obj_desc->
|
||||
reference.object);
|
||||
acpi_namespace_node,
|
||||
&obj_desc->
|
||||
reference.
|
||||
object));
|
||||
#endif
|
||||
break;
|
||||
|
||||
default: /* Other literals, etc.. */
|
||||
default: /* Object name or Debug object */
|
||||
|
||||
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
|
||||
switch (op->common.aml_opcode) {
|
||||
case AML_INT_NAMEPATH_OP:
|
||||
|
||||
/* Node was saved in Op */
|
||||
|
||||
obj_desc->reference.node = op->common.node;
|
||||
obj_desc->reference.object =
|
||||
op->common.node->object;
|
||||
}
|
||||
obj_desc->reference.class = ACPI_REFCLASS_NAME;
|
||||
break;
|
||||
|
||||
obj_desc->reference.opcode = opcode;
|
||||
case AML_DEBUG_OP:
|
||||
|
||||
obj_desc->reference.class = ACPI_REFCLASS_DEBUG;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Unimplemented reference type for AML opcode: %4.4X",
|
||||
opcode));
|
||||
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1330,7 +1330,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
|
|||
(walk_state->results->results.obj_desc[0]) ==
|
||||
ACPI_TYPE_LOCAL_REFERENCE)
|
||||
&& ((walk_state->results->results.obj_desc[0])->
|
||||
reference.opcode != AML_INDEX_OP)) {
|
||||
reference.class != ACPI_REFCLASS_INDEX)) {
|
||||
status =
|
||||
acpi_ex_resolve_to_value(&walk_state->
|
||||
results->results.
|
||||
|
|
|
|||
|
|
@ -166,6 +166,10 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
|
|||
status = AE_CTRL_FALSE;
|
||||
}
|
||||
|
||||
/* Predicate can be used for an implicit return value */
|
||||
|
||||
(void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE);
|
||||
|
||||
cleanup:
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
|
||||
|
|
@ -429,10 +433,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
|
|||
ACPI_TYPE_LOCAL_REFERENCE)
|
||||
&& (walk_state->operands[1]->common.type ==
|
||||
ACPI_TYPE_LOCAL_REFERENCE)
|
||||
&& (walk_state->operands[0]->reference.opcode ==
|
||||
walk_state->operands[1]->reference.opcode)
|
||||
&& (walk_state->operands[0]->reference.offset ==
|
||||
walk_state->operands[1]->reference.offset)) {
|
||||
&& (walk_state->operands[0]->reference.class ==
|
||||
walk_state->operands[1]->reference.class)
|
||||
&& (walk_state->operands[0]->reference.value ==
|
||||
walk_state->operands[1]->reference.value)) {
|
||||
status = AE_OK;
|
||||
} else {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
|
|||
" before undocking");
|
||||
|
||||
static struct atomic_notifier_head dock_notifier_list;
|
||||
static struct platform_device *dock_device;
|
||||
static char dock_device_name[] = "dock";
|
||||
|
||||
static const struct acpi_device_id dock_device_ids[] = {
|
||||
|
|
@ -65,23 +64,29 @@ struct dock_station {
|
|||
struct mutex hp_lock;
|
||||
struct list_head dependent_devices;
|
||||
struct list_head hotplug_devices;
|
||||
|
||||
struct list_head sibiling;
|
||||
struct platform_device *dock_device;
|
||||
};
|
||||
static LIST_HEAD(dock_stations);
|
||||
static int dock_station_count;
|
||||
|
||||
struct dock_dependent_device {
|
||||
struct list_head list;
|
||||
struct list_head hotplug_list;
|
||||
acpi_handle handle;
|
||||
acpi_notify_handler handler;
|
||||
struct acpi_dock_ops *ops;
|
||||
void *context;
|
||||
};
|
||||
|
||||
#define DOCK_DOCKING 0x00000001
|
||||
#define DOCK_UNDOCKING 0x00000002
|
||||
#define DOCK_IS_DOCK 0x00000010
|
||||
#define DOCK_IS_ATA 0x00000020
|
||||
#define DOCK_IS_BAT 0x00000040
|
||||
#define DOCK_EVENT 3
|
||||
#define UNDOCK_EVENT 2
|
||||
|
||||
static struct dock_station *dock_station;
|
||||
|
||||
/*****************************************************************************
|
||||
* Dock Dependent device functions *
|
||||
*****************************************************************************/
|
||||
|
|
@ -199,6 +204,60 @@ static int is_dock(acpi_handle handle)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int is_ejectable(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle tmp;
|
||||
|
||||
status = acpi_get_handle(handle, "_EJ0", &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int is_ata(acpi_handle handle)
|
||||
{
|
||||
acpi_handle tmp;
|
||||
|
||||
if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
|
||||
(ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
|
||||
(ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
|
||||
(ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_battery(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device_info *info;
|
||||
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
int ret = 1;
|
||||
|
||||
if (!ACPI_SUCCESS(acpi_get_object_info(handle, &buffer)))
|
||||
return 0;
|
||||
info = buffer.pointer;
|
||||
if (!(info->valid & ACPI_VALID_HID))
|
||||
ret = 0;
|
||||
else
|
||||
ret = !strcmp("PNP0C0A", info->hardware_id.value);
|
||||
|
||||
kfree(buffer.pointer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int is_ejectable_bay(acpi_handle handle)
|
||||
{
|
||||
acpi_handle phandle;
|
||||
if (!is_ejectable(handle))
|
||||
return 0;
|
||||
if (is_battery(handle) || is_ata(handle))
|
||||
return 1;
|
||||
if (!acpi_get_parent(handle, &phandle) && is_ata(phandle))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* is_dock_device - see if a device is on a dock station
|
||||
* @handle: acpi handle of the device
|
||||
|
|
@ -209,11 +268,17 @@ static int is_dock(acpi_handle handle)
|
|||
*/
|
||||
int is_dock_device(acpi_handle handle)
|
||||
{
|
||||
if (!dock_station)
|
||||
struct dock_station *dock_station;
|
||||
|
||||
if (!dock_station_count)
|
||||
return 0;
|
||||
|
||||
if (is_dock(handle) || find_dock_dependent_device(dock_station, handle))
|
||||
if (is_dock(handle))
|
||||
return 1;
|
||||
list_for_each_entry(dock_station, &dock_stations, sibiling) {
|
||||
if (find_dock_dependent_device(dock_station, handle))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -229,7 +294,7 @@ EXPORT_SYMBOL_GPL(is_dock_device);
|
|||
*/
|
||||
static int dock_present(struct dock_station *ds)
|
||||
{
|
||||
unsigned long sta;
|
||||
unsigned long long sta;
|
||||
acpi_status status;
|
||||
|
||||
if (ds) {
|
||||
|
|
@ -320,8 +385,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
|
|||
* First call driver specific hotplug functions
|
||||
*/
|
||||
list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) {
|
||||
if (dd->handler)
|
||||
dd->handler(dd->handle, event, dd->context);
|
||||
if (dd->ops && dd->ops->handler)
|
||||
dd->ops->handler(dd->handle, event, dd->context);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -341,9 +406,10 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
|
|||
|
||||
static void dock_event(struct dock_station *ds, u32 event, int num)
|
||||
{
|
||||
struct device *dev = &dock_device->dev;
|
||||
struct device *dev = &ds->dock_device->dev;
|
||||
char event_string[13];
|
||||
char *envp[] = { event_string, NULL };
|
||||
struct dock_dependent_device *dd;
|
||||
|
||||
if (num == UNDOCK_EVENT)
|
||||
sprintf(event_string, "EVENT=undock");
|
||||
|
|
@ -354,7 +420,14 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
|
|||
* Indicate that the status of the dock station has
|
||||
* changed.
|
||||
*/
|
||||
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
|
||||
if (num == DOCK_EVENT)
|
||||
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
|
||||
|
||||
list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
|
||||
if (dd->ops && dd->ops->uevent)
|
||||
dd->ops->uevent(dd->handle, event, dd->context);
|
||||
if (num != DOCK_EVENT)
|
||||
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -414,9 +487,10 @@ static void handle_dock(struct dock_station *ds, int dock)
|
|||
arg.type = ACPI_TYPE_INTEGER;
|
||||
arg.integer.value = dock;
|
||||
status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
|
||||
if (ACPI_FAILURE(status))
|
||||
printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n",
|
||||
(char *)name_buffer.pointer);
|
||||
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
|
||||
ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute"
|
||||
" _DCK\n", (char *)name_buffer.pointer));
|
||||
|
||||
kfree(buffer.pointer);
|
||||
kfree(name_buffer.pointer);
|
||||
}
|
||||
|
|
@ -452,6 +526,25 @@ static inline void complete_undock(struct dock_station *ds)
|
|||
ds->flags &= ~(DOCK_UNDOCKING);
|
||||
}
|
||||
|
||||
static void dock_lock(struct dock_station *ds, int lock)
|
||||
{
|
||||
struct acpi_object_list arg_list;
|
||||
union acpi_object arg;
|
||||
acpi_status status;
|
||||
|
||||
arg_list.count = 1;
|
||||
arg_list.pointer = &arg;
|
||||
arg.type = ACPI_TYPE_INTEGER;
|
||||
arg.integer.value = !!lock;
|
||||
status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
|
||||
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
|
||||
if (lock)
|
||||
printk(KERN_WARNING PREFIX "Locking device failed\n");
|
||||
else
|
||||
printk(KERN_WARNING PREFIX "Unlocking device failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dock_in_progress - see if we are in the middle of handling a dock event
|
||||
* @ds: the dock station
|
||||
|
|
@ -479,7 +572,7 @@ static int dock_in_progress(struct dock_station *ds)
|
|||
*/
|
||||
int register_dock_notifier(struct notifier_block *nb)
|
||||
{
|
||||
if (!dock_station)
|
||||
if (!dock_station_count)
|
||||
return -ENODEV;
|
||||
|
||||
return atomic_notifier_chain_register(&dock_notifier_list, nb);
|
||||
|
|
@ -493,7 +586,7 @@ EXPORT_SYMBOL_GPL(register_dock_notifier);
|
|||
*/
|
||||
void unregister_dock_notifier(struct notifier_block *nb)
|
||||
{
|
||||
if (!dock_station)
|
||||
if (!dock_station_count)
|
||||
return;
|
||||
|
||||
atomic_notifier_chain_unregister(&dock_notifier_list, nb);
|
||||
|
|
@ -504,7 +597,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
|
|||
/**
|
||||
* register_hotplug_dock_device - register a hotplug function
|
||||
* @handle: the handle of the device
|
||||
* @handler: the acpi_notifier_handler to call after docking
|
||||
* @ops: handlers to call after docking
|
||||
* @context: device specific data
|
||||
*
|
||||
* If a driver would like to perform a hotplug operation after a dock
|
||||
|
|
@ -512,27 +605,36 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
|
|||
* the dock driver after _DCK is executed.
|
||||
*/
|
||||
int
|
||||
register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
|
||||
register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
|
||||
void *context)
|
||||
{
|
||||
struct dock_dependent_device *dd;
|
||||
struct dock_station *dock_station;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!dock_station)
|
||||
if (!dock_station_count)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* make sure this handle is for a device dependent on the dock,
|
||||
* this would include the dock station itself
|
||||
*/
|
||||
dd = find_dock_dependent_device(dock_station, handle);
|
||||
if (dd) {
|
||||
dd->handler = handler;
|
||||
dd->context = context;
|
||||
dock_add_hotplug_device(dock_station, dd);
|
||||
return 0;
|
||||
list_for_each_entry(dock_station, &dock_stations, sibiling) {
|
||||
/*
|
||||
* An ATA bay can be in a dock and itself can be ejected
|
||||
* seperately, so there are two 'dock stations' which need the
|
||||
* ops
|
||||
*/
|
||||
dd = find_dock_dependent_device(dock_station, handle);
|
||||
if (dd) {
|
||||
dd->ops = ops;
|
||||
dd->context = context;
|
||||
dock_add_hotplug_device(dock_station, dd);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
|
||||
|
|
@ -544,13 +646,16 @@ EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
|
|||
void unregister_hotplug_dock_device(acpi_handle handle)
|
||||
{
|
||||
struct dock_dependent_device *dd;
|
||||
struct dock_station *dock_station;
|
||||
|
||||
if (!dock_station)
|
||||
if (!dock_station_count)
|
||||
return;
|
||||
|
||||
dd = find_dock_dependent_device(dock_station, handle);
|
||||
if (dd)
|
||||
dock_del_hotplug_device(dock_station, dd);
|
||||
list_for_each_entry(dock_station, &dock_stations, sibiling) {
|
||||
dd = find_dock_dependent_device(dock_station, handle);
|
||||
if (dd)
|
||||
dock_del_hotplug_device(dock_station, dd);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
|
||||
|
|
@ -575,13 +680,9 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
|
|||
*/
|
||||
dock_event(ds, event, UNDOCK_EVENT);
|
||||
|
||||
if (!dock_present(ds)) {
|
||||
complete_undock(ds);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
|
||||
undock(ds);
|
||||
dock_lock(ds, 0);
|
||||
eject_dock(ds);
|
||||
if (dock_present(ds)) {
|
||||
printk(KERN_ERR PREFIX "Unable to undock!\n");
|
||||
|
|
@ -604,14 +705,36 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
|
|||
static void dock_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct dock_station *ds = data;
|
||||
struct acpi_device *tmp;
|
||||
int surprise_removal = 0;
|
||||
|
||||
/*
|
||||
* According to acpi spec 3.0a, if a DEVICE_CHECK notification
|
||||
* is sent and _DCK is present, it is assumed to mean an undock
|
||||
* request.
|
||||
*/
|
||||
if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK)
|
||||
event = ACPI_NOTIFY_EJECT_REQUEST;
|
||||
|
||||
/*
|
||||
* dock station: BUS_CHECK - docked or surprise removal
|
||||
* DEVICE_CHECK - undocked
|
||||
* other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal
|
||||
*
|
||||
* To simplify event handling, dock dependent device handler always
|
||||
* get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
|
||||
* ACPI_NOTIFY_EJECT_REQUEST for removal
|
||||
*/
|
||||
switch (event) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
if (!dock_in_progress(ds) && dock_present(ds)) {
|
||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||
if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle,
|
||||
&tmp)) {
|
||||
begin_dock(ds);
|
||||
dock(ds);
|
||||
if (!dock_present(ds)) {
|
||||
printk(KERN_ERR PREFIX "Unable to dock!\n");
|
||||
complete_dock(ds);
|
||||
break;
|
||||
}
|
||||
atomic_notifier_call_chain(&dock_notifier_list,
|
||||
|
|
@ -619,20 +742,19 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
|
|||
hotplug_dock_devices(ds, event);
|
||||
complete_dock(ds);
|
||||
dock_event(ds, event, DOCK_EVENT);
|
||||
dock_lock(ds, 1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||
/*
|
||||
* According to acpi spec 3.0a, if a DEVICE_CHECK notification
|
||||
* is sent and _DCK is present, it is assumed to mean an
|
||||
* undock request. This notify routine will only be called
|
||||
* for objects defining _DCK, so we will fall through to eject
|
||||
* request here. However, we will pass an eject request through
|
||||
* to the driver who wish to hotplug.
|
||||
*/
|
||||
if (dock_present(ds) || dock_in_progress(ds))
|
||||
break;
|
||||
/* This is a surprise removal */
|
||||
surprise_removal = 1;
|
||||
event = ACPI_NOTIFY_EJECT_REQUEST;
|
||||
/* Fall back */
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
begin_undock(ds);
|
||||
if (immediate_undock)
|
||||
if ((immediate_undock && !(ds->flags & DOCK_IS_ATA))
|
||||
|| surprise_removal)
|
||||
handle_eject_request(ds, event);
|
||||
else
|
||||
dock_event(ds, event, UNDOCK_EVENT);
|
||||
|
|
@ -642,6 +764,51 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
struct dock_data {
|
||||
acpi_handle handle;
|
||||
unsigned long event;
|
||||
struct dock_station *ds;
|
||||
};
|
||||
|
||||
static void acpi_dock_deferred_cb(void *context)
|
||||
{
|
||||
struct dock_data *data = (struct dock_data *)context;
|
||||
|
||||
dock_notify(data->handle, data->event, data->ds);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static int acpi_dock_notifier_call(struct notifier_block *this,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct dock_station *dock_station;
|
||||
acpi_handle handle = (acpi_handle)data;
|
||||
|
||||
if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
|
||||
&& event != ACPI_NOTIFY_EJECT_REQUEST)
|
||||
return 0;
|
||||
list_for_each_entry(dock_station, &dock_stations, sibiling) {
|
||||
if (dock_station->handle == handle) {
|
||||
struct dock_data *dock_data;
|
||||
|
||||
dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL);
|
||||
if (!dock_data)
|
||||
return 0;
|
||||
dock_data->handle = handle;
|
||||
dock_data->event = event;
|
||||
dock_data->ds = dock_station;
|
||||
acpi_os_hotplug_execute(acpi_dock_deferred_cb,
|
||||
dock_data);
|
||||
return 0 ;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block dock_acpi_notifier = {
|
||||
.notifier_call = acpi_dock_notifier_call,
|
||||
};
|
||||
|
||||
/**
|
||||
* find_dock_devices - find devices on the dock station
|
||||
* @handle: the handle of the device we are examining
|
||||
|
|
@ -688,6 +855,8 @@ fdd_out:
|
|||
static ssize_t show_docked(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dock_station *dock_station = *((struct dock_station **)
|
||||
dev->platform_data);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
|
||||
|
||||
}
|
||||
|
|
@ -699,6 +868,8 @@ static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
|
|||
static ssize_t show_flags(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dock_station *dock_station = *((struct dock_station **)
|
||||
dev->platform_data);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
|
||||
|
||||
}
|
||||
|
|
@ -711,6 +882,8 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
struct dock_station *dock_station = *((struct dock_station **)
|
||||
dev->platform_data);
|
||||
|
||||
if (!count)
|
||||
return -EINVAL;
|
||||
|
|
@ -727,16 +900,38 @@ static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
|
|||
static ssize_t show_dock_uid(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned long lbuf;
|
||||
unsigned long long lbuf;
|
||||
struct dock_station *dock_station = *((struct dock_station **)
|
||||
dev->platform_data);
|
||||
acpi_status status = acpi_evaluate_integer(dock_station->handle,
|
||||
"_UID", NULL, &lbuf);
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
|
||||
return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf);
|
||||
}
|
||||
static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
|
||||
|
||||
static ssize_t show_dock_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dock_station *dock_station = *((struct dock_station **)
|
||||
dev->platform_data);
|
||||
char *type;
|
||||
|
||||
if (dock_station->flags & DOCK_IS_DOCK)
|
||||
type = "dock_station";
|
||||
else if (dock_station->flags & DOCK_IS_ATA)
|
||||
type = "ata_bay";
|
||||
else if (dock_station->flags & DOCK_IS_BAT)
|
||||
type = "battery_bay";
|
||||
else
|
||||
type = "unknown";
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", type);
|
||||
}
|
||||
static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
|
||||
|
||||
/**
|
||||
* dock_add - add a new dock station
|
||||
* @handle: the dock station handle
|
||||
|
|
@ -747,8 +942,9 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
|
|||
static int dock_add(acpi_handle handle)
|
||||
{
|
||||
int ret;
|
||||
acpi_status status;
|
||||
struct dock_dependent_device *dd;
|
||||
struct dock_station *dock_station;
|
||||
struct platform_device *dock_device;
|
||||
|
||||
/* allocate & initialize the dock_station private data */
|
||||
dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL);
|
||||
|
|
@ -758,22 +954,34 @@ static int dock_add(acpi_handle handle)
|
|||
dock_station->last_dock_time = jiffies - HZ;
|
||||
INIT_LIST_HEAD(&dock_station->dependent_devices);
|
||||
INIT_LIST_HEAD(&dock_station->hotplug_devices);
|
||||
INIT_LIST_HEAD(&dock_station->sibiling);
|
||||
spin_lock_init(&dock_station->dd_lock);
|
||||
mutex_init(&dock_station->hp_lock);
|
||||
ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
|
||||
|
||||
/* initialize platform device stuff */
|
||||
dock_device =
|
||||
platform_device_register_simple(dock_device_name, 0, NULL, 0);
|
||||
dock_station->dock_device =
|
||||
platform_device_register_simple(dock_device_name,
|
||||
dock_station_count, NULL, 0);
|
||||
dock_device = dock_station->dock_device;
|
||||
if (IS_ERR(dock_device)) {
|
||||
kfree(dock_station);
|
||||
dock_station = NULL;
|
||||
return PTR_ERR(dock_device);
|
||||
}
|
||||
platform_device_add_data(dock_device, &dock_station,
|
||||
sizeof(struct dock_station *));
|
||||
|
||||
/* we want the dock device to send uevents */
|
||||
dock_device->dev.uevent_suppress = 0;
|
||||
|
||||
if (is_dock(handle))
|
||||
dock_station->flags |= DOCK_IS_DOCK;
|
||||
if (is_ata(handle))
|
||||
dock_station->flags |= DOCK_IS_ATA;
|
||||
if (is_battery(handle))
|
||||
dock_station->flags |= DOCK_IS_BAT;
|
||||
|
||||
ret = device_create_file(&dock_device->dev, &dev_attr_docked);
|
||||
if (ret) {
|
||||
printk("Error %d adding sysfs file\n", ret);
|
||||
|
|
@ -812,6 +1020,9 @@ static int dock_add(acpi_handle handle)
|
|||
dock_station = NULL;
|
||||
return ret;
|
||||
}
|
||||
ret = device_create_file(&dock_device->dev, &dev_attr_type);
|
||||
if (ret)
|
||||
printk(KERN_ERR"Error %d adding sysfs file\n", ret);
|
||||
|
||||
/* Find dependent devices */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
|
|
@ -828,24 +1039,12 @@ static int dock_add(acpi_handle handle)
|
|||
}
|
||||
add_dock_dependent_device(dock_station, dd);
|
||||
|
||||
/* register for dock events */
|
||||
status = acpi_install_notify_handler(dock_station->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
dock_notify, dock_station);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR PREFIX "Error installing notify handler\n");
|
||||
ret = -ENODEV;
|
||||
goto dock_add_err;
|
||||
}
|
||||
|
||||
printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION);
|
||||
|
||||
dock_station_count++;
|
||||
list_add(&dock_station->sibiling, &dock_stations);
|
||||
return 0;
|
||||
|
||||
dock_add_err:
|
||||
kfree(dd);
|
||||
dock_add_err_unregister:
|
||||
device_remove_file(&dock_device->dev, &dev_attr_type);
|
||||
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
||||
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
||||
device_remove_file(&dock_device->dev, &dev_attr_uid);
|
||||
|
|
@ -859,12 +1058,12 @@ dock_add_err_unregister:
|
|||
/**
|
||||
* dock_remove - free up resources related to the dock station
|
||||
*/
|
||||
static int dock_remove(void)
|
||||
static int dock_remove(struct dock_station *dock_station)
|
||||
{
|
||||
struct dock_dependent_device *dd, *tmp;
|
||||
acpi_status status;
|
||||
struct platform_device *dock_device = dock_station->dock_device;
|
||||
|
||||
if (!dock_station)
|
||||
if (!dock_station_count)
|
||||
return 0;
|
||||
|
||||
/* remove dependent devices */
|
||||
|
|
@ -872,14 +1071,8 @@ static int dock_remove(void)
|
|||
list)
|
||||
kfree(dd);
|
||||
|
||||
/* remove dock notify handler */
|
||||
status = acpi_remove_notify_handler(dock_station->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
dock_notify);
|
||||
if (ACPI_FAILURE(status))
|
||||
printk(KERN_ERR "Error removing notify handler\n");
|
||||
|
||||
/* cleanup sysfs */
|
||||
device_remove_file(&dock_device->dev, &dev_attr_type);
|
||||
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
||||
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
||||
device_remove_file(&dock_device->dev, &dev_attr_uid);
|
||||
|
|
@ -904,41 +1097,60 @@ static int dock_remove(void)
|
|||
static acpi_status
|
||||
find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
int *count = context;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
if (is_dock(handle)) {
|
||||
if (dock_add(handle) >= 0) {
|
||||
(*count)++;
|
||||
status = AE_CTRL_TERMINATE;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
/* If bay is a dock, it's already handled */
|
||||
if (is_ejectable_bay(handle) && !is_dock(handle))
|
||||
dock_add(handle);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int __init dock_init(void)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
dock_station = NULL;
|
||||
|
||||
if (acpi_disabled)
|
||||
return 0;
|
||||
|
||||
/* look for a dock station */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_dock, &num, NULL);
|
||||
ACPI_UINT32_MAX, find_dock, NULL, NULL);
|
||||
|
||||
if (!num)
|
||||
printk(KERN_INFO "No dock devices found.\n");
|
||||
/* look for bay */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_bay, NULL, NULL);
|
||||
if (!dock_station_count) {
|
||||
printk(KERN_INFO PREFIX "No dock devices found.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
register_acpi_bus_notifier(&dock_acpi_notifier);
|
||||
printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
|
||||
ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit dock_exit(void)
|
||||
{
|
||||
dock_remove();
|
||||
struct dock_station *dock_station;
|
||||
|
||||
unregister_acpi_bus_notifier(&dock_acpi_notifier);
|
||||
list_for_each_entry(dock_station, &dock_stations, sibiling)
|
||||
dock_remove(dock_station);
|
||||
}
|
||||
|
||||
postcore_initcall(dock_init);
|
||||
/*
|
||||
* Must be called before drivers of devices in dock, otherwise we can't know
|
||||
* which devices are in a dock
|
||||
*/
|
||||
subsys_initcall(dock_init);
|
||||
module_exit(dock_exit);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* ec.c - ACPI Embedded Controller Driver (v2.0)
|
||||
* ec.c - ACPI Embedded Controller Driver (v2.1)
|
||||
*
|
||||
* Copyright (C) 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
|
||||
* Copyright (C) 2006-2008 Alexey Starikovskiy <astarikovskiy@suse.de>
|
||||
* Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
|
||||
* Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
|
||||
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
/* Uncomment next line to get verbose print outs*/
|
||||
/* Uncomment next line to get verbose printout */
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/io.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
|
|
@ -65,22 +66,21 @@ enum ec_command {
|
|||
ACPI_EC_COMMAND_QUERY = 0x84,
|
||||
};
|
||||
|
||||
/* EC events */
|
||||
enum ec_event {
|
||||
ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */
|
||||
ACPI_EC_EVENT_IBF_0, /* Input buffer empty */
|
||||
};
|
||||
|
||||
#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
|
||||
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
|
||||
#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */
|
||||
|
||||
#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts
|
||||
per one transaction */
|
||||
|
||||
enum {
|
||||
EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
|
||||
EC_FLAGS_QUERY_PENDING, /* Query is pending */
|
||||
EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
|
||||
EC_FLAGS_GPE_MODE, /* Expect GPE to be sent
|
||||
* for status change */
|
||||
EC_FLAGS_NO_GPE, /* Don't use GPE mode */
|
||||
EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */
|
||||
EC_FLAGS_GPE_STORM, /* GPE storm detected */
|
||||
EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and
|
||||
* OpReg are installed */
|
||||
};
|
||||
|
||||
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
|
||||
|
|
@ -95,6 +95,15 @@ struct acpi_ec_query_handler {
|
|||
u8 query_bit;
|
||||
};
|
||||
|
||||
struct transaction {
|
||||
const u8 *wdata;
|
||||
u8 *rdata;
|
||||
unsigned short irq_count;
|
||||
u8 command;
|
||||
u8 wlen;
|
||||
u8 rlen;
|
||||
};
|
||||
|
||||
static struct acpi_ec {
|
||||
acpi_handle handle;
|
||||
unsigned long gpe;
|
||||
|
|
@ -105,9 +114,8 @@ static struct acpi_ec {
|
|||
struct mutex lock;
|
||||
wait_queue_head_t wait;
|
||||
struct list_head list;
|
||||
struct delayed_work work;
|
||||
atomic_t irq_count;
|
||||
u8 handlers_installed;
|
||||
struct transaction *curr;
|
||||
spinlock_t curr_lock;
|
||||
} *boot_ec, *first_ec;
|
||||
|
||||
/*
|
||||
|
|
@ -150,7 +158,7 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
|
|||
{
|
||||
u8 x = inb(ec->data_addr);
|
||||
pr_debug(PREFIX "---> data = 0x%2.2x\n", x);
|
||||
return inb(ec->data_addr);
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
|
||||
|
|
@ -165,158 +173,172 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
|
|||
outb(data, ec->data_addr);
|
||||
}
|
||||
|
||||
static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
|
||||
static int ec_transaction_done(struct acpi_ec *ec)
|
||||
{
|
||||
if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags))
|
||||
return 0;
|
||||
if (event == ACPI_EC_EVENT_OBF_1) {
|
||||
if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF)
|
||||
return 1;
|
||||
} else if (event == ACPI_EC_EVENT_IBF_0) {
|
||||
if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF))
|
||||
return 1;
|
||||
}
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
spin_lock_irqsave(&ec->curr_lock, flags);
|
||||
if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen))
|
||||
ret = 1;
|
||||
spin_unlock_irqrestore(&ec->curr_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gpe_transaction(struct acpi_ec *ec, u8 status)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&ec->curr_lock, flags);
|
||||
if (!ec->curr)
|
||||
goto unlock;
|
||||
if (ec->curr->wlen > 0) {
|
||||
if ((status & ACPI_EC_FLAG_IBF) == 0) {
|
||||
acpi_ec_write_data(ec, *(ec->curr->wdata++));
|
||||
--ec->curr->wlen;
|
||||
} else
|
||||
/* false interrupt, state didn't change */
|
||||
++ec->curr->irq_count;
|
||||
|
||||
} else if (ec->curr->rlen > 0) {
|
||||
if ((status & ACPI_EC_FLAG_OBF) == 1) {
|
||||
*(ec->curr->rdata++) = acpi_ec_read_data(ec);
|
||||
--ec->curr->rlen;
|
||||
} else
|
||||
/* false interrupt, state didn't change */
|
||||
++ec->curr->irq_count;
|
||||
}
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&ec->curr_lock, flags);
|
||||
}
|
||||
|
||||
static int acpi_ec_wait(struct acpi_ec *ec)
|
||||
{
|
||||
if (wait_event_timeout(ec->wait, ec_transaction_done(ec),
|
||||
msecs_to_jiffies(ACPI_EC_DELAY)))
|
||||
return 0;
|
||||
/* missing GPEs, switch back to poll mode */
|
||||
if (printk_ratelimit())
|
||||
pr_info(PREFIX "missing confirmations, "
|
||||
"switch off interrupt mode.\n");
|
||||
set_bit(EC_FLAGS_NO_GPE, &ec->flags);
|
||||
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void acpi_ec_gpe_query(void *ec_cxt);
|
||||
|
||||
static int ec_check_sci(struct acpi_ec *ec, u8 state)
|
||||
{
|
||||
if (state & ACPI_EC_FLAG_SCI) {
|
||||
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
|
||||
return acpi_os_execute(OSL_EC_BURST_HANDLER,
|
||||
acpi_ec_gpe_query, ec);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ec_schedule_ec_poll(struct acpi_ec *ec)
|
||||
static int ec_poll(struct acpi_ec *ec)
|
||||
{
|
||||
if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags))
|
||||
schedule_delayed_work(&ec->work,
|
||||
msecs_to_jiffies(ACPI_EC_DELAY));
|
||||
}
|
||||
|
||||
static void ec_switch_to_poll_mode(struct acpi_ec *ec)
|
||||
{
|
||||
set_bit(EC_FLAGS_NO_GPE, &ec->flags);
|
||||
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
|
||||
acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
|
||||
set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
|
||||
}
|
||||
|
||||
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
|
||||
{
|
||||
atomic_set(&ec->irq_count, 0);
|
||||
if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
|
||||
likely(!force_poll)) {
|
||||
if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
|
||||
msecs_to_jiffies(ACPI_EC_DELAY)))
|
||||
return 0;
|
||||
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
|
||||
if (acpi_ec_check_status(ec, event)) {
|
||||
/* missing GPEs, switch back to poll mode */
|
||||
if (printk_ratelimit())
|
||||
pr_info(PREFIX "missing confirmations, "
|
||||
"switch off interrupt mode.\n");
|
||||
ec_switch_to_poll_mode(ec);
|
||||
ec_schedule_ec_poll(ec);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
|
||||
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
|
||||
while (time_before(jiffies, delay)) {
|
||||
if (acpi_ec_check_status(ec, event))
|
||||
return 0;
|
||||
msleep(1);
|
||||
}
|
||||
if (acpi_ec_check_status(ec,event))
|
||||
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
|
||||
msleep(1);
|
||||
while (time_before(jiffies, delay)) {
|
||||
gpe_transaction(ec, acpi_ec_read_status(ec));
|
||||
msleep(1);
|
||||
if (ec_transaction_done(ec))
|
||||
return 0;
|
||||
}
|
||||
pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n",
|
||||
acpi_ec_read_status(ec),
|
||||
(event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\"");
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
|
||||
const u8 * wdata, unsigned wdata_len,
|
||||
u8 * rdata, unsigned rdata_len,
|
||||
static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
|
||||
struct transaction *t,
|
||||
int force_poll)
|
||||
{
|
||||
int result = 0;
|
||||
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
|
||||
unsigned long tmp;
|
||||
int ret = 0;
|
||||
pr_debug(PREFIX "transaction start\n");
|
||||
acpi_ec_write_cmd(ec, command);
|
||||
for (; wdata_len > 0; --wdata_len) {
|
||||
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
|
||||
if (result) {
|
||||
pr_err(PREFIX
|
||||
"write_cmd timeout, command = %d\n", command);
|
||||
goto end;
|
||||
}
|
||||
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
|
||||
acpi_ec_write_data(ec, *(wdata++));
|
||||
/* disable GPE during transaction if storm is detected */
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
|
||||
acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
|
||||
}
|
||||
|
||||
if (!rdata_len) {
|
||||
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
|
||||
if (result) {
|
||||
pr_err(PREFIX
|
||||
"finish-write timeout, command = %d\n", command);
|
||||
goto end;
|
||||
}
|
||||
} else if (command == ACPI_EC_COMMAND_QUERY)
|
||||
/* start transaction */
|
||||
spin_lock_irqsave(&ec->curr_lock, tmp);
|
||||
/* following two actions should be kept atomic */
|
||||
t->irq_count = 0;
|
||||
ec->curr = t;
|
||||
acpi_ec_write_cmd(ec, ec->curr->command);
|
||||
if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
|
||||
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
|
||||
|
||||
for (; rdata_len > 0; --rdata_len) {
|
||||
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
|
||||
if (result) {
|
||||
pr_err(PREFIX "read timeout, command = %d\n", command);
|
||||
goto end;
|
||||
}
|
||||
/* Don't expect GPE after last read */
|
||||
if (rdata_len > 1)
|
||||
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
|
||||
*(rdata++) = acpi_ec_read_data(ec);
|
||||
}
|
||||
end:
|
||||
spin_unlock_irqrestore(&ec->curr_lock, tmp);
|
||||
/* if we selected poll mode or failed in GPE-mode do a poll loop */
|
||||
if (force_poll ||
|
||||
!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ||
|
||||
acpi_ec_wait(ec))
|
||||
ret = ec_poll(ec);
|
||||
pr_debug(PREFIX "transaction end\n");
|
||||
return result;
|
||||
spin_lock_irqsave(&ec->curr_lock, tmp);
|
||||
ec->curr = NULL;
|
||||
spin_unlock_irqrestore(&ec->curr_lock, tmp);
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
/* check if we received SCI during transaction */
|
||||
ec_check_sci(ec, acpi_ec_read_status(ec));
|
||||
/* it is safe to enable GPE outside of transaction */
|
||||
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
|
||||
} else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
|
||||
t->irq_count > ACPI_EC_STORM_THRESHOLD) {
|
||||
pr_debug(PREFIX "GPE storm detected\n");
|
||||
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
|
||||
const u8 * wdata, unsigned wdata_len,
|
||||
u8 * rdata, unsigned rdata_len,
|
||||
static int ec_check_ibf0(struct acpi_ec *ec)
|
||||
{
|
||||
u8 status = acpi_ec_read_status(ec);
|
||||
return (status & ACPI_EC_FLAG_IBF) == 0;
|
||||
}
|
||||
|
||||
static int ec_wait_ibf0(struct acpi_ec *ec)
|
||||
{
|
||||
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
|
||||
/* interrupt wait manually if GPE mode is not active */
|
||||
unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ?
|
||||
msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1);
|
||||
while (time_before(jiffies, delay))
|
||||
if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout))
|
||||
return 0;
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t,
|
||||
int force_poll)
|
||||
{
|
||||
int status;
|
||||
u32 glk;
|
||||
|
||||
if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
|
||||
if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
|
||||
return -EINVAL;
|
||||
|
||||
if (rdata)
|
||||
memset(rdata, 0, rdata_len);
|
||||
|
||||
if (t->rdata)
|
||||
memset(t->rdata, 0, t->rlen);
|
||||
mutex_lock(&ec->lock);
|
||||
if (ec->global_lock) {
|
||||
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
mutex_unlock(&ec->lock);
|
||||
return -ENODEV;
|
||||
status = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
|
||||
if (status) {
|
||||
if (ec_wait_ibf0(ec)) {
|
||||
pr_err(PREFIX "input buffer is not empty, "
|
||||
"aborting transaction\n");
|
||||
status = -ETIME;
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = acpi_ec_transaction_unlocked(ec, command,
|
||||
wdata, wdata_len,
|
||||
rdata, rdata_len,
|
||||
force_poll);
|
||||
|
||||
end:
|
||||
|
||||
status = acpi_ec_transaction_unlocked(ec, t, force_poll);
|
||||
end:
|
||||
if (ec->global_lock)
|
||||
acpi_release_global_lock(glk);
|
||||
unlock:
|
||||
mutex_unlock(&ec->lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -327,21 +349,32 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
|
|||
int acpi_ec_burst_enable(struct acpi_ec *ec)
|
||||
{
|
||||
u8 d;
|
||||
return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0);
|
||||
struct transaction t = {.command = ACPI_EC_BURST_ENABLE,
|
||||
.wdata = NULL, .rdata = &d,
|
||||
.wlen = 0, .rlen = 1};
|
||||
|
||||
return acpi_ec_transaction(ec, &t, 0);
|
||||
}
|
||||
|
||||
int acpi_ec_burst_disable(struct acpi_ec *ec)
|
||||
{
|
||||
return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0);
|
||||
struct transaction t = {.command = ACPI_EC_BURST_DISABLE,
|
||||
.wdata = NULL, .rdata = NULL,
|
||||
.wlen = 0, .rlen = 0};
|
||||
|
||||
return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
|
||||
acpi_ec_transaction(ec, &t, 0) : 0;
|
||||
}
|
||||
|
||||
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
struct transaction t = {.command = ACPI_EC_COMMAND_READ,
|
||||
.wdata = &address, .rdata = &d,
|
||||
.wlen = 1, .rlen = 1};
|
||||
|
||||
result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ,
|
||||
&address, 1, &d, 1, 0);
|
||||
result = acpi_ec_transaction(ec, &t, 0);
|
||||
*data = d;
|
||||
return result;
|
||||
}
|
||||
|
|
@ -349,8 +382,11 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
|
|||
static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
|
||||
{
|
||||
u8 wdata[2] = { address, data };
|
||||
return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
|
||||
wdata, 2, NULL, 0, 0);
|
||||
struct transaction t = {.command = ACPI_EC_COMMAND_WRITE,
|
||||
.wdata = wdata, .rdata = NULL,
|
||||
.wlen = 2, .rlen = 0};
|
||||
|
||||
return acpi_ec_transaction(ec, &t, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -412,12 +448,13 @@ int ec_transaction(u8 command,
|
|||
u8 * rdata, unsigned rdata_len,
|
||||
int force_poll)
|
||||
{
|
||||
struct transaction t = {.command = command,
|
||||
.wdata = wdata, .rdata = rdata,
|
||||
.wlen = wdata_len, .rlen = rdata_len};
|
||||
if (!first_ec)
|
||||
return -ENODEV;
|
||||
|
||||
return acpi_ec_transaction(first_ec, command, wdata,
|
||||
wdata_len, rdata, rdata_len,
|
||||
force_poll);
|
||||
return acpi_ec_transaction(first_ec, &t, force_poll);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ec_transaction);
|
||||
|
|
@ -426,7 +463,9 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
|
|||
{
|
||||
int result;
|
||||
u8 d;
|
||||
|
||||
struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
|
||||
.wdata = NULL, .rdata = &d,
|
||||
.wlen = 0, .rlen = 1};
|
||||
if (!ec || !data)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -436,7 +475,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
|
|||
* bit to be cleared (and thus clearing the interrupt source).
|
||||
*/
|
||||
|
||||
result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0);
|
||||
result = acpi_ec_transaction(ec, &t, 0);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
|
|
@ -513,46 +552,26 @@ static void acpi_ec_gpe_query(void *ec_cxt)
|
|||
|
||||
static u32 acpi_ec_gpe_handler(void *data)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_ec *ec = data;
|
||||
u8 state = acpi_ec_read_status(ec);
|
||||
u8 status;
|
||||
|
||||
pr_debug(PREFIX "~~~> interrupt\n");
|
||||
atomic_inc(&ec->irq_count);
|
||||
if (atomic_read(&ec->irq_count) > 5) {
|
||||
pr_err(PREFIX "GPE storm detected, disabling EC GPE\n");
|
||||
ec_switch_to_poll_mode(ec);
|
||||
goto end;
|
||||
}
|
||||
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
|
||||
if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
|
||||
status = acpi_ec_read_status(ec);
|
||||
|
||||
gpe_transaction(ec, status);
|
||||
if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0)
|
||||
wake_up(&ec->wait);
|
||||
|
||||
if (state & ACPI_EC_FLAG_SCI) {
|
||||
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
|
||||
status = acpi_os_execute(OSL_EC_BURST_HANDLER,
|
||||
acpi_ec_gpe_query, ec);
|
||||
} else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
|
||||
!test_bit(EC_FLAGS_NO_GPE, &ec->flags) &&
|
||||
in_interrupt()) {
|
||||
ec_check_sci(ec, status);
|
||||
if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
|
||||
!test_bit(EC_FLAGS_NO_GPE, &ec->flags)) {
|
||||
/* this is non-query, must be confirmation */
|
||||
if (printk_ratelimit())
|
||||
pr_info(PREFIX "non-query interrupt received,"
|
||||
" switching to interrupt mode\n");
|
||||
set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
|
||||
clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
|
||||
}
|
||||
end:
|
||||
ec_schedule_ec_poll(ec);
|
||||
return ACPI_SUCCESS(status) ?
|
||||
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
|
||||
}
|
||||
|
||||
static void do_ec_poll(struct work_struct *work)
|
||||
{
|
||||
struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work);
|
||||
atomic_set(&ec->irq_count, 0);
|
||||
(void)acpi_ec_gpe_handler(ec);
|
||||
return ACPI_INTERRUPT_HANDLED;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
|
|
@ -696,8 +715,7 @@ static struct acpi_ec *make_acpi_ec(void)
|
|||
mutex_init(&ec->lock);
|
||||
init_waitqueue_head(&ec->wait);
|
||||
INIT_LIST_HEAD(&ec->list);
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll);
|
||||
atomic_set(&ec->irq_count, 0);
|
||||
spin_lock_init(&ec->curr_lock);
|
||||
return ec;
|
||||
}
|
||||
|
||||
|
|
@ -718,6 +736,7 @@ static acpi_status
|
|||
ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
|
||||
{
|
||||
acpi_status status;
|
||||
unsigned long long tmp;
|
||||
|
||||
struct acpi_ec *ec = context;
|
||||
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
|
||||
|
|
@ -727,31 +746,26 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
|
|||
|
||||
/* Get GPE bit assignment (EC events). */
|
||||
/* TODO: Add support for _GPE returning a package */
|
||||
status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
|
||||
status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return status;
|
||||
ec->gpe = tmp;
|
||||
/* Use the global lock for all EC transactions? */
|
||||
acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
|
||||
acpi_evaluate_integer(handle, "_GLK", NULL, &tmp);
|
||||
ec->global_lock = tmp;
|
||||
ec->handle = handle;
|
||||
return AE_CTRL_TERMINATE;
|
||||
}
|
||||
|
||||
static void ec_poll_stop(struct acpi_ec *ec)
|
||||
{
|
||||
clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
|
||||
cancel_delayed_work(&ec->work);
|
||||
}
|
||||
|
||||
static void ec_remove_handlers(struct acpi_ec *ec)
|
||||
{
|
||||
ec_poll_stop(ec);
|
||||
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
|
||||
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
|
||||
pr_err(PREFIX "failed to remove space handler\n");
|
||||
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
|
||||
&acpi_ec_gpe_handler)))
|
||||
pr_err(PREFIX "failed to remove gpe handler\n");
|
||||
ec->handlers_installed = 0;
|
||||
clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
|
||||
}
|
||||
|
||||
static int acpi_ec_add(struct acpi_device *device)
|
||||
|
|
@ -788,7 +802,7 @@ static int acpi_ec_add(struct acpi_device *device)
|
|||
|
||||
if (!first_ec)
|
||||
first_ec = ec;
|
||||
acpi_driver_data(device) = ec;
|
||||
device->driver_data = ec;
|
||||
acpi_ec_add_fs(device);
|
||||
pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
|
||||
ec->gpe, ec->command_addr, ec->data_addr);
|
||||
|
|
@ -813,7 +827,7 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
|
|||
}
|
||||
mutex_unlock(&ec->lock);
|
||||
acpi_ec_remove_fs(device);
|
||||
acpi_driver_data(device) = NULL;
|
||||
device->driver_data = NULL;
|
||||
if (ec == first_ec)
|
||||
first_ec = NULL;
|
||||
kfree(ec);
|
||||
|
|
@ -846,27 +860,36 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
|
|||
static int ec_install_handlers(struct acpi_ec *ec)
|
||||
{
|
||||
acpi_status status;
|
||||
if (ec->handlers_installed)
|
||||
if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
|
||||
return 0;
|
||||
status = acpi_install_gpe_handler(NULL, ec->gpe,
|
||||
ACPI_GPE_EDGE_TRIGGERED,
|
||||
&acpi_ec_gpe_handler, ec);
|
||||
ACPI_GPE_EDGE_TRIGGERED,
|
||||
&acpi_ec_gpe_handler, ec);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
|
||||
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
|
||||
|
||||
status = acpi_install_address_space_handler(ec->handle,
|
||||
ACPI_ADR_SPACE_EC,
|
||||
&acpi_ec_space_handler,
|
||||
NULL, ec);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
|
||||
return -ENODEV;
|
||||
if (status == AE_NOT_FOUND) {
|
||||
/*
|
||||
* Maybe OS fails in evaluating the _REG object.
|
||||
* The AE_NOT_FOUND error will be ignored and OS
|
||||
* continue to initialize EC.
|
||||
*/
|
||||
printk(KERN_ERR "Fail in evaluating the _REG object"
|
||||
" of EC device. Broken bios is suspected.\n");
|
||||
} else {
|
||||
acpi_remove_gpe_handler(NULL, ec->gpe,
|
||||
&acpi_ec_gpe_handler);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
ec->handlers_installed = 1;
|
||||
set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -887,7 +910,6 @@ static int acpi_ec_start(struct acpi_device *device)
|
|||
|
||||
/* EC is fully operational, allow queries */
|
||||
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
|
||||
ec_schedule_ec_poll(ec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -906,7 +928,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
|
|||
|
||||
int __init acpi_boot_ec_enable(void)
|
||||
{
|
||||
if (!boot_ec || boot_ec->handlers_installed)
|
||||
if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags))
|
||||
return 0;
|
||||
if (!ec_install_handlers(boot_ec)) {
|
||||
first_ec = boot_ec;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/actables.h>
|
||||
#include <acpi/acdispat.h>
|
||||
|
|
@ -91,13 +90,12 @@ acpi_ex_add_table(u32 table_index,
|
|||
|
||||
/* Init the table handle */
|
||||
|
||||
obj_desc->reference.opcode = AML_LOAD_OP;
|
||||
obj_desc->reference.class = ACPI_REFCLASS_TABLE;
|
||||
*ddb_handle = obj_desc;
|
||||
|
||||
/* Install the new table into the local data structures */
|
||||
|
||||
obj_desc->reference.object = ACPI_CAST_PTR(void,
|
||||
(unsigned long)table_index);
|
||||
obj_desc->reference.value = table_index;
|
||||
|
||||
/* Add the table to the namespace */
|
||||
|
||||
|
|
@ -280,6 +278,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
|
|||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object *ddb_handle;
|
||||
struct acpi_table_header *table;
|
||||
struct acpi_table_desc table_desc;
|
||||
u32 table_index;
|
||||
acpi_status status;
|
||||
|
|
@ -294,9 +293,8 @@ 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)));
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"Load table from Region %p\n", obj_desc));
|
||||
|
||||
/* Region must be system_memory (from ACPI spec) */
|
||||
|
||||
|
|
@ -316,22 +314,17 @@ 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.
|
||||
* Map the table header and get the actual table length. The region
|
||||
* length is not guaranteed to be the same as the table length.
|
||||
*/
|
||||
table_desc.address = obj_desc->region.address;
|
||||
table_desc.length = obj_desc->region.length;
|
||||
table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED;
|
||||
break;
|
||||
table = acpi_os_map_memory(obj_desc->region.address,
|
||||
sizeof(struct acpi_table_header));
|
||||
if (!table) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"Load from Buffer or Field %p %s\n", obj_desc,
|
||||
acpi_ut_get_object_type_name(obj_desc)));
|
||||
|
||||
length = obj_desc->buffer.length;
|
||||
length = table->length;
|
||||
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
|
||||
|
||||
/* Must have at least an ACPI table header */
|
||||
|
||||
|
|
@ -339,38 +332,94 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
|
|||
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
|
||||
}
|
||||
|
||||
/* Validate checksum here. It won't get validated in tb_add_table */
|
||||
/*
|
||||
* The memory region is not guaranteed to remain stable and we must
|
||||
* copy the table to a local buffer. For example, the memory region
|
||||
* is corrupted after suspend on some machines. Dynamically loaded
|
||||
* tables are usually small, so this overhead is minimal.
|
||||
*/
|
||||
|
||||
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);
|
||||
/* Allocate a buffer for the table */
|
||||
|
||||
table_desc.pointer = ACPI_ALLOCATE(length);
|
||||
if (!table_desc.pointer) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Map the entire table and copy it */
|
||||
|
||||
table = acpi_os_map_memory(obj_desc->region.address, length);
|
||||
if (!table) {
|
||||
ACPI_FREE(table_desc.pointer);
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
ACPI_MEMCPY(table_desc.pointer, table, length);
|
||||
acpi_os_unmap_memory(table, length);
|
||||
|
||||
table_desc.address = obj_desc->region.address;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"Load table from Buffer or Field %p\n",
|
||||
obj_desc));
|
||||
|
||||
/* Must have at least an ACPI table header */
|
||||
|
||||
if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) {
|
||||
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
|
||||
}
|
||||
|
||||
/* Get the actual table length from the table header */
|
||||
|
||||
table =
|
||||
ACPI_CAST_PTR(struct acpi_table_header,
|
||||
obj_desc->buffer.pointer);
|
||||
length = table->length;
|
||||
|
||||
/* Table cannot extend beyond the buffer */
|
||||
|
||||
if (length > obj_desc->buffer.length) {
|
||||
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
|
||||
}
|
||||
if (length < sizeof(struct acpi_table_header)) {
|
||||
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to copy the buffer since the original buffer could be
|
||||
* changed or deleted in the future
|
||||
* Copy the table from the buffer because the buffer could be modified
|
||||
* or even 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;
|
||||
ACPI_MEMCPY(table_desc.pointer, table, length);
|
||||
table_desc.address = ACPI_TO_INTEGER(table_desc.pointer);
|
||||
break;
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Install the new table into the local data structures
|
||||
*/
|
||||
/* Validate table checksum (will not get validated in tb_add_table) */
|
||||
|
||||
status = acpi_tb_verify_checksum(table_desc.pointer, length);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_FREE(table_desc.pointer);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Complete the table descriptor */
|
||||
|
||||
table_desc.length = length;
|
||||
table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
|
||||
|
||||
/* Install the new table into the local data structures */
|
||||
|
||||
status = acpi_tb_add_table(&table_desc, &table_index);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto cleanup;
|
||||
|
|
@ -379,7 +428,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
|
|||
/*
|
||||
* Add the table to the namespace.
|
||||
*
|
||||
* Note: We load the table objects relative to the root of the namespace.
|
||||
* Note: Load the table objects relative to the root of the namespace.
|
||||
* This appears to go against the ACPI specification, but we do it for
|
||||
* compatibility with other ACPI implementations.
|
||||
*/
|
||||
|
|
@ -415,7 +464,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
|
|||
cleanup:
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
/* Delete allocated buffer or mapping */
|
||||
/* Delete allocated table buffer */
|
||||
|
||||
acpi_tb_delete_table(&table_desc);
|
||||
}
|
||||
|
|
@ -455,9 +504,9 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
|
|||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Get the table index from the ddb_handle (acpi_size for 64-bit case) */
|
||||
/* Get the table index from the ddb_handle */
|
||||
|
||||
table_index = (u32) (acpi_size) table_desc->reference.object;
|
||||
table_index = table_desc->reference.value;
|
||||
|
||||
/* Invoke table handler if present */
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
|
|||
*
|
||||
* FUNCTION: acpi_ex_convert_to_integer
|
||||
*
|
||||
* PARAMETERS: obj_desc - Object to be converted. Must be an
|
||||
* PARAMETERS: obj_desc - Object to be converted. Must be an
|
||||
* Integer, Buffer, or String
|
||||
* result_desc - Where the new Integer object is returned
|
||||
* Flags - Used for string conversion
|
||||
|
|
@ -103,7 +103,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
|
|||
}
|
||||
|
||||
/*
|
||||
* Convert the buffer/string to an integer. Note that both buffers and
|
||||
* Convert the buffer/string to an integer. Note that both buffers and
|
||||
* strings are treated as raw data - we don't convert ascii to hex for
|
||||
* strings.
|
||||
*
|
||||
|
|
@ -120,7 +120,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
|
|||
|
||||
/*
|
||||
* Convert string to an integer - for most cases, the string must be
|
||||
* hexadecimal as per the ACPI specification. The only exception (as
|
||||
* hexadecimal as per the ACPI specification. The only exception (as
|
||||
* of ACPI 3.0) is that the to_integer() operator allows both decimal
|
||||
* and hexadecimal strings (hex prefixed with "0x").
|
||||
*/
|
||||
|
|
@ -159,6 +159,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
|
|||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* No other types can get here */
|
||||
break;
|
||||
}
|
||||
|
|
@ -185,7 +186,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
|
|||
*
|
||||
* FUNCTION: acpi_ex_convert_to_buffer
|
||||
*
|
||||
* PARAMETERS: obj_desc - Object to be converted. Must be an
|
||||
* PARAMETERS: obj_desc - Object to be converted. Must be an
|
||||
* Integer, Buffer, or String
|
||||
* result_desc - Where the new buffer object is returned
|
||||
*
|
||||
|
|
@ -365,7 +366,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
|
|||
}
|
||||
|
||||
/*
|
||||
* Since leading zeros are supressed, we must check for the case where
|
||||
* Since leading zeros are suppressed, we must check for the case where
|
||||
* the integer equals 0
|
||||
*
|
||||
* Finally, null terminate the string and return the length
|
||||
|
|
@ -383,7 +384,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
|
|||
*
|
||||
* FUNCTION: acpi_ex_convert_to_string
|
||||
*
|
||||
* PARAMETERS: obj_desc - Object to be converted. Must be an
|
||||
* PARAMETERS: obj_desc - Object to be converted. Must be an
|
||||
* Integer, Buffer, or String
|
||||
* result_desc - Where the string object is returned
|
||||
* Type - String flags (base and conversion type)
|
||||
|
|
@ -472,7 +473,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
|
|||
base = 10;
|
||||
|
||||
/*
|
||||
* Calculate the final string length. Individual string values
|
||||
* Calculate the final string length. Individual string values
|
||||
* are variable length (include separator for each)
|
||||
*/
|
||||
for (i = 0; i < obj_desc->buffer.length; i++) {
|
||||
|
|
@ -511,9 +512,14 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
|
|||
/*
|
||||
* Create a new string object and string buffer
|
||||
* (-1 because of extra separator included in string_length from above)
|
||||
* Allow creation of zero-length strings from zero-length buffers.
|
||||
*/
|
||||
if (string_length) {
|
||||
string_length--;
|
||||
}
|
||||
|
||||
return_desc = acpi_ut_create_string_object((acpi_size)
|
||||
(string_length - 1));
|
||||
string_length);
|
||||
if (!return_desc) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
|
@ -536,7 +542,9 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
|
|||
* Null terminate the string
|
||||
* (overwrites final comma/space from above)
|
||||
*/
|
||||
new_buf--;
|
||||
if (obj_desc->buffer.length) {
|
||||
new_buf--;
|
||||
}
|
||||
*new_buf = 0;
|
||||
break;
|
||||
|
||||
|
|
@ -617,7 +625,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
|
|||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
/*
|
||||
* These types require an Integer operand. We can convert
|
||||
* These types require an Integer operand. We can convert
|
||||
* a Buffer or a String to an Integer if necessary.
|
||||
*/
|
||||
status =
|
||||
|
|
@ -627,7 +635,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
|
|||
|
||||
case ACPI_TYPE_STRING:
|
||||
/*
|
||||
* The operand must be a String. We can convert an
|
||||
* The operand must be a String. We can convert an
|
||||
* Integer or Buffer if necessary
|
||||
*/
|
||||
status =
|
||||
|
|
@ -637,7 +645,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
|
|||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
/*
|
||||
* The operand must be a Buffer. We can convert an
|
||||
* The operand must be a Buffer. We can convert an
|
||||
* Integer or String if necessary
|
||||
*/
|
||||
status =
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acparser.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME("exdump")
|
||||
|
|
@ -214,10 +213,11 @@ static struct acpi_exdump_info acpi_ex_dump_index_field[5] = {
|
|||
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"}
|
||||
};
|
||||
|
||||
static struct acpi_exdump_info acpi_ex_dump_reference[7] = {
|
||||
static struct acpi_exdump_info acpi_ex_dump_reference[8] = {
|
||||
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL},
|
||||
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.class), "Class"},
|
||||
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"},
|
||||
{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.offset), "Offset"},
|
||||
{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.value), "Value"},
|
||||
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"},
|
||||
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"},
|
||||
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"},
|
||||
|
|
@ -413,10 +413,10 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
|
|||
|
||||
case ACPI_EXD_REFERENCE:
|
||||
|
||||
acpi_ex_out_string("Opcode",
|
||||
(acpi_ps_get_opcode_info
|
||||
(obj_desc->reference.opcode))->
|
||||
name);
|
||||
acpi_ex_out_string("Class Name",
|
||||
(char *)
|
||||
acpi_ut_get_reference_name
|
||||
(obj_desc));
|
||||
acpi_ex_dump_reference_obj(obj_desc);
|
||||
break;
|
||||
|
||||
|
|
@ -494,40 +494,41 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
|
|||
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
switch (obj_desc->reference.opcode) {
|
||||
case AML_DEBUG_OP:
|
||||
acpi_os_printf("Reference: [%s] ",
|
||||
acpi_ut_get_reference_name(obj_desc));
|
||||
|
||||
acpi_os_printf("Reference: Debug\n");
|
||||
switch (obj_desc->reference.class) {
|
||||
case ACPI_REFCLASS_DEBUG:
|
||||
|
||||
acpi_os_printf("\n");
|
||||
break;
|
||||
|
||||
case AML_INDEX_OP:
|
||||
case ACPI_REFCLASS_INDEX:
|
||||
|
||||
acpi_os_printf("Reference: Index %p\n",
|
||||
obj_desc->reference.object);
|
||||
acpi_os_printf("%p\n", obj_desc->reference.object);
|
||||
break;
|
||||
|
||||
case AML_LOAD_OP:
|
||||
case ACPI_REFCLASS_TABLE:
|
||||
|
||||
acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n",
|
||||
obj_desc->reference.object);
|
||||
acpi_os_printf("Table Index %X\n",
|
||||
obj_desc->reference.value);
|
||||
break;
|
||||
|
||||
case AML_REF_OF_OP:
|
||||
case ACPI_REFCLASS_REFOF:
|
||||
|
||||
acpi_os_printf("Reference: (RefOf) %p [%s]\n",
|
||||
obj_desc->reference.object,
|
||||
acpi_os_printf("%p [%s]\n", obj_desc->reference.object,
|
||||
acpi_ut_get_type_name(((union
|
||||
acpi_operand_object
|
||||
*)obj_desc->
|
||||
*)
|
||||
obj_desc->
|
||||
reference.
|
||||
object)->common.
|
||||
type));
|
||||
break;
|
||||
|
||||
case AML_ARG_OP:
|
||||
case ACPI_REFCLASS_ARG:
|
||||
|
||||
acpi_os_printf("Reference: Arg%d",
|
||||
obj_desc->reference.offset);
|
||||
acpi_os_printf("%X", obj_desc->reference.value);
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
|
||||
|
||||
|
|
@ -542,10 +543,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
|
|||
acpi_os_printf("\n");
|
||||
break;
|
||||
|
||||
case AML_LOCAL_OP:
|
||||
case ACPI_REFCLASS_LOCAL:
|
||||
|
||||
acpi_os_printf("Reference: Local%d",
|
||||
obj_desc->reference.offset);
|
||||
acpi_os_printf("%X", obj_desc->reference.value);
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
|
||||
|
||||
|
|
@ -560,21 +560,16 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
|
|||
acpi_os_printf("\n");
|
||||
break;
|
||||
|
||||
case AML_INT_NAMEPATH_OP:
|
||||
case ACPI_REFCLASS_NAME:
|
||||
|
||||
acpi_os_printf("Reference: Namepath %X [%4.4s]\n",
|
||||
obj_desc->reference.node->name.integer,
|
||||
acpi_os_printf("- [%4.4s]\n",
|
||||
obj_desc->reference.node->name.ascii);
|
||||
break;
|
||||
|
||||
default:
|
||||
default: /* Unknown reference class */
|
||||
|
||||
/* Unknown opcode */
|
||||
|
||||
acpi_os_printf("Unknown Reference opcode=%X\n",
|
||||
obj_desc->reference.opcode);
|
||||
acpi_os_printf("%2.2X\n", obj_desc->reference.class);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -865,8 +860,8 @@ 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);
|
||||
if (obj_desc->reference.class == ACPI_REFCLASS_NAME) {
|
||||
acpi_os_printf(" %p ", obj_desc->reference.node);
|
||||
|
||||
status =
|
||||
acpi_ns_handle_to_pathname(obj_desc->reference.node,
|
||||
|
|
@ -882,14 +877,12 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *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");
|
||||
if (obj_desc->reference.class == ACPI_REFCLASS_TABLE) {
|
||||
acpi_os_printf(" Table Index: %X\n",
|
||||
obj_desc->reference.value);
|
||||
} else {
|
||||
acpi_os_printf(" [%s]\n",
|
||||
acpi_os_printf(" Target: %p [%s]\n",
|
||||
obj_desc->reference.object,
|
||||
acpi_ut_get_type_name(((union
|
||||
acpi_operand_object
|
||||
*)
|
||||
|
|
@ -988,9 +981,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
|
|||
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
acpi_os_printf("[Object Reference] %s",
|
||||
(acpi_ps_get_opcode_info
|
||||
(obj_desc->reference.opcode))->name);
|
||||
acpi_os_printf("[Object Reference] Type [%s] %2.2X",
|
||||
acpi_ut_get_reference_name(obj_desc),
|
||||
obj_desc->reference.class);
|
||||
acpi_ex_dump_reference_obj(obj_desc);
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -86,10 +86,10 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
|
|||
/*
|
||||
* Must be a reference to a Local or Arg
|
||||
*/
|
||||
switch (obj_desc->reference.opcode) {
|
||||
case AML_LOCAL_OP:
|
||||
case AML_ARG_OP:
|
||||
case AML_DEBUG_OP:
|
||||
switch (obj_desc->reference.class) {
|
||||
case ACPI_REFCLASS_LOCAL:
|
||||
case ACPI_REFCLASS_ARG:
|
||||
case ACPI_REFCLASS_DEBUG:
|
||||
|
||||
/* The referenced object is the pseudo-node for the local/arg */
|
||||
|
||||
|
|
@ -98,8 +98,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
|
|||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X",
|
||||
obj_desc->reference.opcode));
|
||||
ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X",
|
||||
obj_desc->reference.class));
|
||||
return_ACPI_STATUS(AE_AML_INTERNAL);
|
||||
}
|
||||
break;
|
||||
|
|
@ -127,7 +127,7 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
|
|||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
reference_obj->reference.opcode = AML_REF_OF_OP;
|
||||
reference_obj->reference.class = ACPI_REFCLASS_REFOF;
|
||||
reference_obj->reference.object = referenced_obj;
|
||||
*return_desc = reference_obj;
|
||||
|
||||
|
|
|
|||
|
|
@ -825,16 +825,16 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
|||
*
|
||||
* Must resolve/dereference the local/arg reference first
|
||||
*/
|
||||
switch (operand[0]->reference.opcode) {
|
||||
case AML_LOCAL_OP:
|
||||
case AML_ARG_OP:
|
||||
switch (operand[0]->reference.class) {
|
||||
case ACPI_REFCLASS_LOCAL:
|
||||
case ACPI_REFCLASS_ARG:
|
||||
|
||||
/* Set Operand[0] to the value of the local/arg */
|
||||
|
||||
status =
|
||||
acpi_ds_method_data_get_value
|
||||
(operand[0]->reference.opcode,
|
||||
operand[0]->reference.offset,
|
||||
(operand[0]->reference.class,
|
||||
operand[0]->reference.value,
|
||||
walk_state, &temp_desc);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto cleanup;
|
||||
|
|
@ -848,7 +848,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
|||
operand[0] = temp_desc;
|
||||
break;
|
||||
|
||||
case AML_REF_OF_OP:
|
||||
case ACPI_REFCLASS_REFOF:
|
||||
|
||||
/* Get the object to which the reference refers */
|
||||
|
||||
|
|
@ -928,8 +928,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
|||
* This must be a reference object produced by either the
|
||||
* Index() or ref_of() operator
|
||||
*/
|
||||
switch (operand[0]->reference.opcode) {
|
||||
case AML_INDEX_OP:
|
||||
switch (operand[0]->reference.class) {
|
||||
case ACPI_REFCLASS_INDEX:
|
||||
|
||||
/*
|
||||
* The target type for the Index operator must be
|
||||
|
|
@ -965,7 +965,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
|||
return_desc->integer.value =
|
||||
temp_desc->buffer.
|
||||
pointer[operand[0]->reference.
|
||||
offset];
|
||||
value];
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
|
@ -985,7 +985,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
|||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Unknown Index TargetType %X in obj %p",
|
||||
"Unknown Index TargetType %X in reference object %p",
|
||||
operand[0]->reference.
|
||||
target_type, operand[0]));
|
||||
status = AE_AML_OPERAND_TYPE;
|
||||
|
|
@ -993,7 +993,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
|||
}
|
||||
break;
|
||||
|
||||
case AML_REF_OF_OP:
|
||||
case ACPI_REFCLASS_REFOF:
|
||||
|
||||
return_desc = operand[0]->reference.object;
|
||||
|
||||
|
|
@ -1013,9 +1013,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
|||
|
||||
default:
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Unknown opcode in reference(%p) - %X",
|
||||
"Unknown class in reference(%p) - %2.2X",
|
||||
operand[0],
|
||||
operand[0]->reference.opcode));
|
||||
operand[0]->reference.class));
|
||||
|
||||
status = AE_TYPE;
|
||||
goto cleanup;
|
||||
|
|
|
|||
|
|
@ -391,8 +391,8 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
|
|||
/* Initialize the Index reference object */
|
||||
|
||||
index = operand[1]->integer.value;
|
||||
return_desc->reference.offset = (u32) index;
|
||||
return_desc->reference.opcode = AML_INDEX_OP;
|
||||
return_desc->reference.value = (u32) index;
|
||||
return_desc->reference.class = ACPI_REFCLASS_INDEX;
|
||||
|
||||
/*
|
||||
* At this point, the Source operand is a String, Buffer, or Package.
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@
|
|||
#include <acpi/acdispat.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acparser.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME("exresnte")
|
||||
|
|
@ -238,10 +236,10 @@ 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: /* This is a ddb_handle */
|
||||
case AML_REF_OF_OP:
|
||||
case AML_INDEX_OP:
|
||||
switch (source_desc->reference.class) {
|
||||
case ACPI_REFCLASS_TABLE: /* This is a ddb_handle */
|
||||
case ACPI_REFCLASS_REFOF:
|
||||
case ACPI_REFCLASS_INDEX:
|
||||
|
||||
/* Return an additional reference to the object */
|
||||
|
||||
|
|
@ -253,10 +251,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
|
|||
/* No named references are allowed here */
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Unsupported Reference opcode %X (%s)",
|
||||
source_desc->reference.opcode,
|
||||
acpi_ps_get_opcode_name(source_desc->
|
||||
reference.opcode)));
|
||||
"Unsupported Reference type %X",
|
||||
source_desc->reference.class));
|
||||
|
||||
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@
|
|||
#include <acpi/acdispat.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acparser.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME("exresolv")
|
||||
|
|
@ -141,7 +140,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
|
|||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *stack_desc;
|
||||
union acpi_operand_object *obj_desc = NULL;
|
||||
u16 opcode;
|
||||
u8 ref_type;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
|
||||
|
||||
|
|
@ -152,19 +151,19 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
|
|||
switch (ACPI_GET_OBJECT_TYPE(stack_desc)) {
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
opcode = stack_desc->reference.opcode;
|
||||
ref_type = stack_desc->reference.class;
|
||||
|
||||
switch (opcode) {
|
||||
case AML_LOCAL_OP:
|
||||
case AML_ARG_OP:
|
||||
switch (ref_type) {
|
||||
case ACPI_REFCLASS_LOCAL:
|
||||
case ACPI_REFCLASS_ARG:
|
||||
|
||||
/*
|
||||
* Get the local from the method's state info
|
||||
* Note: this increments the local's object reference count
|
||||
*/
|
||||
status = acpi_ds_method_data_get_value(opcode,
|
||||
status = acpi_ds_method_data_get_value(ref_type,
|
||||
stack_desc->
|
||||
reference.offset,
|
||||
reference.value,
|
||||
walk_state,
|
||||
&obj_desc);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
|
@ -173,7 +172,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
|
|||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"[Arg/Local %X] ValueObj is %p\n",
|
||||
stack_desc->reference.offset,
|
||||
stack_desc->reference.value,
|
||||
obj_desc));
|
||||
|
||||
/*
|
||||
|
|
@ -184,7 +183,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
|
|||
*stack_ptr = obj_desc;
|
||||
break;
|
||||
|
||||
case AML_INDEX_OP:
|
||||
case ACPI_REFCLASS_INDEX:
|
||||
|
||||
switch (stack_desc->reference.target_type) {
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
|
|
@ -239,15 +238,15 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
|
|||
}
|
||||
break;
|
||||
|
||||
case AML_REF_OF_OP:
|
||||
case AML_DEBUG_OP:
|
||||
case AML_LOAD_OP:
|
||||
case ACPI_REFCLASS_REFOF:
|
||||
case ACPI_REFCLASS_DEBUG:
|
||||
case ACPI_REFCLASS_TABLE:
|
||||
|
||||
/* Just leave the object as-is, do not dereference */
|
||||
|
||||
break;
|
||||
|
||||
case AML_INT_NAMEPATH_OP: /* Reference to a named object */
|
||||
case ACPI_REFCLASS_NAME: /* Reference to a named object */
|
||||
|
||||
/* Dereference the name */
|
||||
|
||||
|
|
@ -273,8 +272,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
|
|||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Unknown Reference opcode %X (%s) in %p",
|
||||
opcode, acpi_ps_get_opcode_name(opcode),
|
||||
"Unknown Reference type %X in %p", ref_type,
|
||||
stack_desc));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
|
|
@ -388,13 +386,13 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
|||
* traversing the list of possibly many nested references.
|
||||
*/
|
||||
while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
switch (obj_desc->reference.opcode) {
|
||||
case AML_REF_OF_OP:
|
||||
case AML_INT_NAMEPATH_OP:
|
||||
switch (obj_desc->reference.class) {
|
||||
case ACPI_REFCLASS_REFOF:
|
||||
case ACPI_REFCLASS_NAME:
|
||||
|
||||
/* Dereference the reference pointer */
|
||||
|
||||
if (obj_desc->reference.opcode == AML_REF_OF_OP) {
|
||||
if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) {
|
||||
node = obj_desc->reference.object;
|
||||
} else { /* AML_INT_NAMEPATH_OP */
|
||||
|
||||
|
|
@ -429,7 +427,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
|||
}
|
||||
break;
|
||||
|
||||
case AML_INDEX_OP:
|
||||
case ACPI_REFCLASS_INDEX:
|
||||
|
||||
/* Get the type of this reference (index into another object) */
|
||||
|
||||
|
|
@ -455,22 +453,22 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
|||
}
|
||||
break;
|
||||
|
||||
case AML_LOAD_OP:
|
||||
case ACPI_REFCLASS_TABLE:
|
||||
|
||||
type = ACPI_TYPE_DDB_HANDLE;
|
||||
goto exit;
|
||||
|
||||
case AML_LOCAL_OP:
|
||||
case AML_ARG_OP:
|
||||
case ACPI_REFCLASS_LOCAL:
|
||||
case ACPI_REFCLASS_ARG:
|
||||
|
||||
if (return_desc) {
|
||||
status =
|
||||
acpi_ds_method_data_get_value(obj_desc->
|
||||
reference.
|
||||
opcode,
|
||||
class,
|
||||
obj_desc->
|
||||
reference.
|
||||
offset,
|
||||
value,
|
||||
walk_state,
|
||||
&obj_desc);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
|
@ -481,10 +479,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
|||
status =
|
||||
acpi_ds_method_data_get_node(obj_desc->
|
||||
reference.
|
||||
opcode,
|
||||
class,
|
||||
obj_desc->
|
||||
reference.
|
||||
offset,
|
||||
value,
|
||||
walk_state,
|
||||
&node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
|
@ -499,7 +497,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
|||
}
|
||||
break;
|
||||
|
||||
case AML_DEBUG_OP:
|
||||
case ACPI_REFCLASS_DEBUG:
|
||||
|
||||
/* The Debug Object is of type "DebugObject" */
|
||||
|
||||
|
|
@ -509,8 +507,8 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
|||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Unknown Reference subtype %X",
|
||||
obj_desc->reference.opcode));
|
||||
"Unknown Reference Class %2.2X",
|
||||
obj_desc->reference.class));
|
||||
return_ACPI_STATUS(AE_AML_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,41 +225,36 @@ acpi_ex_resolve_operands(u16 opcode,
|
|||
|
||||
if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
|
||||
/* Decode the Reference */
|
||||
/* Validate the Reference */
|
||||
|
||||
op_info = acpi_ps_get_opcode_info(opcode);
|
||||
if (op_info->class == AML_CLASS_UNKNOWN) {
|
||||
return_ACPI_STATUS(AE_AML_BAD_OPCODE);
|
||||
}
|
||||
switch (obj_desc->reference.class) {
|
||||
case ACPI_REFCLASS_DEBUG:
|
||||
|
||||
switch (obj_desc->reference.opcode) {
|
||||
case AML_DEBUG_OP:
|
||||
target_op = AML_DEBUG_OP;
|
||||
|
||||
/*lint -fallthrough */
|
||||
|
||||
case AML_INDEX_OP:
|
||||
case AML_REF_OF_OP:
|
||||
case AML_ARG_OP:
|
||||
case AML_LOCAL_OP:
|
||||
case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
|
||||
case AML_INT_NAMEPATH_OP: /* Reference to a named object */
|
||||
case ACPI_REFCLASS_ARG:
|
||||
case ACPI_REFCLASS_LOCAL:
|
||||
case ACPI_REFCLASS_INDEX:
|
||||
case ACPI_REFCLASS_REFOF:
|
||||
case ACPI_REFCLASS_TABLE: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
|
||||
case ACPI_REFCLASS_NAME: /* Reference to a named object */
|
||||
|
||||
ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT
|
||||
((ACPI_DB_EXEC,
|
||||
"Operand is a Reference, RefOpcode [%s]\n",
|
||||
(acpi_ps_get_opcode_info
|
||||
(obj_desc->
|
||||
reference.
|
||||
opcode))->
|
||||
name)));
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"Operand is a Reference, Class [%s] %2.2X\n",
|
||||
acpi_ut_get_reference_name
|
||||
(obj_desc),
|
||||
obj_desc->reference.
|
||||
class));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Operand is a Reference, Unknown Reference Opcode: %X",
|
||||
obj_desc->reference.
|
||||
opcode));
|
||||
"Unknown Reference Class %2.2X in %p",
|
||||
obj_desc->reference.class,
|
||||
obj_desc));
|
||||
|
||||
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
|
@ -270,8 +265,7 @@ acpi_ex_resolve_operands(u16 opcode,
|
|||
|
||||
/* Invalid descriptor */
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid descriptor %p [%s]",
|
||||
ACPI_ERROR((AE_INFO, "Invalid descriptor %p [%s]",
|
||||
obj_desc,
|
||||
acpi_ut_get_descriptor_name(obj_desc)));
|
||||
|
||||
|
|
@ -343,7 +337,7 @@ acpi_ex_resolve_operands(u16 opcode,
|
|||
if ((opcode == AML_STORE_OP) &&
|
||||
(ACPI_GET_OBJECT_TYPE(*stack_ptr) ==
|
||||
ACPI_TYPE_LOCAL_REFERENCE)
|
||||
&& ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) {
|
||||
&& ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) {
|
||||
goto next_operand;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@
|
|||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acparser.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME("exstore")
|
||||
|
|
@ -179,22 +178,26 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
|
|||
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
if (source_desc->reference.opcode == AML_INDEX_OP) {
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
|
||||
"[%s, 0x%X]\n",
|
||||
acpi_ps_get_opcode_name
|
||||
(source_desc->reference.opcode),
|
||||
source_desc->reference.offset));
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]",
|
||||
acpi_ps_get_opcode_name
|
||||
(source_desc->reference.opcode)));
|
||||
}
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s] ",
|
||||
acpi_ut_get_reference_name(source_desc)));
|
||||
|
||||
/* Decode the reference */
|
||||
|
||||
switch (source_desc->reference.class) {
|
||||
case ACPI_REFCLASS_INDEX:
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%X\n",
|
||||
source_desc->reference.value));
|
||||
break;
|
||||
|
||||
case ACPI_REFCLASS_TABLE:
|
||||
|
||||
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));
|
||||
"Table Index 0x%X\n",
|
||||
source_desc->reference.value));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -347,15 +350,15 @@ acpi_ex_store(union acpi_operand_object *source_desc,
|
|||
}
|
||||
|
||||
/*
|
||||
* Examine the Reference opcode. These cases are handled:
|
||||
* Examine the Reference class. These cases are handled:
|
||||
*
|
||||
* 1) Store to Name (Change the object associated with a name)
|
||||
* 2) Store to an indexed area of a Buffer or Package
|
||||
* 3) Store to a Method Local or Arg
|
||||
* 4) Store to the debug object
|
||||
*/
|
||||
switch (ref_desc->reference.opcode) {
|
||||
case AML_REF_OF_OP:
|
||||
switch (ref_desc->reference.class) {
|
||||
case ACPI_REFCLASS_REFOF:
|
||||
|
||||
/* Storing an object into a Name "container" */
|
||||
|
||||
|
|
@ -365,7 +368,7 @@ acpi_ex_store(union acpi_operand_object *source_desc,
|
|||
ACPI_IMPLICIT_CONVERSION);
|
||||
break;
|
||||
|
||||
case AML_INDEX_OP:
|
||||
case ACPI_REFCLASS_INDEX:
|
||||
|
||||
/* Storing to an Index (pointer into a packager or buffer) */
|
||||
|
||||
|
|
@ -374,18 +377,18 @@ acpi_ex_store(union acpi_operand_object *source_desc,
|
|||
walk_state);
|
||||
break;
|
||||
|
||||
case AML_LOCAL_OP:
|
||||
case AML_ARG_OP:
|
||||
case ACPI_REFCLASS_LOCAL:
|
||||
case ACPI_REFCLASS_ARG:
|
||||
|
||||
/* Store to a method local/arg */
|
||||
|
||||
status =
|
||||
acpi_ds_store_object_to_local(ref_desc->reference.opcode,
|
||||
ref_desc->reference.offset,
|
||||
acpi_ds_store_object_to_local(ref_desc->reference.class,
|
||||
ref_desc->reference.value,
|
||||
source_desc, walk_state);
|
||||
break;
|
||||
|
||||
case AML_DEBUG_OP:
|
||||
case ACPI_REFCLASS_DEBUG:
|
||||
|
||||
/*
|
||||
* Storing to the Debug object causes the value stored to be
|
||||
|
|
@ -401,9 +404,9 @@ acpi_ex_store(union acpi_operand_object *source_desc,
|
|||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X",
|
||||
ref_desc->reference.opcode));
|
||||
ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR);
|
||||
ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X",
|
||||
ref_desc->reference.class));
|
||||
ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO);
|
||||
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
|
|
@ -458,7 +461,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
|
|||
|
||||
if (ACPI_GET_OBJECT_TYPE(source_desc) ==
|
||||
ACPI_TYPE_LOCAL_REFERENCE
|
||||
&& source_desc->reference.opcode == AML_LOAD_OP) {
|
||||
&& source_desc->reference.class == ACPI_REFCLASS_TABLE) {
|
||||
|
||||
/* This is a DDBHandle, just add a reference to it */
|
||||
|
||||
|
|
@ -553,7 +556,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
|
|||
|
||||
/* Store the source value into the target buffer byte */
|
||||
|
||||
obj_desc->buffer.pointer[index_desc->reference.offset] = value;
|
||||
obj_desc->buffer.pointer[index_desc->reference.value] = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -121,7 +121,8 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
|
|||
(ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) &&
|
||||
!((ACPI_GET_OBJECT_TYPE(source_desc) ==
|
||||
ACPI_TYPE_LOCAL_REFERENCE)
|
||||
&& (source_desc->reference.opcode == AML_LOAD_OP))) {
|
||||
&& (source_desc->reference.class ==
|
||||
ACPI_REFCLASS_TABLE))) {
|
||||
|
||||
/* Conversion successful but still not a valid type */
|
||||
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ static int acpi_fan_add(struct acpi_device *device)
|
|||
|
||||
dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id);
|
||||
|
||||
acpi_driver_data(device) = cdev;
|
||||
device->driver_data = cdev;
|
||||
result = sysfs_create_link(&device->dev.kobj,
|
||||
&cdev->device.kobj,
|
||||
"thermal_cooling");
|
||||
|
|
@ -327,8 +327,8 @@ static int acpi_fan_resume(struct acpi_device *device)
|
|||
|
||||
result = acpi_bus_get_power(device->handle, &power_state);
|
||||
if (result) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Error reading fan power state\n"));
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error reading fan power state\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,19 +78,17 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
|
|||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Set the vector */
|
||||
/*
|
||||
* According to the ACPI specification 2.0c and later, the 64-bit
|
||||
* waking vector should be cleared and the 32-bit waking vector should
|
||||
* be used, unless we want the wake-up code to be called by the BIOS in
|
||||
* Protected Mode. Some systems (for example HP dv5-1004nr) are known
|
||||
* to fail to resume if the 64-bit vector is used.
|
||||
*/
|
||||
if (facs->version >= 1)
|
||||
facs->xfirmware_waking_vector = 0;
|
||||
|
||||
if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
|
||||
/*
|
||||
* ACPI 1.0 FACS or short table or optional X_ field is zero
|
||||
*/
|
||||
facs->firmware_waking_vector = (u32) physical_address;
|
||||
} else {
|
||||
/*
|
||||
* ACPI 2.0 FACS with valid X_ field
|
||||
*/
|
||||
facs->xfirmware_waking_vector = physical_address;
|
||||
}
|
||||
facs->firmware_waking_vector = (u32)physical_address;
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
|
@ -134,20 +132,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
|
|||
}
|
||||
|
||||
/* Get the vector */
|
||||
|
||||
if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
|
||||
/*
|
||||
* ACPI 1.0 FACS or short table or optional X_ field is zero
|
||||
*/
|
||||
*physical_address =
|
||||
(acpi_physical_address) facs->firmware_waking_vector;
|
||||
} else {
|
||||
/*
|
||||
* ACPI 2.0 FACS with valid X_ field
|
||||
*/
|
||||
*physical_address =
|
||||
(acpi_physical_address) facs->xfirmware_waking_vector;
|
||||
}
|
||||
*physical_address = (acpi_physical_address)facs->firmware_waking_vector;
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
|
@ -627,6 +612,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
|
|||
}
|
||||
/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
|
||||
|
||||
/*
|
||||
* Some BIOSes assume that WAK_STS will be cleared on resume and use
|
||||
* it to determine whether the system is rebooting or resuming. Clear
|
||||
* it for compatibility.
|
||||
*/
|
||||
acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1);
|
||||
|
||||
acpi_gbl_system_awake_and_running = TRUE;
|
||||
|
||||
/* Enable power button */
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \
|
||||
nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
|
||||
nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
|
||||
nsparse.o
|
||||
nsparse.o nspredef.o
|
||||
|
||||
obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acparser.h>
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("nsdump")
|
||||
|
|
@ -334,9 +333,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
|
|||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
acpi_os_printf("[%s]\n",
|
||||
acpi_ps_get_opcode_name(obj_desc->
|
||||
reference.
|
||||
opcode));
|
||||
acpi_ut_get_reference_name(obj_desc));
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ ACPI_MODULE_NAME("nseval")
|
|||
acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_namespace_node *node;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_evaluate);
|
||||
|
||||
|
|
@ -117,6 +118,8 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
|
|||
info->resolved_node,
|
||||
acpi_ns_get_attached_object(info->resolved_node)));
|
||||
|
||||
node = info->resolved_node;
|
||||
|
||||
/*
|
||||
* Two major cases here:
|
||||
*
|
||||
|
|
@ -148,21 +151,22 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
|
|||
info->param_count++;
|
||||
}
|
||||
|
||||
/* Error if too few arguments were passed in */
|
||||
/*
|
||||
* Warning if too few or too many arguments have been passed by the
|
||||
* caller. We don't want to abort here with an error because an
|
||||
* incorrect number of arguments may not cause the method to fail.
|
||||
* However, the method will fail if there are too few arguments passed
|
||||
* and the method attempts to use one of the missing ones.
|
||||
*/
|
||||
|
||||
if (info->param_count < info->obj_desc->method.param_count) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Insufficient arguments - "
|
||||
"method [%4.4s] needs %d, found %d",
|
||||
acpi_ut_get_node_name(info->resolved_node),
|
||||
info->obj_desc->method.param_count,
|
||||
info->param_count));
|
||||
return_ACPI_STATUS(AE_MISSING_ARGUMENTS);
|
||||
}
|
||||
|
||||
/* Just a warning if too many arguments */
|
||||
|
||||
else if (info->param_count >
|
||||
} else if (info->param_count >
|
||||
info->obj_desc->method.param_count) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Excess arguments - "
|
||||
|
|
@ -195,7 +199,28 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
|
|||
} else {
|
||||
/*
|
||||
* 2) Object is not a method, return its current value
|
||||
*
|
||||
* Disallow certain object types. For these, "evaluation" is undefined.
|
||||
*/
|
||||
switch (info->resolved_node->type) {
|
||||
case ACPI_TYPE_DEVICE:
|
||||
case ACPI_TYPE_EVENT:
|
||||
case ACPI_TYPE_MUTEX:
|
||||
case ACPI_TYPE_REGION:
|
||||
case ACPI_TYPE_THERMAL:
|
||||
case ACPI_TYPE_LOCAL_SCOPE:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"[%4.4s] Evaluation of object type [%s] is not supported",
|
||||
info->resolved_node->name.ascii,
|
||||
acpi_ut_get_type_name(info->resolved_node->
|
||||
type)));
|
||||
|
||||
return_ACPI_STATUS(AE_TYPE);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Objects require additional resolution steps (e.g., the Node may be
|
||||
|
|
@ -239,9 +264,35 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if there is a return value that must be dealt with
|
||||
*/
|
||||
/* Validation of return values for ACPI-predefined methods and objects */
|
||||
|
||||
if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) {
|
||||
/*
|
||||
* If this is the first evaluation, check the return value. This
|
||||
* ensures that any warnings will only be emitted during the very
|
||||
* first evaluation of the object.
|
||||
*/
|
||||
if (!(node->flags & ANOBJ_EVALUATED)) {
|
||||
/*
|
||||
* Check for a predefined ACPI name. If found, validate the
|
||||
* returned object.
|
||||
*
|
||||
* Note: Ignore return status for now, emit warnings if there are
|
||||
* problems with the returned object. May change later to abort
|
||||
* the method on invalid return object.
|
||||
*/
|
||||
(void)acpi_ns_check_predefined_names(node,
|
||||
info->
|
||||
return_object);
|
||||
}
|
||||
|
||||
/* Mark the node as having been evaluated */
|
||||
|
||||
node->flags |= ANOBJ_EVALUATED;
|
||||
}
|
||||
|
||||
/* Check if there is a return value that must be dealt with */
|
||||
|
||||
if (status == AE_CTRL_RETURN_VALUE) {
|
||||
|
||||
/* If caller does not want the return value, delete it */
|
||||
|
|
|
|||
|
|
@ -115,7 +115,6 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
|
|||
return (AE_OK);
|
||||
}
|
||||
|
||||
#ifdef ACPI_DEBUG_OUTPUT
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_get_external_pathname
|
||||
|
|
@ -142,7 +141,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
|
|||
|
||||
size = acpi_ns_get_pathname_length(node);
|
||||
if (!size) {
|
||||
return (NULL);
|
||||
return_PTR(NULL);
|
||||
}
|
||||
|
||||
/* Allocate a buffer to be returned to caller */
|
||||
|
|
@ -157,12 +156,12 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
|
|||
|
||||
status = acpi_ns_build_external_path(node, size, name_buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (NULL);
|
||||
ACPI_FREE(name_buffer);
|
||||
return_PTR(NULL);
|
||||
}
|
||||
|
||||
return_PTR(name_buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
|
|
|
|||
900
drivers/acpi/namespace/nspredef.c
Normal file
900
drivers/acpi/namespace/nspredef.c
Normal file
|
|
@ -0,0 +1,900 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Module Name: nspredef - Validation of ACPI predefined methods and objects
|
||||
* $Revision: 1.1 $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2008, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acpredef.h>
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("nspredef")
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* This module validates predefined ACPI objects that appear in the namespace,
|
||||
* at the time they are evaluated (via acpi_evaluate_object). The purpose of this
|
||||
* validation is to detect problems with BIOS-exposed predefined ACPI objects
|
||||
* before the results are returned to the ACPI-related drivers.
|
||||
*
|
||||
* There are several areas that are validated:
|
||||
*
|
||||
* 1) The number of input arguments as defined by the method/object in the
|
||||
* ASL is validated against the ACPI specification.
|
||||
* 2) The type of the return object (if any) is validated against the ACPI
|
||||
* specification.
|
||||
* 3) For returned package objects, the count of package elements is
|
||||
* validated, as well as the type of each package element. Nested
|
||||
* packages are supported.
|
||||
*
|
||||
* For any problems found, a warning message is issued.
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Local prototypes */
|
||||
static acpi_status
|
||||
acpi_ns_check_package(char *pathname,
|
||||
union acpi_operand_object *return_object,
|
||||
const union acpi_predefined_info *predefined);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_check_package_elements(char *pathname,
|
||||
union acpi_operand_object **elements,
|
||||
u8 type1, u32 count1, u8 type2, u32 count2);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_check_object_type(char *pathname,
|
||||
union acpi_operand_object *return_object,
|
||||
u32 expected_btypes, u32 package_index);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_check_reference(char *pathname,
|
||||
union acpi_operand_object *return_object);
|
||||
|
||||
/*
|
||||
* Names for the types that can be returned by the predefined objects.
|
||||
* Used for warning messages. Must be in the same order as the ACPI_RTYPEs
|
||||
*/
|
||||
static const char *acpi_rtype_names[] = {
|
||||
"/Integer",
|
||||
"/String",
|
||||
"/Buffer",
|
||||
"/Package",
|
||||
"/Reference",
|
||||
};
|
||||
|
||||
#define ACPI_NOT_PACKAGE ACPI_UINT32_MAX
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_predefined_names
|
||||
*
|
||||
* PARAMETERS: Node - Namespace node for the method/object
|
||||
* return_object - Object returned from the evaluation of this
|
||||
* method/object
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Check an ACPI name for a match in the predefined name list.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
||||
union acpi_operand_object *return_object)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
const union acpi_predefined_info *predefined;
|
||||
char *pathname;
|
||||
|
||||
/* Match the name for this method/object against the predefined list */
|
||||
|
||||
predefined = acpi_ns_check_for_predefined_name(node);
|
||||
if (!predefined) {
|
||||
|
||||
/* Name was not one of the predefined names */
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/* Get the full pathname to the object, for use in error messages */
|
||||
|
||||
pathname = acpi_ns_get_external_pathname(node);
|
||||
if (!pathname) {
|
||||
pathname = ACPI_CAST_PTR(char, predefined->info.name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the parameter count for this method is in accordance
|
||||
* with the ACPI specification.
|
||||
*/
|
||||
acpi_ns_check_parameter_count(pathname, node, predefined);
|
||||
|
||||
/*
|
||||
* If there is no return value, check if we require a return value for
|
||||
* this predefined name. Either one return value is expected, or none,
|
||||
* for both methods and other objects.
|
||||
*
|
||||
* Exit now if there is no return object. Warning if one was expected.
|
||||
*/
|
||||
if (!return_object) {
|
||||
if ((predefined->info.expected_btypes) &&
|
||||
(!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"%s: Missing expected return value",
|
||||
pathname));
|
||||
|
||||
status = AE_AML_NO_RETURN_VALUE;
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a return value, but if one wasn't expected, just exit, this is
|
||||
* not a problem
|
||||
*
|
||||
* For example, if "Implicit return value" is enabled, methods will
|
||||
* always return a value
|
||||
*/
|
||||
if (!predefined->info.expected_btypes) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the type of the return object is what is expected for
|
||||
* this predefined name
|
||||
*/
|
||||
status = acpi_ns_check_object_type(pathname, return_object,
|
||||
predefined->info.expected_btypes,
|
||||
ACPI_NOT_PACKAGE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* For returned Package objects, check the type of all sub-objects */
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) {
|
||||
status =
|
||||
acpi_ns_check_package(pathname, return_object, predefined);
|
||||
}
|
||||
|
||||
exit:
|
||||
if (pathname) {
|
||||
ACPI_FREE(pathname);
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_parameter_count
|
||||
*
|
||||
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
|
||||
* Node - Namespace node for the method/object
|
||||
* Predefined - Pointer to entry in predefined name table
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a
|
||||
* predefined name is what is expected (i.e., what is defined in
|
||||
* the ACPI specification for this predefined name.)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ns_check_parameter_count(char *pathname,
|
||||
struct acpi_namespace_node *node,
|
||||
const union acpi_predefined_info *predefined)
|
||||
{
|
||||
u32 param_count;
|
||||
u32 required_params_current;
|
||||
u32 required_params_old;
|
||||
|
||||
/*
|
||||
* Check that the ASL-defined parameter count is what is expected for
|
||||
* this predefined name.
|
||||
*
|
||||
* Methods have 0-7 parameters. All other types have zero.
|
||||
*/
|
||||
param_count = 0;
|
||||
if (node->type == ACPI_TYPE_METHOD) {
|
||||
param_count = node->object->method.param_count;
|
||||
}
|
||||
|
||||
/* Validate parameter count - allow two different legal counts (_SCP) */
|
||||
|
||||
required_params_current = predefined->info.param_count & 0x0F;
|
||||
required_params_old = predefined->info.param_count >> 4;
|
||||
|
||||
if ((param_count != required_params_current) &&
|
||||
(param_count != required_params_old)) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s: Parameter count mismatch - ASL declared %d, expected %d",
|
||||
pathname, param_count, required_params_current));
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_for_predefined_name
|
||||
*
|
||||
* PARAMETERS: Node - Namespace node for the method/object
|
||||
*
|
||||
* RETURN: Pointer to entry in predefined table. NULL indicates not found.
|
||||
*
|
||||
* DESCRIPTION: Check an object name against the predefined object list.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
|
||||
acpi_namespace_node
|
||||
*node)
|
||||
{
|
||||
const union acpi_predefined_info *this_name;
|
||||
|
||||
/* Quick check for a predefined name, first character must be underscore */
|
||||
|
||||
if (node->name.ascii[0] != '_') {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Search info table for a predefined method/object name */
|
||||
|
||||
this_name = predefined_names;
|
||||
while (this_name->info.name[0]) {
|
||||
if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) {
|
||||
|
||||
/* Return pointer to this table entry */
|
||||
|
||||
return (this_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip next entry in the table if this name returns a Package
|
||||
* (next entry contains the package info)
|
||||
*/
|
||||
if (this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) {
|
||||
this_name++;
|
||||
}
|
||||
|
||||
this_name++;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_package
|
||||
*
|
||||
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
|
||||
* return_object - Object returned from the evaluation of a
|
||||
* method or object
|
||||
* Predefined - Pointer to entry in predefined name table
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Check a returned package object for the correct count and
|
||||
* correct type of all sub-objects.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_check_package(char *pathname,
|
||||
union acpi_operand_object *return_object,
|
||||
const union acpi_predefined_info *predefined)
|
||||
{
|
||||
const union acpi_predefined_info *package;
|
||||
union acpi_operand_object *sub_package;
|
||||
union acpi_operand_object **elements;
|
||||
union acpi_operand_object **sub_elements;
|
||||
acpi_status status;
|
||||
u32 expected_count;
|
||||
u32 count;
|
||||
u32 i;
|
||||
u32 j;
|
||||
|
||||
ACPI_FUNCTION_NAME(ns_check_package);
|
||||
|
||||
/* The package info for this name is in the next table entry */
|
||||
|
||||
package = predefined + 1;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
|
||||
"%s Validating return Package of Type %X, Count %X\n",
|
||||
pathname, package->ret_info.type,
|
||||
return_object->package.count));
|
||||
|
||||
/* Extract package count and elements array */
|
||||
|
||||
elements = return_object->package.elements;
|
||||
count = return_object->package.count;
|
||||
|
||||
/* The package must have at least one element, else invalid */
|
||||
|
||||
if (!count) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s: Return Package has no elements (empty)",
|
||||
pathname));
|
||||
|
||||
return (AE_AML_OPERAND_VALUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the type of the expected package contents
|
||||
*
|
||||
* PTYPE1 packages contain no subpackages
|
||||
* PTYPE2 packages contain sub-packages
|
||||
*/
|
||||
switch (package->ret_info.type) {
|
||||
case ACPI_PTYPE1_FIXED:
|
||||
|
||||
/*
|
||||
* The package count is fixed and there are no sub-packages
|
||||
*
|
||||
* If package is too small, exit.
|
||||
* If package is larger than expected, issue warning but continue
|
||||
*/
|
||||
expected_count =
|
||||
package->ret_info.count1 + package->ret_info.count2;
|
||||
if (count < expected_count) {
|
||||
goto package_too_small;
|
||||
} else if (count > expected_count) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s: Return Package is larger than needed - "
|
||||
"found %u, expected %u", pathname, count,
|
||||
expected_count));
|
||||
}
|
||||
|
||||
/* Validate all elements of the returned package */
|
||||
|
||||
status = acpi_ns_check_package_elements(pathname, elements,
|
||||
package->ret_info.
|
||||
object_type1,
|
||||
package->ret_info.
|
||||
count1,
|
||||
package->ret_info.
|
||||
object_type2,
|
||||
package->ret_info.
|
||||
count2);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_PTYPE1_VAR:
|
||||
|
||||
/*
|
||||
* The package count is variable, there are no sub-packages, and all
|
||||
* elements must be of the same type
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
status = acpi_ns_check_object_type(pathname, *elements,
|
||||
package->ret_info.
|
||||
object_type1, i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
elements++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_PTYPE1_OPTION:
|
||||
|
||||
/*
|
||||
* The package count is variable, there are no sub-packages. There are
|
||||
* a fixed number of required elements, and a variable number of
|
||||
* optional elements.
|
||||
*
|
||||
* Check if package is at least as large as the minimum required
|
||||
*/
|
||||
expected_count = package->ret_info3.count;
|
||||
if (count < expected_count) {
|
||||
goto package_too_small;
|
||||
}
|
||||
|
||||
/* Variable number of sub-objects */
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (i < package->ret_info3.count) {
|
||||
|
||||
/* These are the required package elements (0, 1, or 2) */
|
||||
|
||||
status =
|
||||
acpi_ns_check_object_type(pathname,
|
||||
*elements,
|
||||
package->
|
||||
ret_info3.
|
||||
object_type[i],
|
||||
i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
} else {
|
||||
/* These are the optional package elements */
|
||||
|
||||
status =
|
||||
acpi_ns_check_object_type(pathname,
|
||||
*elements,
|
||||
package->
|
||||
ret_info3.
|
||||
tail_object_type,
|
||||
i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
}
|
||||
elements++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_PTYPE2_PKG_COUNT:
|
||||
|
||||
/* First element is the (Integer) count of sub-packages to follow */
|
||||
|
||||
status = acpi_ns_check_object_type(pathname, *elements,
|
||||
ACPI_RTYPE_INTEGER, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Count cannot be larger than the parent package length, but allow it
|
||||
* to be smaller. The >= accounts for the Integer above.
|
||||
*/
|
||||
expected_count = (u32) (*elements)->integer.value;
|
||||
if (expected_count >= count) {
|
||||
goto package_too_small;
|
||||
}
|
||||
|
||||
count = expected_count;
|
||||
elements++;
|
||||
|
||||
/* Now we can walk the sub-packages */
|
||||
|
||||
/*lint -fallthrough */
|
||||
|
||||
case ACPI_PTYPE2:
|
||||
case ACPI_PTYPE2_FIXED:
|
||||
case ACPI_PTYPE2_MIN:
|
||||
case ACPI_PTYPE2_COUNT:
|
||||
|
||||
/*
|
||||
* These types all return a single package that consists of a variable
|
||||
* number of sub-packages
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
sub_package = *elements;
|
||||
sub_elements = sub_package->package.elements;
|
||||
|
||||
/* Each sub-object must be of type Package */
|
||||
|
||||
status =
|
||||
acpi_ns_check_object_type(pathname, sub_package,
|
||||
ACPI_RTYPE_PACKAGE, i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* Examine the different types of sub-packages */
|
||||
|
||||
switch (package->ret_info.type) {
|
||||
case ACPI_PTYPE2:
|
||||
case ACPI_PTYPE2_PKG_COUNT:
|
||||
|
||||
/* Each subpackage has a fixed number of elements */
|
||||
|
||||
expected_count =
|
||||
package->ret_info.count1 +
|
||||
package->ret_info.count2;
|
||||
if (sub_package->package.count !=
|
||||
expected_count) {
|
||||
count = sub_package->package.count;
|
||||
goto package_too_small;
|
||||
}
|
||||
|
||||
status =
|
||||
acpi_ns_check_package_elements(pathname,
|
||||
sub_elements,
|
||||
package->
|
||||
ret_info.
|
||||
object_type1,
|
||||
package->
|
||||
ret_info.
|
||||
count1,
|
||||
package->
|
||||
ret_info.
|
||||
object_type2,
|
||||
package->
|
||||
ret_info.
|
||||
count2);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_PTYPE2_FIXED:
|
||||
|
||||
/* Each sub-package has a fixed length */
|
||||
|
||||
expected_count = package->ret_info2.count;
|
||||
if (sub_package->package.count < expected_count) {
|
||||
count = sub_package->package.count;
|
||||
goto package_too_small;
|
||||
}
|
||||
|
||||
/* Check the type of each sub-package element */
|
||||
|
||||
for (j = 0; j < expected_count; j++) {
|
||||
status =
|
||||
acpi_ns_check_object_type(pathname,
|
||||
sub_elements
|
||||
[j],
|
||||
package->
|
||||
ret_info2.
|
||||
object_type
|
||||
[j], j);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_PTYPE2_MIN:
|
||||
|
||||
/* Each sub-package has a variable but minimum length */
|
||||
|
||||
expected_count = package->ret_info.count1;
|
||||
if (sub_package->package.count < expected_count) {
|
||||
count = sub_package->package.count;
|
||||
goto package_too_small;
|
||||
}
|
||||
|
||||
/* Check the type of each sub-package element */
|
||||
|
||||
status =
|
||||
acpi_ns_check_package_elements(pathname,
|
||||
sub_elements,
|
||||
package->
|
||||
ret_info.
|
||||
object_type1,
|
||||
sub_package->
|
||||
package.
|
||||
count, 0, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_PTYPE2_COUNT:
|
||||
|
||||
/* First element is the (Integer) count of elements to follow */
|
||||
|
||||
status =
|
||||
acpi_ns_check_object_type(pathname,
|
||||
*sub_elements,
|
||||
ACPI_RTYPE_INTEGER,
|
||||
0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* Make sure package is large enough for the Count */
|
||||
|
||||
expected_count =
|
||||
(u32) (*sub_elements)->integer.value;
|
||||
if (sub_package->package.count < expected_count) {
|
||||
count = sub_package->package.count;
|
||||
goto package_too_small;
|
||||
}
|
||||
|
||||
/* Check the type of each sub-package element */
|
||||
|
||||
status =
|
||||
acpi_ns_check_package_elements(pathname,
|
||||
(sub_elements
|
||||
+ 1),
|
||||
package->
|
||||
ret_info.
|
||||
object_type1,
|
||||
(expected_count
|
||||
- 1), 0, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
elements++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Should not get here if predefined info table is correct */
|
||||
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s: Invalid internal return type in table entry: %X",
|
||||
pathname, package->ret_info.type));
|
||||
|
||||
return (AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
|
||||
package_too_small:
|
||||
|
||||
/* Error exit for the case with an incorrect package count */
|
||||
|
||||
ACPI_WARNING((AE_INFO, "%s: Return Package is too small - "
|
||||
"found %u, expected %u", pathname, count,
|
||||
expected_count));
|
||||
|
||||
return (AE_AML_OPERAND_VALUE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_package_elements
|
||||
*
|
||||
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
|
||||
* Elements - Pointer to the package elements array
|
||||
* Type1 - Object type for first group
|
||||
* Count1 - Count for first group
|
||||
* Type2 - Object type for second group
|
||||
* Count2 - Count for second group
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Check that all elements of a package are of the correct object
|
||||
* type. Supports up to two groups of different object types.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_check_package_elements(char *pathname,
|
||||
union acpi_operand_object **elements,
|
||||
u8 type1, u32 count1, u8 type2, u32 count2)
|
||||
{
|
||||
union acpi_operand_object **this_element = elements;
|
||||
acpi_status status;
|
||||
u32 i;
|
||||
|
||||
/*
|
||||
* Up to two groups of package elements are supported by the data
|
||||
* structure. All elements in each group must be of the same type.
|
||||
* The second group can have a count of zero.
|
||||
*/
|
||||
for (i = 0; i < count1; i++) {
|
||||
status = acpi_ns_check_object_type(pathname, *this_element,
|
||||
type1, i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
this_element++;
|
||||
}
|
||||
|
||||
for (i = 0; i < count2; i++) {
|
||||
status = acpi_ns_check_object_type(pathname, *this_element,
|
||||
type2, (i + count1));
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
this_element++;
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_object_type
|
||||
*
|
||||
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
|
||||
* return_object - Object return from the execution of this
|
||||
* method/object
|
||||
* expected_btypes - Bitmap of expected return type(s)
|
||||
* package_index - Index of object within parent package (if
|
||||
* applicable - ACPI_NOT_PACKAGE otherwise)
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Check the type of the return object against the expected object
|
||||
* type(s). Use of Btype allows multiple expected object types.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_check_object_type(char *pathname,
|
||||
union acpi_operand_object *return_object,
|
||||
u32 expected_btypes, u32 package_index)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
u32 return_btype;
|
||||
char type_buffer[48]; /* Room for 5 types */
|
||||
u32 this_rtype;
|
||||
u32 i;
|
||||
u32 j;
|
||||
|
||||
/*
|
||||
* If we get a NULL return_object here, it is a NULL package element,
|
||||
* and this is always an error.
|
||||
*/
|
||||
if (!return_object) {
|
||||
goto type_error_exit;
|
||||
}
|
||||
|
||||
/* A Namespace node should not get here, but make sure */
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s: Invalid return type - Found a Namespace node [%4.4s] type %s",
|
||||
pathname, return_object->node.name.ascii,
|
||||
acpi_ut_get_type_name(return_object->node.type)));
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type.
|
||||
* The bitmapped type allows multiple possible return types.
|
||||
*
|
||||
* Note, the cases below must handle all of the possible types returned
|
||||
* from all of the predefined names (including elements of returned
|
||||
* packages)
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE(return_object)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
return_btype = ACPI_RTYPE_INTEGER;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
return_btype = ACPI_RTYPE_BUFFER;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
return_btype = ACPI_RTYPE_STRING;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
return_btype = ACPI_RTYPE_PACKAGE;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
return_btype = ACPI_RTYPE_REFERENCE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not one of the supported objects, must be incorrect */
|
||||
|
||||
goto type_error_exit;
|
||||
}
|
||||
|
||||
/* Is the object one of the expected types? */
|
||||
|
||||
if (!(return_btype & expected_btypes)) {
|
||||
goto type_error_exit;
|
||||
}
|
||||
|
||||
/* For reference objects, check that the reference type is correct */
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
status = acpi_ns_check_reference(pathname, return_object);
|
||||
}
|
||||
|
||||
return (status);
|
||||
|
||||
type_error_exit:
|
||||
|
||||
/* Create a string with all expected types for this predefined object */
|
||||
|
||||
j = 1;
|
||||
type_buffer[0] = 0;
|
||||
this_rtype = ACPI_RTYPE_INTEGER;
|
||||
|
||||
for (i = 0; i < ACPI_NUM_RTYPES; i++) {
|
||||
|
||||
/* If one of the expected types, concatenate the name of this type */
|
||||
|
||||
if (expected_btypes & this_rtype) {
|
||||
ACPI_STRCAT(type_buffer, &acpi_rtype_names[i][j]);
|
||||
j = 0; /* Use name separator from now on */
|
||||
}
|
||||
this_rtype <<= 1; /* Next Rtype */
|
||||
}
|
||||
|
||||
if (package_index == ACPI_NOT_PACKAGE) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s: Return type mismatch - found %s, expected %s",
|
||||
pathname,
|
||||
acpi_ut_get_object_type_name(return_object),
|
||||
type_buffer));
|
||||
} else {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s: Return Package type mismatch at index %u - "
|
||||
"found %s, expected %s", pathname, package_index,
|
||||
acpi_ut_get_object_type_name(return_object),
|
||||
type_buffer));
|
||||
}
|
||||
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_reference
|
||||
*
|
||||
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
|
||||
* return_object - Object returned from the evaluation of a
|
||||
* method or object
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Check a returned reference object for the correct reference
|
||||
* type. The only reference type that can be returned from a
|
||||
* predefined method is a named reference. All others are invalid.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_check_reference(char *pathname,
|
||||
union acpi_operand_object *return_object)
|
||||
{
|
||||
|
||||
/*
|
||||
* Check the reference object for the correct reference type (opcode).
|
||||
* The only type of reference that can be converted to an union acpi_object is
|
||||
* a reference to a named object (reference class: NAME)
|
||||
*/
|
||||
if (return_object->reference.class == ACPI_REFCLASS_NAME) {
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s: Return type mismatch - unexpected reference object type [%s] %2.2X",
|
||||
pathname, acpi_ut_get_reference_name(return_object),
|
||||
return_object->reference.class));
|
||||
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
|
@ -331,7 +331,7 @@ acpi_ns_search_and_enter(u32 target_name,
|
|||
"Found bad character(s) in name, repaired: [%4.4s]\n",
|
||||
ACPI_CAST_PTR(char, &target_name)));
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Found bad character(s) in name, repaired: [%4.4s]\n",
|
||||
ACPI_CAST_PTR(char, &target_name)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@
|
|||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("nsxfeval")
|
||||
|
||||
/* Local prototypes */
|
||||
static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
|
||||
|
||||
#ifdef ACPI_FUTURE_USAGE
|
||||
/*******************************************************************************
|
||||
*
|
||||
|
|
@ -69,6 +73,7 @@ ACPI_MODULE_NAME("nsxfeval")
|
|||
* be valid (non-null)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_evaluate_object_typed(acpi_handle handle,
|
||||
acpi_string pathname,
|
||||
|
|
@ -283,6 +288,10 @@ acpi_evaluate_object(acpi_handle handle,
|
|||
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
|
||||
/* Dereference Index and ref_of references */
|
||||
|
||||
acpi_ns_resolve_references(info);
|
||||
|
||||
/* Get the size of the returned object */
|
||||
|
||||
status =
|
||||
|
|
@ -350,6 +359,74 @@ acpi_evaluate_object(acpi_handle handle,
|
|||
|
||||
ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_resolve_references
|
||||
*
|
||||
* PARAMETERS: Info - Evaluation info block
|
||||
*
|
||||
* RETURN: Info->return_object is replaced with the dereferenced object
|
||||
*
|
||||
* DESCRIPTION: Dereference certain reference objects. Called before an
|
||||
* internal return object is converted to an external union acpi_object.
|
||||
*
|
||||
* Performs an automatic dereference of Index and ref_of reference objects.
|
||||
* These reference objects are not supported by the union acpi_object, so this is a
|
||||
* last resort effort to return something useful. Also, provides compatibility
|
||||
* with other ACPI implementations.
|
||||
*
|
||||
* NOTE: does not handle references within returned package objects or nested
|
||||
* references, but this support could be added later if found to be necessary.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
|
||||
{
|
||||
union acpi_operand_object *obj_desc = NULL;
|
||||
struct acpi_namespace_node *node;
|
||||
|
||||
/* We are interested in reference objects only */
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE(info->return_object) !=
|
||||
ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two types of references are supported - those created by Index and
|
||||
* ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted
|
||||
* to an union acpi_object, so it is not dereferenced here. A ddb_handle
|
||||
* (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
|
||||
* an union acpi_object.
|
||||
*/
|
||||
switch (info->return_object->reference.class) {
|
||||
case ACPI_REFCLASS_INDEX:
|
||||
|
||||
obj_desc = *(info->return_object->reference.where);
|
||||
break;
|
||||
|
||||
case ACPI_REFCLASS_REFOF:
|
||||
|
||||
node = info->return_object->reference.object;
|
||||
if (node) {
|
||||
obj_desc = node->object;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Replace the existing reference object */
|
||||
|
||||
if (obj_desc) {
|
||||
acpi_ut_add_reference(obj_desc);
|
||||
acpi_ut_remove_reference(info->return_object);
|
||||
info->return_object = obj_desc;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_walk_namespace
|
||||
|
|
@ -379,6 +456,7 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
|
|||
* function, etc.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_walk_namespace(acpi_object_type type,
|
||||
acpi_handle start_object,
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
|
|||
node = acpi_ns_map_handle_to_node(handle);
|
||||
if (!node) {
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
status = AE_BAD_PARAMETER;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +265,10 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
|
|||
info->name = node->name.integer;
|
||||
info->valid = 0;
|
||||
|
||||
if (node->type == ACPI_TYPE_METHOD) {
|
||||
info->param_count = node->object->method.param_count;
|
||||
}
|
||||
|
||||
status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto cleanup;
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ int __init acpi_numa_init(void)
|
|||
|
||||
int acpi_get_pxm(acpi_handle h)
|
||||
{
|
||||
unsigned long pxm;
|
||||
unsigned long long pxm;
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
acpi_handle phandle = h;
|
||||
|
|
|
|||
|
|
@ -608,7 +608,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
|
|||
acpi_handle handle;
|
||||
struct acpi_pci_id *pci_id = *id;
|
||||
acpi_status status;
|
||||
unsigned long temp;
|
||||
unsigned long long temp;
|
||||
acpi_object_type type;
|
||||
|
||||
acpi_get_parent(chandle, &handle);
|
||||
|
|
@ -620,8 +620,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
|
|||
if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
|
||||
return;
|
||||
|
||||
status =
|
||||
acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
|
||||
status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
|
||||
&temp);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
u32 val;
|
||||
|
|
@ -682,6 +681,22 @@ static void acpi_os_execute_deferred(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
static void acpi_os_execute_hp_deferred(struct work_struct *work)
|
||||
{
|
||||
struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
|
||||
if (!dpc) {
|
||||
printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
|
||||
return;
|
||||
}
|
||||
|
||||
acpi_os_wait_events_complete(NULL);
|
||||
|
||||
dpc->function(dpc->context);
|
||||
kfree(dpc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_os_execute
|
||||
|
|
@ -697,12 +712,13 @@ static void acpi_os_execute_deferred(struct work_struct *work)
|
|||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_os_execute(acpi_execute_type type,
|
||||
acpi_osd_exec_callback function, void *context)
|
||||
static acpi_status __acpi_os_execute(acpi_execute_type type,
|
||||
acpi_osd_exec_callback function, void *context, int hp)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_os_dpc *dpc;
|
||||
struct workqueue_struct *queue;
|
||||
int ret;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"Scheduling function [%p(%p)] for deferred execution.\n",
|
||||
function, context));
|
||||
|
|
@ -726,19 +742,38 @@ acpi_status acpi_os_execute(acpi_execute_type type,
|
|||
dpc->function = function;
|
||||
dpc->context = context;
|
||||
|
||||
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
|
||||
queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq;
|
||||
if (!queue_work(queue, &dpc->work)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Call to queue_work() failed.\n"));
|
||||
if (!hp) {
|
||||
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
|
||||
queue = (type == OSL_NOTIFY_HANDLER) ?
|
||||
kacpi_notify_wq : kacpid_wq;
|
||||
ret = queue_work(queue, &dpc->work);
|
||||
} else {
|
||||
INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred);
|
||||
ret = schedule_work(&dpc->work);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Call to queue_work() failed.\n");
|
||||
status = AE_ERROR;
|
||||
kfree(dpc);
|
||||
}
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
acpi_status acpi_os_execute(acpi_execute_type type,
|
||||
acpi_osd_exec_callback function, void *context)
|
||||
{
|
||||
return __acpi_os_execute(type, function, context, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_os_execute);
|
||||
|
||||
acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function,
|
||||
void *context)
|
||||
{
|
||||
return __acpi_os_execute(0, function, context, 1);
|
||||
}
|
||||
|
||||
void acpi_os_wait_events_complete(void *context)
|
||||
{
|
||||
flush_workqueue(kacpid_wq);
|
||||
|
|
|
|||
|
|
@ -719,6 +719,8 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
|
|||
*op = NULL;
|
||||
}
|
||||
|
||||
ACPI_PREEMPTION_POINT();
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
|||
union acpi_parse_object *next;
|
||||
const struct acpi_opcode_info *parent_info;
|
||||
union acpi_parse_object *replacement_op = NULL;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op);
|
||||
|
||||
|
|
@ -186,7 +187,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
|||
replacement_op =
|
||||
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
|
||||
if (!replacement_op) {
|
||||
goto allocate_error;
|
||||
status = AE_NO_MEMORY;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -211,7 +212,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
|||
replacement_op =
|
||||
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
|
||||
if (!replacement_op) {
|
||||
goto allocate_error;
|
||||
status = AE_NO_MEMORY;
|
||||
}
|
||||
} else
|
||||
if ((op->common.parent->common.aml_opcode ==
|
||||
|
|
@ -226,13 +227,13 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
|||
acpi_ps_alloc_op(op->common.
|
||||
aml_opcode);
|
||||
if (!replacement_op) {
|
||||
goto allocate_error;
|
||||
status = AE_NO_MEMORY;
|
||||
} else {
|
||||
replacement_op->named.data =
|
||||
op->named.data;
|
||||
replacement_op->named.length =
|
||||
op->named.length;
|
||||
}
|
||||
|
||||
replacement_op->named.data =
|
||||
op->named.data;
|
||||
replacement_op->named.length =
|
||||
op->named.length;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -242,7 +243,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
|||
replacement_op =
|
||||
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
|
||||
if (!replacement_op) {
|
||||
goto allocate_error;
|
||||
status = AE_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,14 +303,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
|||
/* Now we can actually delete the subtree rooted at Op */
|
||||
|
||||
acpi_ps_delete_parse_tree(op);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
|
||||
allocate_error:
|
||||
|
||||
/* Always delete the subtree, even on error */
|
||||
|
||||
acpi_ps_delete_parse_tree(op);
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
@ -641,10 +635,12 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
|
|||
ACPI_WALK_METHOD_RESTART;
|
||||
}
|
||||
} else {
|
||||
/* On error, delete any return object */
|
||||
/* On error, delete any return object or implicit return */
|
||||
|
||||
acpi_ut_remove_reference(previous_walk_state->
|
||||
return_desc);
|
||||
acpi_ds_clear_implicit_return
|
||||
(previous_walk_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -709,7 +709,7 @@ int acpi_pci_link_free_irq(acpi_handle handle)
|
|||
acpi_device_bid(link->device)));
|
||||
|
||||
if (link->refcnt == 0) {
|
||||
acpi_ut_evaluate_object(link->device->handle, "_DIS", 0, NULL);
|
||||
acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL);
|
||||
}
|
||||
mutex_unlock(&acpi_link_lock);
|
||||
return (link->irq.active);
|
||||
|
|
@ -737,7 +737,7 @@ static int acpi_pci_link_add(struct acpi_device *device)
|
|||
link->device = device;
|
||||
strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
|
||||
acpi_driver_data(device) = link;
|
||||
device->driver_data = link;
|
||||
|
||||
mutex_lock(&acpi_link_lock);
|
||||
result = acpi_pci_link_get_possible(link);
|
||||
|
|
@ -773,7 +773,7 @@ static int acpi_pci_link_add(struct acpi_device *device)
|
|||
|
||||
end:
|
||||
/* disable all links -- to be activated on use */
|
||||
acpi_ut_evaluate_object(device->handle, "_DIS", 0, NULL);
|
||||
acpi_evaluate_object(device->handle, "_DIS", NULL, NULL);
|
||||
mutex_unlock(&acpi_link_lock);
|
||||
|
||||
if (result)
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
|
|||
struct acpi_pci_root *root = NULL;
|
||||
struct acpi_pci_root *tmp;
|
||||
acpi_status status = AE_OK;
|
||||
unsigned long value = 0;
|
||||
unsigned long long value = 0;
|
||||
acpi_handle handle = NULL;
|
||||
struct acpi_device *child;
|
||||
|
||||
|
|
@ -206,7 +206,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
|
|||
root->device = device;
|
||||
strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
|
||||
acpi_driver_data(device) = root;
|
||||
device->driver_data = root;
|
||||
|
||||
device->ops.bind = acpi_pci_bind;
|
||||
|
||||
|
|
|
|||
|
|
@ -76,10 +76,10 @@ static struct acpi_pci_driver acpi_pci_slot_driver = {
|
|||
};
|
||||
|
||||
static int
|
||||
check_slot(acpi_handle handle, unsigned long *sun)
|
||||
check_slot(acpi_handle handle, unsigned long long *sun)
|
||||
{
|
||||
int device = -1;
|
||||
unsigned long adr, sta;
|
||||
unsigned long long adr, sta;
|
||||
acpi_status status;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ static acpi_status
|
|||
register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
int device;
|
||||
unsigned long sun;
|
||||
unsigned long long sun;
|
||||
char name[SLOT_NAME_SIZE];
|
||||
struct acpi_pci_slot *slot;
|
||||
struct pci_slot *pci_slot;
|
||||
|
|
@ -182,7 +182,7 @@ static acpi_status
|
|||
walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
int device, function;
|
||||
unsigned long adr;
|
||||
unsigned long long adr;
|
||||
acpi_status status;
|
||||
acpi_handle dummy_handle;
|
||||
acpi_walk_callback user_function;
|
||||
|
|
@ -239,7 +239,7 @@ static int
|
|||
walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
|
||||
{
|
||||
int seg, bus;
|
||||
unsigned long tmp;
|
||||
unsigned long long tmp;
|
||||
acpi_status status;
|
||||
acpi_handle dummy_handle;
|
||||
struct pci_bus *pci_bus;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,14 @@ ACPI_MODULE_NAME("power");
|
|||
#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
|
||||
#define ACPI_POWER_RESOURCE_STATE_ON 0x01
|
||||
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
|
||||
|
||||
#ifdef MODULE_PARAM_PREFIX
|
||||
#undef MODULE_PARAM_PREFIX
|
||||
#endif
|
||||
#define MODULE_PARAM_PREFIX "acpi."
|
||||
int acpi_power_nocheck;
|
||||
module_param_named(power_nocheck, acpi_power_nocheck, bool, 000);
|
||||
|
||||
static int acpi_power_add(struct acpi_device *device);
|
||||
static int acpi_power_remove(struct acpi_device *device, int type);
|
||||
static int acpi_power_resume(struct acpi_device *device);
|
||||
|
|
@ -128,16 +136,16 @@ acpi_power_get_context(acpi_handle handle,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_power_get_state(struct acpi_power_resource *resource, int *state)
|
||||
static int acpi_power_get_state(acpi_handle handle, int *state)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
unsigned long sta = 0;
|
||||
unsigned long long sta = 0;
|
||||
|
||||
|
||||
if (!resource || !state)
|
||||
if (!handle || !state)
|
||||
return -EINVAL;
|
||||
|
||||
status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta);
|
||||
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -145,7 +153,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state
|
|||
ACPI_POWER_RESOURCE_STATE_OFF;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
|
||||
resource->name, state ? "on" : "off"));
|
||||
acpi_ut_get_node_name(handle), state ? "on" : "off"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -153,7 +161,6 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state
|
|||
static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
|
||||
{
|
||||
int result = 0, state1;
|
||||
struct acpi_power_resource *resource = NULL;
|
||||
u32 i = 0;
|
||||
|
||||
|
||||
|
|
@ -161,12 +168,15 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
|
|||
return -EINVAL;
|
||||
|
||||
/* The state of the list is 'on' IFF all resources are 'on'. */
|
||||
/* */
|
||||
|
||||
for (i = 0; i < list->count; i++) {
|
||||
result = acpi_power_get_context(list->handles[i], &resource);
|
||||
if (result)
|
||||
return result;
|
||||
result = acpi_power_get_state(resource, &state1);
|
||||
/*
|
||||
* The state of the power resource can be obtained by
|
||||
* using the ACPI handle. In such case it is unnecessary to
|
||||
* get the Power resource first and then get its state again.
|
||||
*/
|
||||
result = acpi_power_get_state(list->handles[i], &state1);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
|
|
@ -226,12 +236,18 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
|
|||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
result = acpi_power_get_state(resource, &state);
|
||||
if (result)
|
||||
return result;
|
||||
if (state != ACPI_POWER_RESOURCE_STATE_ON)
|
||||
return -ENOEXEC;
|
||||
|
||||
if (!acpi_power_nocheck) {
|
||||
/*
|
||||
* If acpi_power_nocheck is set, it is unnecessary to check
|
||||
* the power state after power transition.
|
||||
*/
|
||||
result = acpi_power_get_state(resource->device->handle,
|
||||
&state);
|
||||
if (result)
|
||||
return result;
|
||||
if (state != ACPI_POWER_RESOURCE_STATE_ON)
|
||||
return -ENOEXEC;
|
||||
}
|
||||
/* Update the power resource's _device_ power state */
|
||||
resource->device->power.state = ACPI_STATE_D0;
|
||||
|
||||
|
|
@ -277,11 +293,17 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
|
|||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
result = acpi_power_get_state(resource, &state);
|
||||
if (result)
|
||||
return result;
|
||||
if (state != ACPI_POWER_RESOURCE_STATE_OFF)
|
||||
return -ENOEXEC;
|
||||
if (!acpi_power_nocheck) {
|
||||
/*
|
||||
* If acpi_power_nocheck is set, it is unnecessary to check
|
||||
* the power state after power transition.
|
||||
*/
|
||||
result = acpi_power_get_state(handle, &state);
|
||||
if (result)
|
||||
return result;
|
||||
if (state != ACPI_POWER_RESOURCE_STATE_OFF)
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/* Update the power resource's _device_ power state */
|
||||
resource->device->power.state = ACPI_STATE_D3;
|
||||
|
|
@ -555,7 +577,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
|
|||
if (!resource)
|
||||
goto end;
|
||||
|
||||
result = acpi_power_get_state(resource, &state);
|
||||
result = acpi_power_get_state(resource->device->handle, &state);
|
||||
if (result)
|
||||
goto end;
|
||||
|
||||
|
|
@ -657,7 +679,7 @@ static int acpi_power_add(struct acpi_device *device)
|
|||
strcpy(resource->name, device->pnp.bus_id);
|
||||
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
|
||||
acpi_driver_data(device) = resource;
|
||||
device->driver_data = resource;
|
||||
|
||||
/* Evalute the object to get the system level and resource order. */
|
||||
status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer);
|
||||
|
|
@ -668,7 +690,7 @@ static int acpi_power_add(struct acpi_device *device)
|
|||
resource->system_level = acpi_object.power_resource.system_level;
|
||||
resource->order = acpi_object.power_resource.resource_order;
|
||||
|
||||
result = acpi_power_get_state(resource, &state);
|
||||
result = acpi_power_get_state(device->handle, &state);
|
||||
if (result)
|
||||
goto end;
|
||||
|
||||
|
|
@ -733,9 +755,9 @@ static int acpi_power_resume(struct acpi_device *device)
|
|||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
|
||||
resource = (struct acpi_power_resource *)acpi_driver_data(device);
|
||||
resource = acpi_driver_data(device);
|
||||
|
||||
result = acpi_power_get_state(resource, &state);
|
||||
result = acpi_power_get_state(device->handle, &state);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
|
|
|
|||
|
|
@ -563,7 +563,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
|
|||
|
||||
/* Check if it is a Device with HID and UID */
|
||||
if (has_uid) {
|
||||
unsigned long value;
|
||||
unsigned long long value;
|
||||
status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
|
||||
NULL, &value);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
|
@ -818,7 +818,7 @@ static int acpi_processor_add(struct acpi_device *device)
|
|||
pr->handle = device->handle;
|
||||
strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
|
||||
acpi_driver_data(device) = pr;
|
||||
device->driver_data = pr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -875,7 +875,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
|
|||
static int is_processor_present(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
unsigned long sta = 0;
|
||||
unsigned long long sta = 0;
|
||||
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
|
||||
|
|
|
|||
|
|
@ -1587,6 +1587,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
|
|||
|
||||
if (acpi_idle_bm_check()) {
|
||||
if (dev->safe_state) {
|
||||
dev->last_state = dev->safe_state;
|
||||
return dev->safe_state->enter(dev, dev->safe_state);
|
||||
} else {
|
||||
local_irq_disable();
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include <asm/uaccess.h>
|
||||
#endif
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/processor.h>
|
||||
|
|
@ -126,7 +127,7 @@ static struct notifier_block acpi_ppc_notifier_block = {
|
|||
static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
|
||||
{
|
||||
acpi_status status = 0;
|
||||
unsigned long ppc = 0;
|
||||
unsigned long long ppc = 0;
|
||||
|
||||
|
||||
if (!pr)
|
||||
|
|
@ -334,7 +335,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
|
|||
acpi_status status = AE_OK;
|
||||
acpi_handle handle = NULL;
|
||||
|
||||
|
||||
if (!pr || !pr->performance || !pr->handle)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -347,13 +347,25 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
|
|||
|
||||
result = acpi_processor_get_performance_control(pr);
|
||||
if (result)
|
||||
return result;
|
||||
goto update_bios;
|
||||
|
||||
result = acpi_processor_get_performance_states(pr);
|
||||
if (result)
|
||||
return result;
|
||||
goto update_bios;
|
||||
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that
|
||||
* the BIOS is older than the CPU and does not know its frequencies
|
||||
*/
|
||||
update_bios:
|
||||
if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){
|
||||
if(boot_cpu_has(X86_FEATURE_EST))
|
||||
printk(KERN_WARNING FW_BUG "BIOS needs update for CPU "
|
||||
"frequency support\n");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int acpi_processor_notify_smm(struct module *calling_module)
|
||||
|
|
@ -524,13 +536,13 @@ static int acpi_processor_get_psd(struct acpi_processor *pr)
|
|||
|
||||
psd = buffer.pointer;
|
||||
if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
|
||||
printk(KERN_ERR PREFIX "Invalid _PSD data\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (psd->package.count != 1) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
|
||||
printk(KERN_ERR PREFIX "Invalid _PSD data\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
|
@ -543,19 +555,19 @@ static int acpi_processor_get_psd(struct acpi_processor *pr)
|
|||
status = acpi_extract_package(&(psd->package.elements[0]),
|
||||
&format, &state);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
|
||||
printk(KERN_ERR PREFIX "Invalid _PSD data\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n"));
|
||||
printk(KERN_ERR PREFIX "Unknown _PSD:num_entries\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n"));
|
||||
printk(KERN_ERR PREFIX "Unknown _PSD:revision\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ static int acpi_processor_throttling_notifier(unsigned long event, void *data)
|
|||
static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
|
||||
{
|
||||
acpi_status status = 0;
|
||||
unsigned long tpc = 0;
|
||||
unsigned long long tpc = 0;
|
||||
|
||||
if (!pr)
|
||||
return -EINVAL;
|
||||
|
|
@ -528,13 +528,13 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
|
|||
|
||||
tsd = buffer.pointer;
|
||||
if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
|
||||
printk(KERN_ERR PREFIX "Invalid _TSD data\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (tsd->package.count != 1) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
|
||||
printk(KERN_ERR PREFIX "Invalid _TSD data\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
|
@ -547,19 +547,19 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
|
|||
status = acpi_extract_package(&(tsd->package.elements[0]),
|
||||
&format, &state);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
|
||||
printk(KERN_ERR PREFIX "Invalid _TSD data\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n"));
|
||||
printk(KERN_ERR PREFIX "Unknown _TSD:num_entries\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (pdomain->revision != ACPI_TSD_REV0_REVISION) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n"));
|
||||
printk(KERN_ERR PREFIX "Unknown _TSD:revision\n");
|
||||
result = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,28 @@ void acpi_reboot(void)
|
|||
|
||||
rr = &acpi_gbl_FADT.reset_register;
|
||||
|
||||
/* Is the reset register supported? */
|
||||
if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
|
||||
rr->bit_width != 8 || rr->bit_offset != 0)
|
||||
/*
|
||||
* Is the ACPI reset register supported?
|
||||
*
|
||||
* According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates
|
||||
* whether the ACPI reset mechanism is supported.
|
||||
*
|
||||
* However, some boxes have this bit clear, yet a valid
|
||||
* ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only
|
||||
* mechanism that works for them after S3.
|
||||
*
|
||||
* This suggests that other operating systems may not be checking
|
||||
* the RESET_REG_SUP bit, and are using other means to decide
|
||||
* whether to use the ACPI reboot mechanism or not.
|
||||
*
|
||||
* So when acpi reboot is requested,
|
||||
* only the reset_register is checked. If the following
|
||||
* conditions are met, it indicates that the reset register is supported.
|
||||
* a. reset_register is not zero
|
||||
* b. the access width is eight
|
||||
* c. the bit_offset is zero
|
||||
*/
|
||||
if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0)
|
||||
return;
|
||||
|
||||
reset_value = acpi_gbl_FADT.reset_value;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acresrc.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
|
||||
#define _COMPONENT ACPI_RESOURCES
|
||||
|
|
@ -560,8 +559,8 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
|
|||
ACPI_GET_OBJECT_TYPE(*sub_object_list)) ||
|
||||
((ACPI_TYPE_LOCAL_REFERENCE ==
|
||||
ACPI_GET_OBJECT_TYPE(*sub_object_list)) &&
|
||||
((*sub_object_list)->reference.opcode ==
|
||||
AML_INT_NAMEPATH_OP)))) {
|
||||
((*sub_object_list)->reference.class ==
|
||||
ACPI_REFCLASS_NAME)))) {
|
||||
name_found = TRUE;
|
||||
} else {
|
||||
/* Look at the next element */
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acresrc.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
|
||||
#define _COMPONENT ACPI_RESOURCES
|
||||
|
|
@ -310,13 +309,12 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
|
|||
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
if (obj_desc->reference.opcode !=
|
||||
AML_INT_NAMEPATH_OP) {
|
||||
if (obj_desc->reference.class !=
|
||||
ACPI_REFCLASS_NAME) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"(PRT[%X].Source) Need name, found reference op %X",
|
||||
"(PRT[%X].Source) Need name, found Reference Class %X",
|
||||
index,
|
||||
obj_desc->reference.
|
||||
opcode));
|
||||
obj_desc->reference.class));
|
||||
return_ACPI_STATUS(AE_BAD_DATA);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -931,7 +931,7 @@ static int acpi_sbs_add(struct acpi_device *device)
|
|||
sbs->device = device;
|
||||
strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
|
||||
acpi_driver_data(device) = sbs;
|
||||
device->driver_data = sbs;
|
||||
|
||||
result = acpi_charger_add(sbs);
|
||||
if (result)
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
|||
static int acpi_smbus_hc_add(struct acpi_device *device)
|
||||
{
|
||||
int status;
|
||||
unsigned long val;
|
||||
unsigned long long val;
|
||||
struct acpi_smb_hc *hc;
|
||||
|
||||
if (!device)
|
||||
|
|
@ -282,7 +282,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
|
|||
hc->ec = acpi_driver_data(device->parent);
|
||||
hc->offset = (val >> 8) & 0xff;
|
||||
hc->query_bit = val & 0xff;
|
||||
acpi_driver_data(device) = hc;
|
||||
device->driver_data = hc;
|
||||
|
||||
acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
|
||||
printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n",
|
||||
|
|
@ -303,7 +303,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
|
|||
hc = acpi_driver_data(device);
|
||||
acpi_ec_remove_query_handler(hc->ec, hc->query_bit);
|
||||
kfree(hc);
|
||||
acpi_driver_data(device) = NULL;
|
||||
device->driver_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,16 +113,16 @@ static int acpi_bus_hot_remove_device(void *context)
|
|||
|
||||
|
||||
if (acpi_bus_trim(device, 1)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Removing device failed\n"));
|
||||
printk(KERN_ERR PREFIX
|
||||
"Removing device failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* power off device */
|
||||
status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
|
||||
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
|
||||
"Power-off device failed\n"));
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Power-off device failed\n");
|
||||
|
||||
if (device->flags.lockable) {
|
||||
arg_list.count = 1;
|
||||
|
|
@ -276,6 +276,13 @@ int acpi_match_device_ids(struct acpi_device *device,
|
|||
{
|
||||
const struct acpi_device_id *id;
|
||||
|
||||
/*
|
||||
* If the device is not present, it is unnecessary to load device
|
||||
* driver for it.
|
||||
*/
|
||||
if (!device->status.present)
|
||||
return -ENODEV;
|
||||
|
||||
if (device->flags.hardware_id) {
|
||||
for (id = ids; id->id[0]; id++) {
|
||||
if (!strcmp((char*)id->id, device->pnp.hardware_id))
|
||||
|
|
@ -384,7 +391,7 @@ static int acpi_device_remove(struct device * dev)
|
|||
acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
|
||||
}
|
||||
acpi_dev->driver = NULL;
|
||||
acpi_driver_data(dev) = NULL;
|
||||
acpi_dev->driver_data = NULL;
|
||||
|
||||
put_device(dev);
|
||||
return 0;
|
||||
|
|
@ -477,7 +484,7 @@ static int acpi_device_register(struct acpi_device *device,
|
|||
|
||||
result = acpi_device_setup_files(device);
|
||||
if(result)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error creating sysfs interface for device %s\n", device->dev.bus_id));
|
||||
printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", device->dev.bus_id);
|
||||
|
||||
device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
|
||||
return 0;
|
||||
|
|
@ -537,7 +544,7 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
|
|||
result = driver->ops.add(device);
|
||||
if (result) {
|
||||
device->driver = NULL;
|
||||
acpi_driver_data(device) = NULL;
|
||||
device->driver_data = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -744,6 +751,16 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
|
|||
if (!acpi_match_device_ids(device, button_device_ids))
|
||||
device->wakeup.flags.run_wake = 1;
|
||||
|
||||
/*
|
||||
* Don't set Power button GPE as run_wake
|
||||
* if Fixed Power button is used
|
||||
*/
|
||||
if (!strcmp(device->pnp.hardware_id, "PNP0C0C") &&
|
||||
!(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) {
|
||||
device->wakeup.flags.run_wake = 0;
|
||||
device->wakeup.flags.valid = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
if (ACPI_FAILURE(status))
|
||||
device->flags.wake_capable = 0;
|
||||
|
|
@ -807,6 +824,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
|
|||
/* TBD: System wake support and resource requirements. */
|
||||
|
||||
device->power.state = ACPI_STATE_UNKNOWN;
|
||||
acpi_bus_get_power(device->handle, &(device->power.state));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1152,20 +1170,6 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_is_child_device(struct acpi_device *device,
|
||||
int (*matcher)(struct acpi_device *))
|
||||
{
|
||||
int result = -ENODEV;
|
||||
|
||||
do {
|
||||
if (ACPI_SUCCESS(matcher(device)))
|
||||
return AE_OK;
|
||||
} while ((device = device->parent));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_add_single_object(struct acpi_device **child,
|
||||
struct acpi_device *parent, acpi_handle handle, int type,
|
||||
|
|
@ -1221,15 +1225,18 @@ acpi_add_single_object(struct acpi_device **child,
|
|||
result = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
if (!device->status.present) {
|
||||
/* Bay and dock should be handled even if absent */
|
||||
if (!ACPI_SUCCESS(
|
||||
acpi_is_child_device(device, acpi_bay_match)) &&
|
||||
!ACPI_SUCCESS(
|
||||
acpi_is_child_device(device, acpi_dock_match))) {
|
||||
result = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
/*
|
||||
* When the device is neither present nor functional, the
|
||||
* device should not be added to Linux ACPI device tree.
|
||||
* When the status of the device is not present but functinal,
|
||||
* it should be added to Linux ACPI tree. For example : bay
|
||||
* device , dock device.
|
||||
* In such conditions it is unncessary to check whether it is
|
||||
* bay device or dock device.
|
||||
*/
|
||||
if (!device->status.present && !device->status.functional) {
|
||||
result = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1251,6 +1258,16 @@ acpi_add_single_object(struct acpi_device **child,
|
|||
*/
|
||||
acpi_device_set_id(device, parent, handle, type);
|
||||
|
||||
/*
|
||||
* The ACPI device is attached to acpi handle before getting
|
||||
* the power/wakeup/peformance flags. Otherwise OS can't get
|
||||
* the corresponding ACPI device by the acpi handle in the course
|
||||
* of getting the power/wakeup/performance flags.
|
||||
*/
|
||||
result = acpi_device_set_context(device, type);
|
||||
if (result)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Power Management
|
||||
* ----------------
|
||||
|
|
@ -1281,8 +1298,6 @@ acpi_add_single_object(struct acpi_device **child,
|
|||
goto end;
|
||||
}
|
||||
|
||||
if ((result = acpi_device_set_context(device, type)))
|
||||
goto end;
|
||||
|
||||
result = acpi_device_register(device, parent);
|
||||
|
||||
|
|
@ -1402,7 +1417,12 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
|
|||
* TBD: Need notifications and other detection mechanisms
|
||||
* in place before we can fully implement this.
|
||||
*/
|
||||
if (child->status.present) {
|
||||
/*
|
||||
* When the device is not present but functional, it is also
|
||||
* necessary to scan the children of this device.
|
||||
*/
|
||||
if (child->status.present || (!child->status.present &&
|
||||
child->status.functional)) {
|
||||
status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
|
||||
NULL, NULL);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
|
|
@ -1545,7 +1565,6 @@ static int acpi_bus_scan_fixed(struct acpi_device *root)
|
|||
return result;
|
||||
}
|
||||
|
||||
int __init acpi_boot_ec_enable(void);
|
||||
|
||||
static int __init acpi_scan_init(void)
|
||||
{
|
||||
|
|
@ -1579,9 +1598,6 @@ static int __init acpi_scan_init(void)
|
|||
*/
|
||||
result = acpi_bus_scan_fixed(acpi_root);
|
||||
|
||||
/* EC region might be needed at bus_scan, so enable it now */
|
||||
acpi_boot_ec_enable();
|
||||
|
||||
if (!result)
|
||||
result = acpi_bus_scan(acpi_root, &ops);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/dmi.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
|
|
@ -24,6 +25,36 @@
|
|||
|
||||
u8 sleep_states[ACPI_S_STATE_COUNT];
|
||||
|
||||
static void acpi_sleep_tts_switch(u32 acpi_state)
|
||||
{
|
||||
union acpi_object in_arg = { ACPI_TYPE_INTEGER };
|
||||
struct acpi_object_list arg_list = { 1, &in_arg };
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
in_arg.integer.value = acpi_state;
|
||||
status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL);
|
||||
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
|
||||
/*
|
||||
* OS can't evaluate the _TTS object correctly. Some warning
|
||||
* message will be printed. But it won't break anything.
|
||||
*/
|
||||
printk(KERN_NOTICE "Failure in evaluating _TTS object\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int tts_notify_reboot(struct notifier_block *this,
|
||||
unsigned long code, void *x)
|
||||
{
|
||||
acpi_sleep_tts_switch(ACPI_STATE_S5);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block tts_notifier = {
|
||||
.notifier_call = tts_notify_reboot,
|
||||
.next = NULL,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
static int acpi_sleep_prepare(u32 acpi_state)
|
||||
{
|
||||
#ifdef CONFIG_ACPI_SLEEP
|
||||
|
|
@ -45,9 +76,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_ACPI_SLEEP
|
||||
static u32 acpi_target_sleep_state = ACPI_STATE_S0;
|
||||
|
||||
/*
|
||||
* ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
|
||||
* user to request that behavior by using the 'acpi_old_suspend_ordering'
|
||||
|
|
@ -131,8 +161,9 @@ static void acpi_pm_end(void)
|
|||
* failing transition to a sleep state.
|
||||
*/
|
||||
acpi_target_sleep_state = ACPI_STATE_S0;
|
||||
acpi_sleep_tts_switch(acpi_target_sleep_state);
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
#endif /* CONFIG_ACPI_SLEEP */
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
extern void do_suspend_lowlevel(void);
|
||||
|
|
@ -155,6 +186,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
|
|||
|
||||
if (sleep_states[acpi_state]) {
|
||||
acpi_target_sleep_state = acpi_state;
|
||||
acpi_sleep_tts_switch(acpi_target_sleep_state);
|
||||
} else {
|
||||
printk(KERN_ERR "ACPI does not support this state: %d\n",
|
||||
pm_state);
|
||||
|
|
@ -200,6 +232,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
|
|||
break;
|
||||
}
|
||||
|
||||
/* If ACPI is not enabled by the BIOS, we need to enable it here. */
|
||||
acpi_enable();
|
||||
/* Reprogram control registers and execute _BFS */
|
||||
acpi_leave_sleep_state_prep(acpi_state);
|
||||
|
||||
|
|
@ -296,6 +330,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
|
|||
DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = init_old_suspend_ordering,
|
||||
.ident = "HP xw4600 Workstation",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
};
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
|
|
@ -313,6 +355,7 @@ void __init acpi_no_s4_hw_signature(void)
|
|||
static int acpi_hibernation_begin(void)
|
||||
{
|
||||
acpi_target_sleep_state = ACPI_STATE_S4;
|
||||
acpi_sleep_tts_switch(acpi_target_sleep_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -376,7 +419,15 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
|
|||
*/
|
||||
static int acpi_hibernation_begin_old(void)
|
||||
{
|
||||
int error = acpi_sleep_prepare(ACPI_STATE_S4);
|
||||
int error;
|
||||
/*
|
||||
* The _TTS object should always be evaluated before the _PTS object.
|
||||
* When the old_suspended_ordering is true, the _PTS object is
|
||||
* evaluated in the acpi_sleep_prepare.
|
||||
*/
|
||||
acpi_sleep_tts_switch(ACPI_STATE_S4);
|
||||
|
||||
error = acpi_sleep_prepare(ACPI_STATE_S4);
|
||||
|
||||
if (!error)
|
||||
acpi_target_sleep_state = ACPI_STATE_S4;
|
||||
|
|
@ -444,7 +495,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
|
|||
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
|
||||
struct acpi_device *adev;
|
||||
char acpi_method[] = "_SxD";
|
||||
unsigned long d_min, d_max;
|
||||
unsigned long long d_min, d_max;
|
||||
|
||||
if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
|
||||
printk(KERN_DEBUG "ACPI handle has no context!\n");
|
||||
|
|
@ -596,5 +647,10 @@ int __init acpi_sleep_init(void)
|
|||
pm_power_off = acpi_power_off;
|
||||
}
|
||||
printk(")\n");
|
||||
/*
|
||||
* Register the tts_notifier to reboot notifier list so that the _TTS
|
||||
* object can also be evaluated when the system enters S5.
|
||||
*/
|
||||
register_reboot_notifier(&tts_notifier);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -386,8 +386,8 @@ static ssize_t counter_set(struct kobject *kobj,
|
|||
goto end;
|
||||
|
||||
if (!(all_counters[index].flags & ACPI_EVENT_VALID)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
|
||||
"Can not change Invalid GPE/Fixed Event status\n"));
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Can not change Invalid GPE/Fixed Event status\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ ACPI_MODULE_NAME("tbfadt")
|
|||
/* Local prototypes */
|
||||
static void inline
|
||||
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
|
||||
u8 bit_width, u64 address);
|
||||
u8 byte_width, u64 address);
|
||||
|
||||
static void acpi_tb_convert_fadt(void);
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
|
|||
* FUNCTION: acpi_tb_init_generic_address
|
||||
*
|
||||
* PARAMETERS: generic_address - GAS struct to be initialized
|
||||
* bit_width - Width of this register
|
||||
* byte_width - Width of this register
|
||||
* Address - Address of the register
|
||||
*
|
||||
* RETURN: None
|
||||
|
|
@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
|
|||
|
||||
static void inline
|
||||
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
|
||||
u8 bit_width, u64 address)
|
||||
u8 byte_width, u64 address)
|
||||
{
|
||||
|
||||
/*
|
||||
|
|
@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
|
|||
/* All other fields are byte-wide */
|
||||
|
||||
generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
|
||||
generic_address->bit_width = bit_width;
|
||||
generic_address->bit_width = byte_width << 3;
|
||||
generic_address->bit_offset = 0;
|
||||
generic_address->access_width = 0;
|
||||
}
|
||||
|
|
@ -342,9 +342,20 @@ static void acpi_tb_convert_fadt(void)
|
|||
* useful to calculate them once, here.
|
||||
*
|
||||
* The PM event blocks are split into two register blocks, first is the
|
||||
* PM Status Register block, followed immediately by the PM Enable Register
|
||||
* block. Each is of length (pm1_event_length/2)
|
||||
* PM Status Register block, followed immediately by the PM Enable
|
||||
* Register block. Each is of length (xpm1x_event_block.bit_width/2).
|
||||
*
|
||||
* On various systems the v2 fields (and particularly the bit widths)
|
||||
* cannot be relied upon, though. Hence resort to using the v1 length
|
||||
* here (and warn about the inconsistency).
|
||||
*/
|
||||
if (acpi_gbl_FADT.xpm1a_event_block.bit_width
|
||||
!= acpi_gbl_FADT.pm1_event_length * 8)
|
||||
printk(KERN_WARNING "FADT: "
|
||||
"X_PM1a_EVT_BLK.bit_width (%u) does not match"
|
||||
" PM1_EVT_LEN (%u)\n",
|
||||
acpi_gbl_FADT.xpm1a_event_block.bit_width,
|
||||
acpi_gbl_FADT.pm1_event_length);
|
||||
pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
|
||||
|
||||
/* The PM1A register block is required */
|
||||
|
|
@ -360,13 +371,20 @@ static void acpi_tb_convert_fadt(void)
|
|||
/* The PM1B register block is optional, ignore if not present */
|
||||
|
||||
if (acpi_gbl_FADT.xpm1b_event_block.address) {
|
||||
if (acpi_gbl_FADT.xpm1b_event_block.bit_width
|
||||
!= acpi_gbl_FADT.pm1_event_length * 8)
|
||||
printk(KERN_WARNING "FADT: "
|
||||
"X_PM1b_EVT_BLK.bit_width (%u) does not match"
|
||||
" PM1_EVT_LEN (%u)\n",
|
||||
acpi_gbl_FADT.xpm1b_event_block.bit_width,
|
||||
acpi_gbl_FADT.pm1_event_length);
|
||||
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
|
||||
pm1_register_length,
|
||||
(acpi_gbl_FADT.xpm1b_event_block.
|
||||
address + pm1_register_length));
|
||||
/* Don't forget to copy space_id of the GAS */
|
||||
acpi_gbl_xpm1b_enable.space_id =
|
||||
acpi_gbl_FADT.xpm1a_event_block.space_id;
|
||||
acpi_gbl_FADT.xpm1b_event_block.space_id;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,6 @@ acpi_status
|
|||
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
|
||||
{
|
||||
u32 i;
|
||||
u32 length;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_add_table);
|
||||
|
|
@ -145,25 +144,64 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
|
|||
}
|
||||
}
|
||||
|
||||
length = ACPI_MIN(table_desc->length,
|
||||
acpi_gbl_root_table_list.tables[i].length);
|
||||
if (ACPI_MEMCMP(table_desc->pointer,
|
||||
acpi_gbl_root_table_list.tables[i].pointer,
|
||||
length)) {
|
||||
/*
|
||||
* Check for a table match on the entire table length,
|
||||
* not just the header.
|
||||
*/
|
||||
if (table_desc->length !=
|
||||
acpi_gbl_root_table_list.tables[i].length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Table is already registered */
|
||||
if (ACPI_MEMCMP(table_desc->pointer,
|
||||
acpi_gbl_root_table_list.tables[i].pointer,
|
||||
acpi_gbl_root_table_list.tables[i].length)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the current mechanism does not unregister a table if it is
|
||||
* dynamically unloaded. The related namespace entries are deleted,
|
||||
* but the table remains in the root table list.
|
||||
*
|
||||
* The assumption here is that the number of different tables that
|
||||
* will be loaded is actually small, and there is minimal overhead
|
||||
* in just keeping the table in case it is needed again.
|
||||
*
|
||||
* If this assumption changes in the future (perhaps on large
|
||||
* machines with many table load/unload operations), tables will
|
||||
* need to be unregistered when they are unloaded, and slots in the
|
||||
* root table list should be reused when empty.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Table is already registered.
|
||||
* We can delete the table that was passed as a parameter.
|
||||
*/
|
||||
acpi_tb_delete_table(table_desc);
|
||||
*table_index = i;
|
||||
status = AE_ALREADY_EXISTS;
|
||||
goto release;
|
||||
|
||||
if (acpi_gbl_root_table_list.tables[i].
|
||||
flags & ACPI_TABLE_IS_LOADED) {
|
||||
|
||||
/* Table is still loaded, this is an error */
|
||||
|
||||
status = AE_ALREADY_EXISTS;
|
||||
goto release;
|
||||
} else {
|
||||
/* Table was unloaded, allow it to be reloaded */
|
||||
|
||||
table_desc->pointer =
|
||||
acpi_gbl_root_table_list.tables[i].pointer;
|
||||
table_desc->address =
|
||||
acpi_gbl_root_table_list.tables[i].address;
|
||||
status = AE_OK;
|
||||
goto print_header;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the table to the global table list
|
||||
*/
|
||||
/* Add the table to the global root table list */
|
||||
|
||||
status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
|
||||
table_desc->length, table_desc->flags,
|
||||
table_index);
|
||||
|
|
@ -171,6 +209,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
|
|||
goto release;
|
||||
}
|
||||
|
||||
print_header:
|
||||
acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
|
||||
|
||||
release:
|
||||
|
|
|
|||
|
|
@ -246,18 +246,18 @@ static const struct file_operations acpi_thermal_polling_fops = {
|
|||
static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
unsigned long long tmp;
|
||||
|
||||
if (!tz)
|
||||
return -EINVAL;
|
||||
|
||||
tz->last_temperature = tz->temperature;
|
||||
|
||||
status =
|
||||
acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tz->temperature);
|
||||
status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
tz->temperature = tmp;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
|
||||
tz->temperature));
|
||||
|
||||
|
|
@ -267,17 +267,16 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
|
|||
static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
unsigned long long tmp;
|
||||
|
||||
if (!tz)
|
||||
return -EINVAL;
|
||||
|
||||
status =
|
||||
acpi_evaluate_integer(tz->device->handle, "_TZP", NULL,
|
||||
&tz->polling_frequency);
|
||||
status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
tz->polling_frequency = tmp;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
|
||||
tz->polling_frequency));
|
||||
|
||||
|
|
@ -356,6 +355,7 @@ do { \
|
|||
static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
unsigned long long tmp;
|
||||
struct acpi_handle_list devices;
|
||||
int valid = 0;
|
||||
int i;
|
||||
|
|
@ -363,7 +363,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
/* Critical Shutdown (required) */
|
||||
if (flag & ACPI_TRIPS_CRITICAL) {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_CRT", NULL, &tz->trips.critical.temperature);
|
||||
"_CRT", NULL, &tmp);
|
||||
tz->trips.critical.temperature = tmp;
|
||||
/*
|
||||
* Treat freezing temperatures as invalid as well; some
|
||||
* BIOSes return really low values and cause reboots at startup.
|
||||
|
|
@ -388,10 +389,12 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
} else if (crt > 0) {
|
||||
unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
|
||||
/*
|
||||
* Allow override to lower critical threshold
|
||||
* Allow override critical threshold
|
||||
*/
|
||||
if (crt_k < tz->trips.critical.temperature)
|
||||
tz->trips.critical.temperature = crt_k;
|
||||
if (crt_k > tz->trips.critical.temperature)
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Critical threshold %d C\n", crt);
|
||||
tz->trips.critical.temperature = crt_k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -399,12 +402,13 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
/* Critical Sleep (optional) */
|
||||
if (flag & ACPI_TRIPS_HOT) {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_HOT", NULL, &tz->trips.hot.temperature);
|
||||
"_HOT", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
tz->trips.hot.flags.valid = 0;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"No hot threshold\n"));
|
||||
} else {
|
||||
tz->trips.hot.temperature = tmp;
|
||||
tz->trips.hot.flags.valid = 1;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Found hot threshold [%lu]\n",
|
||||
|
|
@ -418,33 +422,40 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
if (psv == -1) {
|
||||
status = AE_SUPPORT;
|
||||
} else if (psv > 0) {
|
||||
tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
|
||||
tmp = CELSIUS_TO_KELVIN(psv);
|
||||
status = AE_OK;
|
||||
} else {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_PSV", NULL, &tz->trips.passive.temperature);
|
||||
"_PSV", NULL, &tmp);
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
tz->trips.passive.flags.valid = 0;
|
||||
else {
|
||||
tz->trips.passive.temperature = tmp;
|
||||
tz->trips.passive.flags.valid = 1;
|
||||
if (flag == ACPI_TRIPS_INIT) {
|
||||
status = acpi_evaluate_integer(
|
||||
tz->device->handle, "_TC1",
|
||||
NULL, &tz->trips.passive.tc1);
|
||||
NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
tz->trips.passive.flags.valid = 0;
|
||||
else
|
||||
tz->trips.passive.tc1 = tmp;
|
||||
status = acpi_evaluate_integer(
|
||||
tz->device->handle, "_TC2",
|
||||
NULL, &tz->trips.passive.tc2);
|
||||
NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
tz->trips.passive.flags.valid = 0;
|
||||
else
|
||||
tz->trips.passive.tc2 = tmp;
|
||||
status = acpi_evaluate_integer(
|
||||
tz->device->handle, "_TSP",
|
||||
NULL, &tz->trips.passive.tsp);
|
||||
NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
tz->trips.passive.flags.valid = 0;
|
||||
else
|
||||
tz->trips.passive.tsp = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -479,7 +490,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
|
||||
if (flag & ACPI_TRIPS_ACTIVE) {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
name, NULL, &tz->trips.active[i].temperature);
|
||||
name, NULL, &tmp);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
tz->trips.active[i].flags.valid = 0;
|
||||
if (i == 0)
|
||||
|
|
@ -500,8 +511,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
tz->trips.active[i - 2].temperature :
|
||||
CELSIUS_TO_KELVIN(act));
|
||||
break;
|
||||
} else
|
||||
} else {
|
||||
tz->trips.active[i].temperature = tmp;
|
||||
tz->trips.active[i].flags.valid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
name[2] = 'L';
|
||||
|
|
@ -1213,8 +1226,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
|
|||
acpi_bus_private_data_handler,
|
||||
tz->thermal_zone);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Error attaching device data\n"));
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error attaching device data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
@ -1647,7 +1660,7 @@ static int acpi_thermal_add(struct acpi_device *device)
|
|||
strcpy(tz->name, device->pnp.bus_id);
|
||||
strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
|
||||
acpi_driver_data(device) = tz;
|
||||
device->driver_data = tz;
|
||||
mutex_init(&tz->lock);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -548,7 +548,7 @@ static unsigned long write_video(const char *buffer, unsigned long count)
|
|||
|
||||
hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
|
||||
if (hci_result == HCI_SUCCESS) {
|
||||
int new_video_out = video_out;
|
||||
unsigned int new_video_out = video_out;
|
||||
if (lcd_out != -1)
|
||||
_set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
|
||||
if (crt_out != -1)
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer)
|
|||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Validate that the buffer is of the required length or
|
||||
* allocate a new buffer. Returned buffer is always zeroed.
|
||||
* allocate a new buffer. Returned buffer is always zeroed.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ acpi_status
|
|||
acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
|
||||
acpi_size required_length)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
acpi_size input_buffer_length;
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
|
|
@ -248,55 +248,58 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
|
|||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
switch (buffer->length) {
|
||||
/*
|
||||
* Buffer->Length is used as both an input and output parameter. Get the
|
||||
* input actual length and set the output required buffer length.
|
||||
*/
|
||||
input_buffer_length = buffer->length;
|
||||
buffer->length = required_length;
|
||||
|
||||
/*
|
||||
* The input buffer length contains the actual buffer length, or the type
|
||||
* of buffer to be allocated by this routine.
|
||||
*/
|
||||
switch (input_buffer_length) {
|
||||
case ACPI_NO_BUFFER:
|
||||
|
||||
/* Set the exception and returned the required length */
|
||||
/* Return the exception (and the required buffer length) */
|
||||
|
||||
status = AE_BUFFER_OVERFLOW;
|
||||
break;
|
||||
return (AE_BUFFER_OVERFLOW);
|
||||
|
||||
case ACPI_ALLOCATE_BUFFER:
|
||||
|
||||
/* Allocate a new buffer */
|
||||
|
||||
buffer->pointer = acpi_os_allocate(required_length);
|
||||
if (!buffer->pointer) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Clear the buffer */
|
||||
|
||||
ACPI_MEMSET(buffer->pointer, 0, required_length);
|
||||
break;
|
||||
|
||||
case ACPI_ALLOCATE_LOCAL_BUFFER:
|
||||
|
||||
/* Allocate a new buffer with local interface to allow tracking */
|
||||
|
||||
buffer->pointer = ACPI_ALLOCATE_ZEROED(required_length);
|
||||
if (!buffer->pointer) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
buffer->pointer = ACPI_ALLOCATE(required_length);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Existing buffer: Validate the size of the buffer */
|
||||
|
||||
if (buffer->length < required_length) {
|
||||
status = AE_BUFFER_OVERFLOW;
|
||||
break;
|
||||
if (input_buffer_length < required_length) {
|
||||
return (AE_BUFFER_OVERFLOW);
|
||||
}
|
||||
|
||||
/* Clear the buffer */
|
||||
|
||||
ACPI_MEMSET(buffer->pointer, 0, required_length);
|
||||
break;
|
||||
}
|
||||
|
||||
buffer->length = required_length;
|
||||
return (status);
|
||||
/* Validate allocation from above or input buffer pointer */
|
||||
|
||||
if (!buffer->pointer) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Have a valid buffer, clear it */
|
||||
|
||||
ACPI_MEMSET(buffer->pointer, 0, required_length);
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
#ifdef NOT_USED_BY_LINUX
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@
|
|||
*/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
|
||||
|
||||
|
|
@ -176,20 +175,24 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
|
|||
|
||||
/* This is an object reference. */
|
||||
|
||||
switch (internal_object->reference.opcode) {
|
||||
case AML_INT_NAMEPATH_OP:
|
||||
|
||||
/* For namepath, return the object handle ("reference") */
|
||||
|
||||
default:
|
||||
|
||||
/* We are referring to the namespace node */
|
||||
switch (internal_object->reference.class) {
|
||||
case ACPI_REFCLASS_NAME:
|
||||
|
||||
/*
|
||||
* For namepath, return the object handle ("reference")
|
||||
* We are referring to the namespace node
|
||||
*/
|
||||
external_object->reference.handle =
|
||||
internal_object->reference.node;
|
||||
external_object->reference.actual_type =
|
||||
acpi_ns_get_type(internal_object->reference.node);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* All other reference types are unsupported */
|
||||
|
||||
return_ACPI_STATUS(AE_TYPE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -533,7 +536,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
|
|||
|
||||
/* TBD: should validate incoming handle */
|
||||
|
||||
internal_object->reference.opcode = AML_INT_NAMEPATH_OP;
|
||||
internal_object->reference.class = ACPI_REFCLASS_NAME;
|
||||
internal_object->reference.node =
|
||||
external_object->reference.handle;
|
||||
break;
|
||||
|
|
@ -743,11 +746,11 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
|
|||
* We copied the reference object, so we now must add a reference
|
||||
* to the object pointed to by the reference
|
||||
*
|
||||
* DDBHandle reference (from Load/load_table is a special reference,
|
||||
* it's Reference.Object is the table index, so does not need to
|
||||
* DDBHandle reference (from Load/load_table) is a special reference,
|
||||
* it does not have a Reference.Object, so does not need to
|
||||
* increase the reference count
|
||||
*/
|
||||
if (source_desc->reference.opcode == AML_LOAD_OP) {
|
||||
if (source_desc->reference.class == ACPI_REFCLASS_TABLE) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acevents.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
#define _COMPONENT ACPI_UTILITIES
|
||||
ACPI_MODULE_NAME("utdelete")
|
||||
|
|
@ -548,8 +547,8 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
|
|||
* reference must track changes to the ref count of the index or
|
||||
* target object.
|
||||
*/
|
||||
if ((object->reference.opcode == AML_INDEX_OP) ||
|
||||
(object->reference.opcode == AML_INT_NAMEPATH_OP)) {
|
||||
if ((object->reference.class == ACPI_REFCLASS_INDEX) ||
|
||||
(object->reference.class == ACPI_REFCLASS_NAME)) {
|
||||
next_object = object->reference.object;
|
||||
}
|
||||
break;
|
||||
|
|
@ -586,6 +585,13 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
|
|||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"Could not update object reference count"));
|
||||
|
||||
/* Free any stacked Update State objects */
|
||||
|
||||
while (state_list) {
|
||||
state = acpi_ut_pop_generic_state(&state_list);
|
||||
acpi_ut_delete_generic_state(state);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -281,7 +281,6 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = {
|
|||
/* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
|
||||
ACPI_BITPOSITION_RT_CLOCK_ENABLE,
|
||||
ACPI_BITMASK_RT_CLOCK_ENABLE},
|
||||
/* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0},
|
||||
/* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE,
|
||||
ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE,
|
||||
ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
|
||||
|
|
@ -575,6 +574,47 @@ char *acpi_ut_get_descriptor_name(void *object)
|
|||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_get_reference_name
|
||||
*
|
||||
* PARAMETERS: Object - An ACPI reference object
|
||||
*
|
||||
* RETURN: Pointer to a string
|
||||
*
|
||||
* DESCRIPTION: Decode a reference object sub-type to a string.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* Printable names of reference object sub-types */
|
||||
|
||||
static const char *acpi_gbl_ref_class_names[] = {
|
||||
/* 00 */ "Local",
|
||||
/* 01 */ "Argument",
|
||||
/* 02 */ "RefOf",
|
||||
/* 03 */ "Index",
|
||||
/* 04 */ "DdbHandle",
|
||||
/* 05 */ "Named Object",
|
||||
/* 06 */ "Debug"
|
||||
};
|
||||
|
||||
const char *acpi_ut_get_reference_name(union acpi_operand_object *object)
|
||||
{
|
||||
if (!object)
|
||||
return "NULL Object";
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND)
|
||||
return "Not an Operand object";
|
||||
|
||||
if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE)
|
||||
return "Not a Reference object";
|
||||
|
||||
if (object->reference.class > ACPI_REFCLASS_MAX)
|
||||
return "Unknown Reference class";
|
||||
|
||||
return acpi_gbl_ref_class_names[object->reference.class];
|
||||
}
|
||||
|
||||
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
|
||||
/*
|
||||
* Strings and procedures used for debug only
|
||||
|
|
@ -677,14 +717,14 @@ u8 acpi_ut_valid_object_type(acpi_object_type type)
|
|||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: None
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Init library globals. All globals that require specific
|
||||
* initialization should be initialized here!
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_ut_init_globals(void)
|
||||
acpi_status acpi_ut_init_globals(void)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 i;
|
||||
|
|
@ -695,7 +735,7 @@ void acpi_ut_init_globals(void)
|
|||
|
||||
status = acpi_ut_create_caches();
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return;
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Mutex locked flags */
|
||||
|
|
@ -772,8 +812,8 @@ void acpi_ut_init_globals(void)
|
|||
acpi_gbl_display_final_mem_stats = FALSE;
|
||||
#endif
|
||||
|
||||
return_VOID;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_dbg_level)
|
||||
ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
|
||||
ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
|
||||
|
|
|
|||
|
|
@ -995,6 +995,15 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
|
|||
state->pkg.
|
||||
this_target_obj, 0);
|
||||
if (!state) {
|
||||
|
||||
/* Free any stacked Update State objects */
|
||||
|
||||
while (state_list) {
|
||||
state =
|
||||
acpi_ut_pop_generic_state
|
||||
(&state_list);
|
||||
acpi_ut_delete_generic_state(state);
|
||||
}
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
#define _COMPONENT ACPI_UTILITIES
|
||||
ACPI_MODULE_NAME("utobject")
|
||||
|
|
@ -478,8 +477,8 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
|
|||
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
switch (internal_object->reference.opcode) {
|
||||
case AML_INT_NAMEPATH_OP:
|
||||
switch (internal_object->reference.class) {
|
||||
case ACPI_REFCLASS_NAME:
|
||||
|
||||
/*
|
||||
* Get the actual length of the full pathname to this object.
|
||||
|
|
@ -503,8 +502,10 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
|
|||
* required eventually.
|
||||
*/
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Unsupported Reference opcode=%X in object %p",
|
||||
internal_object->reference.opcode,
|
||||
"Cannot convert to external object - "
|
||||
"unsupported Reference Class [%s] %X in object %p",
|
||||
acpi_ut_get_reference_name(internal_object),
|
||||
internal_object->reference.class,
|
||||
internal_object));
|
||||
status = AE_TYPE;
|
||||
break;
|
||||
|
|
@ -513,7 +514,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
|
|||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO, "Unsupported type=%X in object %p",
|
||||
ACPI_ERROR((AE_INFO, "Cannot convert to external object - "
|
||||
"unsupported type [%s] %X in object %p",
|
||||
acpi_ut_get_object_type_name(internal_object),
|
||||
ACPI_GET_OBJECT_TYPE(internal_object),
|
||||
internal_object));
|
||||
status = AE_TYPE;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,12 @@ acpi_status __init acpi_initialize_subsystem(void)
|
|||
|
||||
/* Initialize all globals used by the subsystem */
|
||||
|
||||
acpi_ut_init_globals();
|
||||
status = acpi_ut_init_globals();
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"During initialization of globals"));
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Create the default mutex objects */
|
||||
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ EXPORT_SYMBOL(acpi_extract_package);
|
|||
acpi_status
|
||||
acpi_evaluate_integer(acpi_handle handle,
|
||||
acpi_string pathname,
|
||||
struct acpi_object_list *arguments, unsigned long *data)
|
||||
struct acpi_object_list *arguments, unsigned long long *data)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_object *element;
|
||||
|
|
@ -288,7 +288,7 @@ acpi_evaluate_integer(acpi_handle handle,
|
|||
*data = element->integer.value;
|
||||
kfree(element);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data));
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,20 +291,20 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
|
|||
int level);
|
||||
static int acpi_video_device_lcd_get_level_current(
|
||||
struct acpi_video_device *device,
|
||||
unsigned long *level);
|
||||
unsigned long long *level);
|
||||
static int acpi_video_get_next_level(struct acpi_video_device *device,
|
||||
u32 level_current, u32 event);
|
||||
static void acpi_video_switch_brightness(struct acpi_video_device *device,
|
||||
int event);
|
||||
static int acpi_video_device_get_state(struct acpi_video_device *device,
|
||||
unsigned long *state);
|
||||
unsigned long long *state);
|
||||
static int acpi_video_output_get(struct output_device *od);
|
||||
static int acpi_video_device_set_state(struct acpi_video_device *device, int state);
|
||||
|
||||
/*backlight device sysfs support*/
|
||||
static int acpi_video_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
unsigned long cur_level;
|
||||
unsigned long long cur_level;
|
||||
int i;
|
||||
struct acpi_video_device *vd =
|
||||
(struct acpi_video_device *)bl_get_data(bd);
|
||||
|
|
@ -336,7 +336,7 @@ static struct backlight_ops acpi_backlight_ops = {
|
|||
/*video output device sysfs support*/
|
||||
static int acpi_video_output_get(struct output_device *od)
|
||||
{
|
||||
unsigned long state;
|
||||
unsigned long long state;
|
||||
struct acpi_video_device *vd =
|
||||
(struct acpi_video_device *)dev_get_drvdata(&od->dev);
|
||||
acpi_video_device_get_state(vd, &state);
|
||||
|
|
@ -370,7 +370,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
|
|||
{
|
||||
struct acpi_device *device = cdev->devdata;
|
||||
struct acpi_video_device *video = acpi_driver_data(device);
|
||||
unsigned long level;
|
||||
unsigned long long level;
|
||||
int state;
|
||||
|
||||
acpi_video_device_lcd_get_level_current(video, &level);
|
||||
|
|
@ -410,7 +410,7 @@ static struct thermal_cooling_device_ops video_cooling_ops = {
|
|||
/* device */
|
||||
|
||||
static int
|
||||
acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
|
||||
acpi_video_device_query(struct acpi_video_device *device, unsigned long long *state)
|
||||
{
|
||||
int status;
|
||||
|
||||
|
|
@ -421,7 +421,7 @@ acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
|
|||
|
||||
static int
|
||||
acpi_video_device_get_state(struct acpi_video_device *device,
|
||||
unsigned long *state)
|
||||
unsigned long long *state)
|
||||
{
|
||||
int status;
|
||||
|
||||
|
|
@ -436,7 +436,7 @@ acpi_video_device_set_state(struct acpi_video_device *device, int state)
|
|||
int status;
|
||||
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
|
||||
struct acpi_object_list args = { 1, &arg0 };
|
||||
unsigned long ret;
|
||||
unsigned long long ret;
|
||||
|
||||
|
||||
arg0.integer.value = state;
|
||||
|
|
@ -495,7 +495,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
|
|||
|
||||
static int
|
||||
acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
|
||||
unsigned long *level)
|
||||
unsigned long long *level)
|
||||
{
|
||||
if (device->cap._BQC)
|
||||
return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL,
|
||||
|
|
@ -549,7 +549,7 @@ static int
|
|||
acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
|
||||
{
|
||||
int status;
|
||||
unsigned long tmp;
|
||||
unsigned long long tmp;
|
||||
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
|
||||
struct acpi_object_list args = { 1, &arg0 };
|
||||
|
||||
|
|
@ -564,7 +564,7 @@ acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
|
|||
}
|
||||
|
||||
static int
|
||||
acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
|
||||
acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id)
|
||||
{
|
||||
int status;
|
||||
|
||||
|
|
@ -575,7 +575,7 @@ acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
|
|||
|
||||
static int
|
||||
acpi_video_bus_POST_options(struct acpi_video_bus *video,
|
||||
unsigned long *options)
|
||||
unsigned long long *options)
|
||||
{
|
||||
int status;
|
||||
|
||||
|
|
@ -918,7 +918,7 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
|
|||
{
|
||||
int status;
|
||||
struct acpi_video_device *dev = seq->private;
|
||||
unsigned long state;
|
||||
unsigned long long state;
|
||||
|
||||
|
||||
if (!dev)
|
||||
|
|
@ -927,14 +927,14 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
|
|||
status = acpi_video_device_get_state(dev, &state);
|
||||
seq_printf(seq, "state: ");
|
||||
if (ACPI_SUCCESS(status))
|
||||
seq_printf(seq, "0x%02lx\n", state);
|
||||
seq_printf(seq, "0x%02llx\n", state);
|
||||
else
|
||||
seq_printf(seq, "<not supported>\n");
|
||||
|
||||
status = acpi_video_device_query(dev, &state);
|
||||
seq_printf(seq, "query: ");
|
||||
if (ACPI_SUCCESS(status))
|
||||
seq_printf(seq, "0x%02lx\n", state);
|
||||
seq_printf(seq, "0x%02llx\n", state);
|
||||
else
|
||||
seq_printf(seq, "<not supported>\n");
|
||||
|
||||
|
|
@ -1217,7 +1217,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
|
|||
static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_video_bus *video = seq->private;
|
||||
unsigned long options;
|
||||
unsigned long long options;
|
||||
int status;
|
||||
|
||||
|
||||
|
|
@ -1232,7 +1232,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
|
|||
printk(KERN_WARNING PREFIX
|
||||
"This indicates a BIOS bug. Please contact the manufacturer.\n");
|
||||
}
|
||||
printk("%lx\n", options);
|
||||
printk("%llx\n", options);
|
||||
seq_printf(seq, "can POST: <integrated video>");
|
||||
if (options & 2)
|
||||
seq_printf(seq, " <PCI video>");
|
||||
|
|
@ -1256,7 +1256,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
|
|||
{
|
||||
struct acpi_video_bus *video = seq->private;
|
||||
int status;
|
||||
unsigned long id;
|
||||
unsigned long long id;
|
||||
|
||||
|
||||
if (!video)
|
||||
|
|
@ -1303,7 +1303,7 @@ acpi_video_bus_write_POST(struct file *file,
|
|||
struct seq_file *m = file->private_data;
|
||||
struct acpi_video_bus *video = m->private;
|
||||
char str[12] = { 0 };
|
||||
unsigned long opt, options;
|
||||
unsigned long long opt, options;
|
||||
|
||||
|
||||
if (!video || count + 1 > sizeof str)
|
||||
|
|
@ -1473,7 +1473,7 @@ static int
|
|||
acpi_video_bus_get_one_device(struct acpi_device *device,
|
||||
struct acpi_video_bus *video)
|
||||
{
|
||||
unsigned long device_id;
|
||||
unsigned long long device_id;
|
||||
int status;
|
||||
struct acpi_video_device *data;
|
||||
struct acpi_video_device_attrib* attribute;
|
||||
|
|
@ -1491,7 +1491,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
|
|||
|
||||
strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
|
||||
acpi_driver_data(device) = data;
|
||||
device->driver_data = data;
|
||||
|
||||
data->device_id = device_id;
|
||||
data->video = video;
|
||||
|
|
@ -1530,8 +1530,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
|
|||
acpi_video_device_notify,
|
||||
data);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Error installing notify handler\n"));
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error installing notify handler\n");
|
||||
if(data->brightness)
|
||||
kfree(data->brightness->levels);
|
||||
kfree(data->brightness);
|
||||
|
|
@ -1724,7 +1724,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
|
|||
static void
|
||||
acpi_video_switch_brightness(struct acpi_video_device *device, int event)
|
||||
{
|
||||
unsigned long level_current, level_next;
|
||||
unsigned long long level_current, level_next;
|
||||
if (!device->brightness)
|
||||
return;
|
||||
acpi_video_device_lcd_get_level_current(device, &level_current);
|
||||
|
|
@ -1745,8 +1745,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
|
|||
|
||||
status = acpi_video_bus_get_one_device(dev, video);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
|
||||
"Cant attach device"));
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Cant attach device");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -1982,7 +1982,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
|||
video->device = device;
|
||||
strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
|
||||
acpi_driver_data(device) = video;
|
||||
device->driver_data = video;
|
||||
|
||||
acpi_video_bus_find_cap(video);
|
||||
error = acpi_video_bus_check(video);
|
||||
|
|
@ -2003,8 +2003,8 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
|||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_bus_notify, video);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Error installing notify handler\n"));
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error installing notify handler\n");
|
||||
error = -ENODEV;
|
||||
goto err_stop_video;
|
||||
}
|
||||
|
|
@ -2058,7 +2058,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
|||
acpi_video_bus_remove_fs(device);
|
||||
err_free_video:
|
||||
kfree(video);
|
||||
acpi_driver_data(device) = NULL;
|
||||
device->driver_data = NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,6 +217,35 @@ static bool find_guid(const char *guid_string, struct wmi_block **out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
|
||||
{
|
||||
struct guid_block *block = NULL;
|
||||
char method[5];
|
||||
struct acpi_object_list input;
|
||||
union acpi_object params[1];
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
|
||||
block = &wblock->gblock;
|
||||
handle = wblock->handle;
|
||||
|
||||
if (!block)
|
||||
return AE_NOT_EXIST;
|
||||
|
||||
input.count = 1;
|
||||
input.pointer = params;
|
||||
params[0].type = ACPI_TYPE_INTEGER;
|
||||
params[0].integer.value = enable;
|
||||
|
||||
snprintf(method, 5, "WE%02X", block->notify_id);
|
||||
status = acpi_evaluate_object(handle, method, &input, NULL);
|
||||
|
||||
if (status != AE_OK && status != AE_NOT_FOUND)
|
||||
return status;
|
||||
else
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exported WMI functions
|
||||
*/
|
||||
|
|
@ -242,7 +271,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
|
|||
char method[4] = "WM";
|
||||
|
||||
if (!find_guid(guid_string, &wblock))
|
||||
return AE_BAD_ADDRESS;
|
||||
return AE_ERROR;
|
||||
|
||||
block = &wblock->gblock;
|
||||
handle = wblock->handle;
|
||||
|
|
@ -304,7 +333,7 @@ struct acpi_buffer *out)
|
|||
return AE_BAD_PARAMETER;
|
||||
|
||||
if (!find_guid(guid_string, &wblock))
|
||||
return AE_BAD_ADDRESS;
|
||||
return AE_ERROR;
|
||||
|
||||
block = &wblock->gblock;
|
||||
handle = wblock->handle;
|
||||
|
|
@ -314,7 +343,7 @@ struct acpi_buffer *out)
|
|||
|
||||
/* Check GUID is a data block */
|
||||
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
|
||||
return AE_BAD_ADDRESS;
|
||||
return AE_ERROR;
|
||||
|
||||
input.count = 1;
|
||||
input.pointer = wq_params;
|
||||
|
|
@ -385,7 +414,7 @@ const struct acpi_buffer *in)
|
|||
return AE_BAD_DATA;
|
||||
|
||||
if (!find_guid(guid_string, &wblock))
|
||||
return AE_BAD_ADDRESS;
|
||||
return AE_ERROR;
|
||||
|
||||
block = &wblock->gblock;
|
||||
handle = wblock->handle;
|
||||
|
|
@ -395,7 +424,7 @@ const struct acpi_buffer *in)
|
|||
|
||||
/* Check GUID is a data block */
|
||||
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
|
||||
return AE_BAD_ADDRESS;
|
||||
return AE_ERROR;
|
||||
|
||||
input.count = 2;
|
||||
input.pointer = params;
|
||||
|
|
@ -427,6 +456,7 @@ acpi_status wmi_install_notify_handler(const char *guid,
|
|||
wmi_notify_handler handler, void *data)
|
||||
{
|
||||
struct wmi_block *block;
|
||||
acpi_status status;
|
||||
|
||||
if (!guid || !handler)
|
||||
return AE_BAD_PARAMETER;
|
||||
|
|
@ -441,7 +471,9 @@ wmi_notify_handler handler, void *data)
|
|||
block->handler = handler;
|
||||
block->handler_data = data;
|
||||
|
||||
return AE_OK;
|
||||
status = wmi_method_enable(block, 1);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
|
||||
|
||||
|
|
@ -453,6 +485,7 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
|
|||
acpi_status wmi_remove_notify_handler(const char *guid)
|
||||
{
|
||||
struct wmi_block *block;
|
||||
acpi_status status;
|
||||
|
||||
if (!guid)
|
||||
return AE_BAD_PARAMETER;
|
||||
|
|
@ -464,10 +497,12 @@ acpi_status wmi_remove_notify_handler(const char *guid)
|
|||
if (!block->handler)
|
||||
return AE_NULL_ENTRY;
|
||||
|
||||
status = wmi_method_enable(block, 0);
|
||||
|
||||
block->handler = NULL;
|
||||
block->handler_data = NULL;
|
||||
|
||||
return AE_OK;
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue