1 // SPDX-License-Identifier: GPL-2.0
3 * resource.c - Contains functions for registering and analyzing resource information
5 * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
6 * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
7 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
8 * Bjorn Helgaas <bjorn.helgaas@hp.com>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/errno.h>
14 #include <linux/interrupt.h>
15 #include <linux/kernel.h>
19 #include <linux/pci.h>
20 #include <linux/ioport.h>
21 #include <linux/init.h>
23 #include <linux/pnp.h>
26 static int pnp_reserve_irq
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
27 static int pnp_reserve_dma
[8] = {[0 ... 7] = -1 }; /* reserve (don't use) some DMA */
28 static int pnp_reserve_io
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some I/O region */
29 static int pnp_reserve_mem
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some memory region */
35 static struct pnp_option
*pnp_build_option(struct pnp_dev
*dev
, unsigned long type
,
36 unsigned int option_flags
)
38 struct pnp_option
*option
;
40 option
= kzalloc(sizeof(struct pnp_option
), GFP_KERNEL
);
44 option
->flags
= option_flags
;
47 list_add_tail(&option
->list
, &dev
->options
);
51 int pnp_register_irq_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
52 pnp_irq_mask_t
*map
, unsigned char flags
)
54 struct pnp_option
*option
;
57 option
= pnp_build_option(dev
, IORESOURCE_IRQ
, option_flags
);
69 for (i
= 0; i
< 16; i
++)
70 if (test_bit(i
, irq
->map
.bits
))
71 pcibios_penalize_isa_irq(i
, 0);
75 dbg_pnp_show_option(dev
, option
);
79 int pnp_register_dma_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
80 unsigned char map
, unsigned char flags
)
82 struct pnp_option
*option
;
85 option
= pnp_build_option(dev
, IORESOURCE_DMA
, option_flags
);
93 dbg_pnp_show_option(dev
, option
);
97 int pnp_register_port_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
98 resource_size_t min
, resource_size_t max
,
99 resource_size_t align
, resource_size_t size
,
102 struct pnp_option
*option
;
103 struct pnp_port
*port
;
105 option
= pnp_build_option(dev
, IORESOURCE_IO
, option_flags
);
109 port
= &option
->u
.port
;
116 dbg_pnp_show_option(dev
, option
);
120 int pnp_register_mem_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
121 resource_size_t min
, resource_size_t max
,
122 resource_size_t align
, resource_size_t size
,
125 struct pnp_option
*option
;
128 option
= pnp_build_option(dev
, IORESOURCE_MEM
, option_flags
);
132 mem
= &option
->u
.mem
;
139 dbg_pnp_show_option(dev
, option
);
143 void pnp_free_options(struct pnp_dev
*dev
)
145 struct pnp_option
*option
, *tmp
;
147 list_for_each_entry_safe(option
, tmp
, &dev
->options
, list
) {
148 list_del(&option
->list
);
154 * resource validity checking
157 #define length(start, end) (*(end) - *(start) + 1)
159 /* Two ranges conflict if one doesn't end before the other starts */
160 #define ranged_conflict(starta, enda, startb, endb) \
161 !((*(enda) < *(startb)) || (*(endb) < *(starta)))
163 #define cannot_compare(flags) \
164 ((flags) & IORESOURCE_DISABLED)
166 int pnp_check_port(struct pnp_dev
*dev
, struct resource
*res
)
169 struct pnp_dev
*tdev
;
170 struct resource
*tres
;
171 resource_size_t
*port
, *end
, *tport
, *tend
;
176 /* if the resource doesn't exist, don't complain about it */
177 if (cannot_compare(res
->flags
))
180 /* check if the resource is already in use, skip if the
181 * device is active because it itself may be in use */
183 if (!request_region(*port
, length(port
, end
), "pnp"))
185 release_region(*port
, length(port
, end
));
188 /* check if the resource is reserved */
189 for (i
= 0; i
< 8; i
++) {
190 int rport
= pnp_reserve_io
[i
<< 1];
191 int rend
= pnp_reserve_io
[(i
<< 1) + 1] + rport
- 1;
192 if (ranged_conflict(port
, end
, &rport
, &rend
))
196 /* check for internal conflicts */
197 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_IO
, i
)); i
++) {
198 if (tres
!= res
&& tres
->flags
& IORESOURCE_IO
) {
199 tport
= &tres
->start
;
201 if (ranged_conflict(port
, end
, tport
, tend
))
206 /* check for conflicts with other pnp devices */
207 pnp_for_each_dev(tdev
) {
211 (tres
= pnp_get_resource(tdev
, IORESOURCE_IO
, i
));
213 if (tres
->flags
& IORESOURCE_IO
) {
214 if (cannot_compare(tres
->flags
))
216 if (tres
->flags
& IORESOURCE_WINDOW
)
218 tport
= &tres
->start
;
220 if (ranged_conflict(port
, end
, tport
, tend
))
229 int pnp_check_mem(struct pnp_dev
*dev
, struct resource
*res
)
232 struct pnp_dev
*tdev
;
233 struct resource
*tres
;
234 resource_size_t
*addr
, *end
, *taddr
, *tend
;
239 /* if the resource doesn't exist, don't complain about it */
240 if (cannot_compare(res
->flags
))
243 /* check if the resource is already in use, skip if the
244 * device is active because it itself may be in use */
246 if (!request_mem_region(*addr
, length(addr
, end
), "pnp"))
248 release_mem_region(*addr
, length(addr
, end
));
251 /* check if the resource is reserved */
252 for (i
= 0; i
< 8; i
++) {
253 int raddr
= pnp_reserve_mem
[i
<< 1];
254 int rend
= pnp_reserve_mem
[(i
<< 1) + 1] + raddr
- 1;
255 if (ranged_conflict(addr
, end
, &raddr
, &rend
))
259 /* check for internal conflicts */
260 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_MEM
, i
)); i
++) {
261 if (tres
!= res
&& tres
->flags
& IORESOURCE_MEM
) {
262 taddr
= &tres
->start
;
264 if (ranged_conflict(addr
, end
, taddr
, tend
))
269 /* check for conflicts with other pnp devices */
270 pnp_for_each_dev(tdev
) {
274 (tres
= pnp_get_resource(tdev
, IORESOURCE_MEM
, i
));
276 if (tres
->flags
& IORESOURCE_MEM
) {
277 if (cannot_compare(tres
->flags
))
279 if (tres
->flags
& IORESOURCE_WINDOW
)
281 taddr
= &tres
->start
;
283 if (ranged_conflict(addr
, end
, taddr
, tend
))
292 static irqreturn_t
pnp_test_handler(int irq
, void *dev_id
)
298 static int pci_dev_uses_irq(struct pnp_dev
*pnp
, struct pci_dev
*pci
,
304 if (pci
->irq
== irq
) {
305 pnp_dbg(&pnp
->dev
, " device %s using irq %d\n",
311 * See pci_setup_device() and ata_pci_sff_activate_host() for
312 * similar IDE legacy detection.
314 pci_read_config_dword(pci
, PCI_CLASS_REVISION
, &class);
315 class >>= 8; /* discard revision ID */
316 progif
= class & 0xff;
319 if (class == PCI_CLASS_STORAGE_IDE
) {
321 * Unless both channels are native-PCI mode only,
322 * treat the compatibility IRQs as busy.
324 if ((progif
& 0x5) != 0x5)
325 if (pci_get_legacy_ide_irq(pci
, 0) == irq
||
326 pci_get_legacy_ide_irq(pci
, 1) == irq
) {
327 pnp_dbg(&pnp
->dev
, " legacy IDE device %s "
328 "using irq %d\n", pci_name(pci
), irq
);
337 static int pci_uses_irq(struct pnp_dev
*pnp
, unsigned int irq
)
340 struct pci_dev
*pci
= NULL
;
342 for_each_pci_dev(pci
) {
343 if (pci_dev_uses_irq(pnp
, pci
, irq
)) {
352 int pnp_check_irq(struct pnp_dev
*dev
, struct resource
*res
)
355 struct pnp_dev
*tdev
;
356 struct resource
*tres
;
357 resource_size_t
*irq
;
361 /* if the resource doesn't exist, don't complain about it */
362 if (cannot_compare(res
->flags
))
365 /* check if the resource is valid */
369 /* check if the resource is reserved */
370 for (i
= 0; i
< 16; i
++) {
371 if (pnp_reserve_irq
[i
] == *irq
)
375 /* check for internal conflicts */
376 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_IRQ
, i
)); i
++) {
377 if (tres
!= res
&& tres
->flags
& IORESOURCE_IRQ
) {
378 if (tres
->start
== *irq
)
383 /* check if the resource is being used by a pci device */
384 if (pci_uses_irq(dev
, *irq
))
387 /* check if the resource is already in use, skip if the
388 * device is active because it itself may be in use */
390 if (request_irq(*irq
, pnp_test_handler
,
391 IRQF_PROBE_SHARED
, "pnp", NULL
))
393 free_irq(*irq
, NULL
);
396 /* check for conflicts with other pnp devices */
397 pnp_for_each_dev(tdev
) {
401 (tres
= pnp_get_resource(tdev
, IORESOURCE_IRQ
, i
));
403 if (tres
->flags
& IORESOURCE_IRQ
) {
404 if (cannot_compare(tres
->flags
))
406 if (tres
->start
== *irq
)
415 #ifdef CONFIG_ISA_DMA_API
416 int pnp_check_dma(struct pnp_dev
*dev
, struct resource
*res
)
419 struct pnp_dev
*tdev
;
420 struct resource
*tres
;
421 resource_size_t
*dma
;
425 /* if the resource doesn't exist, don't complain about it */
426 if (cannot_compare(res
->flags
))
429 /* check if the resource is valid */
430 if (*dma
== 4 || *dma
> 7)
433 /* check if the resource is reserved */
434 for (i
= 0; i
< 8; i
++) {
435 if (pnp_reserve_dma
[i
] == *dma
)
439 /* check for internal conflicts */
440 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_DMA
, i
)); i
++) {
441 if (tres
!= res
&& tres
->flags
& IORESOURCE_DMA
) {
442 if (tres
->start
== *dma
)
447 /* check if the resource is already in use, skip if the
448 * device is active because it itself may be in use */
450 if (request_dma(*dma
, "pnp"))
455 /* check for conflicts with other pnp devices */
456 pnp_for_each_dev(tdev
) {
460 (tres
= pnp_get_resource(tdev
, IORESOURCE_DMA
, i
));
462 if (tres
->flags
& IORESOURCE_DMA
) {
463 if (cannot_compare(tres
->flags
))
465 if (tres
->start
== *dma
)
473 #endif /* CONFIG_ISA_DMA_API */
475 unsigned long pnp_resource_type(struct resource
*res
)
477 return res
->flags
& (IORESOURCE_IO
| IORESOURCE_MEM
|
478 IORESOURCE_IRQ
| IORESOURCE_DMA
|
482 struct resource
*pnp_get_resource(struct pnp_dev
*dev
,
483 unsigned long type
, unsigned int num
)
485 struct pnp_resource
*pnp_res
;
486 struct resource
*res
;
488 list_for_each_entry(pnp_res
, &dev
->resources
, list
) {
490 if (pnp_resource_type(res
) == type
&& num
-- == 0)
495 EXPORT_SYMBOL(pnp_get_resource
);
497 static struct pnp_resource
*pnp_new_resource(struct pnp_dev
*dev
)
499 struct pnp_resource
*pnp_res
;
501 pnp_res
= kzalloc(sizeof(struct pnp_resource
), GFP_KERNEL
);
505 list_add_tail(&pnp_res
->list
, &dev
->resources
);
509 struct pnp_resource
*pnp_add_resource(struct pnp_dev
*dev
,
510 struct resource
*res
)
512 struct pnp_resource
*pnp_res
;
514 pnp_res
= pnp_new_resource(dev
);
516 dev_err(&dev
->dev
, "can't add resource %pR\n", res
);
521 pnp_res
->res
.name
= dev
->name
;
522 dev_dbg(&dev
->dev
, "%pR\n", res
);
526 struct pnp_resource
*pnp_add_irq_resource(struct pnp_dev
*dev
, int irq
,
529 struct pnp_resource
*pnp_res
;
530 struct resource
*res
;
532 pnp_res
= pnp_new_resource(dev
);
534 dev_err(&dev
->dev
, "can't add resource for IRQ %d\n", irq
);
539 res
->flags
= IORESOURCE_IRQ
| flags
;
543 dev_printk(KERN_DEBUG
, &dev
->dev
, "%pR\n", res
);
547 struct pnp_resource
*pnp_add_dma_resource(struct pnp_dev
*dev
, int dma
,
550 struct pnp_resource
*pnp_res
;
551 struct resource
*res
;
553 pnp_res
= pnp_new_resource(dev
);
555 dev_err(&dev
->dev
, "can't add resource for DMA %d\n", dma
);
560 res
->flags
= IORESOURCE_DMA
| flags
;
564 dev_printk(KERN_DEBUG
, &dev
->dev
, "%pR\n", res
);
568 struct pnp_resource
*pnp_add_io_resource(struct pnp_dev
*dev
,
569 resource_size_t start
,
570 resource_size_t end
, int flags
)
572 struct pnp_resource
*pnp_res
;
573 struct resource
*res
;
575 pnp_res
= pnp_new_resource(dev
);
577 dev_err(&dev
->dev
, "can't add resource for IO %#llx-%#llx\n",
578 (unsigned long long) start
,
579 (unsigned long long) end
);
584 res
->flags
= IORESOURCE_IO
| flags
;
588 dev_printk(KERN_DEBUG
, &dev
->dev
, "%pR\n", res
);
592 struct pnp_resource
*pnp_add_mem_resource(struct pnp_dev
*dev
,
593 resource_size_t start
,
594 resource_size_t end
, int flags
)
596 struct pnp_resource
*pnp_res
;
597 struct resource
*res
;
599 pnp_res
= pnp_new_resource(dev
);
601 dev_err(&dev
->dev
, "can't add resource for MEM %#llx-%#llx\n",
602 (unsigned long long) start
,
603 (unsigned long long) end
);
608 res
->flags
= IORESOURCE_MEM
| flags
;
612 dev_printk(KERN_DEBUG
, &dev
->dev
, "%pR\n", res
);
616 struct pnp_resource
*pnp_add_bus_resource(struct pnp_dev
*dev
,
617 resource_size_t start
,
620 struct pnp_resource
*pnp_res
;
621 struct resource
*res
;
623 pnp_res
= pnp_new_resource(dev
);
625 dev_err(&dev
->dev
, "can't add resource for BUS %#llx-%#llx\n",
626 (unsigned long long) start
,
627 (unsigned long long) end
);
632 res
->flags
= IORESOURCE_BUS
;
636 dev_printk(KERN_DEBUG
, &dev
->dev
, "%pR\n", res
);
641 * Determine whether the specified resource is a possible configuration
644 int pnp_possible_config(struct pnp_dev
*dev
, int type
, resource_size_t start
,
645 resource_size_t size
)
647 struct pnp_option
*option
;
648 struct pnp_port
*port
;
653 list_for_each_entry(option
, &dev
->options
, list
) {
654 if (option
->type
!= type
)
657 switch (option
->type
) {
659 port
= &option
->u
.port
;
660 if (port
->min
== start
&& port
->size
== size
)
664 mem
= &option
->u
.mem
;
665 if (mem
->min
== start
&& mem
->size
== size
)
669 irq
= &option
->u
.irq
;
670 if (start
< PNP_IRQ_NR
&&
671 test_bit(start
, irq
->map
.bits
))
675 dma
= &option
->u
.dma
;
676 if (dma
->map
& (1 << start
))
684 EXPORT_SYMBOL(pnp_possible_config
);
686 int pnp_range_reserved(resource_size_t start
, resource_size_t end
)
689 struct pnp_resource
*pnp_res
;
690 resource_size_t
*dev_start
, *dev_end
;
692 pnp_for_each_dev(dev
) {
693 list_for_each_entry(pnp_res
, &dev
->resources
, list
) {
694 dev_start
= &pnp_res
->res
.start
;
695 dev_end
= &pnp_res
->res
.end
;
696 if (ranged_conflict(&start
, &end
, dev_start
, dev_end
))
702 EXPORT_SYMBOL(pnp_range_reserved
);
704 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
705 static int __init
pnp_setup_reserve_irq(char *str
)
709 for (i
= 0; i
< 16; i
++)
710 if (get_option(&str
, &pnp_reserve_irq
[i
]) != 2)
715 __setup("pnp_reserve_irq=", pnp_setup_reserve_irq
);
717 /* format is: pnp_reserve_dma=dma1[,dma2] .... */
718 static int __init
pnp_setup_reserve_dma(char *str
)
722 for (i
= 0; i
< 8; i
++)
723 if (get_option(&str
, &pnp_reserve_dma
[i
]) != 2)
728 __setup("pnp_reserve_dma=", pnp_setup_reserve_dma
);
730 /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
731 static int __init
pnp_setup_reserve_io(char *str
)
735 for (i
= 0; i
< 16; i
++)
736 if (get_option(&str
, &pnp_reserve_io
[i
]) != 2)
741 __setup("pnp_reserve_io=", pnp_setup_reserve_io
);
743 /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
744 static int __init
pnp_setup_reserve_mem(char *str
)
748 for (i
= 0; i
< 16; i
++)
749 if (get_option(&str
, &pnp_reserve_mem
[i
]) != 2)
754 __setup("pnp_reserve_mem=", pnp_setup_reserve_mem
);