aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/pnp
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/pnp')
-rw-r--r--drivers/pnp/base.h2
-rw-r--r--drivers/pnp/interface.c105
-rw-r--r--drivers/pnp/manager.c25
-rw-r--r--drivers/pnp/pnpacpi/core.c16
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c354
-rw-r--r--drivers/pnp/pnpbios/bioscalls.c1
-rw-r--r--drivers/pnp/pnpbios/core.c21
-rw-r--r--drivers/pnp/resource.c16
8 files changed, 369 insertions, 171 deletions
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index ffd53e3eb92..fa4e0a5db3f 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -159,8 +159,6 @@ struct pnp_resource {
159 159
160void pnp_free_resource(struct pnp_resource *pnp_res); 160void pnp_free_resource(struct pnp_resource *pnp_res);
161 161
162struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
163 struct resource *res);
164struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, 162struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
165 int flags); 163 int flags);
166struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, 164struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 0c201317284..cfaf5b73540 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -298,39 +298,6 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
298 return ret; 298 return ret;
299} 299}
300 300
301static char *pnp_get_resource_value(char *buf,
302 unsigned long type,
303 resource_size_t *start,
304 resource_size_t *end,
305 unsigned long *flags)
306{
307 if (start)
308 *start = 0;
309 if (end)
310 *end = 0;
311 if (flags)
312 *flags = 0;
313
314 /* TBD: allow for disabled resources */
315
316 buf = skip_spaces(buf);
317 if (start) {
318 *start = simple_strtoull(buf, &buf, 0);
319 if (end) {
320 buf = skip_spaces(buf);
321 if (*buf == '-') {
322 buf = skip_spaces(buf + 1);
323 *end = simple_strtoull(buf, &buf, 0);
324 } else
325 *end = *start;
326 }
327 }
328
329 /* TBD: allow for additional flags, e.g., IORESOURCE_WINDOW */
330
331 return buf;
332}
333
334static ssize_t pnp_set_current_resources(struct device *dmdev, 301static ssize_t pnp_set_current_resources(struct device *dmdev,
335 struct device_attribute *attr, 302 struct device_attribute *attr,
336 const char *ubuf, size_t count) 303 const char *ubuf, size_t count)
@@ -338,6 +305,7 @@ static ssize_t pnp_set_current_resources(struct device *dmdev,
338 struct pnp_dev *dev = to_pnp_dev(dmdev); 305 struct pnp_dev *dev = to_pnp_dev(dmdev);
339 char *buf = (void *)ubuf; 306 char *buf = (void *)ubuf;
340 int retval = 0; 307 int retval = 0;
308 resource_size_t start, end;
341 309
342 if (dev->status & PNP_ATTACHED) { 310 if (dev->status & PNP_ATTACHED) {
343 retval = -EBUSY; 311 retval = -EBUSY;
@@ -381,10 +349,6 @@ static ssize_t pnp_set_current_resources(struct device *dmdev,
381 goto done; 349 goto done;
382 } 350 }
383 if (!strnicmp(buf, "set", 3)) { 351 if (!strnicmp(buf, "set", 3)) {
384 resource_size_t start;
385 resource_size_t end;
386 unsigned long flags;
387
388 if (dev->active) 352 if (dev->active)
389 goto done; 353 goto done;
390 buf += 3; 354 buf += 3;
@@ -393,37 +357,42 @@ static ssize_t pnp_set_current_resources(struct device *dmdev,
393 while (1) { 357 while (1) {
394 buf = skip_spaces(buf); 358 buf = skip_spaces(buf);
395 if (!strnicmp(buf, "io", 2)) { 359 if (!strnicmp(buf, "io", 2)) {
396 buf = pnp_get_resource_value(buf + 2, 360 buf = skip_spaces(buf + 2);
397 IORESOURCE_IO, 361 start = simple_strtoul(buf, &buf, 0);
398 &start, &end, 362 buf = skip_spaces(buf);
399 &flags); 363 if (*buf == '-') {
400 pnp_add_io_resource(dev, start, end, flags); 364 buf = skip_spaces(buf + 1);
401 } else if (!strnicmp(buf, "mem", 3)) { 365 end = simple_strtoul(buf, &buf, 0);
402 buf = pnp_get_resource_value(buf + 3, 366 } else
403 IORESOURCE_MEM, 367 end = start;
404 &start, &end, 368 pnp_add_io_resource(dev, start, end, 0);
405 &flags); 369 continue;
406 pnp_add_mem_resource(dev, start, end, flags); 370 }
407 } else if (!strnicmp(buf, "irq", 3)) { 371 if (!strnicmp(buf, "mem", 3)) {
408 buf = pnp_get_resource_value(buf + 3, 372 buf = skip_spaces(buf + 3);
409 IORESOURCE_IRQ, 373 start = simple_strtoul(buf, &buf, 0);
410 &start, NULL, 374 buf = skip_spaces(buf);
411 &flags); 375 if (*buf == '-') {
412 pnp_add_irq_resource(dev, start, flags); 376 buf = skip_spaces(buf + 1);
413 } else if (!strnicmp(buf, "dma", 3)) { 377 end = simple_strtoul(buf, &buf, 0);
414 buf = pnp_get_resource_value(buf + 3, 378 } else
415 IORESOURCE_DMA, 379 end = start;
416 &start, NULL, 380 pnp_add_mem_resource(dev, start, end, 0);
417 &flags); 381 continue;
418 pnp_add_dma_resource(dev, start, flags); 382 }
419 } else if (!strnicmp(buf, "bus", 3)) { 383 if (!strnicmp(buf, "irq", 3)) {
420 buf = pnp_get_resource_value(buf + 3, 384 buf = skip_spaces(buf + 3);
421 IORESOURCE_BUS, 385 start = simple_strtoul(buf, &buf, 0);
422 &start, &end, 386 pnp_add_irq_resource(dev, start, 0);
423 NULL); 387 continue;
424 pnp_add_bus_resource(dev, start, end); 388 }
425 } else 389 if (!strnicmp(buf, "dma", 3)) {
426 break; 390 buf = skip_spaces(buf + 3);
391 start = simple_strtoul(buf, &buf, 0);
392 pnp_add_dma_resource(dev, start, 0);
393 continue;
394 }
395 break;
427 } 396 }
428 mutex_unlock(&pnp_res_mutex); 397 mutex_unlock(&pnp_res_mutex);
429 goto done; 398 goto done;
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 95cebf0185d..ed9ce507149 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -18,27 +18,11 @@
18 18
19DEFINE_MUTEX(pnp_res_mutex); 19DEFINE_MUTEX(pnp_res_mutex);
20 20
21static struct resource *pnp_find_resource(struct pnp_dev *dev,
22 unsigned char rule,
23 unsigned long type,
24 unsigned int bar)
25{
26 struct resource *res = pnp_get_resource(dev, type, bar);
27
28 /* when the resource already exists, set its resource bits from rule */
29 if (res) {
30 res->flags &= ~IORESOURCE_BITS;
31 res->flags |= rule & IORESOURCE_BITS;
32 }
33
34 return res;
35}
36
37static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) 21static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
38{ 22{
39 struct resource *res, local_res; 23 struct resource *res, local_res;
40 24
41 res = pnp_find_resource(dev, rule->flags, IORESOURCE_IO, idx); 25 res = pnp_get_resource(dev, IORESOURCE_IO, idx);
42 if (res) { 26 if (res) {
43 pnp_dbg(&dev->dev, " io %d already set to %#llx-%#llx " 27 pnp_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
44 "flags %#lx\n", idx, (unsigned long long) res->start, 28 "flags %#lx\n", idx, (unsigned long long) res->start,
@@ -81,7 +65,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
81{ 65{
82 struct resource *res, local_res; 66 struct resource *res, local_res;
83 67
84 res = pnp_find_resource(dev, rule->flags, IORESOURCE_MEM, idx); 68 res = pnp_get_resource(dev, IORESOURCE_MEM, idx);
85 if (res) { 69 if (res) {
86 pnp_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " 70 pnp_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
87 "flags %#lx\n", idx, (unsigned long long) res->start, 71 "flags %#lx\n", idx, (unsigned long long) res->start,
@@ -94,7 +78,6 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
94 res->start = 0; 78 res->start = 0;
95 res->end = 0; 79 res->end = 0;
96 80
97 /* ??? rule->flags restricted to 8 bits, all tests bogus ??? */
98 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) 81 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
99 res->flags |= IORESOURCE_READONLY; 82 res->flags |= IORESOURCE_READONLY;
100 if (rule->flags & IORESOURCE_MEM_CACHEABLE) 83 if (rule->flags & IORESOURCE_MEM_CACHEABLE)
@@ -140,7 +123,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
140 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 123 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
141 }; 124 };
142 125
143 res = pnp_find_resource(dev, rule->flags, IORESOURCE_IRQ, idx); 126 res = pnp_get_resource(dev, IORESOURCE_IRQ, idx);
144 if (res) { 127 if (res) {
145 pnp_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", 128 pnp_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
146 idx, (int) res->start, res->flags); 129 idx, (int) res->start, res->flags);
@@ -199,7 +182,7 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
199 1, 3, 5, 6, 7, 0, 2, 4 182 1, 3, 5, 6, 7, 0, 2, 4
200 }; 183 };
201 184
202 res = pnp_find_resource(dev, rule->flags, IORESOURCE_DMA, idx); 185 res = pnp_get_resource(dev, IORESOURCE_DMA, idx);
203 if (res) { 186 if (res) {
204 pnp_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", 187 pnp_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
205 idx, (int) res->start, res->flags); 188 idx, (int) res->start, res->flags);
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 72e822e17d4..ca84d5099ce 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -19,7 +19,6 @@
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22#include <linux/export.h>
23#include <linux/acpi.h> 22#include <linux/acpi.h>
24#include <linux/pnp.h> 23#include <linux/pnp.h>
25#include <linux/slab.h> 24#include <linux/slab.h>
@@ -58,7 +57,7 @@ static inline int __init is_exclusive_device(struct acpi_device *dev)
58 if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \ 57 if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \
59 return 0 58 return 0
60#define TEST_ALPHA(c) \ 59#define TEST_ALPHA(c) \
61 if (!('A' <= (c) && (c) <= 'Z')) \ 60 if (!('@' <= (c) || (c) <= 'Z')) \
62 return 0 61 return 0
63static int __init ispnpidacpi(const char *id) 62static int __init ispnpidacpi(const char *id)
64{ 63{
@@ -95,9 +94,6 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
95 return -ENODEV; 94 return -ENODEV;
96 } 95 }
97 96
98 if (WARN_ON_ONCE(acpi_dev != dev->data))
99 dev->data = acpi_dev;
100
101 ret = pnpacpi_build_resource_template(dev, &buffer); 97 ret = pnpacpi_build_resource_template(dev, &buffer);
102 if (ret) 98 if (ret)
103 return ret; 99 return ret;
@@ -173,8 +169,8 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
173 } 169 }
174 170
175 if (acpi_bus_power_manageable(handle)) { 171 if (acpi_bus_power_manageable(handle)) {
176 int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL, 172 int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
177 ACPI_STATE_D3); 173
178 if (power_state < 0) 174 if (power_state < 0)
179 power_state = (state.event == PM_EVENT_ON) ? 175 power_state = (state.event == PM_EVENT_ON) ?
180 ACPI_STATE_D0 : ACPI_STATE_D3; 176 ACPI_STATE_D0 : ACPI_STATE_D3;
@@ -245,10 +241,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
245 char *pnpid; 241 char *pnpid;
246 struct acpi_hardware_id *id; 242 struct acpi_hardware_id *id;
247 243
248 /* Skip devices that are already bound */
249 if (device->physical_node_count)
250 return 0;
251
252 /* 244 /*
253 * If a PnPacpi device is not present , the device 245 * If a PnPacpi device is not present , the device
254 * driver should not be loaded. 246 * driver should not be loaded.
@@ -330,7 +322,7 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp)
330 struct pnp_dev *pnp = _pnp; 322 struct pnp_dev *pnp = _pnp;
331 323
332 /* true means it matched */ 324 /* true means it matched */
333 return !acpi->physical_node_count 325 return !acpi_get_physical_device(acpi->handle)
334 && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); 326 && compare_pnp_id(pnp->id, acpi_device_hid(acpi));
335} 327}
336 328
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index b8f4ea7b27f..bbf3edd85be 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -28,6 +28,37 @@
28#include "../base.h" 28#include "../base.h"
29#include "pnpacpi.h" 29#include "pnpacpi.h"
30 30
31#ifdef CONFIG_IA64
32#define valid_IRQ(i) (1)
33#else
34#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
35#endif
36
37/*
38 * Allocated Resources
39 */
40static int irq_flags(int triggering, int polarity, int shareable)
41{
42 int flags;
43
44 if (triggering == ACPI_LEVEL_SENSITIVE) {
45 if (polarity == ACPI_ACTIVE_LOW)
46 flags = IORESOURCE_IRQ_LOWLEVEL;
47 else
48 flags = IORESOURCE_IRQ_HIGHLEVEL;
49 } else {
50 if (polarity == ACPI_ACTIVE_LOW)
51 flags = IORESOURCE_IRQ_LOWEDGE;
52 else
53 flags = IORESOURCE_IRQ_HIGHEDGE;
54 }
55
56 if (shareable == ACPI_SHARED)
57 flags |= IORESOURCE_IRQ_SHAREABLE;
58
59 return flags;
60}
61
31static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering, 62static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
32 int *polarity, int *shareable) 63 int *polarity, int *shareable)
33{ 64{
@@ -63,6 +94,45 @@ static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
63 *shareable = ACPI_EXCLUSIVE; 94 *shareable = ACPI_EXCLUSIVE;
64} 95}
65 96
97static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
98 u32 gsi, int triggering,
99 int polarity, int shareable)
100{
101 int irq, flags;
102 int p, t;
103
104 if (!valid_IRQ(gsi)) {
105 pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
106 return;
107 }
108
109 /*
110 * in IO-APIC mode, use overrided attribute. Two reasons:
111 * 1. BIOS bug in DSDT
112 * 2. BIOS uses IO-APIC mode Interrupt Source Override
113 */
114 if (!acpi_get_override_irq(gsi, &t, &p)) {
115 t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
116 p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
117
118 if (triggering != t || polarity != p) {
119 dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
120 gsi, t ? "edge":"level", p ? "low":"high");
121 triggering = t;
122 polarity = p;
123 }
124 }
125
126 flags = irq_flags(triggering, polarity, shareable);
127 irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
128 if (irq >= 0)
129 pcibios_penalize_isa_irq(irq, 1);
130 else
131 flags |= IORESOURCE_DISABLED;
132
133 pnp_add_irq_resource(dev, irq, flags);
134}
135
66static int dma_flags(struct pnp_dev *dev, int type, int bus_master, 136static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
67 int transfer) 137 int transfer)
68{ 138{
@@ -107,16 +177,21 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
107 return flags; 177 return flags;
108} 178}
109 179
110/* 180static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
111 * Allocated Resources 181 u64 len, int io_decode,
112 */ 182 int window)
113
114static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
115{ 183{
116 if (!(r->flags & IORESOURCE_DISABLED)) 184 int flags = 0;
117 pcibios_penalize_isa_irq(r->start, 1); 185 u64 end = start + len - 1;
186
187 if (io_decode == ACPI_DECODE_16)
188 flags |= IORESOURCE_IO_16BIT_ADDR;
189 if (len == 0 || end >= 0x10003)
190 flags |= IORESOURCE_DISABLED;
191 if (window)
192 flags |= IORESOURCE_WINDOW;
118 193
119 pnp_add_resource(dev, r); 194 pnp_add_io_resource(dev, start, end, flags);
120} 195}
121 196
122/* 197/*
@@ -174,49 +249,130 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
174 } 249 }
175} 250}
176 251
252static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
253 u64 start, u64 len,
254 int write_protect, int window)
255{
256 int flags = 0;
257 u64 end = start + len - 1;
258
259 if (len == 0)
260 flags |= IORESOURCE_DISABLED;
261 if (write_protect == ACPI_READ_WRITE_MEMORY)
262 flags |= IORESOURCE_MEM_WRITEABLE;
263 if (window)
264 flags |= IORESOURCE_WINDOW;
265
266 pnp_add_mem_resource(dev, start, end, flags);
267}
268
269static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
270 u64 start, u64 len)
271{
272 u64 end = start + len - 1;
273
274 pnp_add_bus_resource(dev, start, end);
275}
276
277static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
278 struct acpi_resource *res)
279{
280 struct acpi_resource_address64 addr, *p = &addr;
281 acpi_status status;
282 int window;
283 u64 len;
284
285 status = acpi_resource_to_address64(res, p);
286 if (!ACPI_SUCCESS(status)) {
287 dev_warn(&dev->dev, "failed to convert resource type %d\n",
288 res->type);
289 return;
290 }
291
292 /* Windows apparently computes length rather than using _LEN */
293 len = p->maximum - p->minimum + 1;
294 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
295
296 if (p->resource_type == ACPI_MEMORY_RANGE)
297 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
298 p->info.mem.write_protect, window);
299 else if (p->resource_type == ACPI_IO_RANGE)
300 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
301 p->granularity == 0xfff ? ACPI_DECODE_10 :
302 ACPI_DECODE_16, window);
303 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
304 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
305}
306
307static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
308 struct acpi_resource *res)
309{
310 struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
311 int window;
312 u64 len;
313
314 /* Windows apparently computes length rather than using _LEN */
315 len = p->maximum - p->minimum + 1;
316 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
317
318 if (p->resource_type == ACPI_MEMORY_RANGE)
319 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
320 p->info.mem.write_protect, window);
321 else if (p->resource_type == ACPI_IO_RANGE)
322 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
323 p->granularity == 0xfff ? ACPI_DECODE_10 :
324 ACPI_DECODE_16, window);
325 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
326 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
327}
328
177static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, 329static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
178 void *data) 330 void *data)
179{ 331{
180 struct pnp_dev *dev = data; 332 struct pnp_dev *dev = data;
333 struct acpi_resource_irq *irq;
181 struct acpi_resource_dma *dma; 334 struct acpi_resource_dma *dma;
335 struct acpi_resource_io *io;
336 struct acpi_resource_fixed_io *fixed_io;
182 struct acpi_resource_vendor_typed *vendor_typed; 337 struct acpi_resource_vendor_typed *vendor_typed;
183 struct resource r; 338 struct acpi_resource_memory24 *memory24;
339 struct acpi_resource_memory32 *memory32;
340 struct acpi_resource_fixed_memory32 *fixed_memory32;
341 struct acpi_resource_extended_irq *extended_irq;
184 int i, flags; 342 int i, flags;
185 343
186 if (acpi_dev_resource_memory(res, &r) 344 switch (res->type) {
187 || acpi_dev_resource_io(res, &r) 345 case ACPI_RESOURCE_TYPE_IRQ:
188 || acpi_dev_resource_address_space(res, &r) 346 /*
189 || acpi_dev_resource_ext_address_space(res, &r)) { 347 * Per spec, only one interrupt per descriptor is allowed in
190 pnp_add_resource(dev, &r); 348 * _CRS, but some firmware violates this, so parse them all.
191 return AE_OK; 349 */
192 } 350 irq = &res->data.irq;
193 351 if (irq->interrupt_count == 0)
194 r.flags = 0; 352 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
195 if (acpi_dev_resource_interrupt(res, 0, &r)) { 353 else {
196 pnpacpi_add_irqresource(dev, &r); 354 for (i = 0; i < irq->interrupt_count; i++) {
197 for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++) 355 pnpacpi_parse_allocated_irqresource(dev,
198 pnpacpi_add_irqresource(dev, &r); 356 irq->interrupts[i],
357 irq->triggering,
358 irq->polarity,
359 irq->sharable);
360 }
199 361
200 if (i > 1) {
201 /* 362 /*
202 * The IRQ encoder puts a single interrupt in each 363 * The IRQ encoder puts a single interrupt in each
203 * descriptor, so if a _CRS descriptor has more than 364 * descriptor, so if a _CRS descriptor has more than
204 * one interrupt, we won't be able to re-encode it. 365 * one interrupt, we won't be able to re-encode it.
205 */ 366 */
206 if (pnp_can_write(dev)) { 367 if (pnp_can_write(dev) && irq->interrupt_count > 1) {
207 dev_warn(&dev->dev, "multiple interrupts in " 368 dev_warn(&dev->dev, "multiple interrupts in "
208 "_CRS descriptor; configuration can't " 369 "_CRS descriptor; configuration can't "
209 "be changed\n"); 370 "be changed\n");
210 dev->capabilities &= ~PNP_WRITE; 371 dev->capabilities &= ~PNP_WRITE;
211 } 372 }
212 } 373 }
213 return AE_OK; 374 break;
214 } else if (r.flags & IORESOURCE_DISABLED) {
215 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
216 return AE_OK;
217 }
218 375
219 switch (res->type) {
220 case ACPI_RESOURCE_TYPE_DMA: 376 case ACPI_RESOURCE_TYPE_DMA:
221 dma = &res->data.dma; 377 dma = &res->data.dma;
222 if (dma->channel_count > 0 && dma->channels[0] != (u8) -1) 378 if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
@@ -227,10 +383,26 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
227 pnp_add_dma_resource(dev, dma->channels[0], flags); 383 pnp_add_dma_resource(dev, dma->channels[0], flags);
228 break; 384 break;
229 385
386 case ACPI_RESOURCE_TYPE_IO:
387 io = &res->data.io;
388 pnpacpi_parse_allocated_ioresource(dev,
389 io->minimum,
390 io->address_length,
391 io->io_decode, 0);
392 break;
393
230 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 394 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
231 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 395 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
232 break; 396 break;
233 397
398 case ACPI_RESOURCE_TYPE_FIXED_IO:
399 fixed_io = &res->data.fixed_io;
400 pnpacpi_parse_allocated_ioresource(dev,
401 fixed_io->address,
402 fixed_io->address_length,
403 ACPI_DECODE_10, 0);
404 break;
405
234 case ACPI_RESOURCE_TYPE_VENDOR: 406 case ACPI_RESOURCE_TYPE_VENDOR:
235 vendor_typed = &res->data.vendor_typed; 407 vendor_typed = &res->data.vendor_typed;
236 pnpacpi_parse_allocated_vendor(dev, vendor_typed); 408 pnpacpi_parse_allocated_vendor(dev, vendor_typed);
@@ -239,6 +411,66 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
239 case ACPI_RESOURCE_TYPE_END_TAG: 411 case ACPI_RESOURCE_TYPE_END_TAG:
240 break; 412 break;
241 413
414 case ACPI_RESOURCE_TYPE_MEMORY24:
415 memory24 = &res->data.memory24;
416 pnpacpi_parse_allocated_memresource(dev,
417 memory24->minimum,
418 memory24->address_length,
419 memory24->write_protect, 0);
420 break;
421 case ACPI_RESOURCE_TYPE_MEMORY32:
422 memory32 = &res->data.memory32;
423 pnpacpi_parse_allocated_memresource(dev,
424 memory32->minimum,
425 memory32->address_length,
426 memory32->write_protect, 0);
427 break;
428 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
429 fixed_memory32 = &res->data.fixed_memory32;
430 pnpacpi_parse_allocated_memresource(dev,
431 fixed_memory32->address,
432 fixed_memory32->address_length,
433 fixed_memory32->write_protect, 0);
434 break;
435 case ACPI_RESOURCE_TYPE_ADDRESS16:
436 case ACPI_RESOURCE_TYPE_ADDRESS32:
437 case ACPI_RESOURCE_TYPE_ADDRESS64:
438 pnpacpi_parse_allocated_address_space(dev, res);
439 break;
440
441 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
442 pnpacpi_parse_allocated_ext_address_space(dev, res);
443 break;
444
445 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
446 extended_irq = &res->data.extended_irq;
447
448 if (extended_irq->interrupt_count == 0)
449 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
450 else {
451 for (i = 0; i < extended_irq->interrupt_count; i++) {
452 pnpacpi_parse_allocated_irqresource(dev,
453 extended_irq->interrupts[i],
454 extended_irq->triggering,
455 extended_irq->polarity,
456 extended_irq->sharable);
457 }
458
459 /*
460 * The IRQ encoder puts a single interrupt in each
461 * descriptor, so if a _CRS descriptor has more than
462 * one interrupt, we won't be able to re-encode it.
463 */
464 if (pnp_can_write(dev) &&
465 extended_irq->interrupt_count > 1) {
466 dev_warn(&dev->dev, "multiple interrupts in "
467 "_CRS descriptor; configuration can't "
468 "be changed\n");
469 dev->capabilities &= ~PNP_WRITE;
470 }
471 }
472 break;
473
242 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 474 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
243 break; 475 break;
244 476
@@ -277,12 +509,15 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
277 struct acpi_resource_dma *p) 509 struct acpi_resource_dma *p)
278{ 510{
279 int i; 511 int i;
280 unsigned char map = 0, flags; 512 unsigned char map = 0, flags = 0;
513
514 if (p->channel_count == 0)
515 flags |= IORESOURCE_DISABLED;
281 516
282 for (i = 0; i < p->channel_count; i++) 517 for (i = 0; i < p->channel_count; i++)
283 map |= 1 << p->channels[i]; 518 map |= 1 << p->channels[i];
284 519
285 flags = dma_flags(dev, p->type, p->bus_master, p->transfer); 520 flags |= dma_flags(dev, p->type, p->bus_master, p->transfer);
286 pnp_register_dma_resource(dev, option_flags, map, flags); 521 pnp_register_dma_resource(dev, option_flags, map, flags);
287} 522}
288 523
@@ -292,14 +527,17 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
292{ 527{
293 int i; 528 int i;
294 pnp_irq_mask_t map; 529 pnp_irq_mask_t map;
295 unsigned char flags; 530 unsigned char flags = 0;
531
532 if (p->interrupt_count == 0)
533 flags |= IORESOURCE_DISABLED;
296 534
297 bitmap_zero(map.bits, PNP_IRQ_NR); 535 bitmap_zero(map.bits, PNP_IRQ_NR);
298 for (i = 0; i < p->interrupt_count; i++) 536 for (i = 0; i < p->interrupt_count; i++)
299 if (p->interrupts[i]) 537 if (p->interrupts[i])
300 __set_bit(p->interrupts[i], map.bits); 538 __set_bit(p->interrupts[i], map.bits);
301 539
302 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable); 540 flags |= irq_flags(p->triggering, p->polarity, p->sharable);
303 pnp_register_irq_resource(dev, option_flags, &map, flags); 541 pnp_register_irq_resource(dev, option_flags, &map, flags);
304} 542}
305 543
@@ -309,7 +547,10 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
309{ 547{
310 int i; 548 int i;
311 pnp_irq_mask_t map; 549 pnp_irq_mask_t map;
312 unsigned char flags; 550 unsigned char flags = 0;
551
552 if (p->interrupt_count == 0)
553 flags |= IORESOURCE_DISABLED;
313 554
314 bitmap_zero(map.bits, PNP_IRQ_NR); 555 bitmap_zero(map.bits, PNP_IRQ_NR);
315 for (i = 0; i < p->interrupt_count; i++) { 556 for (i = 0; i < p->interrupt_count; i++) {
@@ -323,7 +564,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
323 } 564 }
324 } 565 }
325 566
326 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable); 567 flags |= irq_flags(p->triggering, p->polarity, p->sharable);
327 pnp_register_irq_resource(dev, option_flags, &map, flags); 568 pnp_register_irq_resource(dev, option_flags, &map, flags);
328} 569}
329 570
@@ -333,8 +574,11 @@ static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
333{ 574{
334 unsigned char flags = 0; 575 unsigned char flags = 0;
335 576
577 if (io->address_length == 0)
578 flags |= IORESOURCE_DISABLED;
579
336 if (io->io_decode == ACPI_DECODE_16) 580 if (io->io_decode == ACPI_DECODE_16)
337 flags = IORESOURCE_IO_16BIT_ADDR; 581 flags |= IORESOURCE_IO_16BIT_ADDR;
338 pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum, 582 pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
339 io->alignment, io->address_length, flags); 583 io->alignment, io->address_length, flags);
340} 584}
@@ -343,8 +587,13 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
343 unsigned int option_flags, 587 unsigned int option_flags,
344 struct acpi_resource_fixed_io *io) 588 struct acpi_resource_fixed_io *io)
345{ 589{
590 unsigned char flags = 0;
591
592 if (io->address_length == 0)
593 flags |= IORESOURCE_DISABLED;
594
346 pnp_register_port_resource(dev, option_flags, io->address, io->address, 595 pnp_register_port_resource(dev, option_flags, io->address, io->address,
347 0, io->address_length, IORESOURCE_IO_FIXED); 596 0, io->address_length, flags | IORESOURCE_IO_FIXED);
348} 597}
349 598
350static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, 599static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
@@ -353,8 +602,11 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
353{ 602{
354 unsigned char flags = 0; 603 unsigned char flags = 0;
355 604
605 if (p->address_length == 0)
606 flags |= IORESOURCE_DISABLED;
607
356 if (p->write_protect == ACPI_READ_WRITE_MEMORY) 608 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
357 flags = IORESOURCE_MEM_WRITEABLE; 609 flags |= IORESOURCE_MEM_WRITEABLE;
358 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum, 610 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
359 p->alignment, p->address_length, flags); 611 p->alignment, p->address_length, flags);
360} 612}
@@ -365,8 +617,11 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
365{ 617{
366 unsigned char flags = 0; 618 unsigned char flags = 0;
367 619
620 if (p->address_length == 0)
621 flags |= IORESOURCE_DISABLED;
622
368 if (p->write_protect == ACPI_READ_WRITE_MEMORY) 623 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
369 flags = IORESOURCE_MEM_WRITEABLE; 624 flags |= IORESOURCE_MEM_WRITEABLE;
370 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum, 625 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
371 p->alignment, p->address_length, flags); 626 p->alignment, p->address_length, flags);
372} 627}
@@ -377,8 +632,11 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
377{ 632{
378 unsigned char flags = 0; 633 unsigned char flags = 0;
379 634
635 if (p->address_length == 0)
636 flags |= IORESOURCE_DISABLED;
637
380 if (p->write_protect == ACPI_READ_WRITE_MEMORY) 638 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
381 flags = IORESOURCE_MEM_WRITEABLE; 639 flags |= IORESOURCE_MEM_WRITEABLE;
382 pnp_register_mem_resource(dev, option_flags, p->address, p->address, 640 pnp_register_mem_resource(dev, option_flags, p->address, p->address,
383 0, p->address_length, flags); 641 0, p->address_length, flags);
384} 642}
@@ -398,16 +656,19 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
398 return; 656 return;
399 } 657 }
400 658
659 if (p->address_length == 0)
660 flags |= IORESOURCE_DISABLED;
661
401 if (p->resource_type == ACPI_MEMORY_RANGE) { 662 if (p->resource_type == ACPI_MEMORY_RANGE) {
402 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) 663 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
403 flags = IORESOURCE_MEM_WRITEABLE; 664 flags |= IORESOURCE_MEM_WRITEABLE;
404 pnp_register_mem_resource(dev, option_flags, p->minimum, 665 pnp_register_mem_resource(dev, option_flags, p->minimum,
405 p->minimum, 0, p->address_length, 666 p->minimum, 0, p->address_length,
406 flags); 667 flags);
407 } else if (p->resource_type == ACPI_IO_RANGE) 668 } else if (p->resource_type == ACPI_IO_RANGE)
408 pnp_register_port_resource(dev, option_flags, p->minimum, 669 pnp_register_port_resource(dev, option_flags, p->minimum,
409 p->minimum, 0, p->address_length, 670 p->minimum, 0, p->address_length,
410 IORESOURCE_IO_FIXED); 671 flags | IORESOURCE_IO_FIXED);
411} 672}
412 673
413static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev, 674static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
@@ -417,16 +678,19 @@ static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
417 struct acpi_resource_extended_address64 *p = &r->data.ext_address64; 678 struct acpi_resource_extended_address64 *p = &r->data.ext_address64;
418 unsigned char flags = 0; 679 unsigned char flags = 0;
419 680
681 if (p->address_length == 0)
682 flags |= IORESOURCE_DISABLED;
683
420 if (p->resource_type == ACPI_MEMORY_RANGE) { 684 if (p->resource_type == ACPI_MEMORY_RANGE) {
421 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) 685 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
422 flags = IORESOURCE_MEM_WRITEABLE; 686 flags |= IORESOURCE_MEM_WRITEABLE;
423 pnp_register_mem_resource(dev, option_flags, p->minimum, 687 pnp_register_mem_resource(dev, option_flags, p->minimum,
424 p->minimum, 0, p->address_length, 688 p->minimum, 0, p->address_length,
425 flags); 689 flags);
426 } else if (p->resource_type == ACPI_IO_RANGE) 690 } else if (p->resource_type == ACPI_IO_RANGE)
427 pnp_register_port_resource(dev, option_flags, p->minimum, 691 pnp_register_port_resource(dev, option_flags, p->minimum,
428 p->minimum, 0, p->address_length, 692 p->minimum, 0, p->address_length,
429 IORESOURCE_IO_FIXED); 693 flags | IORESOURCE_IO_FIXED);
430} 694}
431 695
432struct acpipnp_parse_option_s { 696struct acpipnp_parse_option_s {
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index 769d265b221..b859d16cf78 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -17,6 +17,7 @@
17 17
18#include <asm/page.h> 18#include <asm/page.h>
19#include <asm/desc.h> 19#include <asm/desc.h>
20#include <asm/system.h>
20#include <asm/byteorder.h> 21#include <asm/byteorder.h>
21 22
22#include "pnpbios.h" 23#include "pnpbios.h"
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 5d66e5585f9..cfe86853feb 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -65,6 +65,7 @@
65 65
66#include <asm/page.h> 66#include <asm/page.h>
67#include <asm/desc.h> 67#include <asm/desc.h>
68#include <asm/system.h>
68#include <asm/byteorder.h> 69#include <asm/byteorder.h>
69 70
70#include "../base.h" 71#include "../base.h"
@@ -91,6 +92,8 @@ struct pnp_dev_node_info node_info;
91 * 92 *
92 */ 93 */
93 94
95#ifdef CONFIG_HOTPLUG
96
94static struct completion unload_sem; 97static struct completion unload_sem;
95 98
96/* 99/*
@@ -197,6 +200,8 @@ static int pnp_dock_thread(void *unused)
197 complete_and_exit(&unload_sem, 0); 200 complete_and_exit(&unload_sem, 0);
198} 201}
199 202
203#endif /* CONFIG_HOTPLUG */
204
200static int pnpbios_get_resources(struct pnp_dev *dev) 205static int pnpbios_get_resources(struct pnp_dev *dev)
201{ 206{
202 u8 nodenum = dev->number; 207 u8 nodenum = dev->number;
@@ -569,19 +574,21 @@ fs_initcall(pnpbios_init);
569 574
570static int __init pnpbios_thread_init(void) 575static int __init pnpbios_thread_init(void)
571{ 576{
572 struct task_struct *task;
573#if defined(CONFIG_PPC) 577#if defined(CONFIG_PPC)
574 if (check_legacy_ioport(PNPBIOS_BASE)) 578 if (check_legacy_ioport(PNPBIOS_BASE))
575 return 0; 579 return 0;
576#endif 580#endif
577 if (pnpbios_disabled) 581 if (pnpbios_disabled)
578 return 0; 582 return 0;
579 583#ifdef CONFIG_HOTPLUG
580 init_completion(&unload_sem); 584 {
581 task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd"); 585 struct task_struct *task;
582 if (IS_ERR(task)) 586 init_completion(&unload_sem);
583 return PTR_ERR(task); 587 task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd");
584 588 if (IS_ERR(task))
589 return PTR_ERR(task);
590 }
591#endif
585 return 0; 592 return 0;
586} 593}
587 594
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 3e6db1c1dc2..b0ecacbe53b 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -503,22 +503,6 @@ static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
503 return pnp_res; 503 return pnp_res;
504} 504}
505 505
506struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
507 struct resource *res)
508{
509 struct pnp_resource *pnp_res;
510
511 pnp_res = pnp_new_resource(dev);
512 if (!pnp_res) {
513 dev_err(&dev->dev, "can't add resource %pR\n", res);
514 return NULL;
515 }
516
517 pnp_res->res = *res;
518 dev_dbg(&dev->dev, "%pR\n", res);
519 return pnp_res;
520}
521
522struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, 506struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
523 int flags) 507 int flags)
524{ 508{