]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/pnp/resource.c
PNP: convert resource options to single linked list
[linux-2.6-omap-h63xx.git] / drivers / pnp / resource.c
1 /*
2  * resource.c - Contains functions for registering and analyzing resource information
3  *
4  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
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>
8  */
9
10 #include <linux/module.h>
11 #include <linux/errno.h>
12 #include <linux/interrupt.h>
13 #include <linux/kernel.h>
14 #include <asm/io.h>
15 #include <asm/dma.h>
16 #include <asm/irq.h>
17 #include <linux/pci.h>
18 #include <linux/ioport.h>
19 #include <linux/init.h>
20
21 #include <linux/pnp.h>
22 #include "base.h"
23
24 static int pnp_reserve_irq[16] = {[0 ... 15] = -1 };    /* reserve (don't use) some IRQ */
25 static int pnp_reserve_dma[8] = {[0 ... 7] = -1 };      /* reserve (don't use) some DMA */
26 static int pnp_reserve_io[16] = {[0 ... 15] = -1 };     /* reserve (don't use) some I/O region */
27 static int pnp_reserve_mem[16] = {[0 ... 15] = -1 };    /* reserve (don't use) some memory region */
28
29 /*
30  * option registration
31  */
32
33 struct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type,
34                                     unsigned int option_flags)
35 {
36         struct pnp_option *option;
37
38         option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL);
39         if (!option)
40                 return NULL;
41
42         option->flags = option_flags;
43         option->type = type;
44
45         list_add_tail(&option->list, &dev->options);
46         return option;
47 }
48
49 int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
50                               pnp_irq_mask_t *map, unsigned char flags)
51 {
52         struct pnp_option *option;
53         struct pnp_irq *irq;
54
55         option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
56         if (!option)
57                 return -ENOMEM;
58
59         irq = &option->u.irq;
60         irq->map = *map;
61         irq->flags = flags;
62
63 #ifdef CONFIG_PCI
64         {
65                 int i;
66
67                 for (i = 0; i < 16; i++)
68                         if (test_bit(i, irq->map.bits))
69                                 pcibios_penalize_isa_irq(i, 0);
70         }
71 #endif
72
73         dbg_pnp_show_option(dev, option);
74         return 0;
75 }
76
77 int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
78                               unsigned char map, unsigned char flags)
79 {
80         struct pnp_option *option;
81         struct pnp_dma *dma;
82
83         option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
84         if (!option)
85                 return -ENOMEM;
86
87         dma = &option->u.dma;
88         dma->map = map;
89         dma->flags = flags;
90
91         dbg_pnp_show_option(dev, option);
92         return 0;
93 }
94
95 int 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)
99 {
100         struct pnp_option *option;
101         struct pnp_port *port;
102
103         option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
104         if (!option)
105                 return -ENOMEM;
106
107         port = &option->u.port;
108         port->min = min;
109         port->max = max;
110         port->align = align;
111         port->size = size;
112         port->flags = flags;
113
114         dbg_pnp_show_option(dev, option);
115         return 0;
116 }
117
118 int 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)
122 {
123         struct pnp_option *option;
124         struct pnp_mem *mem;
125
126         option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
127         if (!option)
128                 return -ENOMEM;
129
130         mem = &option->u.mem;
131         mem->min = min;
132         mem->max = max;
133         mem->align = align;
134         mem->size = size;
135         mem->flags = flags;
136
137         dbg_pnp_show_option(dev, option);
138         return 0;
139 }
140
141 void pnp_free_options(struct pnp_dev *dev)
142 {
143         struct pnp_option *option, *tmp;
144
145         list_for_each_entry_safe(option, tmp, &dev->options, list) {
146                 list_del(&option->list);
147                 kfree(option);
148         }
149 }
150
151 /*
152  * resource validity checking
153  */
154
155 #define length(start, end) (*(end) - *(start) + 1)
156
157 /* Two ranges conflict if one doesn't end before the other starts */
158 #define ranged_conflict(starta, enda, startb, endb) \
159         !((*(enda) < *(startb)) || (*(endb) < *(starta)))
160
161 #define cannot_compare(flags) \
162 ((flags) & IORESOURCE_DISABLED)
163
164 int pnp_check_port(struct pnp_dev *dev, struct resource *res)
165 {
166         int i;
167         struct pnp_dev *tdev;
168         struct resource *tres;
169         resource_size_t *port, *end, *tport, *tend;
170
171         port = &res->start;
172         end = &res->end;
173
174         /* if the resource doesn't exist, don't complain about it */
175         if (cannot_compare(res->flags))
176                 return 1;
177
178         /* check if the resource is already in use, skip if the
179          * device is active because it itself may be in use */
180         if (!dev->active) {
181                 if (__check_region(&ioport_resource, *port, length(port, end)))
182                         return 0;
183         }
184
185         /* check if the resource is reserved */
186         for (i = 0; i < 8; i++) {
187                 int rport = pnp_reserve_io[i << 1];
188                 int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1;
189                 if (ranged_conflict(port, end, &rport, &rend))
190                         return 0;
191         }
192
193         /* check for internal conflicts */
194         for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
195                 if (tres != res && tres->flags & IORESOURCE_IO) {
196                         tport = &tres->start;
197                         tend = &tres->end;
198                         if (ranged_conflict(port, end, tport, tend))
199                                 return 0;
200                 }
201         }
202
203         /* check for conflicts with other pnp devices */
204         pnp_for_each_dev(tdev) {
205                 if (tdev == dev)
206                         continue;
207                 for (i = 0;
208                      (tres = pnp_get_resource(tdev, IORESOURCE_IO, i));
209                      i++) {
210                         if (tres->flags & IORESOURCE_IO) {
211                                 if (cannot_compare(tres->flags))
212                                         continue;
213                                 tport = &tres->start;
214                                 tend = &tres->end;
215                                 if (ranged_conflict(port, end, tport, tend))
216                                         return 0;
217                         }
218                 }
219         }
220
221         return 1;
222 }
223
224 int pnp_check_mem(struct pnp_dev *dev, struct resource *res)
225 {
226         int i;
227         struct pnp_dev *tdev;
228         struct resource *tres;
229         resource_size_t *addr, *end, *taddr, *tend;
230
231         addr = &res->start;
232         end = &res->end;
233
234         /* if the resource doesn't exist, don't complain about it */
235         if (cannot_compare(res->flags))
236                 return 1;
237
238         /* check if the resource is already in use, skip if the
239          * device is active because it itself may be in use */
240         if (!dev->active) {
241                 if (check_mem_region(*addr, length(addr, end)))
242                         return 0;
243         }
244
245         /* check if the resource is reserved */
246         for (i = 0; i < 8; i++) {
247                 int raddr = pnp_reserve_mem[i << 1];
248                 int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1;
249                 if (ranged_conflict(addr, end, &raddr, &rend))
250                         return 0;
251         }
252
253         /* check for internal conflicts */
254         for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
255                 if (tres != res && tres->flags & IORESOURCE_MEM) {
256                         taddr = &tres->start;
257                         tend = &tres->end;
258                         if (ranged_conflict(addr, end, taddr, tend))
259                                 return 0;
260                 }
261         }
262
263         /* check for conflicts with other pnp devices */
264         pnp_for_each_dev(tdev) {
265                 if (tdev == dev)
266                         continue;
267                 for (i = 0;
268                      (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i));
269                      i++) {
270                         if (tres->flags & IORESOURCE_MEM) {
271                                 if (cannot_compare(tres->flags))
272                                         continue;
273                                 taddr = &tres->start;
274                                 tend = &tres->end;
275                                 if (ranged_conflict(addr, end, taddr, tend))
276                                         return 0;
277                         }
278                 }
279         }
280
281         return 1;
282 }
283
284 static irqreturn_t pnp_test_handler(int irq, void *dev_id)
285 {
286         return IRQ_HANDLED;
287 }
288
289 int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
290 {
291         int i;
292         struct pnp_dev *tdev;
293         struct resource *tres;
294         resource_size_t *irq;
295
296         irq = &res->start;
297
298         /* if the resource doesn't exist, don't complain about it */
299         if (cannot_compare(res->flags))
300                 return 1;
301
302         /* check if the resource is valid */
303         if (*irq < 0 || *irq > 15)
304                 return 0;
305
306         /* check if the resource is reserved */
307         for (i = 0; i < 16; i++) {
308                 if (pnp_reserve_irq[i] == *irq)
309                         return 0;
310         }
311
312         /* check for internal conflicts */
313         for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
314                 if (tres != res && tres->flags & IORESOURCE_IRQ) {
315                         if (tres->start == *irq)
316                                 return 0;
317                 }
318         }
319
320 #ifdef CONFIG_PCI
321         /* check if the resource is being used by a pci device */
322         {
323                 struct pci_dev *pci = NULL;
324                 for_each_pci_dev(pci) {
325                         if (pci->irq == *irq) {
326                                 pci_dev_put(pci);
327                                 return 0;
328                         }
329                 }
330         }
331 #endif
332
333         /* check if the resource is already in use, skip if the
334          * device is active because it itself may be in use */
335         if (!dev->active) {
336                 if (request_irq(*irq, pnp_test_handler,
337                                 IRQF_DISABLED | IRQF_PROBE_SHARED, "pnp", NULL))
338                         return 0;
339                 free_irq(*irq, NULL);
340         }
341
342         /* check for conflicts with other pnp devices */
343         pnp_for_each_dev(tdev) {
344                 if (tdev == dev)
345                         continue;
346                 for (i = 0;
347                      (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i));
348                      i++) {
349                         if (tres->flags & IORESOURCE_IRQ) {
350                                 if (cannot_compare(tres->flags))
351                                         continue;
352                                 if (tres->start == *irq)
353                                         return 0;
354                         }
355                 }
356         }
357
358         return 1;
359 }
360
361 int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
362 {
363 #ifndef CONFIG_IA64
364         int i;
365         struct pnp_dev *tdev;
366         struct resource *tres;
367         resource_size_t *dma;
368
369         dma = &res->start;
370
371         /* if the resource doesn't exist, don't complain about it */
372         if (cannot_compare(res->flags))
373                 return 1;
374
375         /* check if the resource is valid */
376         if (*dma < 0 || *dma == 4 || *dma > 7)
377                 return 0;
378
379         /* check if the resource is reserved */
380         for (i = 0; i < 8; i++) {
381                 if (pnp_reserve_dma[i] == *dma)
382                         return 0;
383         }
384
385         /* check for internal conflicts */
386         for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
387                 if (tres != res && tres->flags & IORESOURCE_DMA) {
388                         if (tres->start == *dma)
389                                 return 0;
390                 }
391         }
392
393         /* check if the resource is already in use, skip if the
394          * device is active because it itself may be in use */
395         if (!dev->active) {
396                 if (request_dma(*dma, "pnp"))
397                         return 0;
398                 free_dma(*dma);
399         }
400
401         /* check for conflicts with other pnp devices */
402         pnp_for_each_dev(tdev) {
403                 if (tdev == dev)
404                         continue;
405                 for (i = 0;
406                      (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i));
407                      i++) {
408                         if (tres->flags & IORESOURCE_DMA) {
409                                 if (cannot_compare(tres->flags))
410                                         continue;
411                                 if (tres->start == *dma)
412                                         return 0;
413                         }
414                 }
415         }
416
417         return 1;
418 #else
419         /* IA64 does not have legacy DMA */
420         return 0;
421 #endif
422 }
423
424 int pnp_resource_type(struct resource *res)
425 {
426         return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
427                              IORESOURCE_IRQ | IORESOURCE_DMA);
428 }
429
430 struct resource *pnp_get_resource(struct pnp_dev *dev,
431                                   unsigned int type, unsigned int num)
432 {
433         struct pnp_resource *pnp_res;
434         struct resource *res;
435
436         list_for_each_entry(pnp_res, &dev->resources, list) {
437                 res = &pnp_res->res;
438                 if (pnp_resource_type(res) == type && num-- == 0)
439                         return res;
440         }
441         return NULL;
442 }
443 EXPORT_SYMBOL(pnp_get_resource);
444
445 static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
446 {
447         struct pnp_resource *pnp_res;
448
449         pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
450         if (!pnp_res)
451                 return NULL;
452
453         list_add_tail(&pnp_res->list, &dev->resources);
454         return pnp_res;
455 }
456
457 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
458                                           int flags)
459 {
460         struct pnp_resource *pnp_res;
461         struct resource *res;
462
463         pnp_res = pnp_new_resource(dev);
464         if (!pnp_res) {
465                 dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq);
466                 return NULL;
467         }
468
469         res = &pnp_res->res;
470         res->flags = IORESOURCE_IRQ | flags;
471         res->start = irq;
472         res->end = irq;
473
474         dev_dbg(&dev->dev, "  add irq %d flags %#x\n", irq, flags);
475         return pnp_res;
476 }
477
478 struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
479                                           int flags)
480 {
481         struct pnp_resource *pnp_res;
482         struct resource *res;
483
484         pnp_res = pnp_new_resource(dev);
485         if (!pnp_res) {
486                 dev_err(&dev->dev, "can't add resource for DMA %d\n", dma);
487                 return NULL;
488         }
489
490         res = &pnp_res->res;
491         res->flags = IORESOURCE_DMA | flags;
492         res->start = dma;
493         res->end = dma;
494
495         dev_dbg(&dev->dev, "  add dma %d flags %#x\n", dma, flags);
496         return pnp_res;
497 }
498
499 struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
500                                          resource_size_t start,
501                                          resource_size_t end, int flags)
502 {
503         struct pnp_resource *pnp_res;
504         struct resource *res;
505
506         pnp_res = pnp_new_resource(dev);
507         if (!pnp_res) {
508                 dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n",
509                         (unsigned long long) start,
510                         (unsigned long long) end);
511                 return NULL;
512         }
513
514         res = &pnp_res->res;
515         res->flags = IORESOURCE_IO | flags;
516         res->start = start;
517         res->end = end;
518
519         dev_dbg(&dev->dev, "  add io  %#llx-%#llx flags %#x\n",
520                 (unsigned long long) start, (unsigned long long) end, flags);
521         return pnp_res;
522 }
523
524 struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
525                                           resource_size_t start,
526                                           resource_size_t end, int flags)
527 {
528         struct pnp_resource *pnp_res;
529         struct resource *res;
530
531         pnp_res = pnp_new_resource(dev);
532         if (!pnp_res) {
533                 dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n",
534                         (unsigned long long) start,
535                         (unsigned long long) end);
536                 return NULL;
537         }
538
539         res = &pnp_res->res;
540         res->flags = IORESOURCE_MEM | flags;
541         res->start = start;
542         res->end = end;
543
544         dev_dbg(&dev->dev, "  add mem %#llx-%#llx flags %#x\n",
545                 (unsigned long long) start, (unsigned long long) end, flags);
546         return pnp_res;
547 }
548
549 /*
550  * Determine whether the specified resource is a possible configuration
551  * for this device.
552  */
553 int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
554                         resource_size_t size)
555 {
556         struct pnp_option *option;
557         struct pnp_port *port;
558         struct pnp_mem *mem;
559         struct pnp_irq *irq;
560         struct pnp_dma *dma;
561
562         list_for_each_entry(option, &dev->options, list) {
563                 if (option->type != type)
564                         continue;
565
566                 switch (option->type) {
567                 case IORESOURCE_IO:
568                         port = &option->u.port;
569                         if (port->min == start && port->size == size)
570                                 return 1;
571                         break;
572                 case IORESOURCE_MEM:
573                         mem = &option->u.mem;
574                         if (mem->min == start && mem->size == size)
575                                 return 1;
576                         break;
577                 case IORESOURCE_IRQ:
578                         irq = &option->u.irq;
579                         if (start < PNP_IRQ_NR &&
580                             test_bit(start, irq->map.bits))
581                                 return 1;
582                         break;
583                 case IORESOURCE_DMA:
584                         dma = &option->u.dma;
585                         if (dma->map & (1 << start))
586                                 return 1;
587                         break;
588                 }
589         }
590
591         return 0;
592 }
593 EXPORT_SYMBOL(pnp_possible_config);
594
595 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
596 static int __init pnp_setup_reserve_irq(char *str)
597 {
598         int i;
599
600         for (i = 0; i < 16; i++)
601                 if (get_option(&str, &pnp_reserve_irq[i]) != 2)
602                         break;
603         return 1;
604 }
605
606 __setup("pnp_reserve_irq=", pnp_setup_reserve_irq);
607
608 /* format is: pnp_reserve_dma=dma1[,dma2] .... */
609 static int __init pnp_setup_reserve_dma(char *str)
610 {
611         int i;
612
613         for (i = 0; i < 8; i++)
614                 if (get_option(&str, &pnp_reserve_dma[i]) != 2)
615                         break;
616         return 1;
617 }
618
619 __setup("pnp_reserve_dma=", pnp_setup_reserve_dma);
620
621 /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
622 static int __init pnp_setup_reserve_io(char *str)
623 {
624         int i;
625
626         for (i = 0; i < 16; i++)
627                 if (get_option(&str, &pnp_reserve_io[i]) != 2)
628                         break;
629         return 1;
630 }
631
632 __setup("pnp_reserve_io=", pnp_setup_reserve_io);
633
634 /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
635 static int __init pnp_setup_reserve_mem(char *str)
636 {
637         int i;
638
639         for (i = 0; i < 16; i++)
640                 if (get_option(&str, &pnp_reserve_mem[i]) != 2)
641                         break;
642         return 1;
643 }
644
645 __setup("pnp_reserve_mem=", pnp_setup_reserve_mem);