Blame view

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