Merge branches 'acpi-sysfs', 'acpi-pci' and 'acpi-tables'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sat, 1 Oct 2016 23:38:34 +0000 (01:38 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sat, 1 Oct 2016 23:38:34 +0000 (01:38 +0200)
* acpi-sysfs:
  ACPI / sysfs: Update sysfs signature handling code
  ACPI / sysfs: Fix an issue for LoadTable opcode
  ACPI / sysfs: Use new GPE masking mechanism in GPE interface

* acpi-pci:
  ACPI / platform: Pay attention to parent device's resources
  PCI: Add pci_find_resource()
  ACPI / PCI: fix GIC irq model default PCI IRQ polarity

* acpi-tables:
  ACPI / tables: Remove duplicated include from tables.c
  ACPI / tables: do not report the number of entries ignored by acpi_parse_entries()
  ACPI / tables: fix acpi_parse_entries_array() so it traverses all subtables
  ACPI / tables: fix incorrect counts returned by acpi_parse_entries_array()

drivers/acpi/acpi_platform.c
drivers/acpi/pci_irq.c
drivers/acpi/sleep.c
drivers/acpi/sysfs.c
drivers/acpi/tables.c
drivers/pci/pci.c
include/linux/pci.h

index 159f7f1..b200ae1 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
+#include <linux/pci.h>
 #include <linux/platform_device.h>
 
 #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);
        }
index 2c45dd3..c576a6f 100644 (file)
@@ -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;
index 2b38c1b..9788663 100644 (file)
@@ -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;
index 358165e..703c26e 100644 (file)
@@ -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_ENABLE_SET)
+               size += sprintf(buf + size, "  EN");
+       else
+               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");
+               size += sprintf(buf + size, " invalid     ");
        else if (status & ACPI_EVENT_FLAG_ENABLED)
-               size += sprintf(buf + size, "   enabled");
+               size += sprintf(buf + size, " enabled     ");
        else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED)
-               size += sprintf(buf + size, "   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, "   disabled");
+               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;
index 9f0ad6e..cdd56c4 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/earlycpio.h>
 #include <linux/memblock.h>
 #include <linux/initrd.h>
-#include <linux/acpi.h>
 #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
index aab9d51..415956c 100644 (file)
@@ -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
index 0ab8359..a917d4b 100644 (file)
@@ -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) { }