diff --git a/[refs] b/[refs] index b2657b0524a8..b4483355eb02 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 2935b544041bbdc32a6864ba9350a7629c56d722 +refs/heads/master: 5cf4d7338ba23aa8d9eeaf313f16bb50494be369 diff --git a/trunk/Documentation/acpi/apei/output_format.txt b/trunk/Documentation/acpi/apei/output_format.txt index 0c49c197c47a..9146952c612a 100644 --- a/trunk/Documentation/acpi/apei/output_format.txt +++ b/trunk/Documentation/acpi/apei/output_format.txt @@ -92,11 +92,6 @@ vendor_id: , device_id: class_code: ] [serial number: , ] [bridge: secondary_status: , control: ] -[aer_status: , aer_mask: - -[aer_uncor_severity: ] -aer_layer=, aer_agent= -aer_tlp_header: ] * := PCIe end point | legacy PCI end point | \ unknown | unknown | root port | upstream switch port | \ @@ -104,26 +99,6 @@ downstream switch port | PCIe to PCI/PCI-X bridge | \ PCI/PCI-X to PCIe bridge | root complex integrated endpoint device | \ root complex event collector -if section severity is fatal or recoverable -# := -unknown | unknown | unknown | unknown | Data Link Protocol | \ -unknown | unknown | unknown | unknown | unknown | unknown | unknown | \ -Poisoned TLP | Flow Control Protocol | Completion Timeout | \ -Completer Abort | Unexpected Completion | Receiver Overflow | \ -Malformed TLP | ECRC | Unsupported Request -else -# := -Receiver Error | unknown | unknown | unknown | unknown | unknown | \ -Bad TLP | Bad DLLP | RELAY_NUM Rollover | unknown | unknown | unknown | \ -Replay Timer Timeout | Advisory Non-Fatal -fi - - := -Physical Layer | Data Link Layer | Transaction Layer - - := -Receiver ID | Requester ID | Completer ID | Transmitter ID - Where, [] designate corresponding content is optional All description with * has the following format: diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index e4615253ba89..b3f35e5f9c95 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -259,6 +259,14 @@ Who: Zhang Rui --------------------------- +What: /proc/acpi/button +When: August 2007 +Why: /proc/acpi/button has been replaced by events to the input layer + since 2.6.20. +Who: Len Brown + +--------------------------- + What: /proc/acpi/event When: February 2008 Why: /proc/acpi/event has been replaced by events via the input layer diff --git a/trunk/arch/ia64/include/asm/acpi.h b/trunk/arch/ia64/include/asm/acpi.h index a06dfb13d518..837dc82a013e 100644 --- a/trunk/arch/ia64/include/asm/acpi.h +++ b/trunk/arch/ia64/include/asm/acpi.h @@ -128,9 +128,9 @@ static inline const char *acpi_get_sysname (void) int acpi_request_vector (u32 int_type); int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); -/* Low-level suspend routine. */ -extern int acpi_suspend_lowlevel(void); - +/* routines for saving/restoring kernel state */ +extern int acpi_save_state_mem(void); +extern void acpi_restore_state_mem(void); extern unsigned long acpi_wakeup_address; /* diff --git a/trunk/arch/ia64/kernel/acpi.c b/trunk/arch/ia64/kernel/acpi.c index a54d054ed4b0..90ebceb899a0 100644 --- a/trunk/arch/ia64/kernel/acpi.c +++ b/trunk/arch/ia64/kernel/acpi.c @@ -1034,8 +1034,18 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base) EXPORT_SYMBOL(acpi_unregister_ioapic); /* - * acpi_suspend_lowlevel() - save kernel state and suspend. + * acpi_save_state_mem() - save kernel state * * TBD when when IA64 starts to support suspend... */ -int acpi_suspend_lowlevel(void) { return 0; } +int acpi_save_state_mem(void) { return 0; } + +/* + * acpi_restore_state() + */ +void acpi_restore_state_mem(void) {} + +/* + * do_suspend_lowlevel() + */ +void do_suspend_lowlevel(void) {} diff --git a/trunk/arch/x86/include/asm/acpi.h b/trunk/arch/x86/include/asm/acpi.h index ef14da1f4ec5..4ea15ca89b2b 100644 --- a/trunk/arch/x86/include/asm/acpi.h +++ b/trunk/arch/x86/include/asm/acpi.h @@ -113,8 +113,9 @@ static inline void acpi_disable_pci(void) acpi_noirq_set(); } -/* Low-level suspend routine. */ -extern int acpi_suspend_lowlevel(void); +/* routines for saving/restoring kernel state */ +extern int acpi_save_state_mem(void); +extern void acpi_restore_state_mem(void); extern unsigned long acpi_wakeup_address; diff --git a/trunk/arch/x86/kernel/acpi/sleep.c b/trunk/arch/x86/kernel/acpi/sleep.c index 5f1b747f6ef1..68d1537b8c81 100644 --- a/trunk/arch/x86/kernel/acpi/sleep.c +++ b/trunk/arch/x86/kernel/acpi/sleep.c @@ -29,14 +29,14 @@ static char temp_stack[4096]; #endif /** - * acpi_suspend_lowlevel - save kernel state + * acpi_save_state_mem - save kernel state * * Create an identity mapped page table and copy the wakeup routine to * low memory. * * Note that this is too late to change acpi_wakeup_address. */ -int acpi_suspend_lowlevel(void) +int acpi_save_state_mem(void) { struct wakeup_header *header; @@ -107,10 +107,17 @@ int acpi_suspend_lowlevel(void) saved_magic = 0x123456789abcdef0L; #endif /* CONFIG_64BIT */ - do_suspend_lowlevel(); return 0; } +/* + * acpi_restore_state - undo effects of acpi_save_state_mem + */ +void acpi_restore_state_mem(void) +{ +} + + /** * acpi_reserve_wakeup_memory - do _very_ early ACPI initialisation * diff --git a/trunk/arch/x86/kernel/acpi/sleep.h b/trunk/arch/x86/kernel/acpi/sleep.h index 31ce13f20297..adbcbaa6f1df 100644 --- a/trunk/arch/x86/kernel/acpi/sleep.h +++ b/trunk/arch/x86/kernel/acpi/sleep.h @@ -14,5 +14,3 @@ extern char swsusp_pg_dir[PAGE_SIZE]; extern unsigned long acpi_copy_wakeup_routine(unsigned long); extern void wakeup_long64(void); - -extern void do_suspend_lowlevel(void); diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce-apei.c b/trunk/arch/x86/kernel/cpu/mcheck/mce-apei.c index 83930deec3c6..8209472b27a5 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce-apei.c +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce-apei.c @@ -106,34 +106,24 @@ int apei_write_mce(struct mce *m) ssize_t apei_read_mce(struct mce *m, u64 *record_id) { struct cper_mce_record rcd; - int rc, pos; - - rc = erst_get_record_id_begin(&pos); - if (rc) - return rc; -retry: - rc = erst_get_record_id_next(&pos, record_id); - if (rc) - goto out; - /* no more record */ - if (*record_id == APEI_ERST_INVALID_RECORD_ID) - goto out; - rc = erst_read(*record_id, &rcd.hdr, sizeof(rcd)); - /* someone else has cleared the record, try next one */ - if (rc == -ENOENT) - goto retry; - else if (rc < 0) - goto out; - /* try to skip other type records in storage */ - else if (rc != sizeof(rcd) || - uuid_le_cmp(rcd.hdr.creator_id, CPER_CREATOR_MCE)) - goto retry; + ssize_t len; + + len = erst_read_next(&rcd.hdr, sizeof(rcd)); + if (len <= 0) + return len; + /* Can not skip other records in storage via ERST unless clear them */ + else if (len != sizeof(rcd) || + uuid_le_cmp(rcd.hdr.creator_id, CPER_CREATOR_MCE)) { + if (printk_ratelimit()) + pr_warning( + "MCE-APEI: Can not skip the unknown record in ERST"); + return -EIO; + } + memcpy(m, &rcd.mce, sizeof(*m)); - rc = sizeof(*m); -out: - erst_get_record_id_end(); + *record_id = rcd.hdr.record_id; - return rc; + return sizeof(*m); } /* Check whether there is record in ERST */ diff --git a/trunk/drivers/acpi/acpica/aclocal.h b/trunk/drivers/acpi/acpica/aclocal.h index c7f743ca395b..01bcab1c5cc4 100644 --- a/trunk/drivers/acpi/acpica/aclocal.h +++ b/trunk/drivers/acpi/acpica/aclocal.h @@ -397,15 +397,10 @@ struct acpi_gpe_handler_info { u8 originally_enabled; /* True if GPE was originally enabled */ }; -struct acpi_gpe_notify_object { - struct acpi_namespace_node *node; - struct acpi_gpe_notify_object *next; -}; - union acpi_gpe_dispatch_info { struct acpi_namespace_node *method_node; /* Method node for this GPE level */ struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ - struct acpi_gpe_notify_object device; /* List of _PRW devices for implicit notify */ + struct acpi_namespace_node *device_node; /* Parent _PRW device for implicit notify */ }; /* diff --git a/trunk/drivers/acpi/acpica/evgpe.c b/trunk/drivers/acpi/acpica/evgpe.c index 65c79add3b19..67d44ef2fbc1 100644 --- a/trunk/drivers/acpi/acpica/evgpe.c +++ b/trunk/drivers/acpi/acpica/evgpe.c @@ -466,7 +466,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) acpi_status status; struct acpi_gpe_event_info *local_gpe_event_info; struct acpi_evaluate_info *info; - struct acpi_gpe_notify_object *notify_object; ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); @@ -518,18 +517,10 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) * from this thread -- because handlers may in turn run other * control methods. */ - status = acpi_ev_queue_notify_request( - local_gpe_event_info->dispatch.device.node, - ACPI_NOTIFY_DEVICE_WAKE); - - notify_object = local_gpe_event_info->dispatch.device.next; - while (ACPI_SUCCESS(status) && notify_object) { - status = acpi_ev_queue_notify_request( - notify_object->node, - ACPI_NOTIFY_DEVICE_WAKE); - notify_object = notify_object->next; - } - + status = + acpi_ev_queue_notify_request(local_gpe_event_info->dispatch. + device_node, + ACPI_NOTIFY_DEVICE_WAKE); break; case ACPI_GPE_DISPATCH_METHOD: diff --git a/trunk/drivers/acpi/acpica/evxfgpe.c b/trunk/drivers/acpi/acpica/evxfgpe.c index 52aaff3df562..3b20a3401b64 100644 --- a/trunk/drivers/acpi/acpica/evxfgpe.c +++ b/trunk/drivers/acpi/acpica/evxfgpe.c @@ -198,9 +198,7 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, acpi_status status = AE_BAD_PARAMETER; struct acpi_gpe_event_info *gpe_event_info; struct acpi_namespace_node *device_node; - struct acpi_gpe_notify_object *notify_object; acpi_cpu_flags flags; - u8 gpe_dispatch_mask; ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); @@ -223,49 +221,27 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, goto unlock_and_exit; } - if (wake_device == ACPI_ROOT_OBJECT) { - goto out; - } - /* * If there is no method or handler for this GPE, then the * wake_device will be notified whenever this GPE fires (aka * "implicit notify") Note: The GPE is assumed to be * level-triggered (for windows compatibility). */ - gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK; - if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE - && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) { - goto out; - } + if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NONE) && (wake_device != ACPI_ROOT_OBJECT)) { - /* Validate wake_device is of type Device */ + /* Validate wake_device is of type Device */ - device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); - if (device_node->type != ACPI_TYPE_DEVICE) { - goto unlock_and_exit; - } - - if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) { - gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | - ACPI_GPE_LEVEL_TRIGGERED); - gpe_event_info->dispatch.device.node = device_node; - gpe_event_info->dispatch.device.next = NULL; - } else { - /* There are multiple devices to notify implicitly. */ - - notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object)); - if (!notify_object) { - status = AE_NO_MEMORY; + device_node = ACPI_CAST_PTR(struct acpi_namespace_node, + wake_device); + if (device_node->type != ACPI_TYPE_DEVICE) { goto unlock_and_exit; } - - notify_object->node = device_node; - notify_object->next = gpe_event_info->dispatch.device.next; - gpe_event_info->dispatch.device.next = notify_object; + gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | + ACPI_GPE_LEVEL_TRIGGERED); + gpe_event_info->dispatch.device_node = device_node; } - out: gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; status = AE_OK; diff --git a/trunk/drivers/acpi/apei/Kconfig b/trunk/drivers/acpi/apei/Kconfig index 9ecf6feae830..fca34ccfd294 100644 --- a/trunk/drivers/acpi/apei/Kconfig +++ b/trunk/drivers/acpi/apei/Kconfig @@ -21,13 +21,6 @@ config ACPI_APEI_GHES by firmware to produce more valuable hardware error information for Linux. -config ACPI_APEI_PCIEAER - bool "APEI PCIe AER logging/recovering support" - depends on ACPI_APEI && PCIEAER - help - PCIe AER errors may be reported via APEI firmware first mode. - Turn on this option to enable the corresponding support. - config ACPI_APEI_EINJ tristate "APEI Error INJection (EINJ)" depends on ACPI_APEI && DEBUG_FS diff --git a/trunk/drivers/acpi/apei/cper.c b/trunk/drivers/acpi/apei/cper.c index 5d4189464d63..31464a006d76 100644 --- a/trunk/drivers/acpi/apei/cper.c +++ b/trunk/drivers/acpi/apei/cper.c @@ -29,7 +29,6 @@ #include #include #include -#include /* * CPER record ID need to be unique even after reboot, because record @@ -71,8 +70,8 @@ static const char *cper_severity_str(unsigned int severity) * If the output length is longer than 80, multiple line will be * printed, with @pfx is printed at the beginning of each line. */ -void cper_print_bits(const char *pfx, unsigned int bits, - const char *strs[], unsigned int strs_size) +static void cper_print_bits(const char *pfx, unsigned int bits, + const char *strs[], unsigned int strs_size) { int i, len = 0; const char *str; @@ -82,8 +81,6 @@ void cper_print_bits(const char *pfx, unsigned int bits, if (!(bits & (1U << i))) continue; str = strs[i]; - if (!str) - continue; if (len && len + strlen(str) + 2 > 80) { printk("%s\n", buf); len = 0; @@ -246,8 +243,7 @@ static const char *cper_pcie_port_type_strs[] = { "root complex event collector", }; -static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, - const struct acpi_hest_generic_data *gdata) +static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie) { if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, @@ -280,12 +276,6 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, printk( "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", pfx, pcie->bridge.secondary_status, pcie->bridge.control); -#ifdef CONFIG_ACPI_APEI_PCIEAER - if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) { - struct aer_capability_regs *aer_regs = (void *)pcie->aer_info; - cper_print_aer(pfx, gdata->error_severity, aer_regs); - } -#endif } static const char *apei_estatus_section_flag_strs[] = { @@ -332,7 +322,7 @@ static void apei_estatus_print_section( struct cper_sec_pcie *pcie = (void *)(gdata + 1); printk("%s""section_type: PCIe error\n", pfx); if (gdata->error_data_length >= sizeof(*pcie)) - cper_print_pcie(pfx, pcie, gdata); + cper_print_pcie(pfx, pcie); else goto err_section_too_small; } else diff --git a/trunk/drivers/acpi/apei/erst-dbg.c b/trunk/drivers/acpi/apei/erst-dbg.c index a4cfb64c86a1..de73caf3cebc 100644 --- a/trunk/drivers/acpi/apei/erst-dbg.c +++ b/trunk/drivers/acpi/apei/erst-dbg.c @@ -43,27 +43,12 @@ static DEFINE_MUTEX(erst_dbg_mutex); static int erst_dbg_open(struct inode *inode, struct file *file) { - int rc, *pos; - if (erst_disable) return -ENODEV; - pos = (int *)&file->private_data; - - rc = erst_get_record_id_begin(pos); - if (rc) - return rc; - return nonseekable_open(inode, file); } -static int erst_dbg_release(struct inode *inode, struct file *file) -{ - erst_get_record_id_end(); - - return 0; -} - static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { int rc; @@ -94,20 +79,18 @@ static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg) static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf, size_t usize, loff_t *off) { - int rc, *pos; + int rc; ssize_t len = 0; u64 id; - if (*off) + if (*off != 0) return -EINVAL; if (mutex_lock_interruptible(&erst_dbg_mutex) != 0) return -EINTR; - pos = (int *)&filp->private_data; - retry_next: - rc = erst_get_record_id_next(pos, &id); + rc = erst_get_next_record_id(&id); if (rc) goto out; /* no more record */ @@ -198,7 +181,6 @@ static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf, static const struct file_operations erst_dbg_ops = { .owner = THIS_MODULE, .open = erst_dbg_open, - .release = erst_dbg_release, .read = erst_dbg_read, .write = erst_dbg_write, .unlocked_ioctl = erst_dbg_ioctl, diff --git a/trunk/drivers/acpi/apei/erst.c b/trunk/drivers/acpi/apei/erst.c index 8ff8c32fef58..cf6db6b7662a 100644 --- a/trunk/drivers/acpi/apei/erst.c +++ b/trunk/drivers/acpi/apei/erst.c @@ -429,22 +429,6 @@ ssize_t erst_get_record_count(void) } EXPORT_SYMBOL_GPL(erst_get_record_count); -#define ERST_RECORD_ID_CACHE_SIZE_MIN 16 -#define ERST_RECORD_ID_CACHE_SIZE_MAX 1024 - -struct erst_record_id_cache { - struct mutex lock; - u64 *entries; - int len; - int size; - int refcount; -}; - -static struct erst_record_id_cache erst_record_id_cache = { - .lock = __MUTEX_INITIALIZER(erst_record_id_cache.lock), - .refcount = 0, -}; - static int __erst_get_next_record_id(u64 *record_id) { struct apei_exec_context ctx; @@ -459,179 +443,26 @@ static int __erst_get_next_record_id(u64 *record_id) return 0; } -int erst_get_record_id_begin(int *pos) -{ - int rc; - - if (erst_disable) - return -ENODEV; - - rc = mutex_lock_interruptible(&erst_record_id_cache.lock); - if (rc) - return rc; - erst_record_id_cache.refcount++; - mutex_unlock(&erst_record_id_cache.lock); - - *pos = 0; - - return 0; -} -EXPORT_SYMBOL_GPL(erst_get_record_id_begin); - -/* erst_record_id_cache.lock must be held by caller */ -static int __erst_record_id_cache_add_one(void) -{ - u64 id, prev_id, first_id; - int i, rc; - u64 *entries; - unsigned long flags; - - id = prev_id = first_id = APEI_ERST_INVALID_RECORD_ID; -retry: - raw_spin_lock_irqsave(&erst_lock, flags); - rc = __erst_get_next_record_id(&id); - raw_spin_unlock_irqrestore(&erst_lock, flags); - if (rc == -ENOENT) - return 0; - if (rc) - return rc; - if (id == APEI_ERST_INVALID_RECORD_ID) - return 0; - /* can not skip current ID, or loop back to first ID */ - if (id == prev_id || id == first_id) - return 0; - if (first_id == APEI_ERST_INVALID_RECORD_ID) - first_id = id; - prev_id = id; - - entries = erst_record_id_cache.entries; - for (i = 0; i < erst_record_id_cache.len; i++) { - if (entries[i] == id) - break; - } - /* record id already in cache, try next */ - if (i < erst_record_id_cache.len) - goto retry; - if (erst_record_id_cache.len >= erst_record_id_cache.size) { - int new_size, alloc_size; - u64 *new_entries; - - new_size = erst_record_id_cache.size * 2; - new_size = clamp_val(new_size, ERST_RECORD_ID_CACHE_SIZE_MIN, - ERST_RECORD_ID_CACHE_SIZE_MAX); - if (new_size <= erst_record_id_cache.size) { - if (printk_ratelimit()) - pr_warning(FW_WARN ERST_PFX - "too many record ID!\n"); - return 0; - } - alloc_size = new_size * sizeof(entries[0]); - if (alloc_size < PAGE_SIZE) - new_entries = kmalloc(alloc_size, GFP_KERNEL); - else - new_entries = vmalloc(alloc_size); - if (!new_entries) - return -ENOMEM; - memcpy(new_entries, entries, - erst_record_id_cache.len * sizeof(entries[0])); - if (erst_record_id_cache.size < PAGE_SIZE) - kfree(entries); - else - vfree(entries); - erst_record_id_cache.entries = entries = new_entries; - erst_record_id_cache.size = new_size; - } - entries[i] = id; - erst_record_id_cache.len++; - - return 1; -} - /* * Get the record ID of an existing error record on the persistent * storage. If there is no error record on the persistent storage, the * returned record_id is APEI_ERST_INVALID_RECORD_ID. */ -int erst_get_record_id_next(int *pos, u64 *record_id) +int erst_get_next_record_id(u64 *record_id) { - int rc = 0; - u64 *entries; + int rc; + unsigned long flags; if (erst_disable) return -ENODEV; - /* must be enclosed by erst_get_record_id_begin/end */ - BUG_ON(!erst_record_id_cache.refcount); - BUG_ON(*pos < 0 || *pos > erst_record_id_cache.len); - - mutex_lock(&erst_record_id_cache.lock); - entries = erst_record_id_cache.entries; - for (; *pos < erst_record_id_cache.len; (*pos)++) - if (entries[*pos] != APEI_ERST_INVALID_RECORD_ID) - break; - /* found next record id in cache */ - if (*pos < erst_record_id_cache.len) { - *record_id = entries[*pos]; - (*pos)++; - goto out_unlock; - } - - /* Try to add one more record ID to cache */ - rc = __erst_record_id_cache_add_one(); - if (rc < 0) - goto out_unlock; - /* successfully add one new ID */ - if (rc == 1) { - *record_id = erst_record_id_cache.entries[*pos]; - (*pos)++; - rc = 0; - } else { - *pos = -1; - *record_id = APEI_ERST_INVALID_RECORD_ID; - } -out_unlock: - mutex_unlock(&erst_record_id_cache.lock); + raw_spin_lock_irqsave(&erst_lock, flags); + rc = __erst_get_next_record_id(record_id); + raw_spin_unlock_irqrestore(&erst_lock, flags); return rc; } -EXPORT_SYMBOL_GPL(erst_get_record_id_next); - -/* erst_record_id_cache.lock must be held by caller */ -static void __erst_record_id_cache_compact(void) -{ - int i, wpos = 0; - u64 *entries; - - if (erst_record_id_cache.refcount) - return; - - entries = erst_record_id_cache.entries; - for (i = 0; i < erst_record_id_cache.len; i++) { - if (entries[i] == APEI_ERST_INVALID_RECORD_ID) - continue; - if (wpos != i) - memcpy(&entries[wpos], &entries[i], sizeof(entries[i])); - wpos++; - } - erst_record_id_cache.len = wpos; -} - -void erst_get_record_id_end(void) -{ - /* - * erst_disable != 0 should be detected by invoker via the - * return value of erst_get_record_id_begin/next, so this - * function should not be called for erst_disable != 0. - */ - BUG_ON(erst_disable); - - mutex_lock(&erst_record_id_cache.lock); - erst_record_id_cache.refcount--; - BUG_ON(erst_record_id_cache.refcount < 0); - __erst_record_id_cache_compact(); - mutex_unlock(&erst_record_id_cache.lock); -} -EXPORT_SYMBOL_GPL(erst_get_record_id_end); +EXPORT_SYMBOL_GPL(erst_get_next_record_id); static int __erst_write_to_storage(u64 offset) { @@ -872,34 +703,56 @@ ssize_t erst_read(u64 record_id, struct cper_record_header *record, } EXPORT_SYMBOL_GPL(erst_read); -int erst_clear(u64 record_id) +/* + * If return value > buflen, the buffer size is not big enough, + * else if return value = 0, there is no more record to read, + * else if return value < 0, something goes wrong, + * else everything is OK, and return value is record length + */ +ssize_t erst_read_next(struct cper_record_header *record, size_t buflen) { - int rc, i; + int rc; + ssize_t len; unsigned long flags; - u64 *entries; + u64 record_id; if (erst_disable) return -ENODEV; - rc = mutex_lock_interruptible(&erst_record_id_cache.lock); - if (rc) + raw_spin_lock_irqsave(&erst_lock, flags); + rc = __erst_get_next_record_id(&record_id); + if (rc) { + raw_spin_unlock_irqrestore(&erst_lock, flags); return rc; + } + /* no more record */ + if (record_id == APEI_ERST_INVALID_RECORD_ID) { + raw_spin_unlock_irqrestore(&erst_lock, flags); + return 0; + } + + len = __erst_read(record_id, record, buflen); + raw_spin_unlock_irqrestore(&erst_lock, flags); + + return len; +} +EXPORT_SYMBOL_GPL(erst_read_next); + +int erst_clear(u64 record_id) +{ + int rc; + unsigned long flags; + + if (erst_disable) + return -ENODEV; + raw_spin_lock_irqsave(&erst_lock, flags); if (erst_erange.attr & ERST_RANGE_NVRAM) rc = __erst_clear_from_nvram(record_id); else rc = __erst_clear_from_storage(record_id); raw_spin_unlock_irqrestore(&erst_lock, flags); - if (rc) - goto out; - entries = erst_record_id_cache.entries; - for (i = 0; i < erst_record_id_cache.len; i++) { - if (entries[i] == record_id) - entries[i] = APEI_ERST_INVALID_RECORD_ID; - } - __erst_record_id_cache_compact(); -out: - mutex_unlock(&erst_record_id_cache.lock); + return rc; } EXPORT_SYMBOL_GPL(erst_clear); diff --git a/trunk/drivers/acpi/button.c b/trunk/drivers/acpi/button.c index d27d072472f9..76bbb78a5ad9 100644 --- a/trunk/drivers/acpi/button.c +++ b/trunk/drivers/acpi/button.c @@ -78,6 +78,8 @@ static int acpi_button_add(struct acpi_device *device); static int acpi_button_remove(struct acpi_device *device, int type); static int acpi_button_resume(struct acpi_device *device); static void acpi_button_notify(struct acpi_device *device, u32 event); +static int acpi_button_info_open_fs(struct inode *inode, struct file *file); +static int acpi_button_state_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_button_driver = { .name = "button", @@ -96,7 +98,22 @@ struct acpi_button { struct input_dev *input; char phys[32]; /* for input device */ unsigned long pushed; - bool wakeup_enabled; +}; + +static const struct file_operations acpi_button_info_fops = { + .owner = THIS_MODULE, + .open = acpi_button_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations acpi_button_state_fops = { + .owner = THIS_MODULE, + .open = acpi_button_state_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); @@ -107,7 +124,20 @@ static struct acpi_device *lid_device; -------------------------------------------------------------------------- */ static struct proc_dir_entry *acpi_button_dir; -static struct proc_dir_entry *acpi_lid_dir; + +static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_device *device = seq->private; + + seq_printf(seq, "type: %s\n", + acpi_device_name(device)); + return 0; +} + +static int acpi_button_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_button_info_seq_show, PDE(inode)->data); +} static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) { @@ -127,85 +157,77 @@ static int acpi_button_state_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); } -static const struct file_operations acpi_button_state_fops = { - .owner = THIS_MODULE, - .open = acpi_button_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +static struct proc_dir_entry *acpi_power_dir; +static struct proc_dir_entry *acpi_sleep_dir; +static struct proc_dir_entry *acpi_lid_dir; static int acpi_button_add_fs(struct acpi_device *device) { struct acpi_button *button = acpi_driver_data(device); struct proc_dir_entry *entry = NULL; - int ret = 0; - /* procfs I/F for ACPI lid device only */ - if (button->type != ACPI_BUTTON_TYPE_LID) - return 0; - - if (acpi_button_dir || acpi_lid_dir) { - printk(KERN_ERR PREFIX "More than one Lid device found!\n"); - return -EEXIST; + switch (button->type) { + case ACPI_BUTTON_TYPE_POWER: + if (!acpi_power_dir) + acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, + acpi_button_dir); + entry = acpi_power_dir; + break; + case ACPI_BUTTON_TYPE_SLEEP: + if (!acpi_sleep_dir) + acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, + acpi_button_dir); + entry = acpi_sleep_dir; + break; + case ACPI_BUTTON_TYPE_LID: + if (!acpi_lid_dir) + acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, + acpi_button_dir); + entry = acpi_lid_dir; + break; } - /* create /proc/acpi/button */ - acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); - if (!acpi_button_dir) + if (!entry) return -ENODEV; - /* create /proc/acpi/button/lid */ - acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); - if (!acpi_lid_dir) { - ret = -ENODEV; - goto remove_button_dir; - } - - /* create /proc/acpi/button/lid/LID/ */ - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir); - if (!acpi_device_dir(device)) { - ret = -ENODEV; - goto remove_lid_dir; - } + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); + if (!acpi_device_dir(device)) + return -ENODEV; - /* create /proc/acpi/button/lid/LID/state */ - entry = proc_create_data(ACPI_BUTTON_FILE_STATE, + /* 'info' [R] */ + entry = proc_create_data(ACPI_BUTTON_FILE_INFO, S_IRUGO, acpi_device_dir(device), - &acpi_button_state_fops, device); - if (!entry) { - ret = -ENODEV; - goto remove_dev_dir; - } + &acpi_button_info_fops, device); + if (!entry) + return -ENODEV; -done: - return ret; + /* show lid state [R] */ + if (button->type == ACPI_BUTTON_TYPE_LID) { + entry = proc_create_data(ACPI_BUTTON_FILE_STATE, + S_IRUGO, acpi_device_dir(device), + &acpi_button_state_fops, device); + if (!entry) + return -ENODEV; + } -remove_dev_dir: - remove_proc_entry(acpi_device_bid(device), - acpi_lid_dir); - acpi_device_dir(device) = NULL; -remove_lid_dir: - remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); -remove_button_dir: - remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); - goto done; + return 0; } static int acpi_button_remove_fs(struct acpi_device *device) { struct acpi_button *button = acpi_driver_data(device); - if (button->type != ACPI_BUTTON_TYPE_LID) - return 0; + if (acpi_device_dir(device)) { + if (button->type == ACPI_BUTTON_TYPE_LID) + remove_proc_entry(ACPI_BUTTON_FILE_STATE, + acpi_device_dir(device)); + remove_proc_entry(ACPI_BUTTON_FILE_INFO, + acpi_device_dir(device)); - remove_proc_entry(ACPI_BUTTON_FILE_STATE, - acpi_device_dir(device)); - remove_proc_entry(acpi_device_bid(device), - acpi_lid_dir); - acpi_device_dir(device) = NULL; - remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); - remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); + remove_proc_entry(acpi_device_bid(device), + acpi_device_dir(device)->parent); + acpi_device_dir(device) = NULL; + } return 0; } @@ -408,10 +430,8 @@ static int acpi_button_add(struct acpi_device *device) /* Button's GPE is run-wake GPE */ acpi_enable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number); - if (!device_may_wakeup(&device->dev)) { - device_set_wakeup_enable(&device->dev, true); - button->wakeup_enabled = true; - } + device->wakeup.run_wake_count++; + device_set_wakeup_enable(&device->dev, true); } printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); @@ -433,8 +453,8 @@ static int acpi_button_remove(struct acpi_device *device, int type) if (device->wakeup.flags.valid) { acpi_disable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number); - if (button->wakeup_enabled) - device_set_wakeup_enable(&device->dev, false); + device->wakeup.run_wake_count--; + device_set_wakeup_enable(&device->dev, false); } acpi_button_remove_fs(device); @@ -445,12 +465,32 @@ static int acpi_button_remove(struct acpi_device *device, int type) static int __init acpi_button_init(void) { - return acpi_bus_register_driver(&acpi_button_driver); + int result; + + acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); + if (!acpi_button_dir) + return -ENODEV; + + result = acpi_bus_register_driver(&acpi_button_driver); + if (result < 0) { + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); + return -ENODEV; + } + + return 0; } static void __exit acpi_button_exit(void) { acpi_bus_unregister_driver(&acpi_button_driver); + + if (acpi_power_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir); + if (acpi_sleep_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir); + if (acpi_lid_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); } module_init(acpi_button_init); diff --git a/trunk/drivers/acpi/debugfs.c b/trunk/drivers/acpi/debugfs.c index 384f7abcff77..5df67f1d6c61 100644 --- a/trunk/drivers/acpi/debugfs.c +++ b/trunk/drivers/acpi/debugfs.c @@ -26,9 +26,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, size_t count, loff_t *ppos) { static char *buf; - static u32 max_size; - static u32 uncopied_bytes; - + static int uncopied_bytes; struct acpi_table_header table; acpi_status status; @@ -39,24 +37,19 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, if (copy_from_user(&table, user_buf, sizeof(struct acpi_table_header))) return -EFAULT; - uncopied_bytes = max_size = table.length; - buf = kzalloc(max_size, GFP_KERNEL); + uncopied_bytes = table.length; + buf = kzalloc(uncopied_bytes, GFP_KERNEL); if (!buf) return -ENOMEM; } - if (buf == NULL) - return -EINVAL; - - if ((*ppos > max_size) || - (*ppos + count > max_size) || - (*ppos + count < count) || - (count > uncopied_bytes)) + if (uncopied_bytes < count) { + kfree(buf); return -EINVAL; + } if (copy_from_user(buf + (*ppos), user_buf, count)) { kfree(buf); - buf = NULL; return -EFAULT; } @@ -66,7 +59,6 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, if (!uncopied_bytes) { status = acpi_install_method(buf); kfree(buf); - buf = NULL; if (ACPI_FAILURE(status)) return -EINVAL; add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); diff --git a/trunk/drivers/acpi/nvs.c b/trunk/drivers/acpi/nvs.c index 096787b43c96..fa5a1df42b79 100644 --- a/trunk/drivers/acpi/nvs.c +++ b/trunk/drivers/acpi/nvs.c @@ -26,7 +26,6 @@ struct nvs_page { unsigned int size; void *kaddr; void *data; - bool unmap; struct list_head node; }; @@ -45,9 +44,6 @@ int suspend_nvs_register(unsigned long start, unsigned long size) { struct nvs_page *entry, *next; - pr_info("PM: Registering ACPI NVS region at %lx (%ld bytes)\n", - start, size); - while (size > 0) { unsigned int nr_bytes; @@ -85,13 +81,7 @@ void suspend_nvs_free(void) free_page((unsigned long)entry->data); entry->data = NULL; if (entry->kaddr) { - if (entry->unmap) { - iounmap(entry->kaddr); - entry->unmap = false; - } else { - acpi_os_unmap_memory(entry->kaddr, - entry->size); - } + iounmap(entry->kaddr); entry->kaddr = NULL; } } @@ -125,14 +115,8 @@ int suspend_nvs_save(void) list_for_each_entry(entry, &nvs_list, node) if (entry->data) { - unsigned long phys = entry->phys_start; - unsigned int size = entry->size; - - entry->kaddr = acpi_os_get_iomem(phys, size); - if (!entry->kaddr) { - entry->kaddr = acpi_os_ioremap(phys, size); - entry->unmap = !!entry->kaddr; - } + entry->kaddr = acpi_os_ioremap(entry->phys_start, + entry->size); if (!entry->kaddr) { suspend_nvs_free(); return -ENOMEM; diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index 45c6ac8790d7..c90c76aa7f8b 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -76,6 +76,7 @@ EXPORT_SYMBOL(acpi_in_debugger); extern char line_buf[80]; #endif /*ENABLE_DEBUGGER */ +static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; @@ -104,11 +105,11 @@ struct acpi_ioremap { void __iomem *virt; acpi_physical_address phys; acpi_size size; - unsigned long refcount; + struct kref ref; }; static LIST_HEAD(acpi_ioremaps); -static DEFINE_MUTEX(acpi_ioremap_lock); +static DEFINE_SPINLOCK(acpi_ioremap_lock); static void __init acpi_osi_setup_late(void); @@ -284,22 +285,6 @@ acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size) return NULL; } -void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size) -{ - struct acpi_ioremap *map; - void __iomem *virt = NULL; - - mutex_lock(&acpi_ioremap_lock); - map = acpi_map_lookup(phys, size); - if (map) { - virt = map->virt + (phys - map->phys); - map->refcount++; - } - mutex_unlock(&acpi_ioremap_lock); - return virt; -} -EXPORT_SYMBOL_GPL(acpi_os_get_iomem); - /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ static struct acpi_ioremap * acpi_map_lookup_virt(void __iomem *virt, acpi_size size) @@ -317,7 +302,8 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) void __iomem *__init_refok acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { - struct acpi_ioremap *map; + struct acpi_ioremap *map, *tmp_map; + unsigned long flags; void __iomem *virt; acpi_physical_address pg_off; acpi_size pg_sz; @@ -330,25 +316,14 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) if (!acpi_gbl_permanent_mmap) return __acpi_map_table((unsigned long)phys, size); - mutex_lock(&acpi_ioremap_lock); - /* Check if there's a suitable mapping already. */ - map = acpi_map_lookup(phys, size); - if (map) { - map->refcount++; - goto out; - } - map = kzalloc(sizeof(*map), GFP_KERNEL); - if (!map) { - mutex_unlock(&acpi_ioremap_lock); + if (!map) return NULL; - } pg_off = round_down(phys, PAGE_SIZE); pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; virt = acpi_os_ioremap(pg_off, pg_sz); if (!virt) { - mutex_unlock(&acpi_ioremap_lock); kfree(map); return NULL; } @@ -357,51 +332,62 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) map->virt = virt; map->phys = pg_off; map->size = pg_sz; - map->refcount = 1; - + kref_init(&map->ref); + + spin_lock_irqsave(&acpi_ioremap_lock, flags); + /* Check if page has already been mapped. */ + tmp_map = acpi_map_lookup(phys, size); + if (tmp_map) { + kref_get(&tmp_map->ref); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + iounmap(map->virt); + kfree(map); + return tmp_map->virt + (phys - tmp_map->phys); + } list_add_tail_rcu(&map->list, &acpi_ioremaps); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); - out: - mutex_unlock(&acpi_ioremap_lock); return map->virt + (phys - map->phys); } EXPORT_SYMBOL_GPL(acpi_os_map_memory); -static void acpi_os_drop_map_ref(struct acpi_ioremap *map) +static void acpi_kref_del_iomap(struct kref *ref) { - if (!--map->refcount) - list_del_rcu(&map->list); -} + struct acpi_ioremap *map; -static void acpi_os_map_cleanup(struct acpi_ioremap *map) -{ - if (!map->refcount) { - synchronize_rcu(); - iounmap(map->virt); - kfree(map); - } + map = container_of(ref, struct acpi_ioremap, ref); + list_del_rcu(&map->list); } void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) { struct acpi_ioremap *map; + unsigned long flags; + int del; if (!acpi_gbl_permanent_mmap) { __acpi_unmap_table(virt, size); return; } - mutex_lock(&acpi_ioremap_lock); + spin_lock_irqsave(&acpi_ioremap_lock, flags); map = acpi_map_lookup_virt(virt, size); if (!map) { - mutex_unlock(&acpi_ioremap_lock); - WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt); + dump_stack(); return; } - acpi_os_drop_map_ref(map); - mutex_unlock(&acpi_ioremap_lock); - acpi_os_map_cleanup(map); + del = kref_put(&map->ref, acpi_kref_del_iomap); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + + if (!del) + return; + + synchronize_rcu(); + iounmap(map->virt); + kfree(map); } EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); @@ -411,7 +397,7 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size) __acpi_unmap_table(virt, size); } -static int acpi_os_map_generic_address(struct acpi_generic_address *addr) +int acpi_os_map_generic_address(struct acpi_generic_address *addr) { void __iomem *virt; @@ -427,10 +413,13 @@ static int acpi_os_map_generic_address(struct acpi_generic_address *addr) return 0; } +EXPORT_SYMBOL_GPL(acpi_os_map_generic_address); -static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) +void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) { - struct acpi_ioremap *map; + void __iomem *virt; + unsigned long flags; + acpi_size size = addr->bit_width / 8; if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) return; @@ -438,17 +427,13 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) if (!addr->address || !addr->bit_width) return; - mutex_lock(&acpi_ioremap_lock); - map = acpi_map_lookup(addr->address, addr->bit_width / 8); - if (!map) { - mutex_unlock(&acpi_ioremap_lock); - return; - } - acpi_os_drop_map_ref(map); - mutex_unlock(&acpi_ioremap_lock); + spin_lock_irqsave(&acpi_ioremap_lock, flags); + virt = acpi_map_vaddr_lookup(addr->address, size); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); - acpi_os_map_cleanup(map); + acpi_os_unmap_memory(virt, size); } +EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address); #ifdef ACPI_FUTURE_USAGE acpi_status @@ -531,15 +516,11 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_stats_init(); /* - * ACPI interrupts different from the SCI in our copy of the FADT are - * not supported. + * Ignore the GSI from the core, and use the value in our copy of the + * FADT. It may not be the same if an interrupt source override exists + * for the SCI. */ - if (gsi != acpi_gbl_FADT.sci_interrupt) - return AE_BAD_PARAMETER; - - if (acpi_irq_handler) - return AE_ALREADY_ACQUIRED; - + gsi = acpi_gbl_FADT.sci_interrupt; if (acpi_gsi_to_irq(gsi, &irq) < 0) { printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", gsi); @@ -550,20 +531,20 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_context = context; if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); - acpi_irq_handler = NULL; return AE_NOT_ACQUIRED; } + acpi_irq_irq = irq; return AE_OK; } acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) { - if (irq != acpi_gbl_FADT.sci_interrupt) - return AE_BAD_PARAMETER; - - free_irq(irq, acpi_irq); - acpi_irq_handler = NULL; + if (irq) { + free_irq(irq, acpi_irq); + acpi_irq_handler = NULL; + acpi_irq_irq = 0; + } return AE_OK; } @@ -1622,7 +1603,7 @@ acpi_status __init acpi_os_initialize1(void) acpi_status acpi_os_terminate(void) { if (acpi_irq_handler) { - acpi_os_remove_interrupt_handler(acpi_gbl_FADT.sci_interrupt, + acpi_os_remove_interrupt_handler(acpi_irq_irq, acpi_irq_handler); } diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index b136c9c1e531..b99e62494607 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -797,6 +797,7 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) acpi_status status; acpi_event_status event_status; + device->wakeup.run_wake_count = 0; device->wakeup.flags.notifier_present = 0; /* Power button, Lid switch always enable wakeup */ diff --git a/trunk/drivers/acpi/sleep.c b/trunk/drivers/acpi/sleep.c index 84f57143ad7c..d6a8cd14de2e 100644 --- a/trunk/drivers/acpi/sleep.c +++ b/trunk/drivers/acpi/sleep.c @@ -199,6 +199,8 @@ static void acpi_pm_end(void) #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND +extern void do_suspend_lowlevel(void); + static u32 acpi_suspend_states[] = { [PM_SUSPEND_ON] = ACPI_STATE_S0, [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, @@ -241,11 +243,20 @@ static int acpi_suspend_begin(suspend_state_t pm_state) static int acpi_suspend_enter(suspend_state_t pm_state) { acpi_status status = AE_OK; + unsigned long flags = 0; u32 acpi_state = acpi_target_sleep_state; - int error; ACPI_FLUSH_CPU_CACHE(); + /* Do arch specific saving of state. */ + if (acpi_state == ACPI_STATE_S3) { + int error = acpi_save_state_mem(); + + if (error) + return error; + } + + local_irq_save(flags); switch (acpi_state) { case ACPI_STATE_S1: barrier(); @@ -253,10 +264,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) break; case ACPI_STATE_S3: - error = acpi_suspend_lowlevel(); - if (error) - return error; - pr_info(PREFIX "Low-level resume complete\n"); + do_suspend_lowlevel(); break; } @@ -282,6 +290,13 @@ static int acpi_suspend_enter(suspend_state_t pm_state) /* Allow EC transactions to happen. */ acpi_ec_unblock_transactions_early(); + local_irq_restore(flags); + printk(KERN_DEBUG "Back to C!\n"); + + /* restore processor state */ + if (acpi_state == ACPI_STATE_S3) + acpi_restore_state_mem(); + suspend_nvs_restore(); return ACPI_SUCCESS(status) ? 0 : -EFAULT; @@ -457,13 +472,16 @@ static int acpi_hibernation_begin(void) static int acpi_hibernation_enter(void) { acpi_status status = AE_OK; + unsigned long flags = 0; ACPI_FLUSH_CPU_CACHE(); + local_irq_save(flags); /* This shouldn't return. If it returns, we have a problem */ status = acpi_enter_sleep_state(ACPI_STATE_S4); /* Reprogram control registers and execute _BFS */ acpi_leave_sleep_state_prep(ACPI_STATE_S4); + local_irq_restore(flags); return ACPI_SUCCESS(status) ? 0 : -EFAULT; } diff --git a/trunk/drivers/pci/pci-acpi.c b/trunk/drivers/pci/pci-acpi.c index 7c3b18e78cee..6fe0772e0e7d 100644 --- a/trunk/drivers/pci/pci-acpi.c +++ b/trunk/drivers/pci/pci-acpi.c @@ -293,11 +293,19 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable) } if (enable) { - acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); - acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); + if (!dev->wakeup.run_wake_count++) { + acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); + acpi_enable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number); + } + } else if (dev->wakeup.run_wake_count > 0) { + if (!--dev->wakeup.run_wake_count) { + acpi_disable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number); + acpi_disable_wakeup_device_power(dev); + } } else { - acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); - acpi_disable_wakeup_device_power(dev); + error = -EALREADY; } return error; diff --git a/trunk/drivers/pci/pcie/aer/aerdrv.h b/trunk/drivers/pci/pcie/aer/aerdrv.h index 3eb77080366a..80c11d131499 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv.h +++ b/trunk/drivers/pci/pcie/aer/aerdrv.h @@ -35,6 +35,13 @@ PCI_ERR_UNC_UNX_COMP| \ PCI_ERR_UNC_MALF_TLP) +struct header_log_regs { + unsigned int dw0; + unsigned int dw1; + unsigned int dw2; + unsigned int dw3; +}; + #define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */ struct aer_err_info { struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES]; @@ -52,7 +59,7 @@ struct aer_err_info { unsigned int status; /* COR/UNCOR Error Status */ unsigned int mask; /* COR/UNCOR Error Mask */ - struct aer_header_log_regs tlp; /* TLP Header */ + struct header_log_regs tlp; /* TLP Header */ }; struct aer_err_source { diff --git a/trunk/drivers/pci/pcie/aer/aerdrv_errprint.c b/trunk/drivers/pci/pcie/aer/aerdrv_errprint.c index b07a42e0b350..9d3e4c8d0184 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv_errprint.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "aerdrv.h" @@ -58,44 +57,86 @@ (e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \ AER_TRANSACTION_LAYER_ERROR) +#define AER_PR(info, pdev, fmt, args...) \ + printk("%s%s %s: " fmt, (info->severity == AER_CORRECTABLE) ? \ + KERN_WARNING : KERN_ERR, dev_driver_string(&pdev->dev), \ + dev_name(&pdev->dev), ## args) + /* * AER error strings */ -static const char *aer_error_severity_string[] = { +static char *aer_error_severity_string[] = { "Uncorrected (Non-Fatal)", "Uncorrected (Fatal)", "Corrected" }; -static const char *aer_error_layer[] = { +static char *aer_error_layer[] = { "Physical Layer", "Data Link Layer", "Transaction Layer" }; - -static const char *aer_correctable_error_string[] = { - "Receiver Error", /* Bit Position 0 */ +static char *aer_correctable_error_string[] = { + "Receiver Error ", /* Bit Position 0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + "Bad TLP ", /* Bit Position 6 */ + "Bad DLLP ", /* Bit Position 7 */ + "RELAY_NUM Rollover ", /* Bit Position 8 */ + NULL, + NULL, + NULL, + "Replay Timer Timeout ", /* Bit Position 12 */ + "Advisory Non-Fatal ", /* Bit Position 13 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, NULL, NULL, NULL, NULL, NULL, - "Bad TLP", /* Bit Position 6 */ - "Bad DLLP", /* Bit Position 7 */ - "RELAY_NUM Rollover", /* Bit Position 8 */ NULL, NULL, NULL, - "Replay Timer Timeout", /* Bit Position 12 */ - "Advisory Non-Fatal", /* Bit Position 13 */ }; -static const char *aer_uncorrectable_error_string[] = { +static char *aer_uncorrectable_error_string[] = { + NULL, + NULL, + NULL, + NULL, + "Data Link Protocol ", /* Bit Position 4 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Poisoned TLP ", /* Bit Position 12 */ + "Flow Control Protocol ", /* Bit Position 13 */ + "Completion Timeout ", /* Bit Position 14 */ + "Completer Abort ", /* Bit Position 15 */ + "Unexpected Completion ", /* Bit Position 16 */ + "Receiver Overflow ", /* Bit Position 17 */ + "Malformed TLP ", /* Bit Position 18 */ + "ECRC ", /* Bit Position 19 */ + "Unsupported Request ", /* Bit Position 20 */ NULL, NULL, NULL, NULL, - "Data Link Protocol", /* Bit Position 4 */ NULL, NULL, NULL, @@ -103,29 +144,19 @@ static const char *aer_uncorrectable_error_string[] = { NULL, NULL, NULL, - "Poisoned TLP", /* Bit Position 12 */ - "Flow Control Protocol", /* Bit Position 13 */ - "Completion Timeout", /* Bit Position 14 */ - "Completer Abort", /* Bit Position 15 */ - "Unexpected Completion", /* Bit Position 16 */ - "Receiver Overflow", /* Bit Position 17 */ - "Malformed TLP", /* Bit Position 18 */ - "ECRC", /* Bit Position 19 */ - "Unsupported Request", /* Bit Position 20 */ }; -static const char *aer_agent_string[] = { +static char *aer_agent_string[] = { "Receiver ID", "Requester ID", "Completer ID", "Transmitter ID" }; -static void __aer_print_error(const char *prefix, - struct aer_err_info *info) +static void __aer_print_error(struct aer_err_info *info, struct pci_dev *dev) { int i, status; - const char *errmsg = NULL; + char *errmsg = NULL; status = (info->status & ~info->mask); @@ -134,17 +165,15 @@ static void __aer_print_error(const char *prefix, continue; if (info->severity == AER_CORRECTABLE) - errmsg = i < ARRAY_SIZE(aer_correctable_error_string) ? - aer_correctable_error_string[i] : NULL; + errmsg = aer_correctable_error_string[i]; else - errmsg = i < ARRAY_SIZE(aer_uncorrectable_error_string) ? - aer_uncorrectable_error_string[i] : NULL; + errmsg = aer_uncorrectable_error_string[i]; if (errmsg) - printk("%s"" [%2d] %-22s%s\n", prefix, i, errmsg, + AER_PR(info, dev, " [%2d] %s%s\n", i, errmsg, info->first_error == i ? " (First)" : ""); else - printk("%s"" [%2d] Unknown Error Bit%s\n", prefix, i, + AER_PR(info, dev, " [%2d] Unknown Error Bit%s\n", i, info->first_error == i ? " (First)" : ""); } } @@ -152,15 +181,11 @@ static void __aer_print_error(const char *prefix, void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) { int id = ((dev->bus->number << 8) | dev->devfn); - char prefix[44]; - - snprintf(prefix, sizeof(prefix), "%s%s %s: ", - (info->severity == AER_CORRECTABLE) ? KERN_WARNING : KERN_ERR, - dev_driver_string(&dev->dev), dev_name(&dev->dev)); if (info->status == 0) { - printk("%s""PCIe Bus Error: severity=%s, type=Unaccessible, " - "id=%04x(Unregistered Agent ID)\n", prefix, + AER_PR(info, dev, + "PCIe Bus Error: severity=%s, type=Unaccessible, " + "id=%04x(Unregistered Agent ID)\n", aer_error_severity_string[info->severity], id); } else { int layer, agent; @@ -168,22 +193,23 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) layer = AER_GET_LAYER_ERROR(info->severity, info->status); agent = AER_GET_AGENT(info->severity, info->status); - printk("%s""PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", - prefix, aer_error_severity_string[info->severity], + AER_PR(info, dev, + "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", + aer_error_severity_string[info->severity], aer_error_layer[layer], id, aer_agent_string[agent]); - printk("%s"" device [%04x:%04x] error status/mask=%08x/%08x\n", - prefix, dev->vendor, dev->device, - info->status, info->mask); + AER_PR(info, dev, + " device [%04x:%04x] error status/mask=%08x/%08x\n", + dev->vendor, dev->device, info->status, info->mask); - __aer_print_error(prefix, info); + __aer_print_error(info, dev); if (info->tlp_header_valid) { unsigned char *tlp = (unsigned char *) &info->tlp; - printk("%s"" TLP Header:" + AER_PR(info, dev, " TLP Header:" " %02x%02x%02x%02x %02x%02x%02x%02x" " %02x%02x%02x%02x %02x%02x%02x%02x\n", - prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, + *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), *(tlp + 11), *(tlp + 10), *(tlp + 9), *(tlp + 8), *(tlp + 15), *(tlp + 14), @@ -192,8 +218,8 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) } if (info->id && info->error_dev_num > 1 && info->id == id) - printk("%s"" Error of this Agent(%04x) is reported first\n", - prefix, id); + AER_PR(info, dev, + " Error of this Agent(%04x) is reported first\n", id); } void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info) @@ -202,61 +228,3 @@ void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info) info->multi_error_valid ? "Multiple " : "", aer_error_severity_string[info->severity], info->id); } - -#ifdef CONFIG_ACPI_APEI_PCIEAER -static int cper_severity_to_aer(int cper_severity) -{ - switch (cper_severity) { - case CPER_SEV_RECOVERABLE: - return AER_NONFATAL; - case CPER_SEV_FATAL: - return AER_FATAL; - default: - return AER_CORRECTABLE; - } -} - -void cper_print_aer(const char *prefix, int cper_severity, - struct aer_capability_regs *aer) -{ - int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0; - u32 status, mask; - const char **status_strs; - - aer_severity = cper_severity_to_aer(cper_severity); - if (aer_severity == AER_CORRECTABLE) { - status = aer->cor_status; - mask = aer->cor_mask; - status_strs = aer_correctable_error_string; - status_strs_size = ARRAY_SIZE(aer_correctable_error_string); - } else { - status = aer->uncor_status; - mask = aer->uncor_mask; - status_strs = aer_uncorrectable_error_string; - status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string); - tlp_header_valid = status & AER_LOG_TLP_MASKS; - } - layer = AER_GET_LAYER_ERROR(aer_severity, status); - agent = AER_GET_AGENT(aer_severity, status); - printk("%s""aer_status: 0x%08x, aer_mask: 0x%08x\n", - prefix, status, mask); - cper_print_bits(prefix, status, status_strs, status_strs_size); - printk("%s""aer_layer=%s, aer_agent=%s\n", prefix, - aer_error_layer[layer], aer_agent_string[agent]); - if (aer_severity != AER_CORRECTABLE) - printk("%s""aer_uncor_severity: 0x%08x\n", - prefix, aer->uncor_severity); - if (tlp_header_valid) { - const unsigned char *tlp; - tlp = (const unsigned char *)&aer->header_log; - printk("%s""aer_tlp_header:" - " %02x%02x%02x%02x %02x%02x%02x%02x" - " %02x%02x%02x%02x %02x%02x%02x%02x\n", - prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, - *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), - *(tlp + 11), *(tlp + 10), *(tlp + 9), - *(tlp + 8), *(tlp + 15), *(tlp + 14), - *(tlp + 13), *(tlp + 12)); - } -} -#endif diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index f50ebb9bc53b..78ca429929f7 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -250,6 +250,7 @@ struct acpi_device_wakeup { struct acpi_handle_list resources; struct acpi_device_wakeup_flags flags; int prepare_count; + int run_wake_count; }; /* Device */ diff --git a/trunk/include/acpi/actbl2.h b/trunk/include/acpi/actbl2.h index 0fc15dfb2e22..58bdd0545c5a 100644 --- a/trunk/include/acpi/actbl2.h +++ b/trunk/include/acpi/actbl2.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Name: actbl2.h - ACPI Specification Revision 2.0 Tables + * Name: actbl2.h - ACPI Table Definitions (tables not in ACPI spec) * *****************************************************************************/ @@ -714,6 +714,68 @@ struct acpi_table_mchi { u8 pci_function; }; +/******************************************************************************* + * + * SLIC - Software Licensing Description Table + * Version 1 + * + * Conforms to "OEM Activation 2.0 for Windows Vista Operating Systems", + * Copyright 2006 + * + ******************************************************************************/ + +/* Basic SLIC table is only the common ACPI header */ + +struct acpi_table_slic { + struct acpi_table_header header; /* Common ACPI table header */ +}; + +/* Common SLIC subtable header */ + +struct acpi_slic_header { + u32 type; + u32 length; +}; + +/* Values for Type field above */ + +enum acpi_slic_type { + ACPI_SLIC_TYPE_PUBLIC_KEY = 0, + ACPI_SLIC_TYPE_WINDOWS_MARKER = 1, + ACPI_SLIC_TYPE_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* + * SLIC Sub-tables, correspond to Type in struct acpi_slic_header + */ + +/* 0: Public Key Structure */ + +struct acpi_slic_key { + struct acpi_slic_header header; + u8 key_type; + u8 version; + u16 reserved; + u32 algorithm; + char magic[4]; + u32 bit_length; + u32 exponent; + u8 modulus[128]; +}; + +/* 1: Windows Marker Structure */ + +struct acpi_slic_marker { + struct acpi_slic_header header; + u32 version; + char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */ + char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */ + char windows_flag[8]; + u32 slic_version; + u8 reserved[16]; + u8 signature[128]; +}; + /******************************************************************************* * * SPCR - Serial Port Console Redirection table diff --git a/trunk/include/acpi/apei.h b/trunk/include/acpi/apei.h index e67b523a50e1..c4dbb132d902 100644 --- a/trunk/include/acpi/apei.h +++ b/trunk/include/acpi/apei.h @@ -30,11 +30,10 @@ int apei_hest_parse(apei_hest_func_t func, void *data); int erst_write(const struct cper_record_header *record); ssize_t erst_get_record_count(void); -int erst_get_record_id_begin(int *pos); -int erst_get_record_id_next(int *pos, u64 *record_id); -void erst_get_record_id_end(void); +int erst_get_next_record_id(u64 *record_id); ssize_t erst_read(u64 record_id, struct cper_record_header *record, size_t buflen); +ssize_t erst_read_next(struct cper_record_header *record, size_t buflen); int erst_clear(u64 record_id); #endif diff --git a/trunk/include/linux/acpi_io.h b/trunk/include/linux/acpi_io.h index 4afd7102459d..7180013a4a3a 100644 --- a/trunk/include/linux/acpi_io.h +++ b/trunk/include/linux/acpi_io.h @@ -10,6 +10,7 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, return ioremap_cache(phys, size); } -void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size); +int acpi_os_map_generic_address(struct acpi_generic_address *addr); +void acpi_os_unmap_generic_address(struct acpi_generic_address *addr); #endif diff --git a/trunk/include/linux/aer.h b/trunk/include/linux/aer.h index 8414de22a779..f7df1eefc107 100644 --- a/trunk/include/linux/aer.h +++ b/trunk/include/linux/aer.h @@ -7,28 +7,6 @@ #ifndef _AER_H_ #define _AER_H_ -struct aer_header_log_regs { - unsigned int dw0; - unsigned int dw1; - unsigned int dw2; - unsigned int dw3; -}; - -struct aer_capability_regs { - u32 header; - u32 uncor_status; - u32 uncor_mask; - u32 uncor_severity; - u32 cor_status; - u32 cor_mask; - u32 cap_control; - struct aer_header_log_regs header_log; - u32 root_command; - u32 root_status; - u16 cor_err_source; - u16 uncor_err_source; -}; - #if defined(CONFIG_PCIEAER) /* pci-e port driver needs this function to enable aer */ extern int pci_enable_pcie_error_reporting(struct pci_dev *dev); @@ -49,7 +27,5 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) } #endif -extern void cper_print_aer(const char *prefix, int cper_severity, - struct aer_capability_regs *aer); #endif //_AER_H_ diff --git a/trunk/include/linux/cper.h b/trunk/include/linux/cper.h index 372a25839fd1..3104aaff5dd0 100644 --- a/trunk/include/linux/cper.h +++ b/trunk/include/linux/cper.h @@ -388,7 +388,5 @@ struct cper_sec_pcie { #pragma pack() u64 cper_next_record_id(void); -void cper_print_bits(const char *prefix, unsigned int bits, - const char *strs[], unsigned int strs_size); #endif