aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2008-06-27 18:57:17 -0400
committerAndi Kleen <andi@basil.nowhere.org>2008-07-16 17:27:07 -0400
commit1f32ca31e7409d37c1b25e5f81840fb184380cdf (patch)
treee587c85b46b04dbbb5987e2a4986ab174f3bd6fa /drivers/pnp
parentbbe413b4fc7f791248c7ee00ce7b3778491a3700 (diff)
PNP: convert resource options to single linked list
ISAPNP, PNPBIOS, and ACPI describe the "possible resource settings" of a device, i.e., the possibilities an OS bus driver has when it assigns I/O port, MMIO, and other resources to the device. PNP used to maintain this "possible resource setting" information in one independent option structure and a list of dependent option structures for each device. Each of these option structures had lists of I/O, memory, IRQ, and DMA resources, for example: dev independent options ind-io0 -> ind-io1 ... ind-mem0 -> ind-mem1 ... ... dependent option set 0 dep0-io0 -> dep0-io1 ... dep0-mem0 -> dep0-mem1 ... ... dependent option set 1 dep1-io0 -> dep1-io1 ... dep1-mem0 -> dep1-mem1 ... ... ... This data structure was designed for ISAPNP, where the OS configures device resource settings by writing directly to configuration registers. The OS can write the registers in arbitrary order much like it writes PCI BARs. However, for PNPBIOS and ACPI devices, the OS uses firmware interfaces that perform device configuration, and it is important to pass the desired settings to those interfaces in the correct order. The OS learns the correct order by using firmware interfaces that return the "current resource settings" and "possible resource settings," but the option structures above doesn't store the ordering information. This patch replaces the independent and dependent lists with a single list of options. For example, a device might have possible resource settings like this: dev options ind-io0 -> dep0-io0 -> dep1->io0 -> ind-io1 ... All the possible settings are in the same list, in the order they come from the firmware "possible resource settings" list. Each entry is tagged with an independent/dependent flag. Dependent entries also have a "set number" and an optional priority value. All dependent entries must be assigned from the same set. For example, the OS can use all the entries from dependent set 0, or all the entries from dependent set 1, but it cannot mix entries from set 0 with entries from set 1. Prior to this patch PNP didn't keep track of the order of this list, and it assigned all independent options first, then all dependent ones. Using the example above, that resulted in a "desired configuration" list like this: ind->io0 -> ind->io1 -> depN-io0 ... instead of the list the firmware expects, which looks like this: ind->io0 -> depN-io0 -> ind-io1 ... Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Rene Herman <rene.herman@gmail.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pnp')
-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
10 files changed, 567 insertions, 632 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}