Merge branches 'acpi-sysfs', 'acpi-pci' and 'acpi-tables'

* 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()
This commit is contained in:
Rafael J. Wysocki 2016-10-02 01:38:34 +02:00
commit 84a78c724b
7 changed files with 130 additions and 51 deletions

View 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);
}

View 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;

View 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;

View 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_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;

View 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

View 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

View 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) { }