aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp/resource.c')
-rw-r--r--drivers/pnp/resource.c454
1 files changed, 203 insertions, 251 deletions
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 390b50096e30..4cfe3a1efdfb 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,201 +30,121 @@ 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 44
57 dev_dbg(&dev->dev, "new independent option\n"); 45 list_add_tail(&option->list, &dev->options);
58 return option; 46 return option;
59} 47}
60 48
61struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, 49int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
62 int priority) 50 pnp_irq_mask_t *map, unsigned char flags)
63{ 51{
64 struct pnp_option *option; 52 struct pnp_option *option;
53 struct pnp_irq *irq;
65 54
66 option = pnp_build_option(priority); 55 option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
67 56 if (!option)
68 if (dev->dependent) { 57 return -ENOMEM;
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;
78}
79
80int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
81 struct pnp_irq *data)
82{
83 struct pnp_irq *ptr;
84#ifdef DEBUG
85 char buf[PNP_IRQ_NR]; /* hex-encoded, so this is overkill but safe */
86#endif
87 58
88 ptr = option->irq; 59 irq = &option->u.irq;
89 while (ptr && ptr->next) 60 irq->map = *map;
90 ptr = ptr->next; 61 irq->flags = flags;
91 if (ptr)
92 ptr->next = data;
93 else
94 option->irq = data;
95 62
96#ifdef CONFIG_PCI 63#ifdef CONFIG_PCI
97 { 64 {
98 int i; 65 int i;
99 66
100 for (i = 0; i < 16; i++) 67 for (i = 0; i < 16; i++)
101 if (test_bit(i, data->map)) 68 if (test_bit(i, irq->map.bits))
102 pcibios_penalize_isa_irq(i, 0); 69 pcibios_penalize_isa_irq(i, 0);
103 } 70 }
104#endif 71#endif
105 72
106#ifdef DEBUG 73 dbg_pnp_show_option(dev, option);
107 bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR);
108 dev_dbg(&dev->dev, " irq bitmask %s flags %#x\n", buf,
109 data->flags);
110#endif
111 return 0; 74 return 0;
112} 75}
113 76
114int 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,
115 struct pnp_dma *data) 78 unsigned char map, unsigned char flags)
116{ 79{
117 struct pnp_dma *ptr; 80 struct pnp_option *option;
118 81 struct pnp_dma *dma;
119 ptr = option->dma;
120 while (ptr && ptr->next)
121 ptr = ptr->next;
122 if (ptr)
123 ptr->next = data;
124 else
125 option->dma = data;
126
127 dev_dbg(&dev->dev, " dma bitmask %#x flags %#x\n", data->map,
128 data->flags);
129 return 0;
130}
131 82
132int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, 83 option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
133 struct pnp_port *data) 84 if (!option)
134{ 85 return -ENOMEM;
135 struct pnp_port *ptr;
136
137 ptr = option->port;
138 while (ptr && ptr->next)
139 ptr = ptr->next;
140 if (ptr)
141 ptr->next = data;
142 else
143 option->port = data;
144
145 dev_dbg(&dev->dev, " io "
146 "min %#x max %#x align %d size %d flags %#x\n",
147 data->min, data->max, data->align, data->size, data->flags);
148 return 0;
149}
150 86
151int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, 87 dma = &option->u.dma;
152 struct pnp_mem *data) 88 dma->map = map;
153{ 89 dma->flags = flags;
154 struct pnp_mem *ptr; 90
155 91 dbg_pnp_show_option(dev, option);
156 ptr = option->mem;
157 while (ptr && ptr->next)
158 ptr = ptr->next;
159 if (ptr)
160 ptr->next = data;
161 else
162 option->mem = data;
163
164 dev_dbg(&dev->dev, " mem "
165 "min %#x max %#x align %d size %d flags %#x\n",
166 data->min, data->max, data->align, data->size, data->flags);
167 return 0; 92 return 0;
168} 93}
169 94
170static void pnp_free_port(struct pnp_port *port) 95int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
96 resource_size_t min, resource_size_t max,
97 resource_size_t align, resource_size_t size,
98 unsigned char flags)
171{ 99{
172 struct pnp_port *next; 100 struct pnp_option *option;
101 struct pnp_port *port;
173 102
174 while (port) { 103 option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
175 next = port->next; 104 if (!option)
176 kfree(port); 105 return -ENOMEM;
177 port = next;
178 }
179}
180 106
181static void pnp_free_irq(struct pnp_irq *irq) 107 port = &option->u.port;
182{ 108 port->min = min;
183 struct pnp_irq *next; 109 port->max = max;
110 port->align = align;
111 port->size = size;
112 port->flags = flags;
184 113
185 while (irq) { 114 dbg_pnp_show_option(dev, option);
186 next = irq->next; 115 return 0;
187 kfree(irq);
188 irq = next;
189 }
190} 116}
191 117
192static void pnp_free_dma(struct pnp_dma *dma) 118int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
119 resource_size_t min, resource_size_t max,
120 resource_size_t align, resource_size_t size,
121 unsigned char flags)
193{ 122{
194 struct pnp_dma *next; 123 struct pnp_option *option;
124 struct pnp_mem *mem;
195 125
196 while (dma) { 126 option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
197 next = dma->next; 127 if (!option)
198 kfree(dma); 128 return -ENOMEM;
199 dma = next;
200 }
201}
202 129
203static void pnp_free_mem(struct pnp_mem *mem) 130 mem = &option->u.mem;
204{ 131 mem->min = min;
205 struct pnp_mem *next; 132 mem->max = max;
133 mem->align = align;
134 mem->size = size;
135 mem->flags = flags;
206 136
207 while (mem) { 137 dbg_pnp_show_option(dev, option);
208 next = mem->next; 138 return 0;
209 kfree(mem);
210 mem = next;
211 }
212} 139}
213 140
214void pnp_free_option(struct pnp_option *option) 141void pnp_free_options(struct pnp_dev *dev)
215{ 142{
216 struct pnp_option *next; 143 struct pnp_option *option, *tmp;
217 144
218 while (option) { 145 list_for_each_entry_safe(option, tmp, &dev->options, list) {
219 next = option->next; 146 list_del(&option->list);
220 pnp_free_port(option->port);
221 pnp_free_irq(option->irq);
222 pnp_free_dma(option->dma);
223 pnp_free_mem(option->mem);
224 kfree(option); 147 kfree(option);
225 option = next;
226 } 148 }
227} 149}
228 150
@@ -237,7 +159,7 @@ void pnp_free_option(struct pnp_option *option)
237 !((*(enda) < *(startb)) || (*(endb) < *(starta))) 159 !((*(enda) < *(startb)) || (*(endb) < *(starta)))
238 160
239#define cannot_compare(flags) \ 161#define cannot_compare(flags) \
240((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) 162((flags) & IORESOURCE_DISABLED)
241 163
242int pnp_check_port(struct pnp_dev *dev, struct resource *res) 164int pnp_check_port(struct pnp_dev *dev, struct resource *res)
243{ 165{
@@ -364,6 +286,61 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id)
364 return IRQ_HANDLED; 286 return IRQ_HANDLED;
365} 287}
366 288
289#ifdef CONFIG_PCI
290static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
291 unsigned int irq)
292{
293 u32 class;
294 u8 progif;
295
296 if (pci->irq == irq) {
297 dev_dbg(&pnp->dev, "device %s using irq %d\n",
298 pci_name(pci), irq);
299 return 1;
300 }
301
302 /*
303 * See pci_setup_device() and ata_pci_sff_activate_host() for
304 * similar IDE legacy detection.
305 */
306 pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
307 class >>= 8; /* discard revision ID */
308 progif = class & 0xff;
309 class >>= 8;
310
311 if (class == PCI_CLASS_STORAGE_IDE) {
312 /*
313 * Unless both channels are native-PCI mode only,
314 * treat the compatibility IRQs as busy.
315 */
316 if ((progif & 0x5) != 0x5)
317 if (pci_get_legacy_ide_irq(pci, 0) == irq ||
318 pci_get_legacy_ide_irq(pci, 1) == irq) {
319 dev_dbg(&pnp->dev, "legacy IDE device %s "
320 "using irq %d\n", pci_name(pci), irq);
321 return 1;
322 }
323 }
324
325 return 0;
326}
327#endif
328
329static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
330{
331#ifdef CONFIG_PCI
332 struct pci_dev *pci = NULL;
333
334 for_each_pci_dev(pci) {
335 if (pci_dev_uses_irq(pnp, pci, irq)) {
336 pci_dev_put(pci);
337 return 1;
338 }
339 }
340#endif
341 return 0;
342}
343
367int pnp_check_irq(struct pnp_dev *dev, struct resource *res) 344int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
368{ 345{
369 int i; 346 int i;
@@ -395,18 +372,9 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
395 } 372 }
396 } 373 }
397 374
398#ifdef CONFIG_PCI
399 /* check if the resource is being used by a pci device */ 375 /* check if the resource is being used by a pci device */
400 { 376 if (pci_uses_irq(dev, *irq))
401 struct pci_dev *pci = NULL; 377 return 0;
402 for_each_pci_dev(pci) {
403 if (pci->irq == *irq) {
404 pci_dev_put(pci);
405 return 0;
406 }
407 }
408 }
409#endif
410 378
411 /* check if the resource is already in use, skip if the 379 /* check if the resource is already in use, skip if the
412 * device is active because it itself may be in use */ 380 * device is active because it itself may be in use */
@@ -499,81 +467,37 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
499#endif 467#endif
500} 468}
501 469
502struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev, 470int pnp_resource_type(struct resource *res)
503 unsigned int type, unsigned int num)
504{ 471{
505 struct pnp_resource_table *res = dev->res; 472 return res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
506 473 IORESOURCE_IRQ | IORESOURCE_DMA);
507 switch (type) {
508 case IORESOURCE_IO:
509 if (num >= PNP_MAX_PORT)
510 return NULL;
511 return &res->port[num];
512 case IORESOURCE_MEM:
513 if (num >= PNP_MAX_MEM)
514 return NULL;
515 return &res->mem[num];
516 case IORESOURCE_IRQ:
517 if (num >= PNP_MAX_IRQ)
518 return NULL;
519 return &res->irq[num];
520 case IORESOURCE_DMA:
521 if (num >= PNP_MAX_DMA)
522 return NULL;
523 return &res->dma[num];
524 }
525 return NULL;
526} 474}
527 475
528struct resource *pnp_get_resource(struct pnp_dev *dev, 476struct resource *pnp_get_resource(struct pnp_dev *dev,
529 unsigned int type, unsigned int num) 477 unsigned int type, unsigned int num)
530{ 478{
531 struct pnp_resource *pnp_res; 479 struct pnp_resource *pnp_res;
480 struct resource *res;
532 481
533 pnp_res = pnp_get_pnp_resource(dev, type, num); 482 list_for_each_entry(pnp_res, &dev->resources, list) {
534 if (pnp_res) 483 res = &pnp_res->res;
535 return &pnp_res->res; 484 if (pnp_resource_type(res) == type && num-- == 0)
536 485 return res;
486 }
537 return NULL; 487 return NULL;
538} 488}
539EXPORT_SYMBOL(pnp_get_resource); 489EXPORT_SYMBOL(pnp_get_resource);
540 490
541static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type) 491static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
542{ 492{
543 struct pnp_resource *pnp_res; 493 struct pnp_resource *pnp_res;
544 int i;
545 494
546 switch (type) { 495 pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
547 case IORESOURCE_IO: 496 if (!pnp_res)
548 for (i = 0; i < PNP_MAX_PORT; i++) { 497 return NULL;
549 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i); 498
550 if (pnp_res && !pnp_resource_valid(&pnp_res->res)) 499 list_add_tail(&pnp_res->list, &dev->resources);
551 return pnp_res; 500 return pnp_res;
552 }
553 break;
554 case IORESOURCE_MEM:
555 for (i = 0; i < PNP_MAX_MEM; i++) {
556 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i);
557 if (pnp_res && !pnp_resource_valid(&pnp_res->res))
558 return pnp_res;
559 }
560 break;
561 case IORESOURCE_IRQ:
562 for (i = 0; i < PNP_MAX_IRQ; i++) {
563 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i);
564 if (pnp_res && !pnp_resource_valid(&pnp_res->res))
565 return pnp_res;
566 }
567 break;
568 case IORESOURCE_DMA:
569 for (i = 0; i < PNP_MAX_DMA; i++) {
570 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i);
571 if (pnp_res && !pnp_resource_valid(&pnp_res->res))
572 return pnp_res;
573 }
574 break;
575 }
576 return NULL;
577} 501}
578 502
579struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, 503struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
@@ -581,15 +505,10 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
581{ 505{
582 struct pnp_resource *pnp_res; 506 struct pnp_resource *pnp_res;
583 struct resource *res; 507 struct resource *res;
584 static unsigned char warned;
585 508
586 pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ); 509 pnp_res = pnp_new_resource(dev);
587 if (!pnp_res) { 510 if (!pnp_res) {
588 if (!warned) { 511 dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq);
589 dev_err(&dev->dev, "can't add resource for IRQ %d\n",
590 irq);
591 warned = 1;
592 }
593 return NULL; 512 return NULL;
594 } 513 }
595 514
@@ -607,15 +526,10 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
607{ 526{
608 struct pnp_resource *pnp_res; 527 struct pnp_resource *pnp_res;
609 struct resource *res; 528 struct resource *res;
610 static unsigned char warned;
611 529
612 pnp_res = pnp_new_resource(dev, IORESOURCE_DMA); 530 pnp_res = pnp_new_resource(dev);
613 if (!pnp_res) { 531 if (!pnp_res) {
614 if (!warned) { 532 dev_err(&dev->dev, "can't add resource for DMA %d\n", dma);
615 dev_err(&dev->dev, "can't add resource for DMA %d\n",
616 dma);
617 warned = 1;
618 }
619 return NULL; 533 return NULL;
620 } 534 }
621 535
@@ -634,16 +548,12 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
634{ 548{
635 struct pnp_resource *pnp_res; 549 struct pnp_resource *pnp_res;
636 struct resource *res; 550 struct resource *res;
637 static unsigned char warned;
638 551
639 pnp_res = pnp_new_resource(dev, IORESOURCE_IO); 552 pnp_res = pnp_new_resource(dev);
640 if (!pnp_res) { 553 if (!pnp_res) {
641 if (!warned) { 554 dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n",
642 dev_err(&dev->dev, "can't add resource for IO " 555 (unsigned long long) start,
643 "%#llx-%#llx\n",(unsigned long long) start, 556 (unsigned long long) end);
644 (unsigned long long) end);
645 warned = 1;
646 }
647 return NULL; 557 return NULL;
648 } 558 }
649 559
@@ -663,16 +573,12 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
663{ 573{
664 struct pnp_resource *pnp_res; 574 struct pnp_resource *pnp_res;
665 struct resource *res; 575 struct resource *res;
666 static unsigned char warned;
667 576
668 pnp_res = pnp_new_resource(dev, IORESOURCE_MEM); 577 pnp_res = pnp_new_resource(dev);
669 if (!pnp_res) { 578 if (!pnp_res) {
670 if (!warned) { 579 dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n",
671 dev_err(&dev->dev, "can't add resource for MEM " 580 (unsigned long long) start,
672 "%#llx-%#llx\n",(unsigned long long) start, 581 (unsigned long long) end);
673 (unsigned long long) end);
674 warned = 1;
675 }
676 return NULL; 582 return NULL;
677 } 583 }
678 584
@@ -686,6 +592,52 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
686 return pnp_res; 592 return pnp_res;
687} 593}
688 594
595/*
596 * Determine whether the specified resource is a possible configuration
597 * for this device.
598 */
599int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
600 resource_size_t size)
601{
602 struct pnp_option *option;
603 struct pnp_port *port;
604 struct pnp_mem *mem;
605 struct pnp_irq *irq;
606 struct pnp_dma *dma;
607
608 list_for_each_entry(option, &dev->options, list) {
609 if (option->type != type)
610 continue;
611
612 switch (option->type) {
613 case IORESOURCE_IO:
614 port = &option->u.port;
615 if (port->min == start && port->size == size)
616 return 1;
617 break;
618 case IORESOURCE_MEM:
619 mem = &option->u.mem;
620 if (mem->min == start && mem->size == size)
621 return 1;
622 break;
623 case IORESOURCE_IRQ:
624 irq = &option->u.irq;
625 if (start < PNP_IRQ_NR &&
626 test_bit(start, irq->map.bits))
627 return 1;
628 break;
629 case IORESOURCE_DMA:
630 dma = &option->u.dma;
631 if (dma->map & (1 << start))
632 return 1;
633 break;
634 }
635 }
636
637 return 0;
638}
639EXPORT_SYMBOL(pnp_possible_config);
640
689/* format is: pnp_reserve_irq=irq1[,irq2] .... */ 641/* format is: pnp_reserve_irq=irq1[,irq2] .... */
690static int __init pnp_setup_reserve_irq(char *str) 642static int __init pnp_setup_reserve_irq(char *str)
691{ 643{