diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 9 | ||||
-rw-r--r-- | drivers/acpi/acpica/dsopcode.c | 2 | ||||
-rw-r--r-- | drivers/acpi/apei/einj.c | 2 | ||||
-rw-r--r-- | drivers/acpi/apei/erst.c | 16 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 202 | ||||
-rw-r--r-- | drivers/acpi/pci_bind.c | 12 | ||||
-rw-r--r-- | drivers/acpi/pci_irq.c | 17 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 165 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 6 |
9 files changed, 323 insertions, 108 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 0300bf612946..38c5078da11d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -267,6 +267,15 @@ config ACPI_CUSTOM_DSDT bool default ACPI_CUSTOM_DSDT_FILE != "" +config ACPI_INITRD_TABLE_OVERRIDE + bool "ACPI tables can be passed via uncompressed cpio in initrd" + default n + help + This option provides functionality to override arbitrary ACPI tables + via initrd. No functional change if no ACPI tables are passed via + initrd, therefore it's safe to say Y. + See Documentation/acpi/initrd_table_override.txt for details + config ACPI_BLACKLIST_YEAR int "Disable ACPI for systems before Jan 1st this year" if X86_32 default 0 diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 0df024e5fb63..d09c6b4bab2c 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: dsopcode - Dispatcher suport for regions and fields + * Module Name: dsopcode - Dispatcher support for regions and fields * *****************************************************************************/ diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 8e1793649ec0..8d457b55c55a 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -367,7 +367,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, * This will cause resource conflict with regular memory. So * remove it from trigger table resources. */ - if (param_extension && (type & 0x0038) && param2) { + if ((param_extension || acpi5) && (type & 0x0038) && param2) { struct apei_resources addr_resources; apei_resources_init(&addr_resources); trigger_param_region = einj_get_trigger_parameter_region( diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index e4d9d24eb73d..6d894bfd8b8f 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -931,14 +931,14 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) static int erst_open_pstore(struct pstore_info *psi); static int erst_close_pstore(struct pstore_info *psi); -static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, +static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, struct pstore_info *psi); static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, - u64 *id, unsigned int part, + u64 *id, unsigned int part, int count, size_t size, struct pstore_info *psi); -static int erst_clearer(enum pstore_type_id type, u64 id, - struct pstore_info *psi); +static int erst_clearer(enum pstore_type_id type, u64 id, int count, + struct timespec time, struct pstore_info *psi); static struct pstore_info erst_info = { .owner = THIS_MODULE, @@ -987,7 +987,7 @@ static int erst_close_pstore(struct pstore_info *psi) return 0; } -static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, +static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, struct pstore_info *psi) { @@ -1055,7 +1055,7 @@ out: } static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, - u64 *id, unsigned int part, + u64 *id, unsigned int part, int count, size_t size, struct pstore_info *psi) { struct cper_pstore_record *rcd = (struct cper_pstore_record *) @@ -1101,8 +1101,8 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, return ret; } -static int erst_clearer(enum pstore_type_id type, u64 id, - struct pstore_info *psi) +static int erst_clearer(enum pstore_type_id type, u64 id, int count, + struct timespec time, struct pstore_info *psi) { return erst_clear(id); } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6dc4a2b1e956..3ff267861541 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -534,6 +534,137 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val, return AE_OK; } +#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE +#include <linux/earlycpio.h> +#include <linux/memblock.h> + +static u64 acpi_tables_addr; +static int all_tables_size; + +/* Copied from acpica/tbutils.c:acpi_tb_checksum() */ +u8 __init acpi_table_checksum(u8 *buffer, u32 length) +{ + u8 sum = 0; + u8 *end = buffer + length; + + while (buffer < end) + sum = (u8) (sum + *(buffer++)); + return sum; +} + +/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */ +static const char * const table_sigs[] = { + ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ, + ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT, + ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF, + ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET, + ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI, + ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA, + ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT, + ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT, + ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL }; + +/* Non-fatal errors: Affected tables/files are ignored */ +#define INVALID_TABLE(x, path, name) \ + { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; } + +#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) + +/* Must not increase 10 or needs code modification below */ +#define ACPI_OVERRIDE_TABLES 10 + +void __init acpi_initrd_override(void *data, size_t size) +{ + int sig, no, table_nr = 0, total_offset = 0; + long offset = 0; + struct acpi_table_header *table; + char cpio_path[32] = "kernel/firmware/acpi/"; + struct cpio_data file; + struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES]; + char *p; + + if (data == NULL || size == 0) + return; + + for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) { + file = find_cpio_data(cpio_path, data, size, &offset); + if (!file.data) + break; + + data += offset; + size -= offset; + + if (file.size < sizeof(struct acpi_table_header)) + INVALID_TABLE("Table smaller than ACPI header", + cpio_path, file.name); + + table = file.data; + + for (sig = 0; table_sigs[sig]; sig++) + if (!memcmp(table->signature, table_sigs[sig], 4)) + break; + + if (!table_sigs[sig]) + INVALID_TABLE("Unknown signature", + cpio_path, file.name); + if (file.size != table->length) + INVALID_TABLE("File length does not match table length", + cpio_path, file.name); + if (acpi_table_checksum(file.data, table->length)) + INVALID_TABLE("Bad table checksum", + cpio_path, file.name); + + pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n", + table->signature, cpio_path, file.name, table->length); + + all_tables_size += table->length; + early_initrd_files[table_nr].data = file.data; + early_initrd_files[table_nr].size = file.size; + table_nr++; + } + if (table_nr == 0) + return; + + acpi_tables_addr = + memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT, + all_tables_size, PAGE_SIZE); + if (!acpi_tables_addr) { + WARN_ON(1); + return; + } + /* + * Only calling e820_add_reserve does not work and the + * tables are invalid (memory got used) later. + * memblock_reserve works as expected and the tables won't get modified. + * But it's not enough on X86 because ioremap will + * complain later (used by acpi_os_map_memory) that the pages + * that should get mapped are not marked "reserved". + * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area) + * works fine. + */ + memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size); + arch_reserve_mem_area(acpi_tables_addr, all_tables_size); + + p = early_ioremap(acpi_tables_addr, all_tables_size); + + for (no = 0; no < table_nr; no++) { + memcpy(p + total_offset, early_initrd_files[no].data, + early_initrd_files[no].size); + total_offset += early_initrd_files[no].size; + } + early_iounmap(p, all_tables_size); +} +#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */ + +static void acpi_table_taint(struct acpi_table_header *table) +{ + pr_warn(PREFIX + "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n", + table->signature, table->oem_table_id); + add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); +} + + acpi_status acpi_os_table_override(struct acpi_table_header * existing_table, struct acpi_table_header ** new_table) @@ -547,24 +678,73 @@ acpi_os_table_override(struct acpi_table_header * existing_table, if (strncmp(existing_table->signature, "DSDT", 4) == 0) *new_table = (struct acpi_table_header *)AmlCode; #endif - if (*new_table != NULL) { - printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], " - "this is unsafe: tainting kernel\n", - existing_table->signature, - existing_table->oem_table_id); - add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); - } + if (*new_table != NULL) + acpi_table_taint(existing_table); return AE_OK; } acpi_status acpi_os_physical_table_override(struct acpi_table_header *existing_table, - acpi_physical_address * new_address, - u32 *new_table_length) + acpi_physical_address *address, + u32 *table_length) { - return AE_SUPPORT; -} +#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE + *table_length = 0; + *address = 0; + return AE_OK; +#else + int table_offset = 0; + struct acpi_table_header *table; + + *table_length = 0; + *address = 0; + + if (!acpi_tables_addr) + return AE_OK; + + do { + if (table_offset + ACPI_HEADER_SIZE > all_tables_size) { + WARN_ON(1); + return AE_OK; + } + table = acpi_os_map_memory(acpi_tables_addr + table_offset, + ACPI_HEADER_SIZE); + + if (table_offset + table->length > all_tables_size) { + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + WARN_ON(1); + return AE_OK; + } + + table_offset += table->length; + + if (memcmp(existing_table->signature, table->signature, 4)) { + acpi_os_unmap_memory(table, + ACPI_HEADER_SIZE); + continue; + } + + /* Only override tables with matching oem id */ + if (memcmp(table->oem_table_id, existing_table->oem_table_id, + ACPI_OEM_TABLE_ID_SIZE)) { + acpi_os_unmap_memory(table, + ACPI_HEADER_SIZE); + continue; + } + + table_offset -= table->length; + *table_length = table->length; + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + *address = acpi_tables_addr + table_offset; + break; + } while (table_offset + ACPI_HEADER_SIZE < all_tables_size); + + if (*address != 0) + acpi_table_taint(existing_table); + return AE_OK; +#endif +} static irqreturn_t acpi_irq(int irq, void *dev_id) { diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 2ef04098cc1d..a1dee29beed3 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -45,11 +45,12 @@ static int acpi_pci_unbind(struct acpi_device *device) device_set_run_wake(&dev->dev, false); pci_acpi_remove_pm_notifier(device); + acpi_power_resource_unregister_device(&dev->dev, device->handle); if (!dev->subordinate) goto out; - acpi_pci_irq_del_prt(dev->subordinate); + acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number); device->ops.bind = NULL; device->ops.unbind = NULL; @@ -63,7 +64,7 @@ static int acpi_pci_bind(struct acpi_device *device) { acpi_status status; acpi_handle handle; - struct pci_bus *bus; + unsigned char bus; struct pci_dev *dev; dev = acpi_get_pci_dev(device->handle); @@ -71,6 +72,7 @@ static int acpi_pci_bind(struct acpi_device *device) return 0; pci_acpi_add_pm_notifier(device, dev); + acpi_power_resource_register_device(&dev->dev, device->handle); if (device->wakeup.flags.run_wake) device_set_run_wake(&dev->dev, true); @@ -100,11 +102,11 @@ static int acpi_pci_bind(struct acpi_device *device) goto out; if (dev->subordinate) - bus = dev->subordinate; + bus = dev->subordinate->number; else - bus = dev->bus; + bus = dev->bus->number; - acpi_pci_irq_add_prt(device->handle, bus); + acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus); out: pci_dev_put(dev); diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 23a032490130..68a921d03247 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, } } -static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, +static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, struct acpi_pci_routing_table *prt) { struct acpi_prt_entry *entry; @@ -198,8 +198,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert * it here. */ - entry->id.segment = pci_domain_nr(bus); - entry->id.bus = bus->number; + entry->id.segment = segment; + entry->id.bus = bus; entry->id.device = (prt->address >> 16) & 0xFFFF; entry->pin = prt->pin + 1; @@ -244,7 +244,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, return 0; } -int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) +int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) { acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -273,7 +273,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) entry = buffer.pointer; while (entry && (entry->length > 0)) { - acpi_pci_irq_add_entry(handle, bus, entry); + acpi_pci_irq_add_entry(handle, segment, bus, entry); entry = (struct acpi_pci_routing_table *) ((unsigned long)entry + entry->length); } @@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) return 0; } -void acpi_pci_irq_del_prt(struct pci_bus *bus) +void acpi_pci_irq_del_prt(int segment, int bus) { struct acpi_prt_entry *entry, *tmp; printk(KERN_DEBUG "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", - pci_domain_nr(bus), bus->number); + segment, bus); spin_lock(&acpi_prt_lock); list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { - if (pci_domain_nr(bus) == entry->id.segment - && bus->number == entry->id.bus) { + if (segment == entry->id.segment && bus == entry->id.bus) { list_del(&entry->list); kfree(entry); } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index f70b9e5fc1b5..7928d4dc7056 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -454,6 +454,7 @@ static int acpi_pci_root_add(struct acpi_device *device) acpi_handle handle; struct acpi_device *child; u32 flags, base_flags; + bool is_osc_granted = false; root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); if (!root) @@ -501,85 +502,47 @@ static int acpi_pci_root_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); device->driver_data = root; - root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); - - /* - * All supported architectures that use ACPI have support for - * PCI domains, so we indicate this in _OSC support capabilities. - */ - flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; - acpi_pci_osc_support(root, flags); - - /* - * TBD: Need PCI interface for enumeration/configuration of roots. - */ - - mutex_lock(&acpi_pci_root_lock); - list_add_tail(&root->node, &acpi_pci_roots); - mutex_unlock(&acpi_pci_root_lock); - printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", acpi_device_name(device), acpi_device_bid(device), root->segment, &root->secondary); /* - * Scan the Root Bridge - * -------------------- - * Must do this prior to any attempt to bind the root device, as the - * PCI namespace does not get created until this call is made (and - * thus the root bridge's pci_dev does not exist). - */ - root->bus = pci_acpi_scan_root(root); - if (!root->bus) { - printk(KERN_ERR PREFIX - "Bus %04x:%02x not present in PCI namespace\n", - root->segment, (unsigned int)root->secondary.start); - result = -ENODEV; - goto out_del_root; - } - - /* - * Attach ACPI-PCI Context - * ----------------------- - * Thus binding the ACPI and PCI devices. - */ - result = acpi_pci_bind_root(device); - if (result) - goto out_del_root; - - /* * PCI Routing Table * ----------------- * Evaluate and parse _PRT, if exists. */ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_SUCCESS(status)) - result = acpi_pci_irq_add_prt(device->handle, root->bus); + result = acpi_pci_irq_add_prt(device->handle, root->segment, + root->secondary.start); + + root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); /* - * Scan and bind all _ADR-Based Devices + * All supported architectures that use ACPI have support for + * PCI domains, so we indicate this in _OSC support capabilities. */ - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); + flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; + acpi_pci_osc_support(root, flags); /* Indicate support for various _OSC capabilities. */ - if (pci_ext_cfg_avail(root->bus->self)) + if (pci_ext_cfg_avail()) flags |= OSC_EXT_PCI_CONFIG_SUPPORT; - if (pcie_aspm_support_enabled()) + if (pcie_aspm_support_enabled()) { flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | - OSC_CLOCK_PWR_CAPABILITY_SUPPORT; + OSC_CLOCK_PWR_CAPABILITY_SUPPORT; + } if (pci_msi_enabled()) flags |= OSC_MSI_SUPPORT; if (flags != base_flags) { status = acpi_pci_osc_support(root, flags); if (ACPI_FAILURE(status)) { - dev_info(root->bus->bridge, "ACPI _OSC support " + dev_info(&device->dev, "ACPI _OSC support " "notification failed, disabling PCIe ASPM\n"); pcie_no_aspm(); flags = base_flags; } } - if (!pcie_ports_disabled && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL @@ -588,40 +551,81 @@ static int acpi_pci_root_add(struct acpi_device *device) if (pci_aer_available()) { if (aer_acpi_firmware_first()) - dev_dbg(root->bus->bridge, + dev_dbg(&device->dev, "PCIe errors handled by BIOS.\n"); else flags |= OSC_PCI_EXPRESS_AER_CONTROL; } - dev_info(root->bus->bridge, + dev_info(&device->dev, "Requesting ACPI _OSC control (0x%02x)\n", flags); status = acpi_pci_osc_control_set(device->handle, &flags, - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); if (ACPI_SUCCESS(status)) { - dev_info(root->bus->bridge, + is_osc_granted = true; + dev_info(&device->dev, "ACPI _OSC control (0x%02x) granted\n", flags); - if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { - /* - * We have ASPM control, but the FADT indicates - * that it's unsupported. Clear it. - */ - pcie_clear_aspm(root->bus); - } } else { - dev_info(root->bus->bridge, + is_osc_granted = false; + dev_info(&device->dev, "ACPI _OSC request failed (%s), " "returned control mask: 0x%02x\n", acpi_format_exception(status), flags); - pr_info("ACPI _OSC control for PCIe not granted, " - "disabling ASPM\n"); - pcie_no_aspm(); } } else { - dev_info(root->bus->bridge, - "Unable to request _OSC control " - "(_OSC support mask: 0x%02x)\n", flags); + dev_info(&device->dev, + "Unable to request _OSC control " + "(_OSC support mask: 0x%02x)\n", flags); + } + + /* + * TBD: Need PCI interface for enumeration/configuration of roots. + */ + + mutex_lock(&acpi_pci_root_lock); + list_add_tail(&root->node, &acpi_pci_roots); + mutex_unlock(&acpi_pci_root_lock); + + /* + * Scan the Root Bridge + * -------------------- + * Must do this prior to any attempt to bind the root device, as the + * PCI namespace does not get created until this call is made (and + * thus the root bridge's pci_dev does not exist). + */ + root->bus = pci_acpi_scan_root(root); + if (!root->bus) { + printk(KERN_ERR PREFIX + "Bus %04x:%02x not present in PCI namespace\n", + root->segment, (unsigned int)root->secondary.start); + result = -ENODEV; + goto out_del_root; + } + + /* + * Attach ACPI-PCI Context + * ----------------------- + * Thus binding the ACPI and PCI devices. + */ + result = acpi_pci_bind_root(device); + if (result) + goto out_del_root; + + /* + * Scan and bind all _ADR-Based Devices + */ + list_for_each_entry(child, &device->children, node) + acpi_pci_bridge_scan(child); + + /* ASPM setting */ + if (is_osc_granted) { + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) + pcie_clear_aspm(root->bus); + } else { + pr_info("ACPI _OSC control for PCIe not granted, " + "disabling ASPM\n"); + pcie_no_aspm(); } pci_acpi_add_bus_pm_notifier(device, root->bus); @@ -634,6 +638,8 @@ out_del_root: mutex_lock(&acpi_pci_root_lock); list_del(&root->node); mutex_unlock(&acpi_pci_root_lock); + + acpi_pci_irq_del_prt(root->segment, root->secondary.start); end: kfree(root); return result; @@ -644,12 +650,19 @@ static int acpi_pci_root_start(struct acpi_device *device) struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; + if (system_state != SYSTEM_BOOTING) + pci_assign_unassigned_bus_resources(root->bus); + mutex_lock(&acpi_pci_root_lock); list_for_each_entry(driver, &acpi_pci_drivers, node) if (driver->add) driver->add(root); mutex_unlock(&acpi_pci_root_lock); + /* need to after hot-added ioapic is registered */ + if (system_state != SYSTEM_BOOTING) + pci_enable_bridges(root->bus); + pci_bus_add_devices(root->bus); return 0; @@ -657,17 +670,29 @@ static int acpi_pci_root_start(struct acpi_device *device) static int acpi_pci_root_remove(struct acpi_device *device, int type) { + acpi_status status; + acpi_handle handle; struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; + pci_stop_root_bus(root->bus); + mutex_lock(&acpi_pci_root_lock); - list_for_each_entry(driver, &acpi_pci_drivers, node) + list_for_each_entry_reverse(driver, &acpi_pci_drivers, node) if (driver->remove) driver->remove(root); + mutex_unlock(&acpi_pci_root_lock); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); + status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); + if (ACPI_SUCCESS(status)) + acpi_pci_irq_del_prt(root->segment, root->secondary.start); + + pci_remove_root_bus(root->bus); + + mutex_lock(&acpi_pci_root_lock); list_del(&root->node); mutex_unlock(&acpi_pci_root_lock); kfree(root); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 6e8cc16b54c1..506fbd4b5733 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -900,14 +900,14 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) if (tz->trips.passive.flags.valid) tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz, - &acpi_thermal_zone_ops, + &acpi_thermal_zone_ops, NULL, tz->trips.passive.tsp*100, tz->polling_frequency*100); else tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz, - &acpi_thermal_zone_ops, 0, - tz->polling_frequency*100); + &acpi_thermal_zone_ops, NULL, + 0, tz->polling_frequency*100); if (IS_ERR(tz->thermal_zone)) return -ENODEV; |