aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2008-06-27 18:56:57 -0400
committerAndi Kleen <andi@basil.nowhere.org>2008-07-16 17:27:05 -0400
commitaee3ad815dd291a7193ab01da0f1a30c84d00061 (patch)
treeb0549b2a98ddfe6734e1e5f7cedd3958eec18503
parent20bfdbba7212d19613b93dcea93f26cb65af91fe (diff)
PNP: replace pnp_resource_table with dynamically allocated resources
PNP used to have a fixed-size pnp_resource_table for tracking the resources used by a device. This table often overflowed, so we've had to increase the table size, which wastes memory because most devices have very few resources. This patch replaces the table with a linked list of resources where the entries are allocated on demand. This removes messages like these: pnpacpi: exceeded the max number of IO resources 00:01: too many I/O port resources References: http://bugzilla.kernel.org/show_bug.cgi?id=9535 http://bugzilla.kernel.org/show_bug.cgi?id=9740 http://lkml.org/lkml/2007/11/30/110 This patch also changes the way PNP uses the IORESOURCE_UNSET, IORESOURCE_AUTO, and IORESOURCE_DISABLED flags. Prior to this patch, the pnp_resource_table entries used the flags like this: IORESOURCE_UNSET This table entry is unused and available for use. When this flag is set, we shouldn't look at anything else in the resource structure. This flag is set when a resource table entry is initialized. IORESOURCE_AUTO This resource was assigned automatically by pnp_assign_{io,mem,etc}(). This flag is set when a resource table entry is initialized and cleared whenever we discover a resource setting by reading an ISAPNP config register, parsing a PNPBIOS resource data stream, parsing an ACPI _CRS list, or interpreting a sysfs "set" command. Resources marked IORESOURCE_AUTO are reinitialized and marked as IORESOURCE_UNSET by pnp_clean_resource_table() in these cases: - before we attempt to assign resources automatically, - if we fail to assign resources automatically, - after disabling a device IORESOURCE_DISABLED Set by pnp_assign_{io,mem,etc}() when automatic assignment fails. Also set by PNPBIOS and PNPACPI for: - invalid IRQs or GSI registration failures - invalid DMA channels - I/O ports above 0x10000 - mem ranges with negative length After this patch, there is no pnp_resource_table, and the resource list entries use the flags like this: IORESOURCE_UNSET This flag is no longer used in PNP. Instead of keeping IORESOURCE_UNSET entries in the resource list, we remove entries from the list and free them. IORESOURCE_AUTO No change in meaning: it still means the resource was assigned automatically by pnp_assign_{port,mem,etc}(), but these functions now set the bit explicitly. We still "clean" a device's resource list in the same places, but rather than reinitializing IORESOURCE_AUTO entries, we just remove them from the list. Note that IORESOURCE_AUTO entries are always at the end of the list, so removing them doesn't reorder other list entries. This is because non-IORESOURCE_AUTO entries are added by the ISAPNP, PNPBIOS, or PNPACPI "get resources" methods and by the sysfs "set" command. In each of these cases, we completely free the resource list first. IORESOURCE_DISABLED In addition to the cases where we used to set this flag, ISAPNP now adds an IORESOURCE_DISABLED resource when it reads a configuration register with a "disabled" value. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Len Brown <len.brown@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com>
-rw-r--r--drivers/pnp/base.h18
-rw-r--r--drivers/pnp/core.c25
-rw-r--r--drivers/pnp/interface.c60
-rw-r--r--drivers/pnp/isapnp/core.c12
-rw-r--r--drivers/pnp/manager.c220
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c131
-rw-r--r--drivers/pnp/pnpbios/rsparser.c95
-rw-r--r--drivers/pnp/quirks.c3
-rw-r--r--drivers/pnp/resource.c86
-rw-r--r--drivers/pnp/support.c79
-rw-r--r--drivers/pnp/system.c4
-rw-r--r--include/linux/pnp.h20
12 files changed, 331 insertions, 422 deletions
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index c91315826da2..1667ac3ca45b 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -46,27 +46,15 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res);
46char *pnp_resource_type_name(struct resource *res); 46char *pnp_resource_type_name(struct resource *res);
47void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); 47void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
48 48
49void pnp_init_resource(struct resource *res); 49void pnp_free_resources(struct pnp_dev *dev);
50int pnp_resource_type(struct resource *res); 50int pnp_resource_type(struct resource *res);
51 51
52struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
53 unsigned int type, unsigned int num);
54
55#define PNP_MAX_PORT 40
56#define PNP_MAX_MEM 24
57#define PNP_MAX_IRQ 2
58#define PNP_MAX_DMA 2
59
60struct pnp_resource { 52struct pnp_resource {
53 struct list_head list;
61 struct resource res; 54 struct resource res;
62}; 55};
63 56
64struct pnp_resource_table { 57void pnp_free_resource(struct pnp_resource *pnp_res);
65 struct pnp_resource port[PNP_MAX_PORT];
66 struct pnp_resource mem[PNP_MAX_MEM];
67 struct pnp_resource dma[PNP_MAX_DMA];
68 struct pnp_resource irq[PNP_MAX_IRQ];
69};
70 58
71struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, 59struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
72 int flags); 60 int flags);
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 20771b7d4482..7182da92aec3 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -99,6 +99,21 @@ static void pnp_free_ids(struct pnp_dev *dev)
99 } 99 }
100} 100}
101 101
102void pnp_free_resource(struct pnp_resource *pnp_res)
103{
104 list_del(&pnp_res->list);
105 kfree(pnp_res);
106}
107
108void pnp_free_resources(struct pnp_dev *dev)
109{
110 struct pnp_resource *pnp_res, *tmp;
111
112 list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
113 pnp_free_resource(pnp_res);
114 }
115}
116
102static void pnp_release_device(struct device *dmdev) 117static void pnp_release_device(struct device *dmdev)
103{ 118{
104 struct pnp_dev *dev = to_pnp_dev(dmdev); 119 struct pnp_dev *dev = to_pnp_dev(dmdev);
@@ -106,7 +121,7 @@ static void pnp_release_device(struct device *dmdev)
106 pnp_free_option(dev->independent); 121 pnp_free_option(dev->independent);
107 pnp_free_option(dev->dependent); 122 pnp_free_option(dev->dependent);
108 pnp_free_ids(dev); 123 pnp_free_ids(dev);
109 kfree(dev->res); 124 pnp_free_resources(dev);
110 kfree(dev); 125 kfree(dev);
111} 126}
112 127
@@ -119,12 +134,7 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
119 if (!dev) 134 if (!dev)
120 return NULL; 135 return NULL;
121 136
122 dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); 137 INIT_LIST_HEAD(&dev->resources);
123 if (!dev->res) {
124 kfree(dev);
125 return NULL;
126 }
127
128 dev->protocol = protocol; 138 dev->protocol = protocol;
129 dev->number = id; 139 dev->number = id;
130 dev->dma_mask = DMA_24BIT_MASK; 140 dev->dma_mask = DMA_24BIT_MASK;
@@ -140,7 +150,6 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
140 150
141 dev_id = pnp_add_id(dev, pnpid); 151 dev_id = pnp_add_id(dev, pnpid);
142 if (!dev_id) { 152 if (!dev_id) {
143 kfree(dev->res);
144 kfree(dev); 153 kfree(dev);
145 return NULL; 154 return NULL;
146 } 155 }
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 3f8007ab94e3..7fc86bbed88e 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -269,46 +269,38 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
269 pnp_printf(buffer, "disabled\n"); 269 pnp_printf(buffer, "disabled\n");
270 270
271 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { 271 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
272 if (pnp_resource_valid(res)) { 272 pnp_printf(buffer, "io");
273 pnp_printf(buffer, "io"); 273 if (res->flags & IORESOURCE_DISABLED)
274 if (res->flags & IORESOURCE_DISABLED) 274 pnp_printf(buffer, " disabled\n");
275 pnp_printf(buffer, " disabled\n"); 275 else
276 else 276 pnp_printf(buffer, " 0x%llx-0x%llx\n",
277 pnp_printf(buffer, " 0x%llx-0x%llx\n", 277 (unsigned long long) res->start,
278 (unsigned long long) res->start, 278 (unsigned long long) res->end);
279 (unsigned long long) res->end);
280 }
281 } 279 }
282 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { 280 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
283 if (pnp_resource_valid(res)) { 281 pnp_printf(buffer, "mem");
284 pnp_printf(buffer, "mem"); 282 if (res->flags & IORESOURCE_DISABLED)
285 if (res->flags & IORESOURCE_DISABLED) 283 pnp_printf(buffer, " disabled\n");
286 pnp_printf(buffer, " disabled\n"); 284 else
287 else 285 pnp_printf(buffer, " 0x%llx-0x%llx\n",
288 pnp_printf(buffer, " 0x%llx-0x%llx\n", 286 (unsigned long long) res->start,
289 (unsigned long long) res->start, 287 (unsigned long long) res->end);
290 (unsigned long long) res->end);
291 }
292 } 288 }
293 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) { 289 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
294 if (pnp_resource_valid(res)) { 290 pnp_printf(buffer, "irq");
295 pnp_printf(buffer, "irq"); 291 if (res->flags & IORESOURCE_DISABLED)
296 if (res->flags & IORESOURCE_DISABLED) 292 pnp_printf(buffer, " disabled\n");
297 pnp_printf(buffer, " disabled\n"); 293 else
298 else 294 pnp_printf(buffer, " %lld\n",
299 pnp_printf(buffer, " %lld\n", 295 (unsigned long long) res->start);
300 (unsigned long long) res->start);
301 }
302 } 296 }
303 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) { 297 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
304 if (pnp_resource_valid(res)) { 298 pnp_printf(buffer, "dma");
305 pnp_printf(buffer, "dma"); 299 if (res->flags & IORESOURCE_DISABLED)
306 if (res->flags & IORESOURCE_DISABLED) 300 pnp_printf(buffer, " disabled\n");
307 pnp_printf(buffer, " disabled\n"); 301 else
308 else 302 pnp_printf(buffer, " %lld\n",
309 pnp_printf(buffer, " %lld\n", 303 (unsigned long long) res->start);
310 (unsigned long long) res->start);
311 }
312 } 304 }
313 ret = (buffer->curr - buf); 305 ret = (buffer->curr - buf);
314 kfree(buffer); 306 kfree(buffer);
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 752b51fbaa6c..ca4457ec403b 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -973,8 +973,7 @@ static int isapnp_set_resources(struct pnp_dev *dev)
973 dev->active = 1; 973 dev->active = 1;
974 for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { 974 for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
975 res = pnp_get_resource(dev, IORESOURCE_IO, tmp); 975 res = pnp_get_resource(dev, IORESOURCE_IO, tmp);
976 if (res && pnp_resource_valid(res) && 976 if (pnp_resource_enabled(res)) {
977 !(res->flags & IORESOURCE_DISABLED)) {
978 dev_dbg(&dev->dev, " set io %d to %#llx\n", 977 dev_dbg(&dev->dev, " set io %d to %#llx\n",
979 tmp, (unsigned long long) res->start); 978 tmp, (unsigned long long) res->start);
980 isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), 979 isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
@@ -983,8 +982,7 @@ static int isapnp_set_resources(struct pnp_dev *dev)
983 } 982 }
984 for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { 983 for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
985 res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); 984 res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp);
986 if (res && pnp_resource_valid(res) && 985 if (pnp_resource_enabled(res)) {
987 !(res->flags & IORESOURCE_DISABLED)) {
988 int irq = res->start; 986 int irq = res->start;
989 if (irq == 2) 987 if (irq == 2)
990 irq = 9; 988 irq = 9;
@@ -994,8 +992,7 @@ static int isapnp_set_resources(struct pnp_dev *dev)
994 } 992 }
995 for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { 993 for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
996 res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); 994 res = pnp_get_resource(dev, IORESOURCE_DMA, tmp);
997 if (res && pnp_resource_valid(res) && 995 if (pnp_resource_enabled(res)) {
998 !(res->flags & IORESOURCE_DISABLED)) {
999 dev_dbg(&dev->dev, " set dma %d to %lld\n", 996 dev_dbg(&dev->dev, " set dma %d to %lld\n",
1000 tmp, (unsigned long long) res->start); 997 tmp, (unsigned long long) res->start);
1001 isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start); 998 isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start);
@@ -1003,8 +1000,7 @@ static int isapnp_set_resources(struct pnp_dev *dev)
1003 } 1000 }
1004 for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { 1001 for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
1005 res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); 1002 res = pnp_get_resource(dev, IORESOURCE_MEM, tmp);
1006 if (res && pnp_resource_valid(res) && 1003 if (pnp_resource_enabled(res)) {
1007 !(res->flags & IORESOURCE_DISABLED)) {
1008 dev_dbg(&dev->dev, " set mem %d to %#llx\n", 1004 dev_dbg(&dev->dev, " set mem %d to %#llx\n",
1009 tmp, (unsigned long long) res->start); 1005 tmp, (unsigned long long) res->start);
1010 isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), 1006 isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 90bd9cb65563..165b624081ad 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -19,40 +19,30 @@ DEFINE_MUTEX(pnp_res_mutex);
19 19
20static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) 20static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
21{ 21{
22 struct pnp_resource *pnp_res; 22 struct resource *res, local_res;
23 struct resource *res;
24 23
25 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx); 24 res = pnp_get_resource(dev, IORESOURCE_IO, idx);
26 if (!pnp_res) { 25 if (res) {
27 dev_err(&dev->dev, "too many I/O port resources\n");
28 /* pretend we were successful so at least the manager won't try again */
29 return 1;
30 }
31
32 res = &pnp_res->res;
33
34 /* check if this resource has been manually set, if so skip */
35 if (!(res->flags & IORESOURCE_AUTO)) {
36 dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " 26 dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
37 "flags %#lx\n", idx, (unsigned long long) res->start, 27 "flags %#lx\n", idx, (unsigned long long) res->start,
38 (unsigned long long) res->end, res->flags); 28 (unsigned long long) res->end, res->flags);
39 return 1; 29 return 1;
40 } 30 }
41 31
42 /* set the initial values */ 32 res = &local_res;
43 res->flags |= rule->flags | IORESOURCE_IO; 33 res->flags = rule->flags | IORESOURCE_AUTO;
44 res->flags &= ~IORESOURCE_UNSET; 34 res->start = 0;
35 res->end = 0;
45 36
46 if (!rule->size) { 37 if (!rule->size) {
47 res->flags |= IORESOURCE_DISABLED; 38 res->flags |= IORESOURCE_DISABLED;
48 dev_dbg(&dev->dev, " io %d disabled\n", idx); 39 dev_dbg(&dev->dev, " io %d disabled\n", idx);
49 return 1; /* skip disabled resource requests */ 40 goto __add;
50 } 41 }
51 42
52 res->start = rule->min; 43 res->start = rule->min;
53 res->end = res->start + rule->size - 1; 44 res->end = res->start + rule->size - 1;
54 45
55 /* run through until pnp_check_port is happy */
56 while (!pnp_check_port(dev, res)) { 46 while (!pnp_check_port(dev, res)) {
57 res->start += rule->align; 47 res->start += rule->align;
58 res->end = res->start + rule->size - 1; 48 res->end = res->start + rule->size - 1;
@@ -61,38 +51,29 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
61 return 0; 51 return 0;
62 } 52 }
63 } 53 }
64 dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx, 54
65 (unsigned long long) res->start, (unsigned long long) res->end); 55__add:
56 pnp_add_io_resource(dev, res->start, res->end, res->flags);
66 return 1; 57 return 1;
67} 58}
68 59
69static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) 60static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
70{ 61{
71 struct pnp_resource *pnp_res; 62 struct resource *res, local_res;
72 struct resource *res;
73 63
74 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx); 64 res = pnp_get_resource(dev, IORESOURCE_MEM, idx);
75 if (!pnp_res) { 65 if (res) {
76 dev_err(&dev->dev, "too many memory resources\n");
77 /* pretend we were successful so at least the manager won't try again */
78 return 1;
79 }
80
81 res = &pnp_res->res;
82
83 /* check if this resource has been manually set, if so skip */
84 if (!(res->flags & IORESOURCE_AUTO)) {
85 dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " 66 dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
86 "flags %#lx\n", idx, (unsigned long long) res->start, 67 "flags %#lx\n", idx, (unsigned long long) res->start,
87 (unsigned long long) res->end, res->flags); 68 (unsigned long long) res->end, res->flags);
88 return 1; 69 return 1;
89 } 70 }
90 71
91 /* set the initial values */ 72 res = &local_res;
92 res->flags |= rule->flags | IORESOURCE_MEM; 73 res->flags = rule->flags | IORESOURCE_AUTO;
93 res->flags &= ~IORESOURCE_UNSET; 74 res->start = 0;
75 res->end = 0;
94 76
95 /* convert pnp flags to standard Linux flags */
96 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) 77 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
97 res->flags |= IORESOURCE_READONLY; 78 res->flags |= IORESOURCE_READONLY;
98 if (rule->flags & IORESOURCE_MEM_CACHEABLE) 79 if (rule->flags & IORESOURCE_MEM_CACHEABLE)
@@ -105,13 +86,12 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
105 if (!rule->size) { 86 if (!rule->size) {
106 res->flags |= IORESOURCE_DISABLED; 87 res->flags |= IORESOURCE_DISABLED;
107 dev_dbg(&dev->dev, " mem %d disabled\n", idx); 88 dev_dbg(&dev->dev, " mem %d disabled\n", idx);
108 return 1; /* skip disabled resource requests */ 89 goto __add;
109 } 90 }
110 91
111 res->start = rule->min; 92 res->start = rule->min;
112 res->end = res->start + rule->size - 1; 93 res->end = res->start + rule->size - 1;
113 94
114 /* run through until pnp_check_mem is happy */
115 while (!pnp_check_mem(dev, res)) { 95 while (!pnp_check_mem(dev, res)) {
116 res->start += rule->align; 96 res->start += rule->align;
117 res->end = res->start + rule->size - 1; 97 res->end = res->start + rule->size - 1;
@@ -120,15 +100,15 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
120 return 0; 100 return 0;
121 } 101 }
122 } 102 }
123 dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx, 103
124 (unsigned long long) res->start, (unsigned long long) res->end); 104__add:
105 pnp_add_mem_resource(dev, res->start, res->end, res->flags);
125 return 1; 106 return 1;
126} 107}
127 108
128static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 109static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
129{ 110{
130 struct pnp_resource *pnp_res; 111 struct resource *res, local_res;
131 struct resource *res;
132 int i; 112 int i;
133 113
134 /* IRQ priority: this table is good for i386 */ 114 /* IRQ priority: this table is good for i386 */
@@ -136,58 +116,48 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
136 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 116 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
137 }; 117 };
138 118
139 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx); 119 res = pnp_get_resource(dev, IORESOURCE_IRQ, idx);
140 if (!pnp_res) { 120 if (res) {
141 dev_err(&dev->dev, "too many IRQ resources\n");
142 /* pretend we were successful so at least the manager won't try again */
143 return 1;
144 }
145
146 res = &pnp_res->res;
147
148 /* check if this resource has been manually set, if so skip */
149 if (!(res->flags & IORESOURCE_AUTO)) {
150 dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", 121 dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
151 idx, (int) res->start, res->flags); 122 idx, (int) res->start, res->flags);
152 return 1; 123 return 1;
153 } 124 }
154 125
155 /* set the initial values */ 126 res = &local_res;
156 res->flags |= rule->flags | IORESOURCE_IRQ; 127 res->flags = rule->flags | IORESOURCE_AUTO;
157 res->flags &= ~IORESOURCE_UNSET; 128 res->start = -1;
129 res->end = -1;
158 130
159 if (bitmap_empty(rule->map, PNP_IRQ_NR)) { 131 if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
160 res->flags |= IORESOURCE_DISABLED; 132 res->flags |= IORESOURCE_DISABLED;
161 dev_dbg(&dev->dev, " irq %d disabled\n", idx); 133 dev_dbg(&dev->dev, " irq %d disabled\n", idx);
162 return 1; /* skip disabled resource requests */ 134 goto __add;
163 } 135 }
164 136
165 /* TBD: need check for >16 IRQ */ 137 /* TBD: need check for >16 IRQ */
166 res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16); 138 res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
167 if (res->start < PNP_IRQ_NR) { 139 if (res->start < PNP_IRQ_NR) {
168 res->end = res->start; 140 res->end = res->start;
169 dev_dbg(&dev->dev, " assign irq %d %d\n", idx, 141 goto __add;
170 (int) res->start);
171 return 1;
172 } 142 }
173 for (i = 0; i < 16; i++) { 143 for (i = 0; i < 16; i++) {
174 if (test_bit(xtab[i], rule->map)) { 144 if (test_bit(xtab[i], rule->map)) {
175 res->start = res->end = xtab[i]; 145 res->start = res->end = xtab[i];
176 if (pnp_check_irq(dev, res)) { 146 if (pnp_check_irq(dev, res))
177 dev_dbg(&dev->dev, " assign irq %d %d\n", idx, 147 goto __add;
178 (int) res->start);
179 return 1;
180 }
181 } 148 }
182 } 149 }
183 dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); 150 dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
184 return 0; 151 return 0;
152
153__add:
154 pnp_add_irq_resource(dev, res->start, res->flags);
155 return 1;
185} 156}
186 157
187static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 158static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
188{ 159{
189 struct pnp_resource *pnp_res; 160 struct resource *res, local_res;
190 struct resource *res;
191 int i; 161 int i;
192 162
193 /* DMA priority: this table is good for i386 */ 163 /* DMA priority: this table is good for i386 */
@@ -195,127 +165,47 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
195 1, 3, 5, 6, 7, 0, 2, 4 165 1, 3, 5, 6, 7, 0, 2, 4
196 }; 166 };
197 167
198 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx); 168 res = pnp_get_resource(dev, IORESOURCE_DMA, idx);
199 if (!pnp_res) { 169 if (res) {
200 dev_err(&dev->dev, "too many DMA resources\n");
201 return;
202 }
203
204 res = &pnp_res->res;
205
206 /* check if this resource has been manually set, if so skip */
207 if (!(res->flags & IORESOURCE_AUTO)) {
208 dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", 170 dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
209 idx, (int) res->start, res->flags); 171 idx, (int) res->start, res->flags);
210 return; 172 return;
211 } 173 }
212 174
213 /* set the initial values */ 175 res = &local_res;
214 res->flags |= rule->flags | IORESOURCE_DMA; 176 res->flags = rule->flags | IORESOURCE_AUTO;
215 res->flags &= ~IORESOURCE_UNSET; 177 res->start = -1;
178 res->end = -1;
216 179
217 for (i = 0; i < 8; i++) { 180 for (i = 0; i < 8; i++) {
218 if (rule->map & (1 << xtab[i])) { 181 if (rule->map & (1 << xtab[i])) {
219 res->start = res->end = xtab[i]; 182 res->start = res->end = xtab[i];
220 if (pnp_check_dma(dev, res)) { 183 if (pnp_check_dma(dev, res))
221 dev_dbg(&dev->dev, " assign dma %d %d\n", idx, 184 goto __add;
222 (int) res->start);
223 return;
224 }
225 } 185 }
226 } 186 }
227#ifdef MAX_DMA_CHANNELS 187#ifdef MAX_DMA_CHANNELS
228 res->start = res->end = MAX_DMA_CHANNELS; 188 res->start = res->end = MAX_DMA_CHANNELS;
229#endif 189#endif
230 res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; 190 res->flags |= IORESOURCE_DISABLED;
231 dev_dbg(&dev->dev, " disable dma %d\n", idx); 191 dev_dbg(&dev->dev, " disable dma %d\n", idx);
232}
233 192
234void pnp_init_resource(struct resource *res) 193__add:
235{ 194 pnp_add_dma_resource(dev, res->start, res->flags);
236 unsigned long type;
237
238 type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
239 IORESOURCE_IRQ | IORESOURCE_DMA);
240
241 res->name = NULL;
242 res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET;
243 if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) {
244 res->start = -1;
245 res->end = -1;
246 } else {
247 res->start = 0;
248 res->end = 0;
249 }
250} 195}
251 196
252/**
253 * pnp_init_resources - Resets a resource table to default values.
254 * @table: pointer to the desired resource table
255 */
256void pnp_init_resources(struct pnp_dev *dev) 197void pnp_init_resources(struct pnp_dev *dev)
257{ 198{
258 struct resource *res; 199 pnp_free_resources(dev);
259 int idx;
260
261 for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
262 res = &dev->res->irq[idx].res;
263 res->flags = IORESOURCE_IRQ;
264 pnp_init_resource(res);
265 }
266 for (idx = 0; idx < PNP_MAX_DMA; idx++) {
267 res = &dev->res->dma[idx].res;
268 res->flags = IORESOURCE_DMA;
269 pnp_init_resource(res);
270 }
271 for (idx = 0; idx < PNP_MAX_PORT; idx++) {
272 res = &dev->res->port[idx].res;
273 res->flags = IORESOURCE_IO;
274 pnp_init_resource(res);
275 }
276 for (idx = 0; idx < PNP_MAX_MEM; idx++) {
277 res = &dev->res->mem[idx].res;
278 res->flags = IORESOURCE_MEM;
279 pnp_init_resource(res);
280 }
281} 200}
282 201
283/**
284 * pnp_clean_resources - clears resources that were not manually set
285 * @res: the resources to clean
286 */
287static void pnp_clean_resource_table(struct pnp_dev *dev) 202static void pnp_clean_resource_table(struct pnp_dev *dev)
288{ 203{
289 struct resource *res; 204 struct pnp_resource *pnp_res, *tmp;
290 int idx; 205
291 206 list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
292 for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 207 if (pnp_res->res.flags & IORESOURCE_AUTO)
293 res = &dev->res->irq[idx].res; 208 pnp_free_resource(pnp_res);
294 if (res->flags & IORESOURCE_AUTO) {
295 res->flags = IORESOURCE_IRQ;
296 pnp_init_resource(res);
297 }
298 }
299 for (idx = 0; idx < PNP_MAX_DMA; idx++) {
300 res = &dev->res->dma[idx].res;
301 if (res->flags & IORESOURCE_AUTO) {
302 res->flags = IORESOURCE_DMA;
303 pnp_init_resource(res);
304 }
305 }
306 for (idx = 0; idx < PNP_MAX_PORT; idx++) {
307 res = &dev->res->port[idx].res;
308 if (res->flags & IORESOURCE_AUTO) {
309 res->flags = IORESOURCE_IO;
310 pnp_init_resource(res);
311 }
312 }
313 for (idx = 0; idx < PNP_MAX_MEM; idx++) {
314 res = &dev->res->mem[idx].res;
315 if (res->flags & IORESOURCE_AUTO) {
316 res->flags = IORESOURCE_MEM;
317 pnp_init_resource(res);
318 }
319 } 209 }
320} 210}
321 211
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 46c791adb894..9a45c25b46d2 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -806,6 +806,13 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
806 struct acpi_resource_irq *irq = &resource->data.irq; 806 struct acpi_resource_irq *irq = &resource->data.irq;
807 int triggering, polarity, shareable; 807 int triggering, polarity, shareable;
808 808
809 if (!pnp_resource_enabled(p)) {
810 irq->interrupt_count = 0;
811 dev_dbg(&dev->dev, " encode irq (%s)\n",
812 p ? "disabled" : "missing");
813 return;
814 }
815
809 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); 816 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
810 irq->triggering = triggering; 817 irq->triggering = triggering;
811 irq->polarity = polarity; 818 irq->polarity = polarity;
@@ -828,6 +835,13 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
828 struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; 835 struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
829 int triggering, polarity, shareable; 836 int triggering, polarity, shareable;
830 837
838 if (!pnp_resource_enabled(p)) {
839 extended_irq->interrupt_count = 0;
840 dev_dbg(&dev->dev, " encode extended irq (%s)\n",
841 p ? "disabled" : "missing");
842 return;
843 }
844
831 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); 845 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
832 extended_irq->producer_consumer = ACPI_CONSUMER; 846 extended_irq->producer_consumer = ACPI_CONSUMER;
833 extended_irq->triggering = triggering; 847 extended_irq->triggering = triggering;
@@ -848,6 +862,13 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev,
848{ 862{
849 struct acpi_resource_dma *dma = &resource->data.dma; 863 struct acpi_resource_dma *dma = &resource->data.dma;
850 864
865 if (!pnp_resource_enabled(p)) {
866 dma->channel_count = 0;
867 dev_dbg(&dev->dev, " encode dma (%s)\n",
868 p ? "disabled" : "missing");
869 return;
870 }
871
851 /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ 872 /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
852 switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { 873 switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
853 case IORESOURCE_DMA_TYPEA: 874 case IORESOURCE_DMA_TYPEA:
@@ -889,17 +910,21 @@ static void pnpacpi_encode_io(struct pnp_dev *dev,
889{ 910{
890 struct acpi_resource_io *io = &resource->data.io; 911 struct acpi_resource_io *io = &resource->data.io;
891 912
892 /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ 913 if (pnp_resource_enabled(p)) {
893 io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? 914 /* Note: pnp_assign_port copies pnp_port->flags into p->flags */
894 ACPI_DECODE_16 : ACPI_DECODE_10; 915 io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
895 io->minimum = p->start; 916 ACPI_DECODE_16 : ACPI_DECODE_10;
896 io->maximum = p->end; 917 io->minimum = p->start;
897 io->alignment = 0; /* Correct? */ 918 io->maximum = p->end;
898 io->address_length = p->end - p->start + 1; 919 io->alignment = 0; /* Correct? */
899 920 io->address_length = p->end - p->start + 1;
900 dev_dbg(&dev->dev, " encode io %#llx-%#llx decode %#x\n", 921 } else {
901 (unsigned long long) p->start, (unsigned long long) p->end, 922 io->minimum = 0;
902 io->io_decode); 923 io->address_length = 0;
924 }
925
926 dev_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum,
927 io->minimum + io->address_length - 1, io->io_decode);
903} 928}
904 929
905static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, 930static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
@@ -908,11 +933,16 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
908{ 933{
909 struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io; 934 struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
910 935
911 fixed_io->address = p->start; 936 if (pnp_resource_enabled(p)) {
912 fixed_io->address_length = p->end - p->start + 1; 937 fixed_io->address = p->start;
938 fixed_io->address_length = p->end - p->start + 1;
939 } else {
940 fixed_io->address = 0;
941 fixed_io->address_length = 0;
942 }
913 943
914 dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", 944 dev_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address,
915 (unsigned long long) p->start, (unsigned long long) p->end); 945 fixed_io->address + fixed_io->address_length - 1);
916} 946}
917 947
918static void pnpacpi_encode_mem24(struct pnp_dev *dev, 948static void pnpacpi_encode_mem24(struct pnp_dev *dev,
@@ -921,17 +951,22 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev,
921{ 951{
922 struct acpi_resource_memory24 *memory24 = &resource->data.memory24; 952 struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
923 953
924 /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ 954 if (pnp_resource_enabled(p)) {
925 memory24->write_protect = 955 /* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */
926 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 956 memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
927 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 957 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
928 memory24->minimum = p->start; 958 memory24->minimum = p->start;
929 memory24->maximum = p->end; 959 memory24->maximum = p->end;
930 memory24->alignment = 0; 960 memory24->alignment = 0;
931 memory24->address_length = p->end - p->start + 1; 961 memory24->address_length = p->end - p->start + 1;
932 962 } else {
933 dev_dbg(&dev->dev, " encode mem24 %#llx-%#llx write_protect %#x\n", 963 memory24->minimum = 0;
934 (unsigned long long) p->start, (unsigned long long) p->end, 964 memory24->address_length = 0;
965 }
966
967 dev_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n",
968 memory24->minimum,
969 memory24->minimum + memory24->address_length - 1,
935 memory24->write_protect); 970 memory24->write_protect);
936} 971}
937 972
@@ -941,16 +976,21 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev,
941{ 976{
942 struct acpi_resource_memory32 *memory32 = &resource->data.memory32; 977 struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
943 978
944 memory32->write_protect = 979 if (pnp_resource_enabled(p)) {
945 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 980 memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
946 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 981 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
947 memory32->minimum = p->start; 982 memory32->minimum = p->start;
948 memory32->maximum = p->end; 983 memory32->maximum = p->end;
949 memory32->alignment = 0; 984 memory32->alignment = 0;
950 memory32->address_length = p->end - p->start + 1; 985 memory32->address_length = p->end - p->start + 1;
986 } else {
987 memory32->minimum = 0;
988 memory32->alignment = 0;
989 }
951 990
952 dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx write_protect %#x\n", 991 dev_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n",
953 (unsigned long long) p->start, (unsigned long long) p->end, 992 memory32->minimum,
993 memory32->minimum + memory32->address_length - 1,
954 memory32->write_protect); 994 memory32->write_protect);
955} 995}
956 996
@@ -960,15 +1000,20 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
960{ 1000{
961 struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32; 1001 struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
962 1002
963 fixed_memory32->write_protect = 1003 if (pnp_resource_enabled(p)) {
964 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 1004 fixed_memory32->write_protect =
965 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 1005 p->flags & IORESOURCE_MEM_WRITEABLE ?
966 fixed_memory32->address = p->start; 1006 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
967 fixed_memory32->address_length = p->end - p->start + 1; 1007 fixed_memory32->address = p->start;
1008 fixed_memory32->address_length = p->end - p->start + 1;
1009 } else {
1010 fixed_memory32->address = 0;
1011 fixed_memory32->address_length = 0;
1012 }
968 1013
969 dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx " 1014 dev_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n",
970 "write_protect %#x\n", 1015 fixed_memory32->address,
971 (unsigned long long) p->start, (unsigned long long) p->end, 1016 fixed_memory32->address + fixed_memory32->address_length - 1,
972 fixed_memory32->write_protect); 1017 fixed_memory32->write_protect);
973} 1018}
974 1019
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index 5ff9a4c0447e..01f0c3dd1b08 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -526,8 +526,16 @@ len_err:
526static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, 526static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
527 struct resource *res) 527 struct resource *res)
528{ 528{
529 unsigned long base = res->start; 529 unsigned long base;
530 unsigned long len = res->end - res->start + 1; 530 unsigned long len;
531
532 if (pnp_resource_enabled(res)) {
533 base = res->start;
534 len = res->end - res->start + 1;
535 } else {
536 base = 0;
537 len = 0;
538 }
531 539
532 p[4] = (base >> 8) & 0xff; 540 p[4] = (base >> 8) & 0xff;
533 p[5] = ((base >> 8) >> 8) & 0xff; 541 p[5] = ((base >> 8) >> 8) & 0xff;
@@ -536,15 +544,22 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
536 p[10] = (len >> 8) & 0xff; 544 p[10] = (len >> 8) & 0xff;
537 p[11] = ((len >> 8) >> 8) & 0xff; 545 p[11] = ((len >> 8) >> 8) & 0xff;
538 546
539 dev_dbg(&dev->dev, " encode mem %#llx-%#llx\n", 547 dev_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1);
540 (unsigned long long) res->start, (unsigned long long) res->end);
541} 548}
542 549
543static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, 550static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
544 struct resource *res) 551 struct resource *res)
545{ 552{
546 unsigned long base = res->start; 553 unsigned long base;
547 unsigned long len = res->end - res->start + 1; 554 unsigned long len;
555
556 if (pnp_resource_enabled(res)) {
557 base = res->start;
558 len = res->end - res->start + 1;
559 } else {
560 base = 0;
561 len = 0;
562 }
548 563
549 p[4] = base & 0xff; 564 p[4] = base & 0xff;
550 p[5] = (base >> 8) & 0xff; 565 p[5] = (base >> 8) & 0xff;
@@ -559,15 +574,22 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
559 p[18] = (len >> 16) & 0xff; 574 p[18] = (len >> 16) & 0xff;
560 p[19] = (len >> 24) & 0xff; 575 p[19] = (len >> 24) & 0xff;
561 576
562 dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx\n", 577 dev_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1);
563 (unsigned long long) res->start, (unsigned long long) res->end);
564} 578}
565 579
566static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, 580static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
567 struct resource *res) 581 struct resource *res)
568{ 582{
569 unsigned long base = res->start; 583 unsigned long base;
570 unsigned long len = res->end - res->start + 1; 584 unsigned long len;
585
586 if (pnp_resource_enabled(res)) {
587 base = res->start;
588 len = res->end - res->start + 1;
589 } else {
590 base = 0;
591 len = 0;
592 }
571 593
572 p[4] = base & 0xff; 594 p[4] = base & 0xff;
573 p[5] = (base >> 8) & 0xff; 595 p[5] = (base >> 8) & 0xff;
@@ -578,40 +600,54 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
578 p[10] = (len >> 16) & 0xff; 600 p[10] = (len >> 16) & 0xff;
579 p[11] = (len >> 24) & 0xff; 601 p[11] = (len >> 24) & 0xff;
580 602
581 dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx\n", 603 dev_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base,
582 (unsigned long long) res->start, (unsigned long long) res->end); 604 base + len - 1);
583} 605}
584 606
585static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p, 607static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
586 struct resource *res) 608 struct resource *res)
587{ 609{
588 unsigned long map = 0; 610 unsigned long map;
611
612 if (pnp_resource_enabled(res))
613 map = 1 << res->start;
614 else
615 map = 0;
589 616
590 map = 1 << res->start;
591 p[1] = map & 0xff; 617 p[1] = map & 0xff;
592 p[2] = (map >> 8) & 0xff; 618 p[2] = (map >> 8) & 0xff;
593 619
594 dev_dbg(&dev->dev, " encode irq %llu\n", 620 dev_dbg(&dev->dev, " encode irq mask %#lx\n", map);
595 (unsigned long long)res->start);
596} 621}
597 622
598static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p, 623static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
599 struct resource *res) 624 struct resource *res)
600{ 625{
601 unsigned long map = 0; 626 unsigned long map;
627
628 if (pnp_resource_enabled(res))
629 map = 1 << res->start;
630 else
631 map = 0;
602 632
603 map = 1 << res->start;
604 p[1] = map & 0xff; 633 p[1] = map & 0xff;
605 634
606 dev_dbg(&dev->dev, " encode dma %llu\n", 635 dev_dbg(&dev->dev, " encode dma mask %#lx\n", map);
607 (unsigned long long)res->start);
608} 636}
609 637
610static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, 638static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
611 struct resource *res) 639 struct resource *res)
612{ 640{
613 unsigned long base = res->start; 641 unsigned long base;
614 unsigned long len = res->end - res->start + 1; 642 unsigned long len;
643
644 if (pnp_resource_enabled(res)) {
645 base = res->start;
646 len = res->end - res->start + 1;
647 } else {
648 base = 0;
649 len = 0;
650 }
615 651
616 p[2] = base & 0xff; 652 p[2] = base & 0xff;
617 p[3] = (base >> 8) & 0xff; 653 p[3] = (base >> 8) & 0xff;
@@ -619,8 +655,7 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
619 p[5] = (base >> 8) & 0xff; 655 p[5] = (base >> 8) & 0xff;
620 p[7] = len & 0xff; 656 p[7] = len & 0xff;
621 657
622 dev_dbg(&dev->dev, " encode io %#llx-%#llx\n", 658 dev_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1);
623 (unsigned long long) res->start, (unsigned long long) res->end);
624} 659}
625 660
626static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, 661static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
@@ -629,12 +664,20 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
629 unsigned long base = res->start; 664 unsigned long base = res->start;
630 unsigned long len = res->end - res->start + 1; 665 unsigned long len = res->end - res->start + 1;
631 666
667 if (pnp_resource_enabled(res)) {
668 base = res->start;
669 len = res->end - res->start + 1;
670 } else {
671 base = 0;
672 len = 0;
673 }
674
632 p[1] = base & 0xff; 675 p[1] = base & 0xff;
633 p[2] = (base >> 8) & 0xff; 676 p[2] = (base >> 8) & 0xff;
634 p[3] = len & 0xff; 677 p[3] = len & 0xff;
635 678
636 dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", 679 dev_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base,
637 (unsigned long long) res->start, (unsigned long long) res->end); 680 base + len - 1);
638} 681}
639 682
640static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev 683static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 1ff3bb585ab2..21acb54eff6d 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -248,8 +248,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
248 for (j = 0; 248 for (j = 0;
249 (res = pnp_get_resource(dev, IORESOURCE_MEM, j)); 249 (res = pnp_get_resource(dev, IORESOURCE_MEM, j));
250 j++) { 250 j++) {
251 if (res->flags & IORESOURCE_UNSET || 251 if (res->start == 0 && res->end == 0)
252 (res->start == 0 && res->end == 0))
253 continue; 252 continue;
254 253
255 pnp_start = res->start; 254 pnp_start = res->start;
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index cce341f743d4..0797a77bd042 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -237,7 +237,7 @@ void pnp_free_option(struct pnp_option *option)
237 !((*(enda) < *(startb)) || (*(endb) < *(starta))) 237 !((*(enda) < *(startb)) || (*(endb) < *(starta)))
238 238
239#define cannot_compare(flags) \ 239#define cannot_compare(flags) \
240((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) 240((flags) & IORESOURCE_DISABLED)
241 241
242int pnp_check_port(struct pnp_dev *dev, struct resource *res) 242int pnp_check_port(struct pnp_dev *dev, struct resource *res)
243{ 243{
@@ -505,81 +505,31 @@ int pnp_resource_type(struct resource *res)
505 IORESOURCE_IRQ | IORESOURCE_DMA); 505 IORESOURCE_IRQ | IORESOURCE_DMA);
506} 506}
507 507
508struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
509 unsigned int type, unsigned int num)
510{
511 struct pnp_resource_table *res = dev->res;
512
513 switch (type) {
514 case IORESOURCE_IO:
515 if (num >= PNP_MAX_PORT)
516 return NULL;
517 return &res->port[num];
518 case IORESOURCE_MEM:
519 if (num >= PNP_MAX_MEM)
520 return NULL;
521 return &res->mem[num];
522 case IORESOURCE_IRQ:
523 if (num >= PNP_MAX_IRQ)
524 return NULL;
525 return &res->irq[num];
526 case IORESOURCE_DMA:
527 if (num >= PNP_MAX_DMA)
528 return NULL;
529 return &res->dma[num];
530 }
531 return NULL;
532}
533
534struct resource *pnp_get_resource(struct pnp_dev *dev, 508struct resource *pnp_get_resource(struct pnp_dev *dev,
535 unsigned int type, unsigned int num) 509 unsigned int type, unsigned int num)
536{ 510{
537 struct pnp_resource *pnp_res; 511 struct pnp_resource *pnp_res;
512 struct resource *res;
538 513
539 pnp_res = pnp_get_pnp_resource(dev, type, num); 514 list_for_each_entry(pnp_res, &dev->resources, list) {
540 if (pnp_res) 515 res = &pnp_res->res;
541 return &pnp_res->res; 516 if (pnp_resource_type(res) == type && num-- == 0)
542 517 return res;
518 }
543 return NULL; 519 return NULL;
544} 520}
545EXPORT_SYMBOL(pnp_get_resource); 521EXPORT_SYMBOL(pnp_get_resource);
546 522
547static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type) 523static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
548{ 524{
549 struct pnp_resource *pnp_res; 525 struct pnp_resource *pnp_res;
550 int i;
551 526
552 switch (type) { 527 pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
553 case IORESOURCE_IO: 528 if (!pnp_res)
554 for (i = 0; i < PNP_MAX_PORT; i++) { 529 return NULL;
555 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i); 530
556 if (pnp_res && !pnp_resource_valid(&pnp_res->res)) 531 list_add_tail(&pnp_res->list, &dev->resources);
557 return pnp_res; 532 return pnp_res;
558 }
559 break;
560 case IORESOURCE_MEM:
561 for (i = 0; i < PNP_MAX_MEM; i++) {
562 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i);
563 if (pnp_res && !pnp_resource_valid(&pnp_res->res))
564 return pnp_res;
565 }
566 break;
567 case IORESOURCE_IRQ:
568 for (i = 0; i < PNP_MAX_IRQ; i++) {
569 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i);
570 if (pnp_res && !pnp_resource_valid(&pnp_res->res))
571 return pnp_res;
572 }
573 break;
574 case IORESOURCE_DMA:
575 for (i = 0; i < PNP_MAX_DMA; i++) {
576 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i);
577 if (pnp_res && !pnp_resource_valid(&pnp_res->res))
578 return pnp_res;
579 }
580 break;
581 }
582 return NULL;
583} 533}
584 534
585struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, 535struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
@@ -589,7 +539,7 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
589 struct resource *res; 539 struct resource *res;
590 static unsigned char warned; 540 static unsigned char warned;
591 541
592 pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ); 542 pnp_res = pnp_new_resource(dev);
593 if (!pnp_res) { 543 if (!pnp_res) {
594 if (!warned) { 544 if (!warned) {
595 dev_err(&dev->dev, "can't add resource for IRQ %d\n", 545 dev_err(&dev->dev, "can't add resource for IRQ %d\n",
@@ -615,7 +565,7 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
615 struct resource *res; 565 struct resource *res;
616 static unsigned char warned; 566 static unsigned char warned;
617 567
618 pnp_res = pnp_new_resource(dev, IORESOURCE_DMA); 568 pnp_res = pnp_new_resource(dev);
619 if (!pnp_res) { 569 if (!pnp_res) {
620 if (!warned) { 570 if (!warned) {
621 dev_err(&dev->dev, "can't add resource for DMA %d\n", 571 dev_err(&dev->dev, "can't add resource for DMA %d\n",
@@ -642,7 +592,7 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
642 struct resource *res; 592 struct resource *res;
643 static unsigned char warned; 593 static unsigned char warned;
644 594
645 pnp_res = pnp_new_resource(dev, IORESOURCE_IO); 595 pnp_res = pnp_new_resource(dev);
646 if (!pnp_res) { 596 if (!pnp_res) {
647 if (!warned) { 597 if (!warned) {
648 dev_err(&dev->dev, "can't add resource for IO " 598 dev_err(&dev->dev, "can't add resource for IO "
@@ -671,7 +621,7 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
671 struct resource *res; 621 struct resource *res;
672 static unsigned char warned; 622 static unsigned char warned;
673 623
674 pnp_res = pnp_new_resource(dev, IORESOURCE_MEM); 624 pnp_res = pnp_new_resource(dev);
675 if (!pnp_res) { 625 if (!pnp_res) {
676 if (!warned) { 626 if (!warned) {
677 dev_err(&dev->dev, "can't add resource for MEM " 627 dev_err(&dev->dev, "can't add resource for MEM "
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
index eb07345f5cf7..1566e4a73849 100644
--- a/drivers/pnp/support.c
+++ b/drivers/pnp/support.c
@@ -16,6 +16,10 @@
16 */ 16 */
17int pnp_is_active(struct pnp_dev *dev) 17int pnp_is_active(struct pnp_dev *dev)
18{ 18{
19 /*
20 * I don't think this is very reliable because pnp_disable_dev()
21 * only clears out auto-assigned resources.
22 */
19 if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 && 23 if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 &&
20 !pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 && 24 !pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 &&
21 pnp_irq(dev, 0) == -1 && pnp_dma(dev, 0) == -1) 25 pnp_irq(dev, 0) == -1 && pnp_dma(dev, 0) == -1)
@@ -70,54 +74,41 @@ char *pnp_resource_type_name(struct resource *res)
70void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) 74void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
71{ 75{
72#ifdef DEBUG 76#ifdef DEBUG
77 char buf[128];
78 int len = 0;
79 struct pnp_resource *pnp_res;
73 struct resource *res; 80 struct resource *res;
74 int i;
75 81
76 dev_dbg(&dev->dev, "current resources: %s\n", desc); 82 dev_dbg(&dev->dev, "current resources: %s\n", desc);
83 list_for_each_entry(pnp_res, &dev->resources, list) {
84 res = &pnp_res->res;
77 85
78 for (i = 0; i < PNP_MAX_IRQ; i++) { 86 len += snprintf(buf + len, sizeof(buf) - len, " %-3s ",
79 res = pnp_get_resource(dev, IORESOURCE_IRQ, i); 87 pnp_resource_type_name(res));
80 if (res && !(res->flags & IORESOURCE_UNSET)) 88
81 dev_dbg(&dev->dev, " irq %lld flags %#lx%s%s\n", 89 if (res->flags & IORESOURCE_DISABLED) {
82 (unsigned long long) res->start, res->flags, 90 dev_dbg(&dev->dev, "%sdisabled\n", buf);
83 res->flags & IORESOURCE_DISABLED ? 91 continue;
84 " DISABLED" : "", 92 }
85 res->flags & IORESOURCE_AUTO ? 93
86 " AUTO" : ""); 94 switch (pnp_resource_type(res)) {
87 } 95 case IORESOURCE_IO:
88 for (i = 0; i < PNP_MAX_DMA; i++) { 96 case IORESOURCE_MEM:
89 res = pnp_get_resource(dev, IORESOURCE_DMA, i); 97 len += snprintf(buf + len, sizeof(buf) - len,
90 if (res && !(res->flags & IORESOURCE_UNSET)) 98 "%#llx-%#llx flags %#lx",
91 dev_dbg(&dev->dev, " dma %lld flags %#lx%s%s\n", 99 (unsigned long long) res->start,
92 (unsigned long long) res->start, res->flags, 100 (unsigned long long) res->end,
93 res->flags & IORESOURCE_DISABLED ? 101 res->flags);
94 " DISABLED" : "", 102 break;
95 res->flags & IORESOURCE_AUTO ? 103 case IORESOURCE_IRQ:
96 " AUTO" : ""); 104 case IORESOURCE_DMA:
97 } 105 len += snprintf(buf + len, sizeof(buf) - len,
98 for (i = 0; i < PNP_MAX_PORT; i++) { 106 "%lld flags %#lx",
99 res = pnp_get_resource(dev, IORESOURCE_IO, i); 107 (unsigned long long) res->start,
100 if (res && !(res->flags & IORESOURCE_UNSET)) 108 res->flags);
101 dev_dbg(&dev->dev, " io %#llx-%#llx flags %#lx" 109 break;
102 "%s%s\n", 110 }
103 (unsigned long long) res->start, 111 dev_dbg(&dev->dev, "%s\n", buf);
104 (unsigned long long) res->end, res->flags,
105 res->flags & IORESOURCE_DISABLED ?
106 " DISABLED" : "",
107 res->flags & IORESOURCE_AUTO ?
108 " AUTO" : "");
109 }
110 for (i = 0; i < PNP_MAX_MEM; i++) {
111 res = pnp_get_resource(dev, IORESOURCE_MEM, i);
112 if (res && !(res->flags & IORESOURCE_UNSET))
113 dev_dbg(&dev->dev, " mem %#llx-%#llx flags %#lx"
114 "%s%s\n",
115 (unsigned long long) res->start,
116 (unsigned long long) res->end, res->flags,
117 res->flags & IORESOURCE_DISABLED ?
118 " DISABLED" : "",
119 res->flags & IORESOURCE_AUTO ?
120 " AUTO" : "");
121 } 112 }
122#endif 113#endif
123} 114}
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index cf4e07b01d48..764f3a310685 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -60,7 +60,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
60 int i; 60 int i;
61 61
62 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { 62 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
63 if (res->flags & IORESOURCE_UNSET) 63 if (res->flags & IORESOURCE_DISABLED)
64 continue; 64 continue;
65 if (res->start == 0) 65 if (res->start == 0)
66 continue; /* disabled */ 66 continue; /* disabled */
@@ -81,7 +81,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
81 } 81 }
82 82
83 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { 83 for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
84 if (res->flags & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) 84 if (res->flags & IORESOURCE_DISABLED)
85 continue; 85 continue;
86 86
87 reserve_range(dev, res->start, res->end, 0); 87 reserve_range(dev, res->start, res->end, 0);
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index 8b607aecd959..dfaa567e04a8 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -15,7 +15,6 @@
15 15
16struct pnp_protocol; 16struct pnp_protocol;
17struct pnp_dev; 17struct pnp_dev;
18struct pnp_resource_table;
19 18
20/* 19/*
21 * Resource Management 20 * Resource Management
@@ -24,7 +23,14 @@ struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int);
24 23
25static inline int pnp_resource_valid(struct resource *res) 24static inline int pnp_resource_valid(struct resource *res)
26{ 25{
27 if (res && !(res->flags & IORESOURCE_UNSET)) 26 if (res)
27 return 1;
28 return 0;
29}
30
31static inline int pnp_resource_enabled(struct resource *res)
32{
33 if (res && !(res->flags & IORESOURCE_DISABLED))
28 return 1; 34 return 1;
29 return 0; 35 return 0;
30} 36}
@@ -64,7 +70,7 @@ static inline unsigned long pnp_port_flags(struct pnp_dev *dev,
64 70
65 if (pnp_resource_valid(res)) 71 if (pnp_resource_valid(res))
66 return res->flags; 72 return res->flags;
67 return IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; 73 return IORESOURCE_IO | IORESOURCE_AUTO;
68} 74}
69 75
70static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar) 76static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar)
@@ -109,7 +115,7 @@ static inline unsigned long pnp_mem_flags(struct pnp_dev *dev, unsigned int bar)
109 115
110 if (pnp_resource_valid(res)) 116 if (pnp_resource_valid(res))
111 return res->flags; 117 return res->flags;
112 return IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; 118 return IORESOURCE_MEM | IORESOURCE_AUTO;
113} 119}
114 120
115static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar) 121static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar)
@@ -143,7 +149,7 @@ static inline unsigned long pnp_irq_flags(struct pnp_dev *dev, unsigned int bar)
143 149
144 if (pnp_resource_valid(res)) 150 if (pnp_resource_valid(res))
145 return res->flags; 151 return res->flags;
146 return IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; 152 return IORESOURCE_IRQ | IORESOURCE_AUTO;
147} 153}
148 154
149static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar) 155static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar)
@@ -167,7 +173,7 @@ static inline unsigned long pnp_dma_flags(struct pnp_dev *dev, unsigned int bar)
167 173
168 if (pnp_resource_valid(res)) 174 if (pnp_resource_valid(res))
169 return res->flags; 175 return res->flags;
170 return IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; 176 return IORESOURCE_DMA | IORESOURCE_AUTO;
171} 177}
172 178
173static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar) 179static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar)
@@ -296,7 +302,7 @@ struct pnp_dev {
296 int capabilities; 302 int capabilities;
297 struct pnp_option *independent; 303 struct pnp_option *independent;
298 struct pnp_option *dependent; 304 struct pnp_option *dependent;
299 struct pnp_resource_table *res; 305 struct list_head resources;
300 306
301 char name[PNP_NAME_LEN]; /* contains a human-readable name */ 307 char name[PNP_NAME_LEN]; /* contains a human-readable name */
302 int flags; /* used by protocols */ 308 int flags; /* used by protocols */