Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * system.c - a driver for reserving pnp system resources
4 : : *
5 : : * Some code is based on pnpbios_core.c
6 : : * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
7 : : * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
8 : : * Bjorn Helgaas <bjorn.helgaas@hp.com>
9 : : */
10 : :
11 : : #include <linux/pnp.h>
12 : : #include <linux/device.h>
13 : : #include <linux/init.h>
14 : : #include <linux/slab.h>
15 : : #include <linux/kernel.h>
16 : : #include <linux/ioport.h>
17 : :
18 : : static const struct pnp_device_id pnp_dev_table[] = {
19 : : /* General ID for reserving resources */
20 : : {"PNP0c02", 0},
21 : : /* memory controller */
22 : : {"PNP0c01", 0},
23 : : {"", 0}
24 : : };
25 : :
26 : 0 : static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
27 : : {
28 : 0 : char *regionid;
29 [ # # ]: 0 : const char *pnpid = dev_name(&dev->dev);
30 : 0 : resource_size_t start = r->start, end = r->end;
31 : 0 : struct resource *res;
32 : :
33 : 0 : regionid = kmalloc(16, GFP_KERNEL);
34 [ # # ]: 0 : if (!regionid)
35 : : return;
36 : :
37 : 0 : snprintf(regionid, 16, "pnp %s", pnpid);
38 [ # # ]: 0 : if (port)
39 : 0 : res = request_region(start, end - start + 1, regionid);
40 : : else
41 : 0 : res = request_mem_region(start, end - start + 1, regionid);
42 [ # # ]: 0 : if (res)
43 : 0 : res->flags &= ~IORESOURCE_BUSY;
44 : : else
45 : 0 : kfree(regionid);
46 : :
47 : : /*
48 : : * Failures at this point are usually harmless. pci quirks for
49 : : * example do reserve stuff they know about too, so we may well
50 : : * have double reservations.
51 : : */
52 [ # # ]: 0 : dev_info(&dev->dev, "%pR %s reserved\n", r,
53 : : res ? "has been" : "could not be");
54 : : }
55 : :
56 : 0 : static void reserve_resources_of_dev(struct pnp_dev *dev)
57 : : {
58 : 0 : struct resource *res;
59 : 0 : int i;
60 : :
61 [ # # ]: 0 : for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
62 [ # # ]: 0 : if (res->flags & IORESOURCE_DISABLED)
63 : 0 : continue;
64 [ # # ]: 0 : if (res->start == 0)
65 : 0 : continue; /* disabled */
66 [ # # ]: 0 : if (res->start < 0x100)
67 : : /*
68 : : * Below 0x100 is only standard PC hardware
69 : : * (pics, kbd, timer, dma, ...)
70 : : * We should not get resource conflicts there,
71 : : * and the kernel reserves these anyway
72 : : * (see arch/i386/kernel/setup.c).
73 : : * So, do nothing
74 : : */
75 : 0 : continue;
76 [ # # ]: 0 : if (res->end < res->start)
77 : 0 : continue; /* invalid */
78 : :
79 : 0 : reserve_range(dev, res, 1);
80 : : }
81 : :
82 [ # # ]: 0 : for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
83 [ # # ]: 0 : if (res->flags & IORESOURCE_DISABLED)
84 : 0 : continue;
85 : :
86 : 0 : reserve_range(dev, res, 0);
87 : : }
88 : 0 : }
89 : :
90 : 0 : static int system_pnp_probe(struct pnp_dev *dev,
91 : : const struct pnp_device_id *dev_id)
92 : : {
93 : 0 : reserve_resources_of_dev(dev);
94 : 0 : return 0;
95 : : }
96 : :
97 : : static struct pnp_driver system_pnp_driver = {
98 : : .name = "system",
99 : : .id_table = pnp_dev_table,
100 : : .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
101 : : .probe = system_pnp_probe,
102 : : };
103 : :
104 : 78 : static int __init pnp_system_init(void)
105 : : {
106 : 78 : return pnp_register_driver(&system_pnp_driver);
107 : : }
108 : :
109 : : /**
110 : : * Reserve motherboard resources after PCI claim BARs,
111 : : * but before PCI assign resources for uninitialized PCI devices
112 : : */
113 : : fs_initcall(pnp_system_init);
|