aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/acpi_lpss.c7
-rw-r--r--drivers/acpi/osl.c12
-rw-r--r--drivers/acpi/resource.c162
-rw-r--r--drivers/base/power/domain.c13
-rw-r--r--drivers/base/power/wakeirq.c12
-rw-r--r--drivers/base/power/wakeup.c31
-rw-r--r--drivers/pnp/system.c35
-rw-r--r--include/linux/acpi.h10
8 files changed, 49 insertions, 233 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 569ee090343f..46b58abb08c5 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -352,13 +352,16 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
352 pdata->mmio_size = resource_size(rentry->res); 352 pdata->mmio_size = resource_size(rentry->res);
353 pdata->mmio_base = ioremap(rentry->res->start, 353 pdata->mmio_base = ioremap(rentry->res->start,
354 pdata->mmio_size); 354 pdata->mmio_size);
355 if (!pdata->mmio_base)
356 goto err_out;
357 break; 355 break;
358 } 356 }
359 357
360 acpi_dev_free_resource_list(&resource_list); 358 acpi_dev_free_resource_list(&resource_list);
361 359
360 if (!pdata->mmio_base) {
361 ret = -ENOMEM;
362 goto err_out;
363 }
364
362 pdata->dev_desc = dev_desc; 365 pdata->dev_desc = dev_desc;
363 366
364 if (dev_desc->setup) 367 if (dev_desc->setup)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c262e4acd68d..3b8963f21b36 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -175,10 +175,14 @@ static void __init acpi_request_region (struct acpi_generic_address *gas,
175 if (!addr || !length) 175 if (!addr || !length)
176 return; 176 return;
177 177
178 acpi_reserve_region(addr, length, gas->space_id, 0, desc); 178 /* Resources are never freed */
179 if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
180 request_region(addr, length, desc);
181 else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
182 request_mem_region(addr, length, desc);
179} 183}
180 184
181static void __init acpi_reserve_resources(void) 185static int __init acpi_reserve_resources(void)
182{ 186{
183 acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, 187 acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length,
184 "ACPI PM1a_EVT_BLK"); 188 "ACPI PM1a_EVT_BLK");
@@ -207,7 +211,10 @@ static void __init acpi_reserve_resources(void)
207 if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) 211 if (!(acpi_gbl_FADT.gpe1_block_length & 0x1))
208 acpi_request_region(&acpi_gbl_FADT.xgpe1_block, 212 acpi_request_region(&acpi_gbl_FADT.xgpe1_block,
209 acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); 213 acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK");
214
215 return 0;
210} 216}
217fs_initcall_sync(acpi_reserve_resources);
211 218
212void acpi_os_printf(const char *fmt, ...) 219void acpi_os_printf(const char *fmt, ...)
213{ 220{
@@ -1862,7 +1869,6 @@ acpi_status __init acpi_os_initialize(void)
1862 1869
1863acpi_status __init acpi_os_initialize1(void) 1870acpi_status __init acpi_os_initialize1(void)
1864{ 1871{
1865 acpi_reserve_resources();
1866 kacpid_wq = alloc_workqueue("kacpid", 0, 1); 1872 kacpid_wq = alloc_workqueue("kacpid", 0, 1);
1867 kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); 1873 kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
1868 kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); 1874 kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 10561ce16ed1..8244f013f210 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -26,7 +26,6 @@
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/export.h> 27#include <linux/export.h>
28#include <linux/ioport.h> 28#include <linux/ioport.h>
29#include <linux/list.h>
30#include <linux/slab.h> 29#include <linux/slab.h>
31 30
32#ifdef CONFIG_X86 31#ifdef CONFIG_X86
@@ -622,164 +621,3 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares,
622 return (type & types) ? 0 : 1; 621 return (type & types) ? 0 : 1;
623} 622}
624EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); 623EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
625
626struct reserved_region {
627 struct list_head node;
628 u64 start;
629 u64 end;
630};
631
632static LIST_HEAD(reserved_io_regions);
633static LIST_HEAD(reserved_mem_regions);
634
635static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags,
636 char *desc)
637{
638 unsigned int length = end - start + 1;
639 struct resource *res;
640
641 res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ?
642 request_region(start, length, desc) :
643 request_mem_region(start, length, desc);
644 if (!res)
645 return -EIO;
646
647 res->flags &= ~flags;
648 return 0;
649}
650
651static int add_region_before(u64 start, u64 end, u8 space_id,
652 unsigned long flags, char *desc,
653 struct list_head *head)
654{
655 struct reserved_region *reg;
656 int error;
657
658 reg = kmalloc(sizeof(*reg), GFP_KERNEL);
659 if (!reg)
660 return -ENOMEM;
661
662 error = request_range(start, end, space_id, flags, desc);
663 if (error) {
664 kfree(reg);
665 return error;
666 }
667
668 reg->start = start;
669 reg->end = end;
670 list_add_tail(&reg->node, head);
671 return 0;
672}
673
674/**
675 * acpi_reserve_region - Reserve an I/O or memory region as a system resource.
676 * @start: Starting address of the region.
677 * @length: Length of the region.
678 * @space_id: Identifier of address space to reserve the region from.
679 * @flags: Resource flags to clear for the region after requesting it.
680 * @desc: Region description (for messages).
681 *
682 * Reserve an I/O or memory region as a system resource to prevent others from
683 * using it. If the new region overlaps with one of the regions (in the given
684 * address space) already reserved by this routine, only the non-overlapping
685 * parts of it will be reserved.
686 *
687 * Returned is either 0 (success) or a negative error code indicating a resource
688 * reservation problem. It is the code of the first encountered error, but the
689 * routine doesn't abort until it has attempted to request all of the parts of
690 * the new region that don't overlap with other regions reserved previously.
691 *
692 * The resources requested by this routine are never released.
693 */
694int acpi_reserve_region(u64 start, unsigned int length, u8 space_id,
695 unsigned long flags, char *desc)
696{
697 struct list_head *regions;
698 struct reserved_region *reg;
699 u64 end = start + length - 1;
700 int ret = 0, error = 0;
701
702 if (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
703 regions = &reserved_io_regions;
704 else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
705 regions = &reserved_mem_regions;
706 else
707 return -EINVAL;
708
709 if (list_empty(regions))
710 return add_region_before(start, end, space_id, flags, desc, regions);
711
712 list_for_each_entry(reg, regions, node)
713 if (reg->start == end + 1) {
714 /* The new region can be prepended to this one. */
715 ret = request_range(start, end, space_id, flags, desc);
716 if (!ret)
717 reg->start = start;
718
719 return ret;
720 } else if (reg->start > end) {
721 /* No overlap. Add the new region here and get out. */
722 return add_region_before(start, end, space_id, flags,
723 desc, &reg->node);
724 } else if (reg->end == start - 1) {
725 goto combine;
726 } else if (reg->end >= start) {
727 goto overlap;
728 }
729
730 /* The new region goes after the last existing one. */
731 return add_region_before(start, end, space_id, flags, desc, regions);
732
733 overlap:
734 /*
735 * The new region overlaps an existing one.
736 *
737 * The head part of the new region immediately preceding the existing
738 * overlapping one can be combined with it right away.
739 */
740 if (reg->start > start) {
741 error = request_range(start, reg->start - 1, space_id, flags, desc);
742 if (error)
743 ret = error;
744 else
745 reg->start = start;
746 }
747
748 combine:
749 /*
750 * The new region is adjacent to an existing one. If it extends beyond
751 * that region all the way to the next one, it is possible to combine
752 * all three of them.
753 */
754 while (reg->end < end) {
755 struct reserved_region *next = NULL;
756 u64 a = reg->end + 1, b = end;
757
758 if (!list_is_last(&reg->node, regions)) {
759 next = list_next_entry(reg, node);
760 if (next->start <= end)
761 b = next->start - 1;
762 }
763 error = request_range(a, b, space_id, flags, desc);
764 if (!error) {
765 if (next && next->start == b + 1) {
766 reg->end = next->end;
767 list_del(&next->node);
768 kfree(next);
769 } else {
770 reg->end = end;
771 break;
772 }
773 } else if (next) {
774 if (!ret)
775 ret = error;
776
777 reg = next;
778 } else {
779 break;
780 }
781 }
782
783 return ret ? ret : error;
784}
785EXPORT_SYMBOL_GPL(acpi_reserve_region);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index cdd547bd67df..0ee43c1056e0 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -6,6 +6,7 @@
6 * This file is released under the GPLv2. 6 * This file is released under the GPLv2.
7 */ 7 */
8 8
9#include <linux/delay.h>
9#include <linux/kernel.h> 10#include <linux/kernel.h>
10#include <linux/io.h> 11#include <linux/io.h>
11#include <linux/platform_device.h> 12#include <linux/platform_device.h>
@@ -19,6 +20,8 @@
19#include <linux/suspend.h> 20#include <linux/suspend.h>
20#include <linux/export.h> 21#include <linux/export.h>
21 22
23#define GENPD_RETRY_MAX_MS 250 /* Approximate */
24
22#define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \ 25#define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \
23({ \ 26({ \
24 type (*__routine)(struct device *__d); \ 27 type (*__routine)(struct device *__d); \
@@ -2131,6 +2134,7 @@ EXPORT_SYMBOL_GPL(of_genpd_get_from_provider);
2131static void genpd_dev_pm_detach(struct device *dev, bool power_off) 2134static void genpd_dev_pm_detach(struct device *dev, bool power_off)
2132{ 2135{
2133 struct generic_pm_domain *pd; 2136 struct generic_pm_domain *pd;
2137 unsigned int i;
2134 int ret = 0; 2138 int ret = 0;
2135 2139
2136 pd = pm_genpd_lookup_dev(dev); 2140 pd = pm_genpd_lookup_dev(dev);
@@ -2139,10 +2143,12 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)
2139 2143
2140 dev_dbg(dev, "removing from PM domain %s\n", pd->name); 2144 dev_dbg(dev, "removing from PM domain %s\n", pd->name);
2141 2145
2142 while (1) { 2146 for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
2143 ret = pm_genpd_remove_device(pd, dev); 2147 ret = pm_genpd_remove_device(pd, dev);
2144 if (ret != -EAGAIN) 2148 if (ret != -EAGAIN)
2145 break; 2149 break;
2150
2151 mdelay(i);
2146 cond_resched(); 2152 cond_resched();
2147 } 2153 }
2148 2154
@@ -2183,6 +2189,7 @@ int genpd_dev_pm_attach(struct device *dev)
2183{ 2189{
2184 struct of_phandle_args pd_args; 2190 struct of_phandle_args pd_args;
2185 struct generic_pm_domain *pd; 2191 struct generic_pm_domain *pd;
2192 unsigned int i;
2186 int ret; 2193 int ret;
2187 2194
2188 if (!dev->of_node) 2195 if (!dev->of_node)
@@ -2218,10 +2225,12 @@ int genpd_dev_pm_attach(struct device *dev)
2218 2225
2219 dev_dbg(dev, "adding to PM domain %s\n", pd->name); 2226 dev_dbg(dev, "adding to PM domain %s\n", pd->name);
2220 2227
2221 while (1) { 2228 for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
2222 ret = pm_genpd_add_device(pd, dev); 2229 ret = pm_genpd_add_device(pd, dev);
2223 if (ret != -EAGAIN) 2230 if (ret != -EAGAIN)
2224 break; 2231 break;
2232
2233 mdelay(i);
2225 cond_resched(); 2234 cond_resched();
2226 } 2235 }
2227 2236
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index 7470004ca810..eb6e67451dec 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -45,14 +45,12 @@ static int dev_pm_attach_wake_irq(struct device *dev, int irq,
45 return -EEXIST; 45 return -EEXIST;
46 } 46 }
47 47
48 dev->power.wakeirq = wirq;
49 spin_unlock_irqrestore(&dev->power.lock, flags);
50
51 err = device_wakeup_attach_irq(dev, wirq); 48 err = device_wakeup_attach_irq(dev, wirq);
52 if (err) 49 if (!err)
53 return err; 50 dev->power.wakeirq = wirq;
54 51
55 return 0; 52 spin_unlock_irqrestore(&dev->power.lock, flags);
53 return err;
56} 54}
57 55
58/** 56/**
@@ -105,10 +103,10 @@ void dev_pm_clear_wake_irq(struct device *dev)
105 return; 103 return;
106 104
107 spin_lock_irqsave(&dev->power.lock, flags); 105 spin_lock_irqsave(&dev->power.lock, flags);
106 device_wakeup_detach_irq(dev);
108 dev->power.wakeirq = NULL; 107 dev->power.wakeirq = NULL;
109 spin_unlock_irqrestore(&dev->power.lock, flags); 108 spin_unlock_irqrestore(&dev->power.lock, flags);
110 109
111 device_wakeup_detach_irq(dev);
112 if (wirq->dedicated_irq) 110 if (wirq->dedicated_irq)
113 free_irq(wirq->irq, wirq); 111 free_irq(wirq->irq, wirq);
114 kfree(wirq); 112 kfree(wirq);
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 40f71603378c..51f15bc15774 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -281,32 +281,25 @@ EXPORT_SYMBOL_GPL(device_wakeup_enable);
281 * Attach a device wakeirq to the wakeup source so the device 281 * Attach a device wakeirq to the wakeup source so the device
282 * wake IRQ can be configured automatically for suspend and 282 * wake IRQ can be configured automatically for suspend and
283 * resume. 283 * resume.
284 *
285 * Call under the device's power.lock lock.
284 */ 286 */
285int device_wakeup_attach_irq(struct device *dev, 287int device_wakeup_attach_irq(struct device *dev,
286 struct wake_irq *wakeirq) 288 struct wake_irq *wakeirq)
287{ 289{
288 struct wakeup_source *ws; 290 struct wakeup_source *ws;
289 int ret = 0;
290 291
291 spin_lock_irq(&dev->power.lock);
292 ws = dev->power.wakeup; 292 ws = dev->power.wakeup;
293 if (!ws) { 293 if (!ws) {
294 dev_err(dev, "forgot to call call device_init_wakeup?\n"); 294 dev_err(dev, "forgot to call call device_init_wakeup?\n");
295 ret = -EINVAL; 295 return -EINVAL;
296 goto unlock;
297 } 296 }
298 297
299 if (ws->wakeirq) { 298 if (ws->wakeirq)
300 ret = -EEXIST; 299 return -EEXIST;
301 goto unlock;
302 }
303 300
304 ws->wakeirq = wakeirq; 301 ws->wakeirq = wakeirq;
305 302 return 0;
306unlock:
307 spin_unlock_irq(&dev->power.lock);
308
309 return ret;
310} 303}
311 304
312/** 305/**
@@ -314,20 +307,16 @@ unlock:
314 * @dev: Device to handle 307 * @dev: Device to handle
315 * 308 *
316 * Removes a device wakeirq from the wakeup source. 309 * Removes a device wakeirq from the wakeup source.
310 *
311 * Call under the device's power.lock lock.
317 */ 312 */
318void device_wakeup_detach_irq(struct device *dev) 313void device_wakeup_detach_irq(struct device *dev)
319{ 314{
320 struct wakeup_source *ws; 315 struct wakeup_source *ws;
321 316
322 spin_lock_irq(&dev->power.lock);
323 ws = dev->power.wakeup; 317 ws = dev->power.wakeup;
324 if (!ws) 318 if (ws)
325 goto unlock; 319 ws->wakeirq = NULL;
326
327 ws->wakeirq = NULL;
328
329unlock:
330 spin_unlock_irq(&dev->power.lock);
331} 320}
332 321
333/** 322/**
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index 515f33882ab8..49c1720df59a 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -7,7 +7,6 @@
7 * Bjorn Helgaas <bjorn.helgaas@hp.com> 7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
8 */ 8 */
9 9
10#include <linux/acpi.h>
11#include <linux/pnp.h> 10#include <linux/pnp.h>
12#include <linux/device.h> 11#include <linux/device.h>
13#include <linux/init.h> 12#include <linux/init.h>
@@ -23,41 +22,25 @@ static const struct pnp_device_id pnp_dev_table[] = {
23 {"", 0} 22 {"", 0}
24}; 23};
25 24
26#ifdef CONFIG_ACPI
27static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc)
28{
29 u8 space_id = io ? ACPI_ADR_SPACE_SYSTEM_IO : ACPI_ADR_SPACE_SYSTEM_MEMORY;
30 return !acpi_reserve_region(start, length, space_id, IORESOURCE_BUSY, desc);
31}
32#else
33static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc)
34{
35 struct resource *res;
36
37 res = io ? request_region(start, length, desc) :
38 request_mem_region(start, length, desc);
39 if (res) {
40 res->flags &= ~IORESOURCE_BUSY;
41 return true;
42 }
43 return false;
44}
45#endif
46
47static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) 25static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
48{ 26{
49 char *regionid; 27 char *regionid;
50 const char *pnpid = dev_name(&dev->dev); 28 const char *pnpid = dev_name(&dev->dev);
51 resource_size_t start = r->start, end = r->end; 29 resource_size_t start = r->start, end = r->end;
52 bool reserved; 30 struct resource *res;
53 31
54 regionid = kmalloc(16, GFP_KERNEL); 32 regionid = kmalloc(16, GFP_KERNEL);
55 if (!regionid) 33 if (!regionid)
56 return; 34 return;
57 35
58 snprintf(regionid, 16, "pnp %s", pnpid); 36 snprintf(regionid, 16, "pnp %s", pnpid);
59 reserved = __reserve_range(start, end - start + 1, !!port, regionid); 37 if (port)
60 if (!reserved) 38 res = request_region(start, end - start + 1, regionid);
39 else
40 res = request_mem_region(start, end - start + 1, regionid);
41 if (res)
42 res->flags &= ~IORESOURCE_BUSY;
43 else
61 kfree(regionid); 44 kfree(regionid);
62 45
63 /* 46 /*
@@ -66,7 +49,7 @@ static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
66 * have double reservations. 49 * have double reservations.
67 */ 50 */
68 dev_info(&dev->dev, "%pR %s reserved\n", r, 51 dev_info(&dev->dev, "%pR %s reserved\n", r,
69 reserved ? "has been" : "could not be"); 52 res ? "has been" : "could not be");
70} 53}
71 54
72static void reserve_resources_of_dev(struct pnp_dev *dev) 55static void reserve_resources_of_dev(struct pnp_dev *dev)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index c471dfc93b71..fedfd1bea3bf 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -309,9 +309,6 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
309 309
310int acpi_resources_are_enforced(void); 310int acpi_resources_are_enforced(void);
311 311
312int acpi_reserve_region(u64 start, unsigned int length, u8 space_id,
313 unsigned long flags, char *desc);
314
315#ifdef CONFIG_HIBERNATION 312#ifdef CONFIG_HIBERNATION
316void __init acpi_no_s4_hw_signature(void); 313void __init acpi_no_s4_hw_signature(void);
317#endif 314#endif
@@ -507,13 +504,6 @@ static inline int acpi_check_region(resource_size_t start, resource_size_t n,
507 return 0; 504 return 0;
508} 505}
509 506
510static inline int acpi_reserve_region(u64 start, unsigned int length,
511 u8 space_id, unsigned long flags,
512 char *desc)
513{
514 return -ENXIO;
515}
516
517struct acpi_table_header; 507struct acpi_table_header;
518static inline int acpi_table_parse(char *id, 508static inline int acpi_table_parse(char *id,
519 int (*handler)(struct acpi_table_header *)) 509 int (*handler)(struct acpi_table_header *))