diff options
author | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-11-22 19:06:44 +0100 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-11-22 19:06:44 +0100 |
commit | 0bd2af46839ad6262d25714a6ec0365db9d6b98f (patch) | |
tree | dcced72d230d69fd0c5816ac6dd03ab84799a93e /drivers/acpi | |
parent | [SCSI] aic94xx: fix pointer to integer conversion warning (diff) | |
parent | [PATCH] qla4xxx: bug fix: driver hardware semaphore needs to be grabbed befor... (diff) | |
download | linux-0bd2af46839ad6262d25714a6ec0365db9d6b98f.tar.xz linux-0bd2af46839ad6262d25714a6ec0365db9d6b98f.zip |
Merge ../scsi-rc-fixes-2.6
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpi_memhotplug.c | 14 | ||||
-rw-r--r-- | drivers/acpi/asus_acpi.c | 67 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 14 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 1096 | ||||
-rw-r--r-- | drivers/acpi/events/evmisc.c | 14 | ||||
-rw-r--r-- | drivers/acpi/events/evrgnini.c | 13 | ||||
-rw-r--r-- | drivers/acpi/ibm_acpi.c | 2 | ||||
-rw-r--r-- | drivers/acpi/motherboard.c | 6 | ||||
-rw-r--r-- | drivers/acpi/pci_link.c | 2 | ||||
-rw-r--r-- | drivers/acpi/power.c | 9 | ||||
-rw-r--r-- | drivers/acpi/processor_core.c | 2 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 111 | ||||
-rw-r--r-- | drivers/acpi/sbs.c | 20 | ||||
-rw-r--r-- | drivers/acpi/tables/tbget.c | 2 | ||||
-rw-r--r-- | drivers/acpi/tables/tbrsdt.c | 2 |
15 files changed, 461 insertions, 913 deletions
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 98099de59b45..6bcd9e8e7bcb 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -85,6 +85,8 @@ struct acpi_memory_device { struct list_head res_list; }; +static int acpi_hotmem_initialized; + static acpi_status acpi_memory_get_resource(struct acpi_resource *resource, void *context) { @@ -414,7 +416,7 @@ static int acpi_memory_device_add(struct acpi_device *device) /* Set the device state */ mem_device->state = MEMORY_POWER_ON_STATE; - printk(KERN_INFO "%s \n", acpi_device_name(device)); + printk(KERN_DEBUG "%s \n", acpi_device_name(device)); return result; } @@ -438,6 +440,15 @@ static int acpi_memory_device_start (struct acpi_device *device) struct acpi_memory_device *mem_device; int result = 0; + /* + * Early boot code has recognized memory area by EFI/E820. + * If DSDT shows these memory devices on boot, hotplug is not necessary + * for them. So, it just returns until completion of this driver's + * start up. + */ + if (!acpi_hotmem_initialized) + return 0; + mem_device = acpi_driver_data(device); if (!acpi_memory_check_device(mem_device)) { @@ -537,6 +548,7 @@ static int __init acpi_memory_device_init(void) return -ENODEV; } + acpi_hotmem_initialized = 1; return 0; } diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index e9ee4c52a5f6..c7ac9297a204 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -138,6 +138,7 @@ struct asus_hotk { S2x, //S200 (J1 reported), Victor MP-XP7210 W1N, //W1000N W5A, //W5A + W3V, //W3030V xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N //(Centrino) END_MODEL @@ -376,6 +377,17 @@ static struct model_data model_conf[END_MODEL] = { .display_get = "\\ADVG"}, { + .name = "W3V", + .mt_mled = "MLED", + .mt_wled = "WLED", + .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\BKLT", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\INFB"}, + + { .name = "xxN", .mt_mled = "MLED", /* WLED present, but not controlled by ACPI */ @@ -555,11 +567,11 @@ static int write_led(const char __user * buffer, unsigned long count, char *ledname, int ledmask, int invert) { - int value; + int rv, value; int led_out = 0; - count = parse_arg(buffer, count, &value); - if (count > 0) + rv = parse_arg(buffer, count, &value); + if (rv > 0) led_out = value ? 1 : 0; hotk->status = @@ -572,7 +584,7 @@ write_led(const char __user * buffer, unsigned long count, printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n", ledname); - return count; + return rv; } /* @@ -607,20 +619,18 @@ static int proc_write_ledd(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int value; + int rv, value; - count = parse_arg(buffer, count, &value); - if (count > 0) { + rv = parse_arg(buffer, count, &value); + if (rv > 0) { if (!write_acpi_int (hotk->handle, hotk->methods->mt_ledd, value, NULL)) printk(KERN_WARNING "Asus ACPI: LED display write failed\n"); else hotk->ledd_status = (u32) value; - } else if (count < 0) - printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); - - return count; + } + return rv; } /* @@ -761,12 +771,12 @@ static int proc_write_lcd(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int value; + int rv, value; - count = parse_arg(buffer, count, &value); - if (count > 0) + rv = parse_arg(buffer, count, &value); + if (rv > 0) set_lcd_state(value); - return count; + return rv; } static int read_brightness(void) @@ -830,18 +840,15 @@ static int proc_write_brn(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int value; + int rv, value; - count = parse_arg(buffer, count, &value); - if (count > 0) { + rv = parse_arg(buffer, count, &value); + if (rv > 0) { value = (0 < value) ? ((15 < value) ? 15 : value) : 0; /* 0 <= value <= 15 */ set_brightness(value); - } else if (count < 0) { - printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); } - - return count; + return rv; } static void set_display(int value) @@ -880,15 +887,12 @@ static int proc_write_disp(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int value; + int rv, value; - count = parse_arg(buffer, count, &value); - if (count > 0) + rv = parse_arg(buffer, count, &value); + if (rv > 0) set_display(value); - else if (count < 0) - printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); - - return count; + return rv; } typedef int (proc_readfunc) (char *page, char **start, off_t off, int count, @@ -1097,6 +1101,8 @@ static int asus_model_match(char *model) return A4G; else if (strncmp(model, "W1N", 3) == 0) return W1N; + else if (strncmp(model, "W3V", 3) == 0) + return W3V; else if (strncmp(model, "W5A", 3) == 0) return W5A; else @@ -1200,9 +1206,10 @@ static int asus_hotk_get_info(void) hotk->methods->mt_wled = NULL; /* L5D's WLED is not controlled by ACPI */ else if (strncmp(string, "M2N", 3) == 0 || + strncmp(string, "W3V", 3) == 0 || strncmp(string, "S1N", 3) == 0) hotk->methods->mt_wled = "WLED"; - /* M2N and S1N have a usable WLED */ + /* M2N, S1N and W3V have a usable WLED */ else if (asus_info) { if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) hotk->methods->mled_status = NULL; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 9810e2a55d0a..026e40755cdd 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -64,6 +64,7 @@ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); static int acpi_battery_add(struct acpi_device *device); static int acpi_battery_remove(struct acpi_device *device, int type); +static int acpi_battery_resume(struct acpi_device *device, int status); static struct acpi_driver acpi_battery_driver = { .name = ACPI_BATTERY_DRIVER_NAME, @@ -71,6 +72,7 @@ static struct acpi_driver acpi_battery_driver = { .ids = ACPI_BATTERY_HID, .ops = { .add = acpi_battery_add, + .resume = acpi_battery_resume, .remove = acpi_battery_remove, }, }; @@ -753,6 +755,18 @@ static int acpi_battery_remove(struct acpi_device *device, int type) return 0; } +/* this is needed to learn about changes made in suspended state */ +static int acpi_battery_resume(struct acpi_device *device, int state) +{ + struct acpi_battery *battery; + + if (!device) + return -EINVAL; + + battery = device->driver_data; + return acpi_battery_check(battery); +} + static int __init acpi_battery_init(void) { int result; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index e5d796362854..e6d4b084dca2 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -45,206 +45,143 @@ ACPI_MODULE_NAME("acpi_ec") #define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver" #define ACPI_EC_DEVICE_NAME "Embedded Controller" #define ACPI_EC_FILE_INFO "info" + +/* EC status register */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ -#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */ -#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */ -#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ -#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ -#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ -#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ + +/* EC commands */ #define ACPI_EC_COMMAND_READ 0x80 #define ACPI_EC_COMMAND_WRITE 0x81 #define ACPI_EC_BURST_ENABLE 0x82 #define ACPI_EC_BURST_DISABLE 0x83 #define ACPI_EC_COMMAND_QUERY 0x84 -#define EC_POLL 0xFF -#define EC_INTR 0x00 + +/* EC events */ +enum { + ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ + ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ +}; + +#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ +#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ +#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ +#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ + +enum { + EC_INTR = 1, /* Output buffer full */ + EC_POLL, /* Input buffer empty */ +}; + static int acpi_ec_remove(struct acpi_device *device, int type); static int acpi_ec_start(struct acpi_device *device); static int acpi_ec_stop(struct acpi_device *device, int type); -static int acpi_ec_intr_add(struct acpi_device *device); -static int acpi_ec_poll_add(struct acpi_device *device); +static int acpi_ec_add(struct acpi_device *device); static struct acpi_driver acpi_ec_driver = { .name = ACPI_EC_DRIVER_NAME, .class = ACPI_EC_CLASS, .ids = ACPI_EC_HID, .ops = { - .add = acpi_ec_intr_add, + .add = acpi_ec_add, .remove = acpi_ec_remove, .start = acpi_ec_start, .stop = acpi_ec_stop, }, }; -union acpi_ec { - struct { - u32 mode; - acpi_handle handle; - unsigned long uid; - unsigned long gpe_bit; - struct acpi_generic_address status_addr; - struct acpi_generic_address command_addr; - struct acpi_generic_address data_addr; - unsigned long global_lock; - } common; - - struct { - u32 mode; - acpi_handle handle; - unsigned long uid; - unsigned long gpe_bit; - struct acpi_generic_address status_addr; - struct acpi_generic_address command_addr; - struct acpi_generic_address data_addr; - unsigned long global_lock; - unsigned int expect_event; - atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ - atomic_t pending_gpe; - struct semaphore sem; - wait_queue_head_t wait; - } intr; - - struct { - u32 mode; - acpi_handle handle; - unsigned long uid; - unsigned long gpe_bit; - struct acpi_generic_address status_addr; - struct acpi_generic_address command_addr; - struct acpi_generic_address data_addr; - unsigned long global_lock; - struct semaphore sem; - } poll; -}; -static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event); -static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event); -static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data); -static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data); -static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data); -static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data); -static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data); -static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data); -static void acpi_ec_gpe_poll_query(void *ec_cxt); -static void acpi_ec_gpe_intr_query(void *ec_cxt); -static u32 acpi_ec_gpe_poll_handler(void *data); -static u32 acpi_ec_gpe_intr_handler(void *data); -static acpi_status __init -acpi_fake_ecdt_poll_callback(acpi_handle handle, - u32 Level, void *context, void **retval); - -static acpi_status __init -acpi_fake_ecdt_intr_callback(acpi_handle handle, - u32 Level, void *context, void **retval); - -static int __init acpi_ec_poll_get_real_ecdt(void); -static int __init acpi_ec_intr_get_real_ecdt(void); /* If we find an EC via the ECDT, we need to keep a ptr to its context */ -static union acpi_ec *ec_ecdt; +struct acpi_ec { + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + unsigned long command_addr; + unsigned long data_addr; + unsigned long global_lock; + struct semaphore sem; + unsigned int expect_event; + atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ + wait_queue_head_t wait; +} *ec_ecdt; /* External interfaces use first EC only, so remember */ static struct acpi_device *first_ec; -static int acpi_ec_poll_mode = EC_INTR; +static int acpi_ec_mode = EC_INTR; /* -------------------------------------------------------------------------- Transaction Management -------------------------------------------------------------------------- */ -static u32 acpi_ec_read_status(union acpi_ec *ec) +static inline u8 acpi_ec_read_status(struct acpi_ec *ec) { - u32 status = 0; - - acpi_hw_low_level_read(8, &status, &ec->common.status_addr); - return status; + return inb(ec->command_addr); } -static int acpi_ec_wait(union acpi_ec *ec, u8 event) +static inline u8 acpi_ec_read_data(struct acpi_ec *ec) { - if (acpi_ec_poll_mode) - return acpi_ec_poll_wait(ec, event); - else - return acpi_ec_intr_wait(ec, event); + return inb(ec->data_addr); } -static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event) +static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) { - u32 acpi_ec_status = 0; - u32 i = ACPI_EC_UDELAY_COUNT; + outb(command, ec->command_addr); +} - if (!ec) - return -EINVAL; +static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) +{ + outb(data, ec->data_addr); +} - /* Poll the EC status register waiting for the event to occur. */ +static int acpi_ec_check_status(u8 status, u8 event) +{ switch (event) { - case ACPI_EC_EVENT_OBF: - do { - acpi_hw_low_level_read(8, &acpi_ec_status, - &ec->common.status_addr); - if (acpi_ec_status & ACPI_EC_FLAG_OBF) - return 0; - udelay(ACPI_EC_UDELAY); - } while (--i > 0); + case ACPI_EC_EVENT_OBF_1: + if (status & ACPI_EC_FLAG_OBF) + return 1; break; - case ACPI_EC_EVENT_IBE: - do { - acpi_hw_low_level_read(8, &acpi_ec_status, - &ec->common.status_addr); - if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) - return 0; - udelay(ACPI_EC_UDELAY); - } while (--i > 0); + case ACPI_EC_EVENT_IBF_0: + if (!(status & ACPI_EC_FLAG_IBF)) + return 1; break; default: - return -EINVAL; + break; } - return -ETIME; + return 0; } -static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event) -{ - int result = 0; - - ec->intr.expect_event = event; - smp_mb(); +static int acpi_ec_wait(struct acpi_ec *ec, u8 event) +{ + int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0; + long time_left; - switch (event) { - case ACPI_EC_EVENT_IBE: - if (~acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) { - ec->intr.expect_event = 0; - return 0; - } - break; - default: - break; + ec->expect_event = event; + if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) { + ec->expect_event = 0; + return 0; } - result = wait_event_timeout(ec->intr.wait, - !ec->intr.expect_event, + do { + if (acpi_ec_mode == EC_POLL) { + udelay(ACPI_EC_UDELAY); + } else { + time_left = wait_event_timeout(ec->wait, + !ec->expect_event, msecs_to_jiffies(ACPI_EC_DELAY)); - - ec->intr.expect_event = 0; - smp_mb(); - - /* - * Verify that the event in question has actually happened by - * querying EC status. Do the check even if operation timed-out - * to make sure that we did not miss interrupt. - */ - switch (event) { - case ACPI_EC_EVENT_OBF: - if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) + if (time_left > 0) { + ec->expect_event = 0; + return 0; + } + } + if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) { + ec->expect_event = 0; return 0; - break; + } + } while (--i > 0); - case ACPI_EC_EVENT_IBE: - if (~acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) - return 0; - break; - } + ec->expect_event = 0; return -ETIME; } @@ -254,272 +191,150 @@ static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event) * Note: samsung nv5000 doesn't work with ec burst mode. * http://bugzilla.kernel.org/show_bug.cgi?id=4980 */ -int acpi_ec_enter_burst_mode(union acpi_ec *ec) +int acpi_ec_enter_burst_mode(struct acpi_ec *ec) { - u32 tmp = 0; - int status = 0; + u8 tmp = 0; + u8 status = 0; status = acpi_ec_read_status(ec); if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); if (status) goto end; - acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, - &ec->common.command_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); + acpi_ec_write_cmd(ec, ACPI_EC_BURST_ENABLE); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); + tmp = acpi_ec_read_data(ec); if (tmp != 0x90) { /* Burst ACK byte */ return -EINVAL; } } - atomic_set(&ec->intr.leaving_burst, 0); + atomic_set(&ec->leaving_burst, 0); return 0; - end: - ACPI_EXCEPTION ((AE_INFO, status, "EC wait, burst mode"); + end: + ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode")); return -1; } -int acpi_ec_leave_burst_mode(union acpi_ec *ec) +int acpi_ec_leave_burst_mode(struct acpi_ec *ec) { - int status = 0; + u8 status = 0; status = acpi_ec_read_status(ec); if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){ - status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); if(status) goto end; - acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr); - acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); - } - atomic_set(&ec->intr.leaving_burst, 1); + acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE); + acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + } + atomic_set(&ec->leaving_burst, 1); return 0; -end: - ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode"); + end: + ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode")); return -1; } #endif /* ACPI_FUTURE_USAGE */ -static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data) -{ - if (acpi_ec_poll_mode) - return acpi_ec_poll_read(ec, address, data); - else - return acpi_ec_intr_read(ec, address, data); -} -static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data) -{ - if (acpi_ec_poll_mode) - return acpi_ec_poll_write(ec, address, data); - else - return acpi_ec_intr_write(ec, address, data); -} -static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) +static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len) { - acpi_status status = AE_OK; - int result = 0; - u32 glk = 0; + int result; + acpi_ec_write_cmd(ec, command); - if (!ec || !data) - return -EINVAL; - - *data = 0; - - if (ec->common.global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return -ENODEV; + for (; wdata_len > 0; wdata_len --) { + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + if (result) + return result; + acpi_ec_write_data(ec, *(wdata++)); } - if (down_interruptible(&ec->poll.sem)) { - result = -ERESTARTSYS; - goto end_nosem; + if (command == ACPI_EC_COMMAND_WRITE) { + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + if (result) + return result; } - - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, - &ec->common.command_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) - goto end; - - acpi_hw_low_level_write(8, address, &ec->common.data_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (result) - goto end; - - acpi_hw_low_level_read(8, data, &ec->common.data_addr); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", - *data, address)); - - end: - up(&ec->poll.sem); -end_nosem: - if (ec->common.global_lock) - acpi_release_global_lock(glk); - - return result; -} - -static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) -{ - int result = 0; - acpi_status status = AE_OK; - u32 glk = 0; + for (; rdata_len > 0; rdata_len --) { + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); + if (result) + return result; - if (!ec) - return -EINVAL; - - if (ec->common.global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return -ENODEV; - } - - if (down_interruptible(&ec->poll.sem)) { - result = -ERESTARTSYS; - goto end_nosem; + *(rdata++) = acpi_ec_read_data(ec); } - - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, - &ec->common.command_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) - goto end; - - acpi_hw_low_level_write(8, address, &ec->common.data_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) - goto end; - - acpi_hw_low_level_write(8, data, &ec->common.data_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) - goto end; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", - data, address)); - - end: - up(&ec->poll.sem); -end_nosem: - if (ec->common.global_lock) - acpi_release_global_lock(glk); - - return result; + return 0; } -static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data) +static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len) { - int status = 0; + int status; u32 glk; - - if (!ec || !data) + if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) return -EINVAL; - *data = 0; + if (rdata) + memset(rdata, 0, rdata_len); - if (ec->common.global_lock) { + if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return -ENODEV; } + down(&ec->sem); - WARN_ON(in_interrupt()); - down(&ec->intr.sem); - - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); if (status) { printk(KERN_DEBUG PREFIX "read EC, IB not empty\n"); goto end; } - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, - &ec->common.command_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "read EC, IB not empty\n"); - } - acpi_hw_low_level_write(8, address, &ec->common.data_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (status) { - printk(KERN_DEBUG PREFIX "read EC, OB not full\n"); - goto end; - } - acpi_hw_low_level_read(8, data, &ec->common.data_addr); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", - *data, address)); + status = acpi_ec_transaction_unlocked(ec, command, + wdata, wdata_len, + rdata, rdata_len); - end: - up(&ec->intr.sem); +end: + up(&ec->sem); - if (ec->common.global_lock) + if (ec->global_lock) acpi_release_global_lock(glk); return status; } -static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data) +static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) { - int status = 0; - u32 glk; - - - if (!ec) - return -EINVAL; - - if (ec->common.global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return -ENODEV; - } - - WARN_ON(in_interrupt()); - down(&ec->intr.sem); - - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); - } - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, - &ec->common.command_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); - } - - acpi_hw_low_level_write(8, address, &ec->common.data_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); - } - - acpi_hw_low_level_write(8, data, &ec->common.data_addr); + int result; + u8 d; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", - data, address)); - - up(&ec->intr.sem); - - if (ec->common.global_lock) - acpi_release_global_lock(glk); + result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, + &address, 1, &d, 1); + *data = d; + return result; +} - return status; +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); } /* * Externally callable EC access functions. For now, assume 1 EC only */ -int ec_read(u8 addr, u8 * val) +int ec_read(u8 addr, u8 *val) { - union acpi_ec *ec; + struct acpi_ec *ec; int err; - u32 temp_data; + u8 temp_data; if (!first_ec) return -ENODEV; @@ -539,7 +354,7 @@ EXPORT_SYMBOL(ec_read); int ec_write(u8 addr, u8 val) { - union acpi_ec *ec; + struct acpi_ec *ec; int err; if (!first_ec) @@ -554,255 +369,106 @@ int ec_write(u8 addr, u8 val) EXPORT_SYMBOL(ec_write); -static int acpi_ec_query(union acpi_ec *ec, u32 * data) -{ - if (acpi_ec_poll_mode) - return acpi_ec_poll_query(ec, data); - else - return acpi_ec_intr_query(ec, data); -} -static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data) +extern int ec_transaction(u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len) { - int result = 0; - acpi_status status = AE_OK; - u32 glk = 0; - - - if (!ec || !data) - return -EINVAL; - - *data = 0; - - if (ec->common.global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return -ENODEV; - } + struct acpi_ec *ec; - /* - * Query the EC to find out which _Qxx method we need to evaluate. - * Note that successful completion of the query causes the ACPI_EC_SCI - * bit to be cleared (and thus clearing the interrupt source). - */ - if (down_interruptible(&ec->poll.sem)) { - result = -ERESTARTSYS; - goto end_nosem; - } - - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, - &ec->common.command_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (result) - goto end; - - acpi_hw_low_level_read(8, data, &ec->common.data_addr); - if (!*data) - result = -ENODATA; + if (!first_ec) + return -ENODEV; - end: - up(&ec->poll.sem); -end_nosem: - if (ec->common.global_lock) - acpi_release_global_lock(glk); + ec = acpi_driver_data(first_ec); - return result; + return acpi_ec_transaction(ec, command, wdata, + wdata_len, rdata, rdata_len); } -static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data) -{ - int status = 0; - u32 glk; - - if (!ec || !data) - return -EINVAL; - *data = 0; - - if (ec->common.global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return -ENODEV; - } +EXPORT_SYMBOL(ec_transaction); - down(&ec->intr.sem); +static int acpi_ec_query(struct acpi_ec *ec, u8 *data) +{ + int result; + u8 d; - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "query EC, IB not empty\n"); - goto end; - } - /* - * Query the EC to find out which _Qxx method we need to evaluate. - * Note that successful completion of the query causes the ACPI_EC_SCI - * bit to be cleared (and thus clearing the interrupt source). - */ - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, - &ec->common.command_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (status) { - printk(KERN_DEBUG PREFIX "query EC, OB not full\n"); - goto end; - } + if (!ec || !data) + return -EINVAL; - acpi_hw_low_level_read(8, data, &ec->common.data_addr); - if (!*data) - status = -ENODATA; + /* + * Query the EC to find out which _Qxx method we need to evaluate. + * Note that successful completion of the query causes the ACPI_EC_SCI + * bit to be cleared (and thus clearing the interrupt source). + */ - end: - up(&ec->intr.sem); + result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1); + if (result) + return result; - if (ec->common.global_lock) - acpi_release_global_lock(glk); + if (!d) + return -ENODATA; - return status; + *data = d; + return 0; } /* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ -union acpi_ec_query_data { +struct acpi_ec_query_data { acpi_handle handle; u8 data; }; static void acpi_ec_gpe_query(void *ec_cxt) { - if (acpi_ec_poll_mode) - acpi_ec_gpe_poll_query(ec_cxt); - else - acpi_ec_gpe_intr_query(ec_cxt); -} - -static void acpi_ec_gpe_poll_query(void *ec_cxt) -{ - union acpi_ec *ec = (union acpi_ec *)ec_cxt; - u32 value = 0; - static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; - const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - + struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; + u8 value = 0; + static char object_name[8]; - if (!ec_cxt) + if (!ec) goto end; - if (down_interruptible (&ec->poll.sem)) { - return; - } - acpi_hw_low_level_read(8, &value, &ec->common.command_addr); - up(&ec->poll.sem); - - /* TBD: Implement asynch events! - * NOTE: All we care about are EC-SCI's. Other EC events are - * handled via polling (yuck!). This is because some systems - * treat EC-SCIs as level (versus EDGE!) triggered, preventing - * a purely interrupt-driven approach (grumble, grumble). - */ + value = acpi_ec_read_status(ec); + if (!(value & ACPI_EC_FLAG_SCI)) goto end; if (acpi_ec_query(ec, &value)) goto end; - object_name[2] = hex[((value >> 4) & 0x0F)]; - object_name[3] = hex[(value & 0x0F)]; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); + snprintf(object_name, 8, "_Q%2.2X", value); - acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); - end: - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); -} -static void acpi_ec_gpe_intr_query(void *ec_cxt) -{ - union acpi_ec *ec = (union acpi_ec *)ec_cxt; - u32 value; - int result = -ENODATA; - static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; - const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; + acpi_evaluate_object(ec->handle, object_name, NULL, NULL); - - if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) - result = acpi_ec_query(ec, &value); - - if (result) - goto end; - - object_name[2] = hex[((value >> 4) & 0x0F)]; - object_name[3] = hex[(value & 0x0F)]; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); - - acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); end: - atomic_dec(&ec->intr.pending_gpe); - return; + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); } static u32 acpi_ec_gpe_handler(void *data) { - if (acpi_ec_poll_mode) - return acpi_ec_gpe_poll_handler(data); - else - return acpi_ec_gpe_intr_handler(data); -} -static u32 acpi_ec_gpe_poll_handler(void *data) -{ acpi_status status = AE_OK; - union acpi_ec *ec = (union acpi_ec *)data; - - if (!ec) - return ACPI_INTERRUPT_NOT_HANDLED; - - acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); - - status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec); - - if (status == AE_OK) - return ACPI_INTERRUPT_HANDLED; - else - return ACPI_INTERRUPT_NOT_HANDLED; -} -static u32 acpi_ec_gpe_intr_handler(void *data) -{ - acpi_status status = AE_OK; - u32 value; - union acpi_ec *ec = (union acpi_ec *)data; - - if (!ec) - return ACPI_INTERRUPT_NOT_HANDLED; + u8 value; + struct acpi_ec *ec = (struct acpi_ec *)data; - acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); + acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); value = acpi_ec_read_status(ec); - switch (ec->intr.expect_event) { - case ACPI_EC_EVENT_OBF: - if (!(value & ACPI_EC_FLAG_OBF)) - break; - ec->intr.expect_event = 0; - wake_up(&ec->intr.wait); - break; - case ACPI_EC_EVENT_IBE: - if ((value & ACPI_EC_FLAG_IBF)) - break; - ec->intr.expect_event = 0; - wake_up(&ec->intr.wait); - break; - default: - break; + if (acpi_ec_mode == EC_INTR) { + if (acpi_ec_check_status(value, ec->expect_event)) { + ec->expect_event = 0; + wake_up(&ec->wait); + } } if (value & ACPI_EC_FLAG_SCI) { - atomic_add(1, &ec->intr.pending_gpe); - status = acpi_os_execute(OSL_EC_BURST_HANDLER, - acpi_ec_gpe_query, ec); + status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } @@ -833,7 +499,7 @@ acpi_ec_space_handler(u32 function, void *handler_context, void *region_context) { int result = 0; - union acpi_ec *ec = NULL; + struct acpi_ec *ec = NULL; u64 temp = *value; acpi_integer f_v = 0; int i = 0; @@ -843,18 +509,16 @@ acpi_ec_space_handler(u32 function, return AE_BAD_PARAMETER; if (bit_width != 8 && acpi_strict) { - printk(KERN_WARNING PREFIX - "acpi_ec_space_handler: bit_width should be 8\n"); return AE_BAD_PARAMETER; } - ec = (union acpi_ec *)handler_context; + ec = (struct acpi_ec *)handler_context; next_byte: switch (function) { case ACPI_READ: temp = 0; - result = acpi_ec_read(ec, (u8) address, (u32 *) & temp); + result = acpi_ec_read(ec, (u8) address, (u8 *) &temp); break; case ACPI_WRITE: result = acpi_ec_write(ec, (u8) address, (u8) temp); @@ -905,20 +569,20 @@ static struct proc_dir_entry *acpi_ec_dir; static int acpi_ec_read_info(struct seq_file *seq, void *offset) { - union acpi_ec *ec = (union acpi_ec *)seq->private; + struct acpi_ec *ec = (struct acpi_ec *)seq->private; if (!ec) goto end; seq_printf(seq, "gpe bit: 0x%02x\n", - (u32) ec->common.gpe_bit); + (u32) ec->gpe_bit); seq_printf(seq, "ports: 0x%02x, 0x%02x\n", - (u32) ec->common.status_addr.address, - (u32) ec->common.data_addr.address); + (u32) ec->command_addr, + (u32) ec->data_addr); seq_printf(seq, "use global lock: %s\n", - ec->common.global_lock ? "yes" : "no"); - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); + ec->global_lock ? "yes" : "no"); + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); end: return 0; @@ -929,7 +593,7 @@ static int acpi_ec_info_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_ec_read_info, PDE(inode)->data); } -static const struct file_operations acpi_ec_info_ops = { +static struct file_operations acpi_ec_info_ops = { .open = acpi_ec_info_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -978,101 +642,35 @@ static int acpi_ec_remove_fs(struct acpi_device *device) Driver Interface -------------------------------------------------------------------------- */ -static int acpi_ec_poll_add(struct acpi_device *device) +static int acpi_ec_add(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; - union acpi_ec *ec = NULL; + struct acpi_ec *ec = NULL; if (!device) return -EINVAL; - ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); if (!ec) return -ENOMEM; - memset(ec, 0, sizeof(union acpi_ec)); - - ec->common.handle = device->handle; - ec->common.uid = -1; - init_MUTEX(&ec->poll.sem); - strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_EC_CLASS); - acpi_driver_data(device) = ec; - - /* Use the global lock for all EC transactions? */ - acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, - &ec->common.global_lock); - - /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: - http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ - if (ec_ecdt) { - acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, - ACPI_ADR_SPACE_EC, - &acpi_ec_space_handler); - - acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, - &acpi_ec_gpe_handler); - - kfree(ec_ecdt); + memset(ec, 0, sizeof(struct acpi_ec)); + + ec->handle = device->handle; + ec->uid = -1; + init_MUTEX(&ec->sem); + if (acpi_ec_mode == EC_INTR) { + atomic_set(&ec->leaving_burst, 1); + init_waitqueue_head(&ec->wait); } - - /* Get GPE bit assignment (EC events). */ - /* TODO: Add support for _GPE returning a package */ - status = - acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, - &ec->common.gpe_bit); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit")); - result = -ENODEV; - goto end; - } - - result = acpi_ec_add_fs(device); - if (result) - goto end; - - printk(KERN_INFO PREFIX "%s [%s] (gpe %d) polling mode.\n", - acpi_device_name(device), acpi_device_bid(device), - (u32) ec->common.gpe_bit); - - if (!first_ec) - first_ec = device; - - end: - if (result) - kfree(ec); - - return result; -} -static int acpi_ec_intr_add(struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - union acpi_ec *ec = NULL; - - - if (!device) - return -EINVAL; - - ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); - if (!ec) - return -ENOMEM; - memset(ec, 0, sizeof(union acpi_ec)); - - ec->common.handle = device->handle; - ec->common.uid = -1; - atomic_set(&ec->intr.pending_gpe, 0); - atomic_set(&ec->intr.leaving_burst, 1); - init_MUTEX(&ec->intr.sem); - init_waitqueue_head(&ec->intr.wait); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; /* Use the global lock for all EC transactions? */ - acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, - &ec->common.global_lock); + acpi_evaluate_integer(ec->handle, "_GLK", NULL, + &ec->global_lock); /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ @@ -1081,7 +679,7 @@ static int acpi_ec_intr_add(struct acpi_device *device) ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); - acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, + acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); kfree(ec_ecdt); @@ -1090,10 +688,10 @@ static int acpi_ec_intr_add(struct acpi_device *device) /* Get GPE bit assignment (EC events). */ /* TODO: Add support for _GPE returning a package */ status = - acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, - &ec->common.gpe_bit); + acpi_evaluate_integer(ec->handle, "_GPE", NULL, + &ec->gpe_bit); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Obtaining GPE bit assignment\n"); + ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit assignment")); result = -ENODEV; goto end; } @@ -1102,14 +700,14 @@ static int acpi_ec_intr_add(struct acpi_device *device) if (result) goto end; - printk(KERN_INFO PREFIX "%s [%s] (gpe %d) interrupt mode.\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.", acpi_device_name(device), acpi_device_bid(device), - (u32) ec->common.gpe_bit); + (u32) ec->gpe_bit)); if (!first_ec) first_ec = device; - end: + end: if (result) kfree(ec); @@ -1118,7 +716,7 @@ static int acpi_ec_intr_add(struct acpi_device *device) static int acpi_ec_remove(struct acpi_device *device, int type) { - union acpi_ec *ec = NULL; + struct acpi_ec *ec = NULL; if (!device) @@ -1136,8 +734,7 @@ static int acpi_ec_remove(struct acpi_device *device, int type) static acpi_status acpi_ec_io_ports(struct acpi_resource *resource, void *context) { - union acpi_ec *ec = (union acpi_ec *)context; - struct acpi_generic_address *addr; + struct acpi_ec *ec = (struct acpi_ec *)context; if (resource->type != ACPI_RESOURCE_TYPE_IO) { return AE_OK; @@ -1148,26 +745,21 @@ acpi_ec_io_ports(struct acpi_resource *resource, void *context) * the second address region returned is the status/command * port. */ - if (ec->common.data_addr.register_bit_width == 0) { - addr = &ec->common.data_addr; - } else if (ec->common.command_addr.register_bit_width == 0) { - addr = &ec->common.command_addr; + if (ec->data_addr == 0) { + ec->data_addr = resource->data.io.minimum; + } else if (ec->command_addr == 0) { + ec->command_addr = resource->data.io.minimum; } else { return AE_CTRL_TERMINATE; } - addr->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; - addr->register_bit_width = 8; - addr->register_bit_offset = 0; - addr->address = resource->data.io.minimum; - return AE_OK; } static int acpi_ec_start(struct acpi_device *device) { acpi_status status = AE_OK; - union acpi_ec *ec = NULL; + struct acpi_ec *ec = NULL; if (!device) @@ -1181,39 +773,35 @@ static int acpi_ec_start(struct acpi_device *device) /* * Get I/O port addresses. Convert to GAS format. */ - status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS, + status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec); - if (ACPI_FAILURE(status) - || ec->common.command_addr.register_bit_width == 0) { - printk(KERN_ERR PREFIX "Error getting I/O port addresses\n"); + if (ACPI_FAILURE(status) || ec->command_addr == 0) { + ACPI_EXCEPTION((AE_INFO, status, + "Error getting I/O port addresses")); return -ENODEV; } - ec->common.status_addr = ec->common.command_addr; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", - (u32) ec->common.gpe_bit, - (u32) ec->common.command_addr.address, - (u32) ec->common.data_addr.address)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx", + ec->gpe_bit, ec->command_addr, ec->data_addr)); /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit, + status = acpi_install_gpe_handler(NULL, ec->gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); if (ACPI_FAILURE(status)) { return -ENODEV; } - acpi_set_gpe_type(NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type(NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); - status = acpi_install_address_space_handler(ec->common.handle, + status = acpi_install_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, &acpi_ec_space_setup, ec); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, + acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); return -ENODEV; } @@ -1224,7 +812,7 @@ static int acpi_ec_start(struct acpi_device *device) static int acpi_ec_stop(struct acpi_device *device, int type) { acpi_status status = AE_OK; - union acpi_ec *ec = NULL; + struct acpi_ec *ec = NULL; if (!device) @@ -1232,14 +820,14 @@ static int acpi_ec_stop(struct acpi_device *device, int type) ec = acpi_driver_data(device); - status = acpi_remove_address_space_handler(ec->common.handle, + status = acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); if (ACPI_FAILURE(status)) return -ENODEV; status = - acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, + acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); if (ACPI_FAILURE(status)) return -ENODEV; @@ -1251,76 +839,30 @@ static acpi_status __init acpi_fake_ecdt_callback(acpi_handle handle, u32 Level, void *context, void **retval) { - - if (acpi_ec_poll_mode) - return acpi_fake_ecdt_poll_callback(handle, - Level, context, retval); - else - return acpi_fake_ecdt_intr_callback(handle, - Level, context, retval); -} - -static acpi_status __init -acpi_fake_ecdt_poll_callback(acpi_handle handle, - u32 Level, void *context, void **retval) -{ - acpi_status status; - - status = acpi_walk_resources(handle, METHOD_NAME__CRS, - acpi_ec_io_ports, ec_ecdt); - if (ACPI_FAILURE(status)) - return status; - ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; - - ec_ecdt->common.uid = -1; - acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); - - status = - acpi_evaluate_integer(handle, "_GPE", NULL, - &ec_ecdt->common.gpe_bit); - if (ACPI_FAILURE(status)) - return status; - init_MUTEX(&ec_ecdt->poll.sem); - ec_ecdt->common.global_lock = TRUE; - ec_ecdt->common.handle = handle; - - printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", - (u32) ec_ecdt->common.gpe_bit, - (u32) ec_ecdt->common.command_addr.address, - (u32) ec_ecdt->common.data_addr.address); - - return AE_CTRL_TERMINATE; -} - -static acpi_status __init -acpi_fake_ecdt_intr_callback(acpi_handle handle, - u32 Level, void *context, void **retval) -{ acpi_status status; - init_MUTEX(&ec_ecdt->intr.sem); - init_waitqueue_head(&ec_ecdt->intr.wait); + init_MUTEX(&ec_ecdt->sem); + if (acpi_ec_mode == EC_INTR) { + init_waitqueue_head(&ec_ecdt->wait); + } status = acpi_walk_resources(handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec_ecdt); if (ACPI_FAILURE(status)) return status; - ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; - ec_ecdt->common.uid = -1; - acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); + ec_ecdt->uid = -1; + acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); status = acpi_evaluate_integer(handle, "_GPE", NULL, - &ec_ecdt->common.gpe_bit); + &ec_ecdt->gpe_bit); if (ACPI_FAILURE(status)) return status; - ec_ecdt->common.global_lock = TRUE; - ec_ecdt->common.handle = handle; + ec_ecdt->global_lock = TRUE; + ec_ecdt->handle = handle; - printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", - (u32) ec_ecdt->common.gpe_bit, - (u32) ec_ecdt->common.command_addr.address, - (u32) ec_ecdt->common.data_addr.address); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx", + ec_ecdt->gpe_bit, ec_ecdt->command_addr, ec_ecdt->data_addr)); return AE_CTRL_TERMINATE; } @@ -1340,14 +882,14 @@ static int __init acpi_ec_fake_ecdt(void) acpi_status status; int ret = 0; - printk(KERN_INFO PREFIX "Try to make an fake ECDT\n"); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Try to make an fake ECDT")); - ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); if (!ec_ecdt) { ret = -ENOMEM; goto error; } - memset(ec_ecdt, 0, sizeof(union acpi_ec)); + memset(ec_ecdt, 0, sizeof(struct acpi_ec)); status = acpi_get_devices(ACPI_EC_HID, acpi_fake_ecdt_callback, NULL, NULL); @@ -1355,24 +897,16 @@ static int __init acpi_ec_fake_ecdt(void) kfree(ec_ecdt); ec_ecdt = NULL; ret = -ENODEV; + ACPI_EXCEPTION((AE_INFO, status, "Can't make an fake ECDT")); goto error; } return 0; - error: - printk(KERN_ERR PREFIX "Can't make an fake ECDT\n"); + error: return ret; } static int __init acpi_ec_get_real_ecdt(void) { - if (acpi_ec_poll_mode) - return acpi_ec_poll_get_real_ecdt(); - else - return acpi_ec_intr_get_real_ecdt(); -} - -static int __init acpi_ec_poll_get_real_ecdt(void) -{ acpi_status status; struct acpi_table_ecdt *ecdt_ptr; @@ -1382,80 +916,36 @@ static int __init acpi_ec_poll_get_real_ecdt(void) if (ACPI_FAILURE(status)) return -ENODEV; - printk(KERN_INFO PREFIX "Found ECDT\n"); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT")); /* * Generate a temporary ec context to use until the namespace is scanned */ - ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); if (!ec_ecdt) return -ENOMEM; - memset(ec_ecdt, 0, sizeof(union acpi_ec)); - - ec_ecdt->common.command_addr = ecdt_ptr->ec_control; - ec_ecdt->common.status_addr = ecdt_ptr->ec_control; - ec_ecdt->common.data_addr = ecdt_ptr->ec_data; - ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; - init_MUTEX(&ec_ecdt->poll.sem); - /* use the GL just to be safe */ - ec_ecdt->common.global_lock = TRUE; - ec_ecdt->common.uid = ecdt_ptr->uid; + memset(ec_ecdt, 0, sizeof(struct acpi_ec)); - status = - acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); - if (ACPI_FAILURE(status)) { - goto error; + init_MUTEX(&ec_ecdt->sem); + if (acpi_ec_mode == EC_INTR) { + init_waitqueue_head(&ec_ecdt->wait); } - - return 0; - error: - printk(KERN_ERR PREFIX "Could not use ECDT\n"); - kfree(ec_ecdt); - ec_ecdt = NULL; - - return -ENODEV; -} - -static int __init acpi_ec_intr_get_real_ecdt(void) -{ - acpi_status status; - struct acpi_table_ecdt *ecdt_ptr; - - status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, - (struct acpi_table_header **) - &ecdt_ptr); - if (ACPI_FAILURE(status)) - return -ENODEV; - - printk(KERN_INFO PREFIX "Found ECDT\n"); - - /* - * Generate a temporary ec context to use until the namespace is scanned - */ - ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); - if (!ec_ecdt) - return -ENOMEM; - memset(ec_ecdt, 0, sizeof(union acpi_ec)); - - init_MUTEX(&ec_ecdt->intr.sem); - init_waitqueue_head(&ec_ecdt->intr.wait); - ec_ecdt->common.command_addr = ecdt_ptr->ec_control; - ec_ecdt->common.status_addr = ecdt_ptr->ec_control; - ec_ecdt->common.data_addr = ecdt_ptr->ec_data; - ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; + ec_ecdt->command_addr = ecdt_ptr->ec_control.address; + ec_ecdt->data_addr = ecdt_ptr->ec_data.address; + ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; /* use the GL just to be safe */ - ec_ecdt->common.global_lock = TRUE; - ec_ecdt->common.uid = ecdt_ptr->uid; + ec_ecdt->global_lock = TRUE; + ec_ecdt->uid = ecdt_ptr->uid; status = - acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); + acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); if (ACPI_FAILURE(status)) { goto error; } return 0; - error: - printk(KERN_ERR PREFIX "Could not use ECDT\n"); + error: + ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT")); kfree(ec_ecdt); ec_ecdt = NULL; @@ -1480,14 +970,14 @@ int __init acpi_ec_ecdt_probe(void) /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit, + status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec_ecdt); if (ACPI_FAILURE(status)) { goto error; } - acpi_set_gpe_type(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe(NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type(NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe(NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR); status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, @@ -1495,7 +985,7 @@ int __init acpi_ec_ecdt_probe(void) &acpi_ec_space_setup, ec_ecdt); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, + acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); goto error; } @@ -1503,7 +993,7 @@ int __init acpi_ec_ecdt_probe(void) return 0; error: - printk(KERN_ERR PREFIX "Could not use ECDT\n"); + ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT")); kfree(ec_ecdt); ec_ecdt = NULL; @@ -1562,13 +1052,13 @@ static int __init acpi_ec_set_intr_mode(char *str) return 0; if (intr) { - acpi_ec_poll_mode = EC_INTR; - acpi_ec_driver.ops.add = acpi_ec_intr_add; + acpi_ec_mode = EC_INTR; } else { - acpi_ec_poll_mode = EC_POLL; - acpi_ec_driver.ops.add = acpi_ec_poll_add; + acpi_ec_mode = EC_POLL; } - printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling"); + acpi_ec_driver.ops.add = acpi_ec_add; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "EC %s mode.\n", intr ? "interrupt" : "polling")); + return 1; } diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 6eef4efddcf6..ee2a10bf9077 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -342,20 +342,8 @@ static u32 acpi_ev_global_lock_handler(void *context) if (acquired) { /* Got the lock, now wake all threads waiting for it */ - acpi_gbl_global_lock_acquired = TRUE; - - /* Run the Global Lock thread which will signal all waiting threads */ - - status = - acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER, - acpi_ev_global_lock_thread, context); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not queue Global Lock thread")); - - return (ACPI_INTERRUPT_NOT_HANDLED); - } + acpi_ev_global_lock_thread(context); } return (ACPI_INTERRUPT_HANDLED); diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index 5b3c7a85eb9a..203d1359190a 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -225,13 +225,12 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, if (! (ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING, - sizeof(PCI_ROOT_HID_STRING)) - || - !(ACPI_STRNCMP - (object_hID.value, - PCI_EXPRESS_ROOT_HID_STRING, - sizeof(PCI_EXPRESS_ROOT_HID_STRING))))) - { + sizeof(PCI_ROOT_HID_STRING))) + || + !(ACPI_STRNCMP + (object_hID.value, + PCI_EXPRESS_ROOT_HID_STRING, + sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { /* Install a handler for this PCI root bridge */ diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 15fc12482ba0..003a9876c968 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1702,13 +1702,11 @@ static struct ibm_struct ibms[] = { .name = "brightness", .read = brightness_read, .write = brightness_write, - .experimental = 1, }, { .name = "volume", .read = volume_read, .write = volume_write, - .experimental = 1, }, { .name = "fan", diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index ec6b7f9ede34..2e17ec75af03 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -48,6 +48,12 @@ ACPI_MODULE_NAME("acpi_motherboard") * the io ports if they really know they can use it, while * still preventing hotplug PCI devices from using it. */ + +/* + * When CONFIG_PNP is enabled, pnp/system.c binds to PNP0C01 + * and PNP0C02, redundant with acpi_reserve_io_ranges(). + * But acpi_reserve_io_ranges() is necessary for !CONFIG_PNP. + */ static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data) { struct resource *requested_res = NULL; diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 7f3e7e77e794..d53bd9878ca2 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -307,7 +307,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) if (!link || !irq) return -EINVAL; - resource = kmalloc(sizeof(*resource) + 1, GFP_ATOMIC); + resource = kmalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); if (!resource) return -ENOMEM; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index fec225d1b6b7..fe67a8af520e 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -216,10 +216,8 @@ static int acpi_power_off_device(acpi_handle handle) { int result = 0; acpi_status status = AE_OK; - struct acpi_device *device = NULL; struct acpi_power_resource *resource = NULL; - result = acpi_power_get_context(handle, &resource); if (result) return result; @@ -230,13 +228,13 @@ static int acpi_power_off_device(acpi_handle handle) if (resource->references) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is still in use, dereferencing\n", - device->pnp.bus_id)); + resource->device->pnp.bus_id)); return 0; } if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n", - device->pnp.bus_id)); + resource->device->pnp.bus_id)); return 0; } @@ -251,8 +249,7 @@ static int acpi_power_off_device(acpi_handle handle) return -ENOEXEC; /* Update the power resource's _device_ power state */ - device = resource->device; - device->power.state = ACPI_STATE_D3; + resource->device->power.state = ACPI_STATE_D3; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n", resource->name)); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index b13d64415b7a..1908e0d20222 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -519,7 +519,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr) static void *processor_device_array[NR_CPUS]; -static int acpi_processor_start(struct acpi_device *device) +static int __cpuinit acpi_processor_start(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0a395fca843b..65b3f056ad89 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -219,6 +219,23 @@ static void acpi_safe_halt(void) static atomic_t c3_cpu_count; +/* Common C-state entry for C2, C3, .. */ +static void acpi_cstate_enter(struct acpi_processor_cx *cstate) +{ + if (cstate->space_id == ACPI_CSTATE_FFH) { + /* Call into architectural FFH based C-state */ + acpi_processor_ffh_cstate_enter(cstate); + } else { + int unused; + /* IO port based C-state */ + inb(cstate->address); + /* Dummy wait op - must do something useless after P_LVL2 read + because chipsets cannot guarantee that STPCLK# signal + gets asserted in time to freeze execution properly. */ + unused = inl(acpi_fadt.xpm_tmr_blk.address); + } +} + static void acpi_processor_idle(void) { struct acpi_processor *pr = NULL; @@ -361,11 +378,7 @@ static void acpi_processor_idle(void) /* Get start time (ticks) */ t1 = inl(acpi_fadt.xpm_tmr_blk.address); /* Invoke C2 */ - inb(cx->address); - /* Dummy wait op - must do something useless after P_LVL2 read - because chipsets cannot guarantee that STPCLK# signal - gets asserted in time to freeze execution properly. */ - t2 = inl(acpi_fadt.xpm_tmr_blk.address); + acpi_cstate_enter(cx); /* Get end time (ticks) */ t2 = inl(acpi_fadt.xpm_tmr_blk.address); @@ -401,9 +414,7 @@ static void acpi_processor_idle(void) /* Get start time (ticks) */ t1 = inl(acpi_fadt.xpm_tmr_blk.address); /* Invoke C3 */ - inb(cx->address); - /* Dummy wait op (see above) */ - t2 = inl(acpi_fadt.xpm_tmr_blk.address); + acpi_cstate_enter(cx); /* Get end time (ticks) */ t2 = inl(acpi_fadt.xpm_tmr_blk.address); if (pr->flags.bm_check) { @@ -628,20 +639,16 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) return 0; } -static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr) +static int acpi_processor_get_power_info_default(struct acpi_processor *pr) { - - /* Zero initialize all the C-states info. */ - memset(pr->power.states, 0, sizeof(pr->power.states)); - - /* set the first C-State to C1 */ - pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; - - /* the C0 state only exists as a filler in our array, - * and all processors need to support C1 */ + if (!pr->power.states[ACPI_STATE_C1].valid) { + /* set the first C-State to C1 */ + /* all processors need to support C1 */ + pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; + pr->power.states[ACPI_STATE_C1].valid = 1; + } + /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; - pr->power.states[ACPI_STATE_C1].valid = 1; - return 0; } @@ -658,12 +665,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) if (nocst) return -ENODEV; - current_count = 1; - - /* Zero initialize C2 onwards and prepare for fresh CST lookup */ - for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++) - memset(&(pr->power.states[i]), 0, - sizeof(struct acpi_processor_cx)); + current_count = 0; status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -718,22 +720,39 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) continue; - cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ? - 0 : reg->address; - /* There should be an easy way to extract an integer... */ obj = (union acpi_object *)&(element->package.elements[1]); if (obj->type != ACPI_TYPE_INTEGER) continue; cx.type = obj->integer.value; - - if ((cx.type != ACPI_STATE_C1) && - (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) - continue; - - if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3)) - continue; + /* + * Some buggy BIOSes won't list C1 in _CST - + * Let acpi_processor_get_power_info_default() handle them later + */ + if (i == 1 && cx.type != ACPI_STATE_C1) + current_count++; + + cx.address = reg->address; + cx.index = current_count + 1; + + cx.space_id = ACPI_CSTATE_SYSTEMIO; + if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { + if (acpi_processor_ffh_cstate_probe + (pr->id, &cx, reg) == 0) { + cx.space_id = ACPI_CSTATE_FFH; + } else if (cx.type != ACPI_STATE_C1) { + /* + * C1 is a special case where FIXED_HARDWARE + * can be handled in non-MWAIT way as well. + * In that case, save this _CST entry info. + * That is, we retain space_id of SYSTEM_IO for + * halt based C1. + * Otherwise, ignore this info and continue. + */ + continue; + } + } obj = (union acpi_object *)&(element->package.elements[2]); if (obj->type != ACPI_TYPE_INTEGER) @@ -938,11 +957,17 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) /* NOTE: the idle thread may not be running while calling * this function */ - /* Adding C1 state */ - acpi_processor_get_power_info_default_c1(pr); + /* Zero initialize all the C-states info. */ + memset(pr->power.states, 0, sizeof(pr->power.states)); + result = acpi_processor_get_power_info_cst(pr); if (result == -ENODEV) - acpi_processor_get_power_info_fadt(pr); + result = acpi_processor_get_power_info_fadt(pr); + + if (result) + return result; + + acpi_processor_get_power_info_default(pr); pr->power.count = acpi_processor_power_verify(pr); @@ -1083,6 +1108,7 @@ static const struct file_operations acpi_processor_power_fops = { .release = single_release, }; +#ifdef CONFIG_SMP static void smp_callback(void *v) { /* we already woke the CPU up, nothing more to do */ @@ -1104,8 +1130,9 @@ static int acpi_processor_latency_notify(struct notifier_block *b, static struct notifier_block acpi_processor_latency_notifier = { .notifier_call = acpi_processor_latency_notify, }; +#endif -int acpi_processor_power_init(struct acpi_processor *pr, +int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device) { acpi_status status = 0; @@ -1121,7 +1148,9 @@ int acpi_processor_power_init(struct acpi_processor *pr, "ACPI: processor limited to max C-state %d\n", max_cstate); first_run++; +#ifdef CONFIG_SMP register_latency_notifier(&acpi_processor_latency_notifier); +#endif } if (!pr) @@ -1193,7 +1222,9 @@ int acpi_processor_power_exit(struct acpi_processor *pr, * copies of pm_idle before proceeding. */ cpu_idle_wait(); +#ifdef CONFIG_SMP unregister_latency_notifier(&acpi_processor_latency_notifier); +#endif } return 0; diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 62bef0b3b614..8908a975e575 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -98,11 +98,11 @@ static int update_info_mode = UPDATE_INFO_MODE; static int update_time = UPDATE_TIME; static int update_time2 = UPDATE_TIME2; -module_param(capacity_mode, int, CAPACITY_UNIT); -module_param(update_mode, int, UPDATE_MODE); -module_param(update_info_mode, int, UPDATE_INFO_MODE); -module_param(update_time, int, UPDATE_TIME); -module_param(update_time2, int, UPDATE_TIME2); +module_param(capacity_mode, int, 0); +module_param(update_mode, int, 0); +module_param(update_info_mode, int, 0); +module_param(update_time, int, 0); +module_param(update_time2, int, 0); static int acpi_sbs_add(struct acpi_device *device); static int acpi_sbs_remove(struct acpi_device *device, int type); @@ -1685,10 +1685,16 @@ static int acpi_sbs_add(struct acpi_device *device) int acpi_sbs_remove(struct acpi_device *device, int type) { - struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device); + struct acpi_sbs *sbs = NULL; int id; - if (!device || !sbs) { + if (!device) { + return -EINVAL; + } + + sbs = (struct acpi_sbs *)acpi_driver_data(device); + + if (!sbs) { return -EINVAL; } diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c index 7856db759af0..11e2d4454e05 100644 --- a/drivers/acpi/tables/tbget.c +++ b/drivers/acpi/tables/tbget.c @@ -324,7 +324,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address, if (header->length < sizeof(struct acpi_table_header)) { ACPI_ERROR((AE_INFO, - "Table length (%X) is smaller than minimum (%X)", + "Table length (%X) is smaller than minimum (%zX)", header->length, sizeof(struct acpi_table_header))); return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index 0ad3dbb9ebca..86a5fca9b739 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -187,7 +187,7 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) if (table_ptr->length < sizeof(struct acpi_table_header)) { ACPI_ERROR((AE_INFO, - "RSDT/XSDT length (%X) is smaller than minimum (%X)", + "RSDT/XSDT length (%X) is smaller than minimum (%zX)", table_ptr->length, sizeof(struct acpi_table_header))); |