diff options
Diffstat (limited to 'drivers/pnp/system.c')
-rw-r--r-- | drivers/pnp/system.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index 49c1720df59a..515f33882ab8 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | 7 | * Bjorn Helgaas <bjorn.helgaas@hp.com> |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/acpi.h> | ||
10 | #include <linux/pnp.h> | 11 | #include <linux/pnp.h> |
11 | #include <linux/device.h> | 12 | #include <linux/device.h> |
12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
@@ -22,25 +23,41 @@ static const struct pnp_device_id pnp_dev_table[] = { | |||
22 | {"", 0} | 23 | {"", 0} |
23 | }; | 24 | }; |
24 | 25 | ||
26 | #ifdef CONFIG_ACPI | ||
27 | static 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 | ||
33 | static 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 | |||
25 | static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) | 47 | static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) |
26 | { | 48 | { |
27 | char *regionid; | 49 | char *regionid; |
28 | const char *pnpid = dev_name(&dev->dev); | 50 | const char *pnpid = dev_name(&dev->dev); |
29 | resource_size_t start = r->start, end = r->end; | 51 | resource_size_t start = r->start, end = r->end; |
30 | struct resource *res; | 52 | bool reserved; |
31 | 53 | ||
32 | regionid = kmalloc(16, GFP_KERNEL); | 54 | regionid = kmalloc(16, GFP_KERNEL); |
33 | if (!regionid) | 55 | if (!regionid) |
34 | return; | 56 | return; |
35 | 57 | ||
36 | snprintf(regionid, 16, "pnp %s", pnpid); | 58 | snprintf(regionid, 16, "pnp %s", pnpid); |
37 | if (port) | 59 | reserved = __reserve_range(start, end - start + 1, !!port, regionid); |
38 | res = request_region(start, end - start + 1, regionid); | 60 | if (!reserved) |
39 | else | ||
40 | res = request_mem_region(start, end - start + 1, regionid); | ||
41 | if (res) | ||
42 | res->flags &= ~IORESOURCE_BUSY; | ||
43 | else | ||
44 | kfree(regionid); | 61 | kfree(regionid); |
45 | 62 | ||
46 | /* | 63 | /* |
@@ -49,7 +66,7 @@ static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) | |||
49 | * have double reservations. | 66 | * have double reservations. |
50 | */ | 67 | */ |
51 | dev_info(&dev->dev, "%pR %s reserved\n", r, | 68 | dev_info(&dev->dev, "%pR %s reserved\n", r, |
52 | res ? "has been" : "could not be"); | 69 | reserved ? "has been" : "could not be"); |
53 | } | 70 | } |
54 | 71 | ||
55 | static void reserve_resources_of_dev(struct pnp_dev *dev) | 72 | static void reserve_resources_of_dev(struct pnp_dev *dev) |