diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 4 | ||||
-rw-r--r-- | drivers/acpi/device_sysfs.c | 44 | ||||
-rw-r--r-- | drivers/acpi/pci_link.c | 131 | ||||
-rw-r--r-- | drivers/acpi/sysfs.c | 7 | ||||
-rw-r--r-- | drivers/acpi/utils.c | 6 |
5 files changed, 108 insertions, 84 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b225c4b9ba14..b7e2e776397d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -5,10 +5,10 @@ menuconfig ACPI bool "ACPI (Advanced Configuration and Power Interface) Support" depends on !IA64_HP_SIM - depends on IA64 || X86 || (ARM64 && EXPERT) + depends on IA64 || X86 || ARM64 depends on PCI select PNP - default y + default y if (IA64 || X86) help Advanced Configuration and Power Interface (ACPI) support for Linux requires an ACPI-compliant platform (hardware/firmware), diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index b9afb47db7ed..7b2c48fde4e2 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -35,7 +35,7 @@ static ssize_t acpi_object_path(acpi_handle handle, char *buf) if (result) return result; - result = sprintf(buf, "%s\n", (char*)path.pointer); + result = sprintf(buf, "%s\n", (char *)path.pointer); kfree(path.pointer); return result; } @@ -333,7 +333,8 @@ int acpi_device_modalias(struct device *dev, char *buf, int size) EXPORT_SYMBOL_GPL(acpi_device_modalias); static ssize_t -acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { +acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) +{ return __acpi_device_modalias(to_acpi_device(dev), buf, 1024); } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); @@ -397,7 +398,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); static ssize_t -acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) { +acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) +{ struct acpi_device *acpi_dev = to_acpi_device(dev); return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev)); @@ -467,12 +469,27 @@ acpi_device_sun_show(struct device *dev, struct device_attribute *attr, status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun); if (ACPI_FAILURE(status)) - return -ENODEV; + return -EIO; return sprintf(buf, "%llu\n", sun); } static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); +static ssize_t +acpi_device_hrv_show(struct device *dev, struct device_attribute *attr, + char *buf) { + struct acpi_device *acpi_dev = to_acpi_device(dev); + acpi_status status; + unsigned long long hrv; + + status = acpi_evaluate_integer(acpi_dev->handle, "_HRV", NULL, &hrv); + if (ACPI_FAILURE(status)) + return -EIO; + + return sprintf(buf, "%llu\n", hrv); +} +static DEVICE_ATTR(hrv, 0444, acpi_device_hrv_show, NULL); + static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -481,7 +498,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta); if (ACPI_FAILURE(status)) - return -ENODEV; + return -EIO; return sprintf(buf, "%llu\n", sta); } @@ -541,16 +558,22 @@ int acpi_device_setup_files(struct acpi_device *dev) goto end; } + if (acpi_has_method(dev->handle, "_HRV")) { + result = device_create_file(&dev->dev, &dev_attr_hrv); + if (result) + goto end; + } + if (acpi_has_method(dev->handle, "_STA")) { result = device_create_file(&dev->dev, &dev_attr_status); if (result) goto end; } - /* - * If device has _EJ0, 'eject' file is created that is used to trigger - * hot-removal function from userland. - */ + /* + * If device has _EJ0, 'eject' file is created that is used to trigger + * hot-removal function from userland. + */ if (acpi_has_method(dev->handle, "_EJ0")) { result = device_create_file(&dev->dev, &dev_attr_eject); if (result) @@ -604,6 +627,9 @@ void acpi_device_remove_files(struct acpi_device *dev) if (acpi_has_method(dev->handle, "_SUN")) device_remove_file(&dev->dev, &dev_attr_sun); + if (acpi_has_method(dev->handle, "_HRV")) + device_remove_file(&dev->dev, &dev_attr_hrv); + if (dev->pnp.unique_id) device_remove_file(&dev->dev, &dev_attr_uid); if (dev->pnp.type.bus_address) diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index ededa909df2f..8fc7323ed3e8 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -36,6 +36,7 @@ #include <linux/mutex.h> #include <linux/slab.h> #include <linux/acpi.h> +#include <linux/irq.h> #include "internal.h" @@ -437,17 +438,15 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) * enabled system. */ -#define ACPI_MAX_IRQS 256 -#define ACPI_MAX_ISA_IRQ 16 +#define ACPI_MAX_ISA_IRQS 16 -#define PIRQ_PENALTY_PCI_AVAILABLE (0) #define PIRQ_PENALTY_PCI_POSSIBLE (16*16) #define PIRQ_PENALTY_PCI_USING (16*16*16) #define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16) #define PIRQ_PENALTY_ISA_USED (16*16*16*16*16) #define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16) -static int acpi_irq_penalty[ACPI_MAX_IRQS] = { +static int acpi_isa_irq_penalty[ACPI_MAX_ISA_IRQS] = { PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ @@ -457,9 +456,9 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */ PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */ PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */ - PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ - PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ - PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ + 0, /* IRQ9 PCI, often acpi */ + 0, /* IRQ10 PCI */ + 0, /* IRQ11 PCI */ PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ @@ -467,39 +466,58 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { /* >IRQ15 */ }; -int __init acpi_irq_penalty_init(void) +static int acpi_irq_pci_sharing_penalty(int irq) { struct acpi_pci_link *link; - int i; + int penalty = 0; - /* - * Update penalties to facilitate IRQ balancing. - */ list_for_each_entry(link, &acpi_link_list, list) { - /* - * reflect the possible and active irqs in the penalty table -- - * useful for breaking ties. + * If a link is active, penalize its IRQ heavily + * so we try to choose a different IRQ. */ - if (link->irq.possible_count) { - int penalty = - PIRQ_PENALTY_PCI_POSSIBLE / - link->irq.possible_count; - - for (i = 0; i < link->irq.possible_count; i++) { - if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) - acpi_irq_penalty[link->irq. - possible[i]] += - penalty; - } - - } else if (link->irq.active) { - acpi_irq_penalty[link->irq.active] += - PIRQ_PENALTY_PCI_POSSIBLE; + if (link->irq.active && link->irq.active == irq) + penalty += PIRQ_PENALTY_PCI_USING; + else { + int i; + + /* + * If a link is inactive, penalize the IRQs it + * might use, but not as severely. + */ + for (i = 0; i < link->irq.possible_count; i++) + if (link->irq.possible[i] == irq) + penalty += PIRQ_PENALTY_PCI_POSSIBLE / + link->irq.possible_count; } } - return 0; + return penalty; +} + +static int acpi_irq_get_penalty(int irq) +{ + int penalty = 0; + + if (irq < ACPI_MAX_ISA_IRQS) + penalty += acpi_isa_irq_penalty[irq]; + + /* + * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict + * with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be + * use for PCI IRQs. + */ + if (irq == acpi_gbl_FADT.sci_interrupt) { + u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK; + + if (type != IRQ_TYPE_LEVEL_LOW) + penalty += PIRQ_PENALTY_ISA_ALWAYS; + else + penalty += PIRQ_PENALTY_PCI_USING; + } + + penalty += acpi_irq_pci_sharing_penalty(irq); + return penalty; } static int acpi_irq_balance = -1; /* 0: static, 1: balance */ @@ -547,12 +565,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) * the use of IRQs 9, 10, 11, and >15. */ for (i = (link->irq.possible_count - 1); i >= 0; i--) { - if (acpi_irq_penalty[irq] > - acpi_irq_penalty[link->irq.possible[i]]) + if (acpi_irq_get_penalty(irq) > + acpi_irq_get_penalty(link->irq.possible[i])) irq = link->irq.possible[i]; } } - if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) { + if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) { printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. " "Try pci=noacpi or acpi=off\n", acpi_device_name(link->device), @@ -568,7 +586,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) acpi_device_bid(link->device)); return -ENODEV; } else { - acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", acpi_device_name(link->device), acpi_device_bid(link->device), link->irq.active); @@ -778,7 +795,7 @@ static void acpi_pci_link_remove(struct acpi_device *device) } /* - * modify acpi_irq_penalty[] from cmdline + * modify acpi_isa_irq_penalty[] from cmdline */ static int __init acpi_irq_penalty_update(char *str, int used) { @@ -787,23 +804,24 @@ static int __init acpi_irq_penalty_update(char *str, int used) for (i = 0; i < 16; i++) { int retval; int irq; + int new_penalty; retval = get_option(&str, &irq); if (!retval) break; /* no number found */ - if (irq < 0) - continue; - - if (irq >= ARRAY_SIZE(acpi_irq_penalty)) + /* see if this is a ISA IRQ */ + if ((irq < 0) || (irq >= ACPI_MAX_ISA_IRQS)) continue; if (used) - acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; + new_penalty = acpi_irq_get_penalty(irq) + + PIRQ_PENALTY_ISA_USED; else - acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE; + new_penalty = 0; + acpi_isa_irq_penalty[irq] = new_penalty; if (retval != 2) /* no next number */ break; } @@ -819,34 +837,15 @@ static int __init acpi_irq_penalty_update(char *str, int used) */ void acpi_penalize_isa_irq(int irq, int active) { - if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { - if (active) - acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; - else - acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; - } + if ((irq >= 0) && (irq < ARRAY_SIZE(acpi_isa_irq_penalty))) + acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) + + active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING; } bool acpi_isa_irq_available(int irq) { - return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) || - acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS); -} - -/* - * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with - * PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for - * PCI IRQs. - */ -void acpi_penalize_sci_irq(int irq, int trigger, int polarity) -{ - if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { - if (trigger != ACPI_MADT_TRIGGER_LEVEL || - polarity != ACPI_MADT_POLARITY_ACTIVE_LOW) - acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS; - else - acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; - } + return irq >= 0 && (irq >= ARRAY_SIZE(acpi_isa_irq_penalty) || + acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS); } /* diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 0243d375c6fd..4b3a9e27f1b6 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -555,23 +555,22 @@ static void acpi_global_event_handler(u32 event_type, acpi_handle device, static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) { - int result = 0; + int result; if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) - goto end; + return -EINVAL; if (index < num_gpes) { result = acpi_get_gpe_device(index, handle); if (result) { ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, "Invalid GPE 0x%x", index)); - goto end; + return result; } result = acpi_get_gpe_status(*handle, index, status); } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) result = acpi_get_event_status(index - num_gpes, status); -end: return result; } diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 050673f0c0b3..ac832bf6f8c9 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -707,7 +707,7 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) EXPORT_SYMBOL(acpi_check_dsm); /** - * acpi_dev_present - Detect presence of a given ACPI device in the system. + * acpi_dev_found - Detect presence of a given ACPI device in the namespace. * @hid: Hardware ID of the device. * * Return %true if the device was present at the moment of invocation. @@ -719,7 +719,7 @@ EXPORT_SYMBOL(acpi_check_dsm); * instead). Calling from module_init() is fine (which is synonymous * with device_initcall()). */ -bool acpi_dev_present(const char *hid) +bool acpi_dev_found(const char *hid) { struct acpi_device_bus_id *acpi_device_bus_id; bool found = false; @@ -734,7 +734,7 @@ bool acpi_dev_present(const char *hid) return found; } -EXPORT_SYMBOL(acpi_dev_present); +EXPORT_SYMBOL(acpi_dev_found); /* * acpi_backlight= handling, this is done here rather then in video_detect.c |