aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pnp/base.h93
-rw-r--r--drivers/pnp/core.c4
-rw-r--r--drivers/pnp/interface.c75
-rw-r--r--drivers/pnp/isapnp/core.c72
-rw-r--r--drivers/pnp/manager.c145
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c93
-rw-r--r--drivers/pnp/pnpbios/rsparser.c67
-rw-r--r--drivers/pnp/quirks.c290
-rw-r--r--drivers/pnp/resource.c268
-rw-r--r--drivers/pnp/support.c92
-rw-r--r--include/linux/pnp.h6
11 files changed, 571 insertions, 634 deletions
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 360c6385686c..e3fa9a2d9a3d 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -1,3 +1,8 @@
1/*
2 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
3 * Bjorn Helgaas <bjorn.helgaas@hp.com>
4 */
5
1extern spinlock_t pnp_lock; 6extern spinlock_t pnp_lock;
2void *pnp_alloc(long size); 7void *pnp_alloc(long size);
3 8
@@ -25,8 +30,6 @@ struct pnp_port {
25 resource_size_t align; /* align boundary */ 30 resource_size_t align; /* align boundary */
26 resource_size_t size; /* size of range */ 31 resource_size_t size; /* size of range */
27 unsigned char flags; /* port flags */ 32 unsigned char flags; /* port flags */
28 unsigned char pad; /* pad */
29 struct pnp_port *next; /* next port */
30}; 33};
31 34
32#define PNP_IRQ_NR 256 35#define PNP_IRQ_NR 256
@@ -35,14 +38,11 @@ typedef struct { DECLARE_BITMAP(bits, PNP_IRQ_NR); } pnp_irq_mask_t;
35struct pnp_irq { 38struct pnp_irq {
36 pnp_irq_mask_t map; /* bitmap for IRQ lines */ 39 pnp_irq_mask_t map; /* bitmap for IRQ lines */
37 unsigned char flags; /* IRQ flags */ 40 unsigned char flags; /* IRQ flags */
38 unsigned char pad; /* pad */
39 struct pnp_irq *next; /* next IRQ */
40}; 41};
41 42
42struct pnp_dma { 43struct pnp_dma {
43 unsigned char map; /* bitmask for DMA channels */ 44 unsigned char map; /* bitmask for DMA channels */
44 unsigned char flags; /* DMA flags */ 45 unsigned char flags; /* DMA flags */
45 struct pnp_dma *next; /* next port */
46}; 46};
47 47
48struct pnp_mem { 48struct pnp_mem {
@@ -51,44 +51,91 @@ struct pnp_mem {
51 resource_size_t align; /* align boundary */ 51 resource_size_t align; /* align boundary */
52 resource_size_t size; /* size of range */ 52 resource_size_t size; /* size of range */
53 unsigned char flags; /* memory flags */ 53 unsigned char flags; /* memory flags */
54 unsigned char pad; /* pad */
55 struct pnp_mem *next; /* next memory resource */
56}; 54};
57 55
56#define PNP_OPTION_DEPENDENT 0x80000000
57#define PNP_OPTION_SET_MASK 0xffff
58#define PNP_OPTION_SET_SHIFT 12
59#define PNP_OPTION_PRIORITY_MASK 0xfff
60#define PNP_OPTION_PRIORITY_SHIFT 0
61
58#define PNP_RES_PRIORITY_PREFERRED 0 62#define PNP_RES_PRIORITY_PREFERRED 0
59#define PNP_RES_PRIORITY_ACCEPTABLE 1 63#define PNP_RES_PRIORITY_ACCEPTABLE 1
60#define PNP_RES_PRIORITY_FUNCTIONAL 2 64#define PNP_RES_PRIORITY_FUNCTIONAL 2
61#define PNP_RES_PRIORITY_INVALID 65535 65#define PNP_RES_PRIORITY_INVALID PNP_OPTION_PRIORITY_MASK
62 66
63struct pnp_option { 67struct pnp_option {
64 unsigned short priority; /* priority */ 68 struct list_head list;
65 struct pnp_port *port; /* first port */ 69 unsigned int flags; /* independent/dependent, set, priority */
66 struct pnp_irq *irq; /* first IRQ */ 70
67 struct pnp_dma *dma; /* first DMA */ 71 unsigned long type; /* IORESOURCE_{IO,MEM,IRQ,DMA} */
68 struct pnp_mem *mem; /* first memory resource */ 72 union {
69 struct pnp_option *next; /* used to chain dependent resources */ 73 struct pnp_port port;
74 struct pnp_irq irq;
75 struct pnp_dma dma;
76 struct pnp_mem mem;
77 } u;
70}; 78};
71 79
72struct pnp_option *pnp_build_option(int priority); 80int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
73struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
74struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
75 int priority);
76int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
77 pnp_irq_mask_t *map, unsigned char flags); 81 pnp_irq_mask_t *map, unsigned char flags);
78int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, 82int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
79 unsigned char map, unsigned char flags); 83 unsigned char map, unsigned char flags);
80int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, 84int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
81 resource_size_t min, resource_size_t max, 85 resource_size_t min, resource_size_t max,
82 resource_size_t align, resource_size_t size, 86 resource_size_t align, resource_size_t size,
83 unsigned char flags); 87 unsigned char flags);
84int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, 88int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
85 resource_size_t min, resource_size_t max, 89 resource_size_t min, resource_size_t max,
86 resource_size_t align, resource_size_t size, 90 resource_size_t align, resource_size_t size,
87 unsigned char flags); 91 unsigned char flags);
92
93static inline int pnp_option_is_dependent(struct pnp_option *option)
94{
95 return option->flags & PNP_OPTION_DEPENDENT ? 1 : 0;
96}
97
98static inline unsigned int pnp_option_set(struct pnp_option *option)
99{
100 return (option->flags >> PNP_OPTION_SET_SHIFT) & PNP_OPTION_SET_MASK;
101}
102
103static inline unsigned int pnp_option_priority(struct pnp_option *option)
104{
105 return (option->flags >> PNP_OPTION_PRIORITY_SHIFT) &
106 PNP_OPTION_PRIORITY_MASK;
107}
108
109static inline unsigned int pnp_new_dependent_set(struct pnp_dev *dev,
110 int priority)
111{
112 unsigned int flags;
113
114 if (priority > PNP_RES_PRIORITY_FUNCTIONAL) {
115 dev_warn(&dev->dev, "invalid dependent option priority %d "
116 "clipped to %d", priority,
117 PNP_RES_PRIORITY_INVALID);
118 priority = PNP_RES_PRIORITY_INVALID;
119 }
120
121 flags = PNP_OPTION_DEPENDENT |
122 ((dev->num_dependent_sets & PNP_OPTION_SET_MASK) <<
123 PNP_OPTION_SET_SHIFT) |
124 ((priority & PNP_OPTION_PRIORITY_MASK) <<
125 PNP_OPTION_PRIORITY_SHIFT);
126
127 dev->num_dependent_sets++;
128
129 return flags;
130}
131
132char *pnp_option_priority_name(struct pnp_option *option);
133void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option);
134
88void pnp_init_resources(struct pnp_dev *dev); 135void pnp_init_resources(struct pnp_dev *dev);
89 136
90void pnp_fixup_device(struct pnp_dev *dev); 137void pnp_fixup_device(struct pnp_dev *dev);
91void pnp_free_option(struct pnp_option *option); 138void pnp_free_options(struct pnp_dev *dev);
92int __pnp_add_device(struct pnp_dev *dev); 139int __pnp_add_device(struct pnp_dev *dev);
93void __pnp_remove_device(struct pnp_dev *dev); 140void __pnp_remove_device(struct pnp_dev *dev);
94 141
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 7182da92aec3..a411582bcd72 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -118,10 +118,9 @@ static void pnp_release_device(struct device *dmdev)
118{ 118{
119 struct pnp_dev *dev = to_pnp_dev(dmdev); 119 struct pnp_dev *dev = to_pnp_dev(dmdev);
120 120
121 pnp_free_option(dev->independent);
122 pnp_free_option(dev->dependent);
123 pnp_free_ids(dev); 121 pnp_free_ids(dev);
124 pnp_free_resources(dev); 122 pnp_free_resources(dev);
123 pnp_free_options(dev);
125 kfree(dev); 124 kfree(dev);
126} 125}
127 126
@@ -135,6 +134,7 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
135 return NULL; 134 return NULL;
136 135
137 INIT_LIST_HEAD(&dev->resources); 136 INIT_LIST_HEAD(&dev->resources);
137 INIT_LIST_HEAD(&dev->options);
138 dev->protocol = protocol; 138 dev->protocol = protocol;
139 dev->number = id; 139 dev->number = id;
140 dev->dma_mask = DMA_24BIT_MASK; 140 dev->dma_mask = DMA_24BIT_MASK;
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 7a9fb5544b80..a876ecf7028c 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -3,6 +3,8 @@
3 * 3 *
4 * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz> 4 * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz>
5 * Copyright 2002 Adam Belay <ambx1@neo.rr.com> 5 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
6 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
6 */ 8 */
7 9
8#include <linux/pnp.h> 10#include <linux/pnp.h>
@@ -184,39 +186,22 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space,
184} 186}
185 187
186static void pnp_print_option(pnp_info_buffer_t * buffer, char *space, 188static void pnp_print_option(pnp_info_buffer_t * buffer, char *space,
187 struct pnp_option *option, int dep) 189 struct pnp_option *option)
188{ 190{
189 char *s; 191 switch (option->type) {
190 struct pnp_port *port; 192 case IORESOURCE_IO:
191 struct pnp_irq *irq; 193 pnp_print_port(buffer, space, &option->u.port);
192 struct pnp_dma *dma; 194 break;
193 struct pnp_mem *mem; 195 case IORESOURCE_MEM:
194 196 pnp_print_mem(buffer, space, &option->u.mem);
195 if (dep) { 197 break;
196 switch (option->priority) { 198 case IORESOURCE_IRQ:
197 case PNP_RES_PRIORITY_PREFERRED: 199 pnp_print_irq(buffer, space, &option->u.irq);
198 s = "preferred"; 200 break;
199 break; 201 case IORESOURCE_DMA:
200 case PNP_RES_PRIORITY_ACCEPTABLE: 202 pnp_print_dma(buffer, space, &option->u.dma);
201 s = "acceptable"; 203 break;
202 break;
203 case PNP_RES_PRIORITY_FUNCTIONAL:
204 s = "functional";
205 break;
206 default:
207 s = "invalid";
208 }
209 pnp_printf(buffer, "Dependent: %02i - Priority %s\n", dep, s);
210 } 204 }
211
212 for (port = option->port; port; port = port->next)
213 pnp_print_port(buffer, space, port);
214 for (irq = option->irq; irq; irq = irq->next)
215 pnp_print_irq(buffer, space, irq);
216 for (dma = option->dma; dma; dma = dma->next)
217 pnp_print_dma(buffer, space, dma);
218 for (mem = option->mem; mem; mem = mem->next)
219 pnp_print_mem(buffer, space, mem);
220} 205}
221 206
222static ssize_t pnp_show_options(struct device *dmdev, 207static ssize_t pnp_show_options(struct device *dmdev,
@@ -224,9 +209,9 @@ static ssize_t pnp_show_options(struct device *dmdev,
224{ 209{
225 struct pnp_dev *dev = to_pnp_dev(dmdev); 210 struct pnp_dev *dev = to_pnp_dev(dmdev);
226 pnp_info_buffer_t *buffer; 211 pnp_info_buffer_t *buffer;
227 struct pnp_option *independent = dev->independent; 212 struct pnp_option *option;
228 struct pnp_option *dependent = dev->dependent; 213 int ret, dep = 0, set = 0;
229 int ret, dep = 1; 214 char *indent;
230 215
231 buffer = pnp_alloc(sizeof(pnp_info_buffer_t)); 216 buffer = pnp_alloc(sizeof(pnp_info_buffer_t));
232 if (!buffer) 217 if (!buffer)
@@ -235,14 +220,24 @@ static ssize_t pnp_show_options(struct device *dmdev,
235 buffer->len = PAGE_SIZE; 220 buffer->len = PAGE_SIZE;
236 buffer->buffer = buf; 221 buffer->buffer = buf;
237 buffer->curr = buffer->buffer; 222 buffer->curr = buffer->buffer;
238 if (independent)
239 pnp_print_option(buffer, "", independent, 0);
240 223
241 while (dependent) { 224 list_for_each_entry(option, &dev->options, list) {
242 pnp_print_option(buffer, " ", dependent, dep); 225 if (pnp_option_is_dependent(option)) {
243 dependent = dependent->next; 226 indent = " ";
244 dep++; 227 if (!dep || pnp_option_set(option) != set) {
228 set = pnp_option_set(option);
229 dep = 1;
230 pnp_printf(buffer, "Dependent: %02i - "
231 "Priority %s\n", set,
232 pnp_option_priority_name(option));
233 }
234 } else {
235 dep = 0;
236 indent = "";
237 }
238 pnp_print_option(buffer, indent, option);
245 } 239 }
240
246 ret = (buffer->curr - buf); 241 ret = (buffer->curr - buf);
247 kfree(buffer); 242 kfree(buffer);
248 return ret; 243 return ret;
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 53cc4d6133e6..101a835e8759 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -429,7 +429,7 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card,
429 * Add IRQ resource to resources list. 429 * Add IRQ resource to resources list.
430 */ 430 */
431static void __init isapnp_parse_irq_resource(struct pnp_dev *dev, 431static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
432 struct pnp_option *option, 432 unsigned int option_flags,
433 int size) 433 int size)
434{ 434{
435 unsigned char tmp[3]; 435 unsigned char tmp[3];
@@ -446,27 +446,27 @@ static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
446 if (size > 2) 446 if (size > 2)
447 flags = tmp[2]; 447 flags = tmp[2];
448 448
449 pnp_register_irq_resource(dev, option, &map, flags); 449 pnp_register_irq_resource(dev, option_flags, &map, flags);
450} 450}
451 451
452/* 452/*
453 * Add DMA resource to resources list. 453 * Add DMA resource to resources list.
454 */ 454 */
455static void __init isapnp_parse_dma_resource(struct pnp_dev *dev, 455static void __init isapnp_parse_dma_resource(struct pnp_dev *dev,
456 struct pnp_option *option, 456 unsigned int option_flags,
457 int size) 457 int size)
458{ 458{
459 unsigned char tmp[2]; 459 unsigned char tmp[2];
460 460
461 isapnp_peek(tmp, size); 461 isapnp_peek(tmp, size);
462 pnp_register_dma_resource(dev, option, tmp[0], tmp[1]); 462 pnp_register_dma_resource(dev, option_flags, tmp[0], tmp[1]);
463} 463}
464 464
465/* 465/*
466 * Add port resource to resources list. 466 * Add port resource to resources list.
467 */ 467 */
468static void __init isapnp_parse_port_resource(struct pnp_dev *dev, 468static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
469 struct pnp_option *option, 469 unsigned int option_flags,
470 int size) 470 int size)
471{ 471{
472 unsigned char tmp[7]; 472 unsigned char tmp[7];
@@ -479,14 +479,15 @@ static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
479 align = tmp[5]; 479 align = tmp[5];
480 len = tmp[6]; 480 len = tmp[6];
481 flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0; 481 flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0;
482 pnp_register_port_resource(dev, option, min, max, align, len, flags); 482 pnp_register_port_resource(dev, option_flags,
483 min, max, align, len, flags);
483} 484}
484 485
485/* 486/*
486 * Add fixed port resource to resources list. 487 * Add fixed port resource to resources list.
487 */ 488 */
488static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev, 489static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
489 struct pnp_option *option, 490 unsigned int option_flags,
490 int size) 491 int size)
491{ 492{
492 unsigned char tmp[3]; 493 unsigned char tmp[3];
@@ -495,7 +496,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
495 isapnp_peek(tmp, size); 496 isapnp_peek(tmp, size);
496 base = (tmp[1] << 8) | tmp[0]; 497 base = (tmp[1] << 8) | tmp[0];
497 len = tmp[2]; 498 len = tmp[2];
498 pnp_register_port_resource(dev, option, base, base, 0, len, 499 pnp_register_port_resource(dev, option_flags, base, base, 0, len,
499 IORESOURCE_IO_FIXED); 500 IORESOURCE_IO_FIXED);
500} 501}
501 502
@@ -503,7 +504,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
503 * Add memory resource to resources list. 504 * Add memory resource to resources list.
504 */ 505 */
505static void __init isapnp_parse_mem_resource(struct pnp_dev *dev, 506static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
506 struct pnp_option *option, 507 unsigned int option_flags,
507 int size) 508 int size)
508{ 509{
509 unsigned char tmp[9]; 510 unsigned char tmp[9];
@@ -516,14 +517,15 @@ static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
516 align = (tmp[6] << 8) | tmp[5]; 517 align = (tmp[6] << 8) | tmp[5];
517 len = ((tmp[8] << 8) | tmp[7]) << 8; 518 len = ((tmp[8] << 8) | tmp[7]) << 8;
518 flags = tmp[0]; 519 flags = tmp[0];
519 pnp_register_mem_resource(dev, option, min, max, align, len, flags); 520 pnp_register_mem_resource(dev, option_flags,
521 min, max, align, len, flags);
520} 522}
521 523
522/* 524/*
523 * Add 32-bit memory resource to resources list. 525 * Add 32-bit memory resource to resources list.
524 */ 526 */
525static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev, 527static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
526 struct pnp_option *option, 528 unsigned int option_flags,
527 int size) 529 int size)
528{ 530{
529 unsigned char tmp[17]; 531 unsigned char tmp[17];
@@ -536,14 +538,15 @@ static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
536 align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9]; 538 align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
537 len = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; 539 len = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
538 flags = tmp[0]; 540 flags = tmp[0];
539 pnp_register_mem_resource(dev, option, min, max, align, len, flags); 541 pnp_register_mem_resource(dev, option_flags,
542 min, max, align, len, flags);
540} 543}
541 544
542/* 545/*
543 * Add 32-bit fixed memory resource to resources list. 546 * Add 32-bit fixed memory resource to resources list.
544 */ 547 */
545static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev, 548static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
546 struct pnp_option *option, 549 unsigned int option_flags,
547 int size) 550 int size)
548{ 551{
549 unsigned char tmp[9]; 552 unsigned char tmp[9];
@@ -554,7 +557,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
554 base = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; 557 base = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
555 len = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; 558 len = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
556 flags = tmp[0]; 559 flags = tmp[0];
557 pnp_register_mem_resource(dev, option, base, base, 0, len, flags); 560 pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags);
558} 561}
559 562
560/* 563/*
@@ -584,18 +587,14 @@ static int __init isapnp_create_device(struct pnp_card *card,
584{ 587{
585 int number = 0, skip = 0, priority, compat = 0; 588 int number = 0, skip = 0, priority, compat = 0;
586 unsigned char type, tmp[17]; 589 unsigned char type, tmp[17];
587 struct pnp_option *option, *option_independent; 590 unsigned int option_flags;
588 struct pnp_dev *dev; 591 struct pnp_dev *dev;
589 u32 eisa_id; 592 u32 eisa_id;
590 char id[8]; 593 char id[8];
591 594
592 if ((dev = isapnp_parse_device(card, size, number++)) == NULL) 595 if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
593 return 1; 596 return 1;
594 option_independent = option = pnp_register_independent_option(dev); 597 option_flags = 0;
595 if (!option) {
596 kfree(dev);
597 return 1;
598 }
599 pnp_add_card_device(card, dev); 598 pnp_add_card_device(card, dev);
600 599
601 while (1) { 600 while (1) {
@@ -612,12 +611,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
612 return 1; 611 return 1;
613 size = 0; 612 size = 0;
614 skip = 0; 613 skip = 0;
615 option = pnp_register_independent_option(dev); 614 option_flags = 0;
616 option_independent = option;
617 if (!option) {
618 kfree(dev);
619 return 1;
620 }
621 pnp_add_card_device(card, dev); 615 pnp_add_card_device(card, dev);
622 } else { 616 } else {
623 skip = 1; 617 skip = 1;
@@ -638,13 +632,13 @@ static int __init isapnp_create_device(struct pnp_card *card,
638 case _STAG_IRQ: 632 case _STAG_IRQ:
639 if (size < 2 || size > 3) 633 if (size < 2 || size > 3)
640 goto __skip; 634 goto __skip;
641 isapnp_parse_irq_resource(dev, option, size); 635 isapnp_parse_irq_resource(dev, option_flags, size);
642 size = 0; 636 size = 0;
643 break; 637 break;
644 case _STAG_DMA: 638 case _STAG_DMA:
645 if (size != 2) 639 if (size != 2)
646 goto __skip; 640 goto __skip;
647 isapnp_parse_dma_resource(dev, option, size); 641 isapnp_parse_dma_resource(dev, option_flags, size);
648 size = 0; 642 size = 0;
649 break; 643 break;
650 case _STAG_STARTDEP: 644 case _STAG_STARTDEP:
@@ -656,29 +650,24 @@ static int __init isapnp_create_device(struct pnp_card *card,
656 priority = tmp[0]; 650 priority = tmp[0];
657 size = 0; 651 size = 0;
658 } 652 }
659 option = pnp_register_dependent_option(dev, priority); 653 option_flags = pnp_new_dependent_set(dev, priority);
660 if (!option)
661 return 1;
662 break; 654 break;
663 case _STAG_ENDDEP: 655 case _STAG_ENDDEP:
664 if (size != 0) 656 if (size != 0)
665 goto __skip; 657 goto __skip;
666 if (option_independent == option) 658 option_flags = 0;
667 dev_warn(&dev->dev, "missing "
668 "_STAG_STARTDEP tag\n");
669 option = option_independent;
670 dev_dbg(&dev->dev, "end dependent options\n");
671 break; 659 break;
672 case _STAG_IOPORT: 660 case _STAG_IOPORT:
673 if (size != 7) 661 if (size != 7)
674 goto __skip; 662 goto __skip;
675 isapnp_parse_port_resource(dev, option, size); 663 isapnp_parse_port_resource(dev, option_flags, size);
676 size = 0; 664 size = 0;
677 break; 665 break;
678 case _STAG_FIXEDIO: 666 case _STAG_FIXEDIO:
679 if (size != 3) 667 if (size != 3)
680 goto __skip; 668 goto __skip;
681 isapnp_parse_fixed_port_resource(dev, option, size); 669 isapnp_parse_fixed_port_resource(dev, option_flags,
670 size);
682 size = 0; 671 size = 0;
683 break; 672 break;
684 case _STAG_VENDOR: 673 case _STAG_VENDOR:
@@ -686,7 +675,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
686 case _LTAG_MEMRANGE: 675 case _LTAG_MEMRANGE:
687 if (size != 9) 676 if (size != 9)
688 goto __skip; 677 goto __skip;
689 isapnp_parse_mem_resource(dev, option, size); 678 isapnp_parse_mem_resource(dev, option_flags, size);
690 size = 0; 679 size = 0;
691 break; 680 break;
692 case _LTAG_ANSISTR: 681 case _LTAG_ANSISTR:
@@ -701,13 +690,14 @@ static int __init isapnp_create_device(struct pnp_card *card,
701 case _LTAG_MEM32RANGE: 690 case _LTAG_MEM32RANGE:
702 if (size != 17) 691 if (size != 17)
703 goto __skip; 692 goto __skip;
704 isapnp_parse_mem32_resource(dev, option, size); 693 isapnp_parse_mem32_resource(dev, option_flags, size);
705 size = 0; 694 size = 0;
706 break; 695 break;
707 case _LTAG_FIXEDMEM32RANGE: 696 case _LTAG_FIXEDMEM32RANGE:
708 if (size != 9) 697 if (size != 9)
709 goto __skip; 698 goto __skip;
710 isapnp_parse_fixed_mem32_resource(dev, option, size); 699 isapnp_parse_fixed_mem32_resource(dev, option_flags,
700 size);
711 size = 0; 701 size = 0;
712 break; 702 break;
713 case _STAG_END: 703 case _STAG_END:
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index a20accb5ef8f..b526eaad3f6c 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -3,6 +3,8 @@
3 * 3 *
4 * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz> 4 * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
5 * Copyright 2003 Adam Belay <ambx1@neo.rr.com> 5 * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
6 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
6 */ 8 */
7 9
8#include <linux/errno.h> 10#include <linux/errno.h>
@@ -228,102 +230,51 @@ static void pnp_clean_resource_table(struct pnp_dev *dev)
228/** 230/**
229 * pnp_assign_resources - assigns resources to the device based on the specified dependent number 231 * pnp_assign_resources - assigns resources to the device based on the specified dependent number
230 * @dev: pointer to the desired device 232 * @dev: pointer to the desired device
231 * @depnum: the dependent function number 233 * @set: the dependent function number
232 *
233 * Only set depnum to 0 if the device does not have dependent options.
234 */ 234 */
235static int pnp_assign_resources(struct pnp_dev *dev, int depnum) 235static int pnp_assign_resources(struct pnp_dev *dev, int set)
236{ 236{
237 struct pnp_port *port; 237 struct pnp_option *option;
238 struct pnp_mem *mem;
239 struct pnp_irq *irq;
240 struct pnp_dma *dma;
241 int nport = 0, nmem = 0, nirq = 0, ndma = 0; 238 int nport = 0, nmem = 0, nirq = 0, ndma = 0;
239 int ret = 0;
242 240
243 dbg_pnp_show_resources(dev, "before pnp_assign_resources"); 241 dev_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
244 mutex_lock(&pnp_res_mutex); 242 mutex_lock(&pnp_res_mutex);
245 pnp_clean_resource_table(dev); 243 pnp_clean_resource_table(dev);
246 if (dev->independent) {
247 dev_dbg(&dev->dev, "assigning independent options\n");
248 port = dev->independent->port;
249 mem = dev->independent->mem;
250 irq = dev->independent->irq;
251 dma = dev->independent->dma;
252 while (port) {
253 if (pnp_assign_port(dev, port, nport) < 0)
254 goto fail;
255 nport++;
256 port = port->next;
257 }
258 while (mem) {
259 if (pnp_assign_mem(dev, mem, nmem) < 0)
260 goto fail;
261 nmem++;
262 mem = mem->next;
263 }
264 while (irq) {
265 if (pnp_assign_irq(dev, irq, nirq) < 0)
266 goto fail;
267 nirq++;
268 irq = irq->next;
269 }
270 while (dma) {
271 if (pnp_assign_dma(dev, dma, ndma) < 0)
272 goto fail;
273 ndma++;
274 dma = dma->next;
275 }
276 }
277 244
278 if (depnum) { 245 list_for_each_entry(option, &dev->options, list) {
279 struct pnp_option *dep; 246 if (pnp_option_is_dependent(option) &&
280 int i; 247 pnp_option_set(option) != set)
281 248 continue;
282 dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum); 249
283 for (i = 1, dep = dev->dependent; i < depnum; 250 switch (option->type) {
284 i++, dep = dep->next) 251 case IORESOURCE_IO:
285 if (!dep) 252 ret = pnp_assign_port(dev, &option->u.port, nport++);
286 goto fail; 253 break;
287 port = dep->port; 254 case IORESOURCE_MEM:
288 mem = dep->mem; 255 ret = pnp_assign_mem(dev, &option->u.mem, nmem++);
289 irq = dep->irq; 256 break;
290 dma = dep->dma; 257 case IORESOURCE_IRQ:
291 while (port) { 258 ret = pnp_assign_irq(dev, &option->u.irq, nirq++);
292 if (pnp_assign_port(dev, port, nport) < 0) 259 break;
293 goto fail; 260 case IORESOURCE_DMA:
294 nport++; 261 ret = pnp_assign_dma(dev, &option->u.dma, ndma++);
295 port = port->next; 262 break;
296 } 263 default:
297 while (mem) { 264 ret = -EINVAL;
298 if (pnp_assign_mem(dev, mem, nmem) < 0) 265 break;
299 goto fail;
300 nmem++;
301 mem = mem->next;
302 }
303 while (irq) {
304 if (pnp_assign_irq(dev, irq, nirq) < 0)
305 goto fail;
306 nirq++;
307 irq = irq->next;
308 }
309 while (dma) {
310 if (pnp_assign_dma(dev, dma, ndma) < 0)
311 goto fail;
312 ndma++;
313 dma = dma->next;
314 } 266 }
315 } else if (dev->dependent) 267 if (ret < 0)
316 goto fail; 268 break;
317 269 }
318 mutex_unlock(&pnp_res_mutex);
319 dbg_pnp_show_resources(dev, "after pnp_assign_resources");
320 return 1;
321 270
322fail:
323 pnp_clean_resource_table(dev);
324 mutex_unlock(&pnp_res_mutex); 271 mutex_unlock(&pnp_res_mutex);
325 dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); 272 if (ret < 0) {
326 return 0; 273 dev_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret);
274 pnp_clean_resource_table(dev);
275 } else
276 dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded");
277 return ret;
327} 278}
328 279
329/** 280/**
@@ -332,29 +283,25 @@ fail:
332 */ 283 */
333int pnp_auto_config_dev(struct pnp_dev *dev) 284int pnp_auto_config_dev(struct pnp_dev *dev)
334{ 285{
335 struct pnp_option *dep; 286 int i, ret;
336 int i = 1;
337 287
338 if (!pnp_can_configure(dev)) { 288 if (!pnp_can_configure(dev)) {
339 dev_dbg(&dev->dev, "configuration not supported\n"); 289 dev_dbg(&dev->dev, "configuration not supported\n");
340 return -ENODEV; 290 return -ENODEV;
341 } 291 }
342 292
343 if (!dev->dependent) { 293 ret = pnp_assign_resources(dev, 0);
344 if (pnp_assign_resources(dev, 0)) 294 if (ret == 0)
295 return 0;
296
297 for (i = 1; i < dev->num_dependent_sets; i++) {
298 ret = pnp_assign_resources(dev, i);
299 if (ret == 0)
345 return 0; 300 return 0;
346 } else {
347 dep = dev->dependent;
348 do {
349 if (pnp_assign_resources(dev, i))
350 return 0;
351 dep = dep->next;
352 i++;
353 } while (dep);
354 } 301 }
355 302
356 dev_err(&dev->dev, "unable to assign resources\n"); 303 dev_err(&dev->dev, "unable to assign resources\n");
357 return -EBUSY; 304 return ret;
358} 305}
359 306
360/** 307/**
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index e114b3d2b933..c2f59f4d20bc 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -407,7 +407,7 @@ int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
407} 407}
408 408
409static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, 409static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
410 struct pnp_option *option, 410 unsigned int option_flags,
411 struct acpi_resource_dma *p) 411 struct acpi_resource_dma *p)
412{ 412{
413 int i; 413 int i;
@@ -420,11 +420,11 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
420 map |= 1 << p->channels[i]; 420 map |= 1 << p->channels[i];
421 421
422 flags = dma_flags(p->type, p->bus_master, p->transfer); 422 flags = dma_flags(p->type, p->bus_master, p->transfer);
423 pnp_register_dma_resource(dev, option, map, flags); 423 pnp_register_dma_resource(dev, option_flags, map, flags);
424} 424}
425 425
426static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, 426static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
427 struct pnp_option *option, 427 unsigned int option_flags,
428 struct acpi_resource_irq *p) 428 struct acpi_resource_irq *p)
429{ 429{
430 int i; 430 int i;
@@ -440,11 +440,11 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
440 __set_bit(p->interrupts[i], map.bits); 440 __set_bit(p->interrupts[i], map.bits);
441 441
442 flags = irq_flags(p->triggering, p->polarity, p->sharable); 442 flags = irq_flags(p->triggering, p->polarity, p->sharable);
443 pnp_register_irq_resource(dev, option, &map, flags); 443 pnp_register_irq_resource(dev, option_flags, &map, flags);
444} 444}
445 445
446static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, 446static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
447 struct pnp_option *option, 447 unsigned int option_flags,
448 struct acpi_resource_extended_irq *p) 448 struct acpi_resource_extended_irq *p)
449{ 449{
450 int i; 450 int i;
@@ -467,11 +467,11 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
467 } 467 }
468 468
469 flags = irq_flags(p->triggering, p->polarity, p->sharable); 469 flags = irq_flags(p->triggering, p->polarity, p->sharable);
470 pnp_register_irq_resource(dev, option, &map, flags); 470 pnp_register_irq_resource(dev, option_flags, &map, flags);
471} 471}
472 472
473static __init void pnpacpi_parse_port_option(struct pnp_dev *dev, 473static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
474 struct pnp_option *option, 474 unsigned int option_flags,
475 struct acpi_resource_io *io) 475 struct acpi_resource_io *io)
476{ 476{
477 unsigned char flags = 0; 477 unsigned char flags = 0;
@@ -481,23 +481,23 @@ static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
481 481
482 if (io->io_decode == ACPI_DECODE_16) 482 if (io->io_decode == ACPI_DECODE_16)
483 flags = IORESOURCE_IO_16BIT_ADDR; 483 flags = IORESOURCE_IO_16BIT_ADDR;
484 pnp_register_port_resource(dev, option, io->minimum, io->maximum, 484 pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
485 io->alignment, io->address_length, flags); 485 io->alignment, io->address_length, flags);
486} 486}
487 487
488static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev, 488static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
489 struct pnp_option *option, 489 unsigned int option_flags,
490 struct acpi_resource_fixed_io *io) 490 struct acpi_resource_fixed_io *io)
491{ 491{
492 if (io->address_length == 0) 492 if (io->address_length == 0)
493 return; 493 return;
494 494
495 pnp_register_port_resource(dev, option, io->address, io->address, 0, 495 pnp_register_port_resource(dev, option_flags, io->address, io->address,
496 io->address_length, IORESOURCE_IO_FIXED); 496 0, io->address_length, IORESOURCE_IO_FIXED);
497} 497}
498 498
499static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, 499static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
500 struct pnp_option *option, 500 unsigned int option_flags,
501 struct acpi_resource_memory24 *p) 501 struct acpi_resource_memory24 *p)
502{ 502{
503 unsigned char flags = 0; 503 unsigned char flags = 0;
@@ -507,12 +507,12 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
507 507
508 if (p->write_protect == ACPI_READ_WRITE_MEMORY) 508 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
509 flags = IORESOURCE_MEM_WRITEABLE; 509 flags = IORESOURCE_MEM_WRITEABLE;
510 pnp_register_mem_resource(dev, option, p->minimum, p->maximum, 510 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
511 p->alignment, p->address_length, flags); 511 p->alignment, p->address_length, flags);
512} 512}
513 513
514static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev, 514static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
515 struct pnp_option *option, 515 unsigned int option_flags,
516 struct acpi_resource_memory32 *p) 516 struct acpi_resource_memory32 *p)
517{ 517{
518 unsigned char flags = 0; 518 unsigned char flags = 0;
@@ -522,12 +522,12 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
522 522
523 if (p->write_protect == ACPI_READ_WRITE_MEMORY) 523 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
524 flags = IORESOURCE_MEM_WRITEABLE; 524 flags = IORESOURCE_MEM_WRITEABLE;
525 pnp_register_mem_resource(dev, option, p->minimum, p->maximum, 525 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
526 p->alignment, p->address_length, flags); 526 p->alignment, p->address_length, flags);
527} 527}
528 528
529static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev, 529static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
530 struct pnp_option *option, 530 unsigned int option_flags,
531 struct acpi_resource_fixed_memory32 *p) 531 struct acpi_resource_fixed_memory32 *p)
532{ 532{
533 unsigned char flags = 0; 533 unsigned char flags = 0;
@@ -537,12 +537,12 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
537 537
538 if (p->write_protect == ACPI_READ_WRITE_MEMORY) 538 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
539 flags = IORESOURCE_MEM_WRITEABLE; 539 flags = IORESOURCE_MEM_WRITEABLE;
540 pnp_register_mem_resource(dev, option, p->address, p->address, 540 pnp_register_mem_resource(dev, option_flags, p->address, p->address,
541 0, p->address_length, flags); 541 0, p->address_length, flags);
542} 542}
543 543
544static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, 544static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
545 struct pnp_option *option, 545 unsigned int option_flags,
546 struct acpi_resource *r) 546 struct acpi_resource *r)
547{ 547{
548 struct acpi_resource_address64 addr, *p = &addr; 548 struct acpi_resource_address64 addr, *p = &addr;
@@ -562,18 +562,18 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
562 if (p->resource_type == ACPI_MEMORY_RANGE) { 562 if (p->resource_type == ACPI_MEMORY_RANGE) {
563 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) 563 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
564 flags = IORESOURCE_MEM_WRITEABLE; 564 flags = IORESOURCE_MEM_WRITEABLE;
565 pnp_register_mem_resource(dev, option, p->minimum, p->minimum, 565 pnp_register_mem_resource(dev, option_flags, p->minimum,
566 0, p->address_length, flags); 566 p->minimum, 0, p->address_length,
567 flags);
567 } else if (p->resource_type == ACPI_IO_RANGE) 568 } else if (p->resource_type == ACPI_IO_RANGE)
568 pnp_register_port_resource(dev, option, p->minimum, p->minimum, 569 pnp_register_port_resource(dev, option_flags, p->minimum,
569 0, p->address_length, 570 p->minimum, 0, p->address_length,
570 IORESOURCE_IO_FIXED); 571 IORESOURCE_IO_FIXED);
571} 572}
572 573
573struct acpipnp_parse_option_s { 574struct acpipnp_parse_option_s {
574 struct pnp_option *option;
575 struct pnp_option *option_independent;
576 struct pnp_dev *dev; 575 struct pnp_dev *dev;
576 unsigned int option_flags;
577}; 577};
578 578
579static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, 579static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
@@ -582,15 +582,15 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
582 int priority; 582 int priority;
583 struct acpipnp_parse_option_s *parse_data = data; 583 struct acpipnp_parse_option_s *parse_data = data;
584 struct pnp_dev *dev = parse_data->dev; 584 struct pnp_dev *dev = parse_data->dev;
585 struct pnp_option *option = parse_data->option; 585 unsigned int option_flags = parse_data->option_flags;
586 586
587 switch (res->type) { 587 switch (res->type) {
588 case ACPI_RESOURCE_TYPE_IRQ: 588 case ACPI_RESOURCE_TYPE_IRQ:
589 pnpacpi_parse_irq_option(dev, option, &res->data.irq); 589 pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq);
590 break; 590 break;
591 591
592 case ACPI_RESOURCE_TYPE_DMA: 592 case ACPI_RESOURCE_TYPE_DMA:
593 pnpacpi_parse_dma_option(dev, option, &res->data.dma); 593 pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma);
594 break; 594 break;
595 595
596 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 596 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -610,31 +610,19 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
610 priority = PNP_RES_PRIORITY_INVALID; 610 priority = PNP_RES_PRIORITY_INVALID;
611 break; 611 break;
612 } 612 }
613 /* TBD: Consider performance/robustness bits */ 613 parse_data->option_flags = pnp_new_dependent_set(dev, priority);
614 option = pnp_register_dependent_option(dev, priority);
615 if (!option)
616 return AE_ERROR;
617 parse_data->option = option;
618 break; 614 break;
619 615
620 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 616 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
621 /*only one EndDependentFn is allowed */ 617 parse_data->option_flags = 0;
622 if (!parse_data->option_independent) {
623 dev_warn(&dev->dev, "more than one EndDependentFn "
624 "in _PRS\n");
625 return AE_ERROR;
626 }
627 parse_data->option = parse_data->option_independent;
628 parse_data->option_independent = NULL;
629 dev_dbg(&dev->dev, "end dependent options\n");
630 break; 618 break;
631 619
632 case ACPI_RESOURCE_TYPE_IO: 620 case ACPI_RESOURCE_TYPE_IO:
633 pnpacpi_parse_port_option(dev, option, &res->data.io); 621 pnpacpi_parse_port_option(dev, option_flags, &res->data.io);
634 break; 622 break;
635 623
636 case ACPI_RESOURCE_TYPE_FIXED_IO: 624 case ACPI_RESOURCE_TYPE_FIXED_IO:
637 pnpacpi_parse_fixed_port_option(dev, option, 625 pnpacpi_parse_fixed_port_option(dev, option_flags,
638 &res->data.fixed_io); 626 &res->data.fixed_io);
639 break; 627 break;
640 628
@@ -643,29 +631,31 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
643 break; 631 break;
644 632
645 case ACPI_RESOURCE_TYPE_MEMORY24: 633 case ACPI_RESOURCE_TYPE_MEMORY24:
646 pnpacpi_parse_mem24_option(dev, option, &res->data.memory24); 634 pnpacpi_parse_mem24_option(dev, option_flags,
635 &res->data.memory24);
647 break; 636 break;
648 637
649 case ACPI_RESOURCE_TYPE_MEMORY32: 638 case ACPI_RESOURCE_TYPE_MEMORY32:
650 pnpacpi_parse_mem32_option(dev, option, &res->data.memory32); 639 pnpacpi_parse_mem32_option(dev, option_flags,
640 &res->data.memory32);
651 break; 641 break;
652 642
653 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 643 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
654 pnpacpi_parse_fixed_mem32_option(dev, option, 644 pnpacpi_parse_fixed_mem32_option(dev, option_flags,
655 &res->data.fixed_memory32); 645 &res->data.fixed_memory32);
656 break; 646 break;
657 647
658 case ACPI_RESOURCE_TYPE_ADDRESS16: 648 case ACPI_RESOURCE_TYPE_ADDRESS16:
659 case ACPI_RESOURCE_TYPE_ADDRESS32: 649 case ACPI_RESOURCE_TYPE_ADDRESS32:
660 case ACPI_RESOURCE_TYPE_ADDRESS64: 650 case ACPI_RESOURCE_TYPE_ADDRESS64:
661 pnpacpi_parse_address_option(dev, option, res); 651 pnpacpi_parse_address_option(dev, option_flags, res);
662 break; 652 break;
663 653
664 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 654 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
665 break; 655 break;
666 656
667 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 657 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
668 pnpacpi_parse_ext_irq_option(dev, option, 658 pnpacpi_parse_ext_irq_option(dev, option_flags,
669 &res->data.extended_irq); 659 &res->data.extended_irq);
670 break; 660 break;
671 661
@@ -689,12 +679,9 @@ int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
689 679
690 dev_dbg(&dev->dev, "parse resource options\n"); 680 dev_dbg(&dev->dev, "parse resource options\n");
691 681
692 parse_data.option = pnp_register_independent_option(dev);
693 if (!parse_data.option)
694 return -ENOMEM;
695
696 parse_data.option_independent = parse_data.option;
697 parse_data.dev = dev; 682 parse_data.dev = dev;
683 parse_data.option_flags = 0;
684
698 status = acpi_walk_resources(handle, METHOD_NAME__PRS, 685 status = acpi_walk_resources(handle, METHOD_NAME__PRS,
699 pnpacpi_option_resource, &parse_data); 686 pnpacpi_option_resource, &parse_data);
700 687
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index db23ba78d39c..ca567671379e 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -216,7 +216,7 @@ len_err:
216 216
217static __init void pnpbios_parse_mem_option(struct pnp_dev *dev, 217static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
218 unsigned char *p, int size, 218 unsigned char *p, int size,
219 struct pnp_option *option) 219 unsigned int option_flags)
220{ 220{
221 resource_size_t min, max, align, len; 221 resource_size_t min, max, align, len;
222 unsigned char flags; 222 unsigned char flags;
@@ -226,12 +226,13 @@ static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
226 align = (p[9] << 8) | p[8]; 226 align = (p[9] << 8) | p[8];
227 len = ((p[11] << 8) | p[10]) << 8; 227 len = ((p[11] << 8) | p[10]) << 8;
228 flags = p[3]; 228 flags = p[3];
229 pnp_register_mem_resource(dev, option, min, max, align, len, flags); 229 pnp_register_mem_resource(dev, option_flags, min, max, align, len,
230 flags);
230} 231}
231 232
232static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev, 233static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
233 unsigned char *p, int size, 234 unsigned char *p, int size,
234 struct pnp_option *option) 235 unsigned int option_flags)
235{ 236{
236 resource_size_t min, max, align, len; 237 resource_size_t min, max, align, len;
237 unsigned char flags; 238 unsigned char flags;
@@ -241,12 +242,13 @@ static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
241 align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; 242 align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
242 len = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; 243 len = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
243 flags = p[3]; 244 flags = p[3];
244 pnp_register_mem_resource(dev, option, min, max, align, len, flags); 245 pnp_register_mem_resource(dev, option_flags, min, max, align, len,
246 flags);
245} 247}
246 248
247static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev, 249static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
248 unsigned char *p, int size, 250 unsigned char *p, int size,
249 struct pnp_option *option) 251 unsigned int option_flags)
250{ 252{
251 resource_size_t base, len; 253 resource_size_t base, len;
252 unsigned char flags; 254 unsigned char flags;
@@ -254,12 +256,12 @@ static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
254 base = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; 256 base = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
255 len = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; 257 len = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
256 flags = p[3]; 258 flags = p[3];
257 pnp_register_mem_resource(dev, option, base, base, 0, len, flags); 259 pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags);
258} 260}
259 261
260static __init void pnpbios_parse_irq_option(struct pnp_dev *dev, 262static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
261 unsigned char *p, int size, 263 unsigned char *p, int size,
262 struct pnp_option *option) 264 unsigned int option_flags)
263{ 265{
264 unsigned long bits; 266 unsigned long bits;
265 pnp_irq_mask_t map; 267 pnp_irq_mask_t map;
@@ -273,19 +275,19 @@ static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
273 if (size > 2) 275 if (size > 2)
274 flags = p[3]; 276 flags = p[3];
275 277
276 pnp_register_irq_resource(dev, option, &map, flags); 278 pnp_register_irq_resource(dev, option_flags, &map, flags);
277} 279}
278 280
279static __init void pnpbios_parse_dma_option(struct pnp_dev *dev, 281static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
280 unsigned char *p, int size, 282 unsigned char *p, int size,
281 struct pnp_option *option) 283 unsigned int option_flags)
282{ 284{
283 pnp_register_dma_resource(dev, option, p[1], p[2]); 285 pnp_register_dma_resource(dev, option_flags, p[1], p[2]);
284} 286}
285 287
286static __init void pnpbios_parse_port_option(struct pnp_dev *dev, 288static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
287 unsigned char *p, int size, 289 unsigned char *p, int size,
288 struct pnp_option *option) 290 unsigned int option_flags)
289{ 291{
290 resource_size_t min, max, align, len; 292 resource_size_t min, max, align, len;
291 unsigned char flags; 293 unsigned char flags;
@@ -295,38 +297,35 @@ static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
295 align = p[6]; 297 align = p[6];
296 len = p[7]; 298 len = p[7];
297 flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0; 299 flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0;
298 pnp_register_port_resource(dev, option, min, max, align, len, flags); 300 pnp_register_port_resource(dev, option_flags, min, max, align, len,
301 flags);
299} 302}
300 303
301static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev, 304static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
302 unsigned char *p, int size, 305 unsigned char *p, int size,
303 struct pnp_option *option) 306 unsigned int option_flags)
304{ 307{
305 resource_size_t base, len; 308 resource_size_t base, len;
306 309
307 base = (p[2] << 8) | p[1]; 310 base = (p[2] << 8) | p[1];
308 len = p[3]; 311 len = p[3];
309 pnp_register_port_resource(dev, option, base, base, 0, len, 312 pnp_register_port_resource(dev, option_flags, base, base, 0, len,
310 IORESOURCE_IO_FIXED); 313 IORESOURCE_IO_FIXED);
311} 314}
312 315
313static __init unsigned char * 316static __init unsigned char *
314pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, 317pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
315 struct pnp_dev *dev) 318 struct pnp_dev *dev)
316{ 319{
317 unsigned int len, tag; 320 unsigned int len, tag;
318 int priority; 321 int priority;
319 struct pnp_option *option, *option_independent; 322 unsigned int option_flags;
320 323
321 if (!p) 324 if (!p)
322 return NULL; 325 return NULL;
323 326
324 dev_dbg(&dev->dev, "parse resource options\n"); 327 dev_dbg(&dev->dev, "parse resource options\n");
325 328 option_flags = 0;
326 option_independent = option = pnp_register_independent_option(dev);
327 if (!option)
328 return NULL;
329
330 while ((char *)p < (char *)end) { 329 while ((char *)p < (char *)end) {
331 330
332 /* determine the type of tag */ 331 /* determine the type of tag */
@@ -343,37 +342,38 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
343 case LARGE_TAG_MEM: 342 case LARGE_TAG_MEM:
344 if (len != 9) 343 if (len != 9)
345 goto len_err; 344 goto len_err;
346 pnpbios_parse_mem_option(dev, p, len, option); 345 pnpbios_parse_mem_option(dev, p, len, option_flags);
347 break; 346 break;
348 347
349 case LARGE_TAG_MEM32: 348 case LARGE_TAG_MEM32:
350 if (len != 17) 349 if (len != 17)
351 goto len_err; 350 goto len_err;
352 pnpbios_parse_mem32_option(dev, p, len, option); 351 pnpbios_parse_mem32_option(dev, p, len, option_flags);
353 break; 352 break;
354 353
355 case LARGE_TAG_FIXEDMEM32: 354 case LARGE_TAG_FIXEDMEM32:
356 if (len != 9) 355 if (len != 9)
357 goto len_err; 356 goto len_err;
358 pnpbios_parse_fixed_mem32_option(dev, p, len, option); 357 pnpbios_parse_fixed_mem32_option(dev, p, len,
358 option_flags);
359 break; 359 break;
360 360
361 case SMALL_TAG_IRQ: 361 case SMALL_TAG_IRQ:
362 if (len < 2 || len > 3) 362 if (len < 2 || len > 3)
363 goto len_err; 363 goto len_err;
364 pnpbios_parse_irq_option(dev, p, len, option); 364 pnpbios_parse_irq_option(dev, p, len, option_flags);
365 break; 365 break;
366 366
367 case SMALL_TAG_DMA: 367 case SMALL_TAG_DMA:
368 if (len != 2) 368 if (len != 2)
369 goto len_err; 369 goto len_err;
370 pnpbios_parse_dma_option(dev, p, len, option); 370 pnpbios_parse_dma_option(dev, p, len, option_flags);
371 break; 371 break;
372 372
373 case SMALL_TAG_PORT: 373 case SMALL_TAG_PORT:
374 if (len != 7) 374 if (len != 7)
375 goto len_err; 375 goto len_err;
376 pnpbios_parse_port_option(dev, p, len, option); 376 pnpbios_parse_port_option(dev, p, len, option_flags);
377 break; 377 break;
378 378
379 case SMALL_TAG_VENDOR: 379 case SMALL_TAG_VENDOR:
@@ -383,7 +383,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
383 case SMALL_TAG_FIXEDPORT: 383 case SMALL_TAG_FIXEDPORT:
384 if (len != 3) 384 if (len != 3)
385 goto len_err; 385 goto len_err;
386 pnpbios_parse_fixed_port_option(dev, p, len, option); 386 pnpbios_parse_fixed_port_option(dev, p, len,
387 option_flags);
387 break; 388 break;
388 389
389 case SMALL_TAG_STARTDEP: 390 case SMALL_TAG_STARTDEP:
@@ -392,19 +393,13 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
392 priority = PNP_RES_PRIORITY_ACCEPTABLE; 393 priority = PNP_RES_PRIORITY_ACCEPTABLE;
393 if (len > 0) 394 if (len > 0)
394 priority = p[1]; 395 priority = p[1];
395 option = pnp_register_dependent_option(dev, priority); 396 option_flags = pnp_new_dependent_set(dev, priority);
396 if (!option)
397 return NULL;
398 break; 397 break;
399 398
400 case SMALL_TAG_ENDDEP: 399 case SMALL_TAG_ENDDEP:
401 if (len != 0) 400 if (len != 0)
402 goto len_err; 401 goto len_err;
403 if (option_independent == option) 402 option_flags = 0;
404 dev_warn(&dev->dev, "missing "
405 "SMALL_TAG_STARTDEP tag\n");
406 option = option_independent;
407 dev_dbg(&dev->dev, "end dependent options\n");
408 break; 403 break;
409 404
410 case SMALL_TAG_END: 405 case SMALL_TAG_END:
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index e8515ce0d296..55f55ed72dc7 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -5,6 +5,8 @@
5 * when building up the resource structure for the first time. 5 * when building up the resource structure for the first time.
6 * 6 *
7 * Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk> 7 * Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
8 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
9 * Bjorn Helgaas <bjorn.helgaas@hp.com>
8 * 10 *
9 * Heavily based on PCI quirks handling which is 11 * Heavily based on PCI quirks handling which is
10 * 12 *
@@ -20,189 +22,207 @@
20#include <linux/kallsyms.h> 22#include <linux/kallsyms.h>
21#include "base.h" 23#include "base.h"
22 24
25static void quirk_awe32_add_ports(struct pnp_dev *dev,
26 struct pnp_option *option,
27 unsigned int offset)
28{
29 struct pnp_option *new_option;
30
31 new_option = kmalloc(sizeof(struct pnp_option), GFP_KERNEL);
32 if (!new_option) {
33 dev_err(&dev->dev, "couldn't add ioport region to option set "
34 "%d\n", pnp_option_set(option));
35 return;
36 }
37
38 *new_option = *option;
39 new_option->u.port.min += offset;
40 new_option->u.port.max += offset;
41 list_add(&new_option->list, &option->list);
42
43 dev_info(&dev->dev, "added ioport region %#llx-%#llx to set %d\n",
44 (unsigned long long) new_option->u.port.min,
45 (unsigned long long) new_option->u.port.max,
46 pnp_option_set(option));
47}
48
23static void quirk_awe32_resources(struct pnp_dev *dev) 49static void quirk_awe32_resources(struct pnp_dev *dev)
24{ 50{
25 struct pnp_port *port, *port2, *port3; 51 struct pnp_option *option;
26 struct pnp_option *res = dev->dependent; 52 unsigned int set = ~0;
27 53
28 /* 54 /*
29 * Unfortunately the isapnp_add_port_resource is too tightly bound 55 * Add two extra ioport regions (at offset 0x400 and 0x800 from the
30 * into the PnP discovery sequence, and cannot be used. Link in the 56 * one given) to every dependent option set.
31 * two extra ports (at offset 0x400 and 0x800 from the one given) by
32 * hand.
33 */ 57 */
34 for (; res; res = res->next) { 58 list_for_each_entry(option, &dev->options, list) {
35 port2 = pnp_alloc(sizeof(struct pnp_port)); 59 if (pnp_option_is_dependent(option) &&
36 if (!port2) 60 pnp_option_set(option) != set) {
37 return; 61 set = pnp_option_set(option);
38 port3 = pnp_alloc(sizeof(struct pnp_port)); 62 quirk_awe32_add_ports(dev, option, 0x800);
39 if (!port3) { 63 quirk_awe32_add_ports(dev, option, 0x400);
40 kfree(port2);
41 return;
42 } 64 }
43 port = res->port;
44 memcpy(port2, port, sizeof(struct pnp_port));
45 memcpy(port3, port, sizeof(struct pnp_port));
46 port->next = port2;
47 port2->next = port3;
48 port2->min += 0x400;
49 port2->max += 0x400;
50 port3->min += 0x800;
51 port3->max += 0x800;
52 dev_info(&dev->dev,
53 "AWE32 quirk - added ioports 0x%lx and 0x%lx\n",
54 (unsigned long)port2->min,
55 (unsigned long)port3->min);
56 } 65 }
57} 66}
58 67
59static void quirk_cmi8330_resources(struct pnp_dev *dev) 68static void quirk_cmi8330_resources(struct pnp_dev *dev)
60{ 69{
61 struct pnp_option *res = dev->dependent; 70 struct pnp_option *option;
62 unsigned long tmp; 71 struct pnp_irq *irq;
63 72 struct pnp_dma *dma;
64 for (; res; res = res->next) {
65
66 struct pnp_irq *irq;
67 struct pnp_dma *dma;
68 73
69 for (irq = res->irq; irq; irq = irq->next) { 74 list_for_each_entry(option, &dev->options, list) {
70 /* Valid irqs are 5, 7, 10 */ 75 if (!pnp_option_is_dependent(option))
71 tmp = 0x04A0; 76 continue;
72 bitmap_copy(irq->map.bits, &tmp, 16);
73 }
74 77
75 for (dma = res->dma; dma; dma = dma->next) { 78 if (option->type == IORESOURCE_IRQ) {
76 /* Valid 8bit dma channels are 1,3 */ 79 irq = &option->u.irq;
80 bitmap_zero(irq->map.bits, PNP_IRQ_NR);
81 __set_bit(5, irq->map.bits);
82 __set_bit(7, irq->map.bits);
83 __set_bit(10, irq->map.bits);
84 dev_info(&dev->dev, "set possible IRQs in "
85 "option set %d to 5, 7, 10\n",
86 pnp_option_set(option));
87 } else if (option->type == IORESOURCE_DMA) {
88 dma = &option->u.dma;
77 if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) == 89 if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) ==
78 IORESOURCE_DMA_8BIT) 90 IORESOURCE_DMA_8BIT &&
79 dma->map = 0x000A; 91 dma->map != 0x0A) {
92 dev_info(&dev->dev, "changing possible "
93 "DMA channel mask in option set %d "
94 "from %#02x to 0x0A (1, 3)\n",
95 pnp_option_set(option), dma->map);
96 dma->map = 0x0A;
97 }
80 } 98 }
81 } 99 }
82 dev_info(&dev->dev, "CMI8330 quirk - forced possible IRQs to 5, 7, 10 "
83 "and DMA channels to 1, 3\n");
84} 100}
85 101
86static void quirk_sb16audio_resources(struct pnp_dev *dev) 102static void quirk_sb16audio_resources(struct pnp_dev *dev)
87{ 103{
104 struct pnp_option *option;
105 unsigned int prev_option_flags = ~0, n = 0;
88 struct pnp_port *port; 106 struct pnp_port *port;
89 struct pnp_option *res = dev->dependent;
90 int changed = 0;
91 107
92 /* 108 /*
93 * The default range on the mpu port for these devices is 0x388-0x388. 109 * The default range on the OPL port for these devices is 0x388-0x388.
94 * Here we increase that range so that two such cards can be 110 * Here we increase that range so that two such cards can be
95 * auto-configured. 111 * auto-configured.
96 */ 112 */
113 list_for_each_entry(option, &dev->options, list) {
114 if (prev_option_flags != option->flags) {
115 prev_option_flags = option->flags;
116 n = 0;
117 }
97 118
98 for (; res; res = res->next) { 119 if (pnp_option_is_dependent(option) &&
99 port = res->port; 120 option->type == IORESOURCE_IO) {
100 if (!port) 121 n++;
101 continue; 122 port = &option->u.port;
102 port = port->next; 123 if (n == 3 && port->min == port->max) {
103 if (!port) 124 port->max += 0x70;
104 continue; 125 dev_info(&dev->dev, "increased option port "
105 port = port->next; 126 "range from %#llx-%#llx to "
106 if (!port) 127 "%#llx-%#llx\n",
107 continue; 128 (unsigned long long) port->min,
108 if (port->min != port->max) 129 (unsigned long long) port->min,
109 continue; 130 (unsigned long long) port->min,
110 port->max += 0x70; 131 (unsigned long long) port->max);
111 changed = 1; 132 }
133 }
112 } 134 }
113 if (changed)
114 dev_info(&dev->dev, "SB audio device quirk - increased port range\n");
115} 135}
116 136
117static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev) 137static struct pnp_option *pnp_clone_dependent_set(struct pnp_dev *dev,
138 unsigned int set)
118{ 139{
119 struct pnp_option *head = NULL; 140 struct pnp_option *tail = NULL, *first_new_option = NULL;
120 struct pnp_option *prev = NULL; 141 struct pnp_option *option, *new_option;
121 struct pnp_option *res; 142 unsigned int flags;
122
123 /*
124 * Build a functional IRQ-optional variant of each MPU option.
125 */
126
127 for (res = dev->dependent; res; res = res->next) {
128 struct pnp_option *curr;
129 struct pnp_port *port;
130 struct pnp_port *copy_port;
131 struct pnp_irq *irq;
132 struct pnp_irq *copy_irq;
133
134 port = res->port;
135 irq = res->irq;
136 if (!port || !irq)
137 continue;
138 143
139 copy_port = pnp_alloc(sizeof *copy_port); 144 list_for_each_entry(option, &dev->options, list) {
140 if (!copy_port) 145 if (pnp_option_is_dependent(option))
141 break; 146 tail = option;
142 147 }
143 copy_irq = pnp_alloc(sizeof *copy_irq); 148 if (!tail) {
144 if (!copy_irq) { 149 dev_err(&dev->dev, "no dependent option sets\n");
145 kfree(copy_port); 150 return NULL;
146 break; 151 }
147 }
148 152
149 *copy_port = *port; 153 flags = pnp_new_dependent_set(dev, PNP_RES_PRIORITY_FUNCTIONAL);
150 copy_port->next = NULL; 154 list_for_each_entry(option, &dev->options, list) {
155 if (pnp_option_is_dependent(option) &&
156 pnp_option_set(option) == set) {
157 new_option = kmalloc(sizeof(struct pnp_option),
158 GFP_KERNEL);
159 if (!new_option) {
160 dev_err(&dev->dev, "couldn't clone dependent "
161 "set %d\n", set);
162 return NULL;
163 }
151 164
152 *copy_irq = *irq; 165 *new_option = *option;
153 copy_irq->flags |= IORESOURCE_IRQ_OPTIONAL; 166 new_option->flags = flags;
154 copy_irq->next = NULL; 167 if (!first_new_option)
168 first_new_option = new_option;
155 169
156 curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL); 170 list_add(&new_option->list, &tail->list);
157 if (!curr) { 171 tail = new_option;
158 kfree(copy_port);
159 kfree(copy_irq);
160 break;
161 } 172 }
162 curr->port = copy_port;
163 curr->irq = copy_irq;
164
165 if (prev)
166 prev->next = curr;
167 else
168 head = curr;
169 prev = curr;
170 } 173 }
171 if (head)
172 dev_info(&dev->dev, "adding IRQ-optional MPU options\n");
173 174
174 return head; 175 return first_new_option;
175} 176}
176 177
177static void quirk_ad1815_mpu_resources(struct pnp_dev *dev) 178
179static void quirk_add_irq_optional_dependent_sets(struct pnp_dev *dev)
178{ 180{
179 struct pnp_option *res; 181 struct pnp_option *new_option;
182 unsigned int num_sets, i, set;
180 struct pnp_irq *irq; 183 struct pnp_irq *irq;
181 184
182 res = dev->independent; 185 num_sets = dev->num_dependent_sets;
183 if (!res) 186 for (i = 0; i < num_sets; i++) {
184 return; 187 new_option = pnp_clone_dependent_set(dev, i);
188 if (!new_option)
189 return;
185 190
186 irq = res->irq; 191 set = pnp_option_set(new_option);
187 if (!irq || irq->next) 192 while (new_option && pnp_option_set(new_option) == set) {
188 return; 193 if (new_option->type == IORESOURCE_IRQ) {
194 irq = &new_option->u.irq;
195 irq->flags |= IORESOURCE_IRQ_OPTIONAL;
196 }
197 dbg_pnp_show_option(dev, new_option);
198 new_option = list_entry(new_option->list.next,
199 struct pnp_option, list);
200 }
189 201
190 irq->flags |= IORESOURCE_IRQ_OPTIONAL; 202 dev_info(&dev->dev, "added dependent option set %d (same as "
191 dev_info(&dev->dev, "made independent IRQ optional\n"); 203 "set %d except IRQ optional)\n", set, i);
204 }
192} 205}
193 206
194static void quirk_isapnp_mpu_resources(struct pnp_dev *dev) 207static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
195{ 208{
196 struct pnp_option *res; 209 struct pnp_option *option;
210 struct pnp_irq *irq = NULL;
211 unsigned int independent_irqs = 0;
212
213 list_for_each_entry(option, &dev->options, list) {
214 if (option->type == IORESOURCE_IRQ &&
215 !pnp_option_is_dependent(option)) {
216 independent_irqs++;
217 irq = &option->u.irq;
218 }
219 }
197 220
198 res = dev->dependent; 221 if (independent_irqs != 1)
199 if (!res)
200 return; 222 return;
201 223
202 while (res->next) 224 irq->flags |= IORESOURCE_IRQ_OPTIONAL;
203 res = res->next; 225 dev_info(&dev->dev, "made independent IRQ optional\n");
204
205 res->next = quirk_isapnp_mpu_options(dev);
206} 226}
207 227
208#include <linux/pci.h> 228#include <linux/pci.h>
@@ -297,10 +317,10 @@ static struct pnp_fixup pnp_fixups[] = {
297 {"CTL0043", quirk_sb16audio_resources}, 317 {"CTL0043", quirk_sb16audio_resources},
298 {"CTL0044", quirk_sb16audio_resources}, 318 {"CTL0044", quirk_sb16audio_resources},
299 {"CTL0045", quirk_sb16audio_resources}, 319 {"CTL0045", quirk_sb16audio_resources},
300 /* Add IRQ-less MPU options */ 320 /* Add IRQ-optional MPU options */
301 {"ADS7151", quirk_ad1815_mpu_resources}, 321 {"ADS7151", quirk_ad1815_mpu_resources},
302 {"ADS7181", quirk_isapnp_mpu_resources}, 322 {"ADS7181", quirk_add_irq_optional_dependent_sets},
303 {"AZT0002", quirk_isapnp_mpu_resources}, 323 {"AZT0002", quirk_add_irq_optional_dependent_sets},
304 /* PnP resources that might overlap PCI BARs */ 324 /* PnP resources that might overlap PCI BARs */
305 {"PNP0c01", quirk_system_pci_resources}, 325 {"PNP0c01", quirk_system_pci_resources},
306 {"PNP0c02", quirk_system_pci_resources}, 326 {"PNP0c02", quirk_system_pci_resources},
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index a795864dc695..d6388970a1a4 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -3,6 +3,8 @@
3 * 3 *
4 * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz> 4 * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
5 * Copyright 2003 Adam Belay <ambx1@neo.rr.com> 5 * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
6 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
6 */ 8 */
7 9
8#include <linux/module.h> 10#include <linux/module.h>
@@ -28,78 +30,36 @@ static int pnp_reserve_mem[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some
28 * option registration 30 * option registration
29 */ 31 */
30 32
31struct pnp_option *pnp_build_option(int priority) 33struct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type,
34 unsigned int option_flags)
32{ 35{
33 struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option)); 36 struct pnp_option *option;
34 37
38 option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL);
35 if (!option) 39 if (!option)
36 return NULL; 40 return NULL;
37 41
38 option->priority = priority & 0xff; 42 option->flags = option_flags;
39 /* make sure the priority is valid */ 43 option->type = type;
40 if (option->priority > PNP_RES_PRIORITY_FUNCTIONAL)
41 option->priority = PNP_RES_PRIORITY_INVALID;
42
43 return option;
44}
45
46struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev)
47{
48 struct pnp_option *option;
49
50 option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED);
51
52 /* this should never happen but if it does we'll try to continue */
53 if (dev->independent)
54 dev_err(&dev->dev, "independent resource already registered\n");
55 dev->independent = option;
56
57 dev_dbg(&dev->dev, "new independent option\n");
58 return option;
59}
60
61struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
62 int priority)
63{
64 struct pnp_option *option;
65 44
66 option = pnp_build_option(priority); 45 list_add_tail(&option->list, &dev->options);
67
68 if (dev->dependent) {
69 struct pnp_option *parent = dev->dependent;
70 while (parent->next)
71 parent = parent->next;
72 parent->next = option;
73 } else
74 dev->dependent = option;
75
76 dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority);
77 return option; 46 return option;
78} 47}
79 48
80int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, 49int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
81 pnp_irq_mask_t *map, unsigned char flags) 50 pnp_irq_mask_t *map, unsigned char flags)
82{ 51{
83 struct pnp_irq *irq, *ptr; 52 struct pnp_option *option;
84#ifdef DEBUG 53 struct pnp_irq *irq;
85 char buf[PNP_IRQ_NR]; /* hex-encoded, so this is overkill but safe */
86#endif
87 54
88 irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); 55 option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
89 if (!irq) 56 if (!option)
90 return -ENOMEM; 57 return -ENOMEM;
91 58
59 irq = &option->u.irq;
92 irq->map = *map; 60 irq->map = *map;
93 irq->flags = flags; 61 irq->flags = flags;
94 62
95 ptr = option->irq;
96 while (ptr && ptr->next)
97 ptr = ptr->next;
98 if (ptr)
99 ptr->next = irq;
100 else
101 option->irq = irq;
102
103#ifdef CONFIG_PCI 63#ifdef CONFIG_PCI
104 { 64 {
105 int i; 65 int i;
@@ -110,163 +70,81 @@ int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
110 } 70 }
111#endif 71#endif
112 72
113#ifdef DEBUG 73 dbg_pnp_show_option(dev, option);
114 bitmap_scnprintf(buf, sizeof(buf), irq->map.bits, PNP_IRQ_NR);
115 dev_dbg(&dev->dev, " irq bitmask %s flags %#x\n", buf,
116 irq->flags);
117#endif
118 return 0; 74 return 0;
119} 75}
120 76
121int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, 77int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
122 unsigned char map, unsigned char flags) 78 unsigned char map, unsigned char flags)
123{ 79{
124 struct pnp_dma *dma, *ptr; 80 struct pnp_option *option;
81 struct pnp_dma *dma;
125 82
126 dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); 83 option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
127 if (!dma) 84 if (!option)
128 return -ENOMEM; 85 return -ENOMEM;
129 86
87 dma = &option->u.dma;
130 dma->map = map; 88 dma->map = map;
131 dma->flags = flags; 89 dma->flags = flags;
132 90
133 ptr = option->dma; 91 dbg_pnp_show_option(dev, option);
134 while (ptr && ptr->next)
135 ptr = ptr->next;
136 if (ptr)
137 ptr->next = dma;
138 else
139 option->dma = dma;
140
141 dev_dbg(&dev->dev, " dma bitmask %#x flags %#x\n", dma->map,
142 dma->flags);
143 return 0; 92 return 0;
144} 93}
145 94
146int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, 95int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
147 resource_size_t min, resource_size_t max, 96 resource_size_t min, resource_size_t max,
148 resource_size_t align, resource_size_t size, 97 resource_size_t align, resource_size_t size,
149 unsigned char flags) 98 unsigned char flags)
150{ 99{
151 struct pnp_port *port, *ptr; 100 struct pnp_option *option;
101 struct pnp_port *port;
152 102
153 port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); 103 option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
154 if (!port) 104 if (!option)
155 return -ENOMEM; 105 return -ENOMEM;
156 106
107 port = &option->u.port;
157 port->min = min; 108 port->min = min;
158 port->max = max; 109 port->max = max;
159 port->align = align; 110 port->align = align;
160 port->size = size; 111 port->size = size;
161 port->flags = flags; 112 port->flags = flags;
162 113
163 ptr = option->port; 114 dbg_pnp_show_option(dev, option);
164 while (ptr && ptr->next)
165 ptr = ptr->next;
166 if (ptr)
167 ptr->next = port;
168 else
169 option->port = port;
170
171 dev_dbg(&dev->dev, " io "
172 "min %#llx max %#llx align %lld size %lld flags %#x\n",
173 (unsigned long long) port->min,
174 (unsigned long long) port->max,
175 (unsigned long long) port->align,
176 (unsigned long long) port->size, port->flags);
177 return 0; 115 return 0;
178} 116}
179 117
180int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, 118int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
181 resource_size_t min, resource_size_t max, 119 resource_size_t min, resource_size_t max,
182 resource_size_t align, resource_size_t size, 120 resource_size_t align, resource_size_t size,
183 unsigned char flags) 121 unsigned char flags)
184{ 122{
185 struct pnp_mem *mem, *ptr; 123 struct pnp_option *option;
124 struct pnp_mem *mem;
186 125
187 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); 126 option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
188 if (!mem) 127 if (!option)
189 return -ENOMEM; 128 return -ENOMEM;
190 129
130 mem = &option->u.mem;
191 mem->min = min; 131 mem->min = min;
192 mem->max = max; 132 mem->max = max;
193 mem->align = align; 133 mem->align = align;
194 mem->size = size; 134 mem->size = size;
195 mem->flags = flags; 135 mem->flags = flags;
196 136
197 ptr = option->mem; 137 dbg_pnp_show_option(dev, option);
198 while (ptr && ptr->next)
199 ptr = ptr->next;
200 if (ptr)
201 ptr->next = mem;
202 else
203 option->mem = mem;
204
205 dev_dbg(&dev->dev, " mem "
206 "min %#llx max %#llx align %lld size %lld flags %#x\n",
207 (unsigned long long) mem->min,
208 (unsigned long long) mem->max,
209 (unsigned long long) mem->align,
210 (unsigned long long) mem->size, mem->flags);
211 return 0; 138 return 0;
212} 139}
213 140
214static void pnp_free_port(struct pnp_port *port) 141void pnp_free_options(struct pnp_dev *dev)
215{
216 struct pnp_port *next;
217
218 while (port) {
219 next = port->next;
220 kfree(port);
221 port = next;
222 }
223}
224
225static void pnp_free_irq(struct pnp_irq *irq)
226{
227 struct pnp_irq *next;
228
229 while (irq) {
230 next = irq->next;
231 kfree(irq);
232 irq = next;
233 }
234}
235
236static void pnp_free_dma(struct pnp_dma *dma)
237{
238 struct pnp_dma *next;
239
240 while (dma) {
241 next = dma->next;
242 kfree(dma);
243 dma = next;
244 }
245}
246
247static void pnp_free_mem(struct pnp_mem *mem)
248{ 142{
249 struct pnp_mem *next; 143 struct pnp_option *option, *tmp;
250
251 while (mem) {
252 next = mem->next;
253 kfree(mem);
254 mem = next;
255 }
256}
257 144
258void pnp_free_option(struct pnp_option *option) 145 list_for_each_entry_safe(option, tmp, &dev->options, list) {
259{ 146 list_del(&option->list);
260 struct pnp_option *next;
261
262 while (option) {
263 next = option->next;
264 pnp_free_port(option->port);
265 pnp_free_irq(option->irq);
266 pnp_free_dma(option->dma);
267 pnp_free_mem(option->mem);
268 kfree(option); 147 kfree(option);
269 option = next;
270 } 148 }
271} 149}
272 150
@@ -668,66 +546,50 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
668 return pnp_res; 546 return pnp_res;
669} 547}
670 548
671static int pnp_possible_option(struct pnp_option *option, int type, 549/*
672 resource_size_t start, resource_size_t size) 550 * Determine whether the specified resource is a possible configuration
551 * for this device.
552 */
553int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
554 resource_size_t size)
673{ 555{
674 struct pnp_option *tmp; 556 struct pnp_option *option;
675 struct pnp_port *port; 557 struct pnp_port *port;
676 struct pnp_mem *mem; 558 struct pnp_mem *mem;
677 struct pnp_irq *irq; 559 struct pnp_irq *irq;
678 struct pnp_dma *dma; 560 struct pnp_dma *dma;
679 561
680 if (!option) 562 list_for_each_entry(option, &dev->options, list) {
681 return 0; 563 if (option->type != type)
564 continue;
682 565
683 for (tmp = option; tmp; tmp = tmp->next) { 566 switch (option->type) {
684 switch (type) {
685 case IORESOURCE_IO: 567 case IORESOURCE_IO:
686 for (port = tmp->port; port; port = port->next) { 568 port = &option->u.port;
687 if (port->min == start && port->size == size) 569 if (port->min == start && port->size == size)
688 return 1; 570 return 1;
689 }
690 break; 571 break;
691 case IORESOURCE_MEM: 572 case IORESOURCE_MEM:
692 for (mem = tmp->mem; mem; mem = mem->next) { 573 mem = &option->u.mem;
693 if (mem->min == start && mem->size == size) 574 if (mem->min == start && mem->size == size)
694 return 1; 575 return 1;
695 }
696 break; 576 break;
697 case IORESOURCE_IRQ: 577 case IORESOURCE_IRQ:
698 for (irq = tmp->irq; irq; irq = irq->next) { 578 irq = &option->u.irq;
699 if (start < PNP_IRQ_NR && 579 if (start < PNP_IRQ_NR &&
700 test_bit(start, irq->map.bits)) 580 test_bit(start, irq->map.bits))
701 return 1; 581 return 1;
702 }
703 break; 582 break;
704 case IORESOURCE_DMA: 583 case IORESOURCE_DMA:
705 for (dma = tmp->dma; dma; dma = dma->next) { 584 dma = &option->u.dma;
706 if (dma->map & (1 << start)) 585 if (dma->map & (1 << start))
707 return 1; 586 return 1;
708 }
709 break; 587 break;
710 } 588 }
711 } 589 }
712 590
713 return 0; 591 return 0;
714} 592}
715
716/*
717 * Determine whether the specified resource is a possible configuration
718 * for this device.
719 */
720int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
721 resource_size_t size)
722{
723 if (pnp_possible_option(dev->independent, type, start, size))
724 return 1;
725
726 if (pnp_possible_option(dev->dependent, type, start, size))
727 return 1;
728
729 return 0;
730}
731EXPORT_SYMBOL(pnp_possible_config); 593EXPORT_SYMBOL(pnp_possible_config);
732 594
733/* format is: pnp_reserve_irq=irq1[,irq2] .... */ 595/* format is: pnp_reserve_irq=irq1[,irq2] .... */
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
index 0ad42db94884..bbf78ef4ba02 100644
--- a/drivers/pnp/support.c
+++ b/drivers/pnp/support.c
@@ -2,6 +2,8 @@
2 * support.c - standard functions for the use of pnp protocol drivers 2 * support.c - standard functions for the use of pnp protocol drivers
3 * 3 *
4 * Copyright 2003 Adam Belay <ambx1@neo.rr.com> 4 * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
5 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
6 * Bjorn Helgaas <bjorn.helgaas@hp.com>
5 */ 7 */
6 8
7#include <linux/module.h> 9#include <linux/module.h>
@@ -117,3 +119,93 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
117 } 119 }
118#endif 120#endif
119} 121}
122
123char *pnp_option_priority_name(struct pnp_option *option)
124{
125 switch (pnp_option_priority(option)) {
126 case PNP_RES_PRIORITY_PREFERRED:
127 return "preferred";
128 case PNP_RES_PRIORITY_ACCEPTABLE:
129 return "acceptable";
130 case PNP_RES_PRIORITY_FUNCTIONAL:
131 return "functional";
132 }
133 return "invalid";
134}
135
136void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option)
137{
138#ifdef DEBUG
139 char buf[128];
140 int len = 0, i;
141 struct pnp_port *port;
142 struct pnp_mem *mem;
143 struct pnp_irq *irq;
144 struct pnp_dma *dma;
145
146 if (pnp_option_is_dependent(option))
147 len += snprintf(buf + len, sizeof(buf) - len,
148 " dependent set %d (%s) ",
149 pnp_option_set(option),
150 pnp_option_priority_name(option));
151 else
152 len += snprintf(buf + len, sizeof(buf) - len, " independent ");
153
154 switch (option->type) {
155 case IORESOURCE_IO:
156 port = &option->u.port;
157 len += snprintf(buf + len, sizeof(buf) - len, "io min %#llx "
158 "max %#llx align %lld size %lld flags %#x",
159 (unsigned long long) port->min,
160 (unsigned long long) port->max,
161 (unsigned long long) port->align,
162 (unsigned long long) port->size, port->flags);
163 break;
164 case IORESOURCE_MEM:
165 mem = &option->u.mem;
166 len += snprintf(buf + len, sizeof(buf) - len, "mem min %#llx "
167 "max %#llx align %lld size %lld flags %#x",
168 (unsigned long long) mem->min,
169 (unsigned long long) mem->max,
170 (unsigned long long) mem->align,
171 (unsigned long long) mem->size, mem->flags);
172 break;
173 case IORESOURCE_IRQ:
174 irq = &option->u.irq;
175 len += snprintf(buf + len, sizeof(buf) - len, "irq");
176 if (bitmap_empty(irq->map.bits, PNP_IRQ_NR))
177 len += snprintf(buf + len, sizeof(buf) - len,
178 " <none>");
179 else {
180 for (i = 0; i < PNP_IRQ_NR; i++)
181 if (test_bit(i, irq->map.bits))
182 len += snprintf(buf + len,
183 sizeof(buf) - len,
184 " %d", i);
185 }
186 len += snprintf(buf + len, sizeof(buf) - len, " flags %#x",
187 irq->flags);
188 if (irq->flags & IORESOURCE_IRQ_OPTIONAL)
189 len += snprintf(buf + len, sizeof(buf) - len,
190 " (optional)");
191 break;
192 case IORESOURCE_DMA:
193 dma = &option->u.dma;
194 len += snprintf(buf + len, sizeof(buf) - len, "dma");
195 if (!dma->map)
196 len += snprintf(buf + len, sizeof(buf) - len,
197 " <none>");
198 else {
199 for (i = 0; i < 8; i++)
200 if (dma->map & (1 << i))
201 len += snprintf(buf + len,
202 sizeof(buf) - len,
203 " %d", i);
204 }
205 len += snprintf(buf + len, sizeof(buf) - len, " (bitmask %#x) "
206 "flags %#x", dma->map, dma->flags);
207 break;
208 }
209 dev_dbg(&dev->dev, "%s\n", buf);
210#endif
211}
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index 785126ffcc11..1ce54b63085d 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -1,6 +1,8 @@
1/* 1/*
2 * Linux Plug and Play Support 2 * Linux Plug and Play Support
3 * Copyright by Adam Belay <ambx1@neo.rr.com> 3 * Copyright by Adam Belay <ambx1@neo.rr.com>
4 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
5 * Bjorn Helgaas <bjorn.helgaas@hp.com>
4 */ 6 */
5 7
6#ifndef _LINUX_PNP_H 8#ifndef _LINUX_PNP_H
@@ -249,9 +251,9 @@ struct pnp_dev {
249 251
250 int active; 252 int active;
251 int capabilities; 253 int capabilities;
252 struct pnp_option *independent; 254 unsigned int num_dependent_sets;
253 struct pnp_option *dependent;
254 struct list_head resources; 255 struct list_head resources;
256 struct list_head options;
255 257
256 char name[PNP_NAME_LEN]; /* contains a human-readable name */ 258 char name[PNP_NAME_LEN]; /* contains a human-readable name */
257 int flags; /* used by protocols */ 259 int flags; /* used by protocols */