diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 159f7f19abce..b200ae1f3c6f 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "internal.h" @@ -30,6 +31,22 @@ static const struct acpi_device_id forbidden_id_list[] = { {"", 0}, }; +static void acpi_platform_fill_resource(struct acpi_device *adev, + const struct resource *src, struct resource *dest) +{ + struct device *parent; + + *dest = *src; + + /* + * If the device has parent we need to take its resources into + * account as well because this device might consume part of those. + */ + parent = acpi_get_first_physical_node(adev->parent); + if (parent && dev_is_pci(parent)) + dest->parent = pci_find_resource(to_pci_dev(parent), dest); +} + /** * acpi_create_platform_device - Create platform device for ACPI device node * @adev: ACPI device node to create a platform device for. @@ -70,7 +87,8 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) } count = 0; list_for_each_entry(rentry, &resource_list, node) - resources[count++] = *rentry->res; + acpi_platform_fill_resource(adev, rentry->res, + &resources[count++]); acpi_dev_free_resource_list(&resource_list); } diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 2c45dd3acc17..c576a6fe4ebb 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -411,7 +411,15 @@ int acpi_pci_irq_enable(struct pci_dev *dev) int gsi; u8 pin; int triggering = ACPI_LEVEL_SENSITIVE; - int polarity = ACPI_ACTIVE_LOW; + /* + * On ARM systems with the GIC interrupt model, level interrupts + * are always polarity high by specification; PCI legacy + * IRQs lines are inverted before reaching the interrupt + * controller and must therefore be considered active high + * as default. + */ + int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ? + ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW; char *link = NULL; char link_desc[16]; int rc; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 2b38c1bb0446..97886634e39f 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -572,7 +572,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status); - if (pwr_btn_status & ACPI_EVENT_FLAG_SET) { + if (pwr_btn_status & ACPI_EVENT_FLAG_STATUS_SET) { acpi_clear_event(ACPI_EVENT_POWER_BUTTON); /* Flag for later */ pwr_btn_event_pending = true; diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 358165e9f5b8..703c26e7022c 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -314,10 +314,14 @@ static struct kobject *tables_kobj; static struct kobject *dynamic_tables_kobj; static struct kobject *hotplug_kobj; +#define ACPI_MAX_TABLE_INSTANCES 999 +#define ACPI_INST_SIZE 4 /* including trailing 0 */ + struct acpi_table_attr { struct bin_attribute attr; - char name[8]; + char name[ACPI_NAME_SIZE]; int instance; + char filename[ACPI_NAME_SIZE+ACPI_INST_SIZE]; struct list_head node; }; @@ -329,14 +333,9 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, container_of(bin_attr, struct acpi_table_attr, attr); struct acpi_table_header *table_header = NULL; acpi_status status; - char name[ACPI_NAME_SIZE]; - if (strncmp(table_attr->name, "NULL", 4)) - memcpy(name, table_attr->name, ACPI_NAME_SIZE); - else - memcpy(name, "\0\0\0\0", 4); - - status = acpi_get_table(name, table_attr->instance, &table_header); + status = acpi_get_table(table_attr->name, table_attr->instance, + &table_header); if (ACPI_FAILURE(status)) return -ENODEV; @@ -344,38 +343,45 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, table_header, table_header->length); } -static void acpi_table_attr_init(struct acpi_table_attr *table_attr, - struct acpi_table_header *table_header) +static int acpi_table_attr_init(struct kobject *tables_obj, + struct acpi_table_attr *table_attr, + struct acpi_table_header *table_header) { struct acpi_table_header *header = NULL; struct acpi_table_attr *attr = NULL; + char instance_str[ACPI_INST_SIZE]; sysfs_attr_init(&table_attr->attr.attr); - if (table_header->signature[0] != '\0') - memcpy(table_attr->name, table_header->signature, - ACPI_NAME_SIZE); - else - memcpy(table_attr->name, "NULL", 4); + ACPI_MOVE_NAME(table_attr->name, table_header->signature); list_for_each_entry(attr, &acpi_table_attr_list, node) { - if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) + if (ACPI_COMPARE_NAME(table_attr->name, attr->name)) if (table_attr->instance < attr->instance) table_attr->instance = attr->instance; } table_attr->instance++; + if (table_attr->instance > ACPI_MAX_TABLE_INSTANCES) { + pr_warn("%4.4s: too many table instances\n", + table_attr->name); + return -ERANGE; + } + ACPI_MOVE_NAME(table_attr->filename, table_header->signature); + table_attr->filename[ACPI_NAME_SIZE] = '\0'; if (table_attr->instance > 1 || (table_attr->instance == 1 && !acpi_get_table - (table_header->signature, 2, &header))) - sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", - table_attr->instance); + (table_header->signature, 2, &header))) { + snprintf(instance_str, sizeof(instance_str), "%u", + table_attr->instance); + strcat(table_attr->filename, instance_str); + } table_attr->attr.size = table_header->length; table_attr->attr.read = acpi_table_show; - table_attr->attr.attr.name = table_attr->name; + table_attr->attr.attr.name = table_attr->filename; table_attr->attr.attr.mode = 0400; - return; + return sysfs_create_bin_file(tables_obj, &table_attr->attr); } acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context) @@ -383,21 +389,22 @@ acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context) struct acpi_table_attr *table_attr; switch (event) { - case ACPI_TABLE_EVENT_LOAD: + case ACPI_TABLE_EVENT_INSTALL: table_attr = kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); if (!table_attr) return AE_NO_MEMORY; - acpi_table_attr_init(table_attr, table); - if (sysfs_create_bin_file(dynamic_tables_kobj, - &table_attr->attr)) { + if (acpi_table_attr_init(dynamic_tables_kobj, + table_attr, table)) { kfree(table_attr); return AE_ERROR; - } else - list_add_tail(&table_attr->node, &acpi_table_attr_list); + } + list_add_tail(&table_attr->node, &acpi_table_attr_list); break; + case ACPI_TABLE_EVENT_LOAD: case ACPI_TABLE_EVENT_UNLOAD: + case ACPI_TABLE_EVENT_UNINSTALL: /* * we do not need to do anything right now * because the table is not deleted from the @@ -435,13 +442,12 @@ static int acpi_tables_sysfs_init(void) if (ACPI_FAILURE(status)) continue; - table_attr = NULL; table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL); if (!table_attr) return -ENOMEM; - acpi_table_attr_init(table_attr, table_header); - ret = sysfs_create_bin_file(tables_kobj, &table_attr->attr); + ret = acpi_table_attr_init(tables_kobj, + table_attr, table_header); if (ret) { kfree(table_attr); return ret; @@ -597,14 +603,27 @@ static ssize_t counter_show(struct kobject *kobj, if (result) goto end; - if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER)) - size += sprintf(buf + size, " invalid"); - else if (status & ACPI_EVENT_FLAG_ENABLED) - size += sprintf(buf + size, " enabled"); - else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) - size += sprintf(buf + size, " wake_enabled"); + if (status & ACPI_EVENT_FLAG_ENABLE_SET) + size += sprintf(buf + size, " EN"); else - size += sprintf(buf + size, " disabled"); + size += sprintf(buf + size, " "); + if (status & ACPI_EVENT_FLAG_STATUS_SET) + size += sprintf(buf + size, " STS"); + else + size += sprintf(buf + size, " "); + + if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER)) + size += sprintf(buf + size, " invalid "); + else if (status & ACPI_EVENT_FLAG_ENABLED) + size += sprintf(buf + size, " enabled "); + else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) + size += sprintf(buf + size, " wake_enabled"); + else + size += sprintf(buf + size, " disabled "); + if (status & ACPI_EVENT_FLAG_MASKED) + size += sprintf(buf + size, " masked "); + else + size += sprintf(buf + size, " unmasked"); end: size += sprintf(buf + size, "\n"); @@ -655,8 +674,12 @@ static ssize_t counter_set(struct kobject *kobj, !(status & ACPI_EVENT_FLAG_ENABLED)) result = acpi_enable_gpe(handle, index); else if (!strcmp(buf, "clear\n") && - (status & ACPI_EVENT_FLAG_SET)) + (status & ACPI_EVENT_FLAG_STATUS_SET)) result = acpi_clear_gpe(handle, index); + else if (!strcmp(buf, "mask\n")) + result = acpi_mask_gpe(handle, index, TRUE); + else if (!strcmp(buf, "unmask\n")) + result = acpi_mask_gpe(handle, index, FALSE); else if (!kstrtoul(buf, 0, &tmp)) all_counters[index].count = tmp; else @@ -664,13 +687,13 @@ static ssize_t counter_set(struct kobject *kobj, } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { int event = index - num_gpes; if (!strcmp(buf, "disable\n") && - (status & ACPI_EVENT_FLAG_ENABLED)) + (status & ACPI_EVENT_FLAG_ENABLE_SET)) result = acpi_disable_event(event, ACPI_NOT_ISR); else if (!strcmp(buf, "enable\n") && - !(status & ACPI_EVENT_FLAG_ENABLED)) + !(status & ACPI_EVENT_FLAG_ENABLE_SET)) result = acpi_enable_event(event, ACPI_NOT_ISR); else if (!strcmp(buf, "clear\n") && - (status & ACPI_EVENT_FLAG_SET)) + (status & ACPI_EVENT_FLAG_STATUS_SET)) result = acpi_clear_event(event); else if (!kstrtoul(buf, 0, &tmp)) all_counters[index].count = tmp; diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 9f0ad6ebb368..cdd56c4657e0 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -35,7 +35,6 @@ #include #include #include -#include #include "internal.h" #ifdef CONFIG_ACPI_CUSTOM_DSDT @@ -246,6 +245,7 @@ acpi_parse_entries_array(char *id, unsigned long table_size, struct acpi_subtable_header *entry; unsigned long table_end; int count = 0; + int errs = 0; int i; if (acpi_disabled) @@ -278,10 +278,12 @@ acpi_parse_entries_array(char *id, unsigned long table_size, if (entry->type != proc[i].id) continue; if (!proc[i].handler || - proc[i].handler(entry, table_end)) - return -EINVAL; + (!errs && proc[i].handler(entry, table_end))) { + errs++; + continue; + } - proc->count++; + proc[i].count++; break; } if (i != proc_num) @@ -301,11 +303,11 @@ acpi_parse_entries_array(char *id, unsigned long table_size, } if (max_entries && count > max_entries) { - pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n", - id, proc->id, count - max_entries, count); + pr_warn("[%4.4s:0x%02x] found the maximum %i entries\n", + id, proc->id, count); } - return count; + return errs ? -EINVAL : count; } int __init diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index aab9d5115a5f..415956c5c593 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -479,6 +479,30 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev, } EXPORT_SYMBOL(pci_find_parent_resource); +/** + * pci_find_resource - Return matching PCI device resource + * @dev: PCI device to query + * @res: Resource to look for + * + * Goes over standard PCI resources (BARs) and checks if the given resource + * is partially or fully contained in any of them. In that case the + * matching resource is returned, %NULL otherwise. + */ +struct resource *pci_find_resource(struct pci_dev *dev, struct resource *res) +{ + int i; + + for (i = 0; i < PCI_ROM_RESOURCE; i++) { + struct resource *r = &dev->resource[i]; + + if (r->start && resource_contains(r, res)) + return r; + } + + return NULL; +} +EXPORT_SYMBOL(pci_find_resource); + /** * pci_find_pcie_root_port - return PCIe Root Port * @dev: PCI device to query diff --git a/include/linux/pci.h b/include/linux/pci.h index 0ab835965669..a917d4b20554 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1126,6 +1126,7 @@ void pdev_enable_device(struct pci_dev *); int pci_enable_resources(struct pci_dev *, int mask); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), int (*)(const struct pci_dev *, u8, u8)); +struct resource *pci_find_resource(struct pci_dev *dev, struct resource *res); #define HAVE_PCI_REQ_REGIONS 2 int __must_check pci_request_regions(struct pci_dev *, const char *); int __must_check pci_request_regions_exclusive(struct pci_dev *, const char *); @@ -1542,6 +1543,9 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; } +static inline struct resource *pci_find_resource(struct pci_dev *dev, + struct resource *res) +{ return NULL; } static inline int pci_request_regions(struct pci_dev *dev, const char *res_name) { return -EIO; } static inline void pci_release_regions(struct pci_dev *dev) { }