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.c268
1 files changed, 65 insertions, 203 deletions
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] .... */