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/libata.h>
21 #include <linux/ioport.h>
22 #include <linux/init.h>
24 #include <linux/pnp.h>
27 static int pnp_reserve_irq
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
28 static int pnp_reserve_dma
[8] = {[0 ... 7] = -1 }; /* reserve (don't use) some DMA */
29 static int pnp_reserve_io
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some I/O region */
30 static int pnp_reserve_mem
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some memory region */
36 static struct pnp_option
*pnp_build_option(struct pnp_dev
*dev
, unsigned long type
,
37 unsigned int option_flags
)
39 struct pnp_option
*option
;
41 option
= kzalloc(sizeof(struct pnp_option
), GFP_KERNEL
);
45 option
->flags
= option_flags
;
48 list_add_tail(&option
->list
, &dev
->options
);
52 int pnp_register_irq_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
53 pnp_irq_mask_t
*map
, unsigned char flags
)
55 struct pnp_option
*option
;
58 option
= pnp_build_option(dev
, IORESOURCE_IRQ
, option_flags
);
70 for (i
= 0; i
< 16; i
++)
71 if (test_bit(i
, irq
->map
.bits
))
72 pcibios_penalize_isa_irq(i
, 0);
76 dbg_pnp_show_option(dev
, option
);
80 int pnp_register_dma_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
81 unsigned char map
, unsigned char flags
)
83 struct pnp_option
*option
;
86 option
= pnp_build_option(dev
, IORESOURCE_DMA
, option_flags
);
94 dbg_pnp_show_option(dev
, option
);
98 int pnp_register_port_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
99 resource_size_t min
, resource_size_t max
,
100 resource_size_t align
, resource_size_t size
,
103 struct pnp_option
*option
;
104 struct pnp_port
*port
;
106 option
= pnp_build_option(dev
, IORESOURCE_IO
, option_flags
);
110 port
= &option
->u
.port
;
117 dbg_pnp_show_option(dev
, option
);
121 int pnp_register_mem_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
122 resource_size_t min
, resource_size_t max
,
123 resource_size_t align
, resource_size_t size
,
126 struct pnp_option
*option
;
129 option
= pnp_build_option(dev
, IORESOURCE_MEM
, option_flags
);
133 mem
= &option
->u
.mem
;
140 dbg_pnp_show_option(dev
, option
);
144 void pnp_free_options(struct pnp_dev
*dev
)
146 struct pnp_option
*option
, *tmp
;
148 list_for_each_entry_safe(option
, tmp
, &dev
->options
, list
) {
149 list_del(&option
->list
);
155 * resource validity checking
158 #define length(start, end) (*(end) - *(start) + 1)
160 /* Two ranges conflict if one doesn't end before the other starts */
161 #define ranged_conflict(starta, enda, startb, endb) \
162 !((*(enda) < *(startb)) || (*(endb) < *(starta)))
164 #define cannot_compare(flags) \
165 ((flags) & IORESOURCE_DISABLED)
167 int pnp_check_port(struct pnp_dev
*dev
, struct resource
*res
)
170 struct pnp_dev
*tdev
;
171 struct resource
*tres
;
172 resource_size_t
*port
, *end
, *tport
, *tend
;
177 /* if the resource doesn't exist, don't complain about it */
178 if (cannot_compare(res
->flags
))
181 /* check if the resource is already in use, skip if the
182 * device is active because it itself may be in use */
184 if (!request_region(*port
, length(port
, end
), "pnp"))
186 release_region(*port
, length(port
, end
));
189 /* check if the resource is reserved */
190 for (i
= 0; i
< 8; i
++) {
191 int rport
= pnp_reserve_io
[i
<< 1];
192 int rend
= pnp_reserve_io
[(i
<< 1) + 1] + rport
- 1;
193 if (ranged_conflict(port
, end
, &rport
, &rend
))
197 /* check for internal conflicts */
198 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_IO
, i
)); i
++) {
199 if (tres
!= res
&& tres
->flags
& IORESOURCE_IO
) {
200 tport
= &tres
->start
;
202 if (ranged_conflict(port
, end
, tport
, tend
))
207 /* check for conflicts with other pnp devices */
208 pnp_for_each_dev(tdev
) {
212 (tres
= pnp_get_resource(tdev
, IORESOURCE_IO
, i
));
214 if (tres
->flags
& IORESOURCE_IO
) {
215 if (cannot_compare(tres
->flags
))
217 if (tres
->flags
& IORESOURCE_WINDOW
)
219 tport
= &tres
->start
;
221 if (ranged_conflict(port
, end
, tport
, tend
))
230 int pnp_check_mem(struct pnp_dev
*dev
, struct resource
*res
)
233 struct pnp_dev
*tdev
;
234 struct resource
*tres
;
235 resource_size_t
*addr
, *end
, *taddr
, *tend
;
240 /* if the resource doesn't exist, don't complain about it */
241 if (cannot_compare(res
->flags
))
244 /* check if the resource is already in use, skip if the
245 * device is active because it itself may be in use */
247 if (!request_mem_region(*addr
, length(addr
, end
), "pnp"))
249 release_mem_region(*addr
, length(addr
, end
));
252 /* check if the resource is reserved */
253 for (i
= 0; i
< 8; i
++) {
254 int raddr
= pnp_reserve_mem
[i
<< 1];
255 int rend
= pnp_reserve_mem
[(i
<< 1) + 1] + raddr
- 1;
256 if (ranged_conflict(addr
, end
, &raddr
, &rend
))
260 /* check for internal conflicts */
261 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_MEM
, i
)); i
++) {
262 if (tres
!= res
&& tres
->flags
& IORESOURCE_MEM
) {
263 taddr
= &tres
->start
;
265 if (ranged_conflict(addr
, end
, taddr
, tend
))
270 /* check for conflicts with other pnp devices */
271 pnp_for_each_dev(tdev
) {
275 (tres
= pnp_get_resource(tdev
, IORESOURCE_MEM
, i
));
277 if (tres
->flags
& IORESOURCE_MEM
) {
278 if (cannot_compare(tres
->flags
))
280 if (tres
->flags
& IORESOURCE_WINDOW
)
282 taddr
= &tres
->start
;
284 if (ranged_conflict(addr
, end
, taddr
, tend
))
293 static irqreturn_t
pnp_test_handler(int irq
, void *dev_id
)
299 static int pci_dev_uses_irq(struct pnp_dev
*pnp
, struct pci_dev
*pci
,
305 if (pci
->irq
== irq
) {
306 pnp_dbg(&pnp
->dev
, " device %s using irq %d\n",
312 * See pci_setup_device() and ata_pci_sff_activate_host() for
313 * similar IDE legacy detection.
315 pci_read_config_dword(pci
, PCI_CLASS_REVISION
, &class);
316 class >>= 8; /* discard revision ID */
317 progif
= class & 0xff;
320 if (class == PCI_CLASS_STORAGE_IDE
) {
322 * Unless both channels are native-PCI mode only,
323 * treat the compatibility IRQs as busy.
325 if ((progif
& 0x5) != 0x5)
326 if (ATA_PRIMARY_IRQ(pci
) == irq
||
327 ATA_SECONDARY_IRQ(pci
) == irq
) {
328 pnp_dbg(&pnp
->dev
, " legacy IDE device %s "
329 "using irq %d\n", pci_name(pci
), irq
);
338 static int pci_uses_irq(struct pnp_dev
*pnp
, unsigned int irq
)
341 struct pci_dev
*pci
= NULL
;
343 for_each_pci_dev(pci
) {
344 if (pci_dev_uses_irq(pnp
, pci
, irq
)) {
353 int pnp_check_irq(struct pnp_dev
*dev
, struct resource
*res
)
356 struct pnp_dev
*tdev
;
357 struct resource
*tres
;
358 resource_size_t
*irq
;
362 /* if the resource doesn't exist, don't complain about it */
363 if (cannot_compare(res
->flags
))
366 /* check if the resource is valid */
370 /* check if the resource is reserved */
371 for (i
= 0; i
< 16; i
++) {
372 if (pnp_reserve_irq
[i
] == *irq
)
376 /* check for internal conflicts */
377 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_IRQ
, i
)); i
++) {
378 if (tres
!= res
&& tres
->flags
& IORESOURCE_IRQ
) {
379 if (tres
->start
== *irq
)
384 /* check if the resource is being used by a pci device */
385 if (pci_uses_irq(dev
, *irq
))
388 /* check if the resource is already in use, skip if the
389 * device is active because it itself may be in use */
391 if (request_irq(*irq
, pnp_test_handler
,
392 IRQF_PROBE_SHARED
, "pnp", NULL
))
394 free_irq(*irq
, NULL
);
397 /* check for conflicts with other pnp devices */
398 pnp_for_each_dev(tdev
) {
402 (tres
= pnp_get_resource(tdev
, IORESOURCE_IRQ
, i
));
404 if (tres
->flags
& IORESOURCE_IRQ
) {
405 if (cannot_compare(tres
->flags
))
407 if (tres
->start
== *irq
)
416 #ifdef CONFIG_ISA_DMA_API
417 int pnp_check_dma(struct pnp_dev
*dev
, struct resource
*res
)
420 struct pnp_dev
*tdev
;
421 struct resource
*tres
;
422 resource_size_t
*dma
;
426 /* if the resource doesn't exist, don't complain about it */
427 if (cannot_compare(res
->flags
))
430 /* check if the resource is valid */
431 if (*dma
== 4 || *dma
> 7)
434 /* check if the resource is reserved */
435 for (i
= 0; i
< 8; i
++) {
436 if (pnp_reserve_dma
[i
] == *dma
)
440 /* check for internal conflicts */
441 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_DMA
, i
)); i
++) {
442 if (tres
!= res
&& tres
->flags
& IORESOURCE_DMA
) {
443 if (tres
->start
== *dma
)
448 /* check if the resource is already in use, skip if the
449 * device is active because it itself may be in use */
451 if (request_dma(*dma
, "pnp"))
456 /* check for conflicts with other pnp devices */
457 pnp_for_each_dev(tdev
) {
461 (tres
= pnp_get_resource(tdev
, IORESOURCE_DMA
, i
));
463 if (tres
->flags
& IORESOURCE_DMA
) {
464 if (cannot_compare(tres
->flags
))
466 if (tres
->start
== *dma
)
474 #endif /* CONFIG_ISA_DMA_API */
476 unsigned long pnp_resource_type(struct resource
*res
)
478 return res
->flags
& (IORESOURCE_IO
| IORESOURCE_MEM
|
479 IORESOURCE_IRQ
| IORESOURCE_DMA
|
483 struct resource
*pnp_get_resource(struct pnp_dev
*dev
,
484 unsigned long type
, unsigned int num
)
486 struct pnp_resource
*pnp_res
;
487 struct resource
*res
;
489 list_for_each_entry(pnp_res
, &dev
->resources
, list
) {
491 if (pnp_resource_type(res
) == type
&& num
-- == 0)
496 EXPORT_SYMBOL(pnp_get_resource
);
498 static struct pnp_resource
*pnp_new_resource(struct pnp_dev
*dev
)
500 struct pnp_resource
*pnp_res
;
502 pnp_res
= kzalloc(sizeof(struct pnp_resource
), GFP_KERNEL
);
506 list_add_tail(&pnp_res
->list
, &dev
->resources
);
510 struct pnp_resource
*pnp_add_resource(struct pnp_dev
*dev
,
511 struct resource
*res
)
513 struct pnp_resource
*pnp_res
;
515 pnp_res
= pnp_new_resource(dev
);
517 dev_err(&dev
->dev
, "can't add resource %pR\n", res
);
522 pnp_res
->res
.name
= dev
->name
;
523 dev_dbg(&dev
->dev
, "%pR\n", res
);
527 struct pnp_resource
*pnp_add_irq_resource(struct pnp_dev
*dev
, int irq
,
530 struct pnp_resource
*pnp_res
;
531 struct resource
*res
;
533 pnp_res
= pnp_new_resource(dev
);
535 dev_err(&dev
->dev
, "can't add resource for IRQ %d\n", irq
);
540 res
->flags
= IORESOURCE_IRQ
| flags
;
544 dev_dbg(&dev
->dev
, "%pR\n", res
);
548 struct pnp_resource
*pnp_add_dma_resource(struct pnp_dev
*dev
, int dma
,
551 struct pnp_resource
*pnp_res
;
552 struct resource
*res
;
554 pnp_res
= pnp_new_resource(dev
);
556 dev_err(&dev
->dev
, "can't add resource for DMA %d\n", dma
);
561 res
->flags
= IORESOURCE_DMA
| flags
;
565 dev_printk(KERN_DEBUG
, &dev
->dev
, "%pR\n", res
);
569 struct pnp_resource
*pnp_add_io_resource(struct pnp_dev
*dev
,
570 resource_size_t start
,
571 resource_size_t end
, int flags
)
573 struct pnp_resource
*pnp_res
;
574 struct resource
*res
;
576 pnp_res
= pnp_new_resource(dev
);
578 dev_err(&dev
->dev
, "can't add resource for IO %#llx-%#llx\n",
579 (unsigned long long) start
,
580 (unsigned long long) end
);
585 res
->flags
= IORESOURCE_IO
| flags
;
589 dev_printk(KERN_DEBUG
, &dev
->dev
, "%pR\n", res
);
593 struct pnp_resource
*pnp_add_mem_resource(struct pnp_dev
*dev
,
594 resource_size_t start
,
595 resource_size_t end
, int flags
)
597 struct pnp_resource
*pnp_res
;
598 struct resource
*res
;
600 pnp_res
= pnp_new_resource(dev
);
602 dev_err(&dev
->dev
, "can't add resource for MEM %#llx-%#llx\n",
603 (unsigned long long) start
,
604 (unsigned long long) end
);
609 res
->flags
= IORESOURCE_MEM
| flags
;
613 dev_printk(KERN_DEBUG
, &dev
->dev
, "%pR\n", res
);
617 struct pnp_resource
*pnp_add_bus_resource(struct pnp_dev
*dev
,
618 resource_size_t start
,
621 struct pnp_resource
*pnp_res
;
622 struct resource
*res
;
624 pnp_res
= pnp_new_resource(dev
);
626 dev_err(&dev
->dev
, "can't add resource for BUS %#llx-%#llx\n",
627 (unsigned long long) start
,
628 (unsigned long long) end
);
633 res
->flags
= IORESOURCE_BUS
;
637 dev_printk(KERN_DEBUG
, &dev
->dev
, "%pR\n", res
);
642 * Determine whether the specified resource is a possible configuration
645 int pnp_possible_config(struct pnp_dev
*dev
, int type
, resource_size_t start
,
646 resource_size_t size
)
648 struct pnp_option
*option
;
649 struct pnp_port
*port
;
654 list_for_each_entry(option
, &dev
->options
, list
) {
655 if (option
->type
!= type
)
658 switch (option
->type
) {
660 port
= &option
->u
.port
;
661 if (port
->min
== start
&& port
->size
== size
)
665 mem
= &option
->u
.mem
;
666 if (mem
->min
== start
&& mem
->size
== size
)
670 irq
= &option
->u
.irq
;
671 if (start
< PNP_IRQ_NR
&&
672 test_bit(start
, irq
->map
.bits
))
676 dma
= &option
->u
.dma
;
677 if (dma
->map
& (1 << start
))
685 EXPORT_SYMBOL(pnp_possible_config
);
687 int pnp_range_reserved(resource_size_t start
, resource_size_t end
)
690 struct pnp_resource
*pnp_res
;
691 resource_size_t
*dev_start
, *dev_end
;
693 pnp_for_each_dev(dev
) {
694 list_for_each_entry(pnp_res
, &dev
->resources
, list
) {
695 dev_start
= &pnp_res
->res
.start
;
696 dev_end
= &pnp_res
->res
.end
;
697 if (ranged_conflict(&start
, &end
, dev_start
, dev_end
))
703 EXPORT_SYMBOL(pnp_range_reserved
);
705 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
706 static int __init
pnp_setup_reserve_irq(char *str
)
710 for (i
= 0; i
< 16; i
++)
711 if (get_option(&str
, &pnp_reserve_irq
[i
]) != 2)
716 __setup("pnp_reserve_irq=", pnp_setup_reserve_irq
);
718 /* format is: pnp_reserve_dma=dma1[,dma2] .... */
719 static int __init
pnp_setup_reserve_dma(char *str
)
723 for (i
= 0; i
< 8; i
++)
724 if (get_option(&str
, &pnp_reserve_dma
[i
]) != 2)
729 __setup("pnp_reserve_dma=", pnp_setup_reserve_dma
);
731 /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
732 static int __init
pnp_setup_reserve_io(char *str
)
736 for (i
= 0; i
< 16; i
++)
737 if (get_option(&str
, &pnp_reserve_io
[i
]) != 2)
742 __setup("pnp_reserve_io=", pnp_setup_reserve_io
);
744 /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
745 static int __init
pnp_setup_reserve_mem(char *str
)
749 for (i
= 0; i
< 16; i
++)
750 if (get_option(&str
, &pnp_reserve_mem
[i
]) != 2)
755 __setup("pnp_reserve_mem=", pnp_setup_reserve_mem
);