aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2008-04-28 18:34:32 -0400
committerLen Brown <len.brown@intel.com>2008-04-29 03:22:28 -0400
commit21855d69d1e3ace3efdb8159a4a7ab1ab98a6f19 (patch)
treebfa5bc70ab7dabe5e4117fde96199df6c05cd261 /drivers/pnp
parent0a977f15469457d9a19eed992caf71995c674064 (diff)
PNP: add pnp_resource index for ISAPNP
Save the ISAPNP config register index in the struct pnp_resource. We need this because it is important to write ISAPNP configuration back to the same registers we read it from. For example, if we read valid regions from memory descriptors 0, 1, and 3, we'd better write them back to the same registers, without compressing them to descriptors 0, 1, and 2. This was previously guaranteed by using the index into the pnp_resource_table array as the ISAPNP config register index. However, I am removing those fixed-size arrays, so we need to save the ISAPNP register index elsewhere. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pnp')
-rw-r--r--drivers/pnp/base.h1
-rw-r--r--drivers/pnp/interface.c33
-rw-r--r--drivers/pnp/isapnp/core.c63
-rw-r--r--drivers/pnp/manager.c32
4 files changed, 92 insertions, 37 deletions
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 49b4138f3476..786735770684 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -31,6 +31,7 @@ struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
31 31
32struct pnp_resource { 32struct pnp_resource {
33 struct resource res; 33 struct resource res;
34 unsigned int index; /* ISAPNP config register index */
34}; 35};
35 36
36struct pnp_resource_table { 37struct pnp_resource_table {
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index e9e66ed4fa31..ead151242a64 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -320,6 +320,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
320 const char *ubuf, size_t count) 320 const char *ubuf, size_t count)
321{ 321{
322 struct pnp_dev *dev = to_pnp_dev(dmdev); 322 struct pnp_dev *dev = to_pnp_dev(dmdev);
323 struct pnp_resource *pnp_res;
323 struct resource *res; 324 struct resource *res;
324 char *buf = (void *)ubuf; 325 char *buf = (void *)ubuf;
325 int retval = 0; 326 int retval = 0;
@@ -380,10 +381,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
380 buf += 2; 381 buf += 2;
381 while (isspace(*buf)) 382 while (isspace(*buf))
382 ++buf; 383 ++buf;
383 res = pnp_get_resource(dev, IORESOURCE_IO, 384 pnp_res = pnp_get_pnp_resource(dev,
384 nport); 385 IORESOURCE_IO, nport);
385 if (!res) 386 if (!pnp_res)
386 break; 387 break;
388 pnp_res->index = nport;
389 res = &pnp_res->res;
387 res->start = simple_strtoul(buf, &buf, 0); 390 res->start = simple_strtoul(buf, &buf, 0);
388 while (isspace(*buf)) 391 while (isspace(*buf))
389 ++buf; 392 ++buf;
@@ -402,10 +405,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
402 buf += 3; 405 buf += 3;
403 while (isspace(*buf)) 406 while (isspace(*buf))
404 ++buf; 407 ++buf;
405 res = pnp_get_resource(dev, IORESOURCE_MEM, 408 pnp_res = pnp_get_pnp_resource(dev,
406 nmem); 409 IORESOURCE_MEM, nmem);
407 if (!res) 410 if (!pnp_res)
408 break; 411 break;
412 pnp_res->index = nmem;
413 res = &pnp_res->res;
409 res->start = simple_strtoul(buf, &buf, 0); 414 res->start = simple_strtoul(buf, &buf, 0);
410 while (isspace(*buf)) 415 while (isspace(*buf))
411 ++buf; 416 ++buf;
@@ -424,10 +429,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
424 buf += 3; 429 buf += 3;
425 while (isspace(*buf)) 430 while (isspace(*buf))
426 ++buf; 431 ++buf;
427 res = pnp_get_resource(dev, IORESOURCE_IRQ, 432 pnp_res = pnp_get_pnp_resource(dev,
428 nirq); 433 IORESOURCE_IRQ, nirq);
429 if (!res) 434 if (!pnp_res)
430 break; 435 break;
436 pnp_res->index = nirq;
437 res = &pnp_res->res;
431 res->start = res->end = 438 res->start = res->end =
432 simple_strtoul(buf, &buf, 0); 439 simple_strtoul(buf, &buf, 0);
433 res->flags = IORESOURCE_IRQ; 440 res->flags = IORESOURCE_IRQ;
@@ -438,10 +445,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
438 buf += 3; 445 buf += 3;
439 while (isspace(*buf)) 446 while (isspace(*buf))
440 ++buf; 447 ++buf;
441 res = pnp_get_resource(dev, IORESOURCE_DMA, 448 pnp_res = pnp_get_pnp_resource(dev,
442 ndma); 449 IORESOURCE_DMA, ndma);
443 if (!res) 450 if (!pnp_res)
444 break; 451 break;
452 pnp_res->index = ndma;
453 res = &pnp_res->res;
445 res->start = res->end = 454 res->start = res->end =
446 simple_strtoul(buf, &buf, 0); 455 simple_strtoul(buf, &buf, 0);
447 res->flags = IORESOURCE_DMA; 456 res->flags = IORESOURCE_DMA;
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index a62ecc6f13bd..f949a538ccde 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -931,6 +931,7 @@ EXPORT_SYMBOL(isapnp_write_byte);
931 931
932static int isapnp_read_resources(struct pnp_dev *dev) 932static int isapnp_read_resources(struct pnp_dev *dev)
933{ 933{
934 struct pnp_resource *pnp_res;
934 struct resource *res; 935 struct resource *res;
935 int tmp, ret; 936 int tmp, ret;
936 937
@@ -940,7 +941,9 @@ static int isapnp_read_resources(struct pnp_dev *dev)
940 ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1)); 941 ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
941 if (!ret) 942 if (!ret)
942 continue; 943 continue;
943 res = pnp_get_resource(dev, IORESOURCE_IO, tmp); 944 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp);
945 pnp_res->index = tmp;
946 res = &pnp_res->res;
944 res->start = ret; 947 res->start = ret;
945 res->flags = IORESOURCE_IO; 948 res->flags = IORESOURCE_IO;
946 } 949 }
@@ -949,7 +952,10 @@ static int isapnp_read_resources(struct pnp_dev *dev)
949 isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; 952 isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8;
950 if (!ret) 953 if (!ret)
951 continue; 954 continue;
952 res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); 955 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM,
956 tmp);
957 pnp_res->index = tmp;
958 res = &pnp_res->res;
953 res->start = ret; 959 res->start = ret;
954 res->flags = IORESOURCE_MEM; 960 res->flags = IORESOURCE_MEM;
955 } 961 }
@@ -959,7 +965,10 @@ static int isapnp_read_resources(struct pnp_dev *dev)
959 8); 965 8);
960 if (!ret) 966 if (!ret)
961 continue; 967 continue;
962 res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); 968 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ,
969 tmp);
970 pnp_res->index = tmp;
971 res = &pnp_res->res;
963 res->start = res->end = ret; 972 res->start = res->end = ret;
964 res->flags = IORESOURCE_IRQ; 973 res->flags = IORESOURCE_IRQ;
965 } 974 }
@@ -967,7 +976,10 @@ static int isapnp_read_resources(struct pnp_dev *dev)
967 ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); 976 ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
968 if (ret == 4) 977 if (ret == 4)
969 continue; 978 continue;
970 res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); 979 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA,
980 tmp);
981 pnp_res->index = tmp;
982 res = &pnp_res->res;
971 res->start = res->end = ret; 983 res->start = res->end = ret;
972 res->flags = IORESOURCE_DMA; 984 res->flags = IORESOURCE_DMA;
973 } 985 }
@@ -989,45 +1001,62 @@ static int isapnp_get_resources(struct pnp_dev *dev)
989 1001
990static int isapnp_set_resources(struct pnp_dev *dev) 1002static int isapnp_set_resources(struct pnp_dev *dev)
991{ 1003{
1004 struct pnp_resource *pnp_res;
992 struct resource *res; 1005 struct resource *res;
993 int tmp; 1006 int tmp, index;
994 1007
995 dev_dbg(&dev->dev, "set resources\n"); 1008 dev_dbg(&dev->dev, "set resources\n");
996 isapnp_cfg_begin(dev->card->number, dev->number); 1009 isapnp_cfg_begin(dev->card->number, dev->number);
997 dev->active = 1; 1010 dev->active = 1;
998 for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { 1011 for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
999 res = pnp_get_resource(dev, IORESOURCE_IO, tmp); 1012 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp);
1013 if (!pnp_res)
1014 continue;
1015 res = &pnp_res->res;
1000 if (pnp_resource_valid(res)) { 1016 if (pnp_resource_valid(res)) {
1017 index = pnp_res->index;
1001 dev_dbg(&dev->dev, " set io %d to %#llx\n", 1018 dev_dbg(&dev->dev, " set io %d to %#llx\n",
1002 tmp, (unsigned long long) res->start); 1019 index, (unsigned long long) res->start);
1003 isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), 1020 isapnp_write_word(ISAPNP_CFG_PORT + (index << 1),
1004 res->start); 1021 res->start);
1005 } 1022 }
1006 } 1023 }
1007 for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { 1024 for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
1008 res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); 1025 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp);
1026 if (!pnp_res)
1027 continue;
1028 res = &pnp_res->res;
1009 if (pnp_resource_valid(res)) { 1029 if (pnp_resource_valid(res)) {
1010 int irq = res->start; 1030 int irq = res->start;
1011 if (irq == 2) 1031 if (irq == 2)
1012 irq = 9; 1032 irq = 9;
1013 dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); 1033 index = pnp_res->index;
1014 isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); 1034 dev_dbg(&dev->dev, " set irq %d to %d\n", index, irq);
1035 isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq);
1015 } 1036 }
1016 } 1037 }
1017 for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { 1038 for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
1018 res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); 1039 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp);
1040 if (!pnp_res)
1041 continue;
1042 res = &pnp_res->res;
1019 if (pnp_resource_valid(res)) { 1043 if (pnp_resource_valid(res)) {
1044 index = pnp_res->index;
1020 dev_dbg(&dev->dev, " set dma %d to %lld\n", 1045 dev_dbg(&dev->dev, " set dma %d to %lld\n",
1021 tmp, (unsigned long long) res->start); 1046 index, (unsigned long long) res->start);
1022 isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start); 1047 isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start);
1023 } 1048 }
1024 } 1049 }
1025 for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { 1050 for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
1026 res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); 1051 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp);
1052 if (!pnp_res)
1053 continue;
1054 res = &pnp_res->res;
1027 if (pnp_resource_valid(res)) { 1055 if (pnp_resource_valid(res)) {
1056 index = pnp_res->index;
1028 dev_dbg(&dev->dev, " set mem %d to %#llx\n", 1057 dev_dbg(&dev->dev, " set mem %d to %#llx\n",
1029 tmp, (unsigned long long) res->start); 1058 index, (unsigned long long) res->start);
1030 isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), 1059 isapnp_write_word(ISAPNP_CFG_MEM + (index << 3),
1031 (res->start >> 8) & 0xffff); 1060 (res->start >> 8) & 0xffff);
1032 } 1061 }
1033 } 1062 }
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 4823da27e640..bea0914ff947 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -19,15 +19,18 @@ 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; 23 struct resource *res;
23 24
24 res = pnp_get_resource(dev, IORESOURCE_IO, idx); 25 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx);
25 if (!res) { 26 if (!pnp_res) {
26 dev_err(&dev->dev, "too many I/O port resources\n"); 27 dev_err(&dev->dev, "too many I/O port resources\n");
27 /* pretend we were successful so at least the manager won't try again */ 28 /* pretend we were successful so at least the manager won't try again */
28 return 1; 29 return 1;
29 } 30 }
30 31
32 res = &pnp_res->res;
33
31 /* check if this resource has been manually set, if so skip */ 34 /* check if this resource has been manually set, if so skip */
32 if (!(res->flags & IORESOURCE_AUTO)) { 35 if (!(res->flags & IORESOURCE_AUTO)) {
33 dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " 36 dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
@@ -37,6 +40,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
37 } 40 }
38 41
39 /* set the initial values */ 42 /* set the initial values */
43 pnp_res->index = idx;
40 res->flags |= rule->flags | IORESOURCE_IO; 44 res->flags |= rule->flags | IORESOURCE_IO;
41 res->flags &= ~IORESOURCE_UNSET; 45 res->flags &= ~IORESOURCE_UNSET;
42 46
@@ -65,15 +69,18 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
65 69
66static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) 70static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
67{ 71{
72 struct pnp_resource *pnp_res;
68 struct resource *res; 73 struct resource *res;
69 74
70 res = pnp_get_resource(dev, IORESOURCE_MEM, idx); 75 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx);
71 if (!res) { 76 if (!pnp_res) {
72 dev_err(&dev->dev, "too many memory resources\n"); 77 dev_err(&dev->dev, "too many memory resources\n");
73 /* pretend we were successful so at least the manager won't try again */ 78 /* pretend we were successful so at least the manager won't try again */
74 return 1; 79 return 1;
75 } 80 }
76 81
82 res = &pnp_res->res;
83
77 /* check if this resource has been manually set, if so skip */ 84 /* check if this resource has been manually set, if so skip */
78 if (!(res->flags & IORESOURCE_AUTO)) { 85 if (!(res->flags & IORESOURCE_AUTO)) {
79 dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " 86 dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
@@ -83,6 +90,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
83 } 90 }
84 91
85 /* set the initial values */ 92 /* set the initial values */
93 pnp_res->index = idx;
86 res->flags |= rule->flags | IORESOURCE_MEM; 94 res->flags |= rule->flags | IORESOURCE_MEM;
87 res->flags &= ~IORESOURCE_UNSET; 95 res->flags &= ~IORESOURCE_UNSET;
88 96
@@ -121,6 +129,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
121 129
122static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 130static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
123{ 131{
132 struct pnp_resource *pnp_res;
124 struct resource *res; 133 struct resource *res;
125 int i; 134 int i;
126 135
@@ -129,13 +138,15 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
129 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 138 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
130 }; 139 };
131 140
132 res = pnp_get_resource(dev, IORESOURCE_IRQ, idx); 141 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx);
133 if (!res) { 142 if (!pnp_res) {
134 dev_err(&dev->dev, "too many IRQ resources\n"); 143 dev_err(&dev->dev, "too many IRQ resources\n");
135 /* pretend we were successful so at least the manager won't try again */ 144 /* pretend we were successful so at least the manager won't try again */
136 return 1; 145 return 1;
137 } 146 }
138 147
148 res = &pnp_res->res;
149
139 /* check if this resource has been manually set, if so skip */ 150 /* check if this resource has been manually set, if so skip */
140 if (!(res->flags & IORESOURCE_AUTO)) { 151 if (!(res->flags & IORESOURCE_AUTO)) {
141 dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", 152 dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
@@ -144,6 +155,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
144 } 155 }
145 156
146 /* set the initial values */ 157 /* set the initial values */
158 pnp_res->index = idx;
147 res->flags |= rule->flags | IORESOURCE_IRQ; 159 res->flags |= rule->flags | IORESOURCE_IRQ;
148 res->flags &= ~IORESOURCE_UNSET; 160 res->flags &= ~IORESOURCE_UNSET;
149 161
@@ -177,6 +189,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
177 189
178static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 190static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
179{ 191{
192 struct pnp_resource *pnp_res;
180 struct resource *res; 193 struct resource *res;
181 int i; 194 int i;
182 195
@@ -185,12 +198,14 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
185 1, 3, 5, 6, 7, 0, 2, 4 198 1, 3, 5, 6, 7, 0, 2, 4
186 }; 199 };
187 200
188 res = pnp_get_resource(dev, IORESOURCE_DMA, idx); 201 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx);
189 if (!res) { 202 if (!pnp_res) {
190 dev_err(&dev->dev, "too many DMA resources\n"); 203 dev_err(&dev->dev, "too many DMA resources\n");
191 return; 204 return;
192 } 205 }
193 206
207 res = &pnp_res->res;
208
194 /* check if this resource has been manually set, if so skip */ 209 /* check if this resource has been manually set, if so skip */
195 if (!(res->flags & IORESOURCE_AUTO)) { 210 if (!(res->flags & IORESOURCE_AUTO)) {
196 dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", 211 dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
@@ -199,6 +214,7 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
199 } 214 }
200 215
201 /* set the initial values */ 216 /* set the initial values */
217 pnp_res->index = idx;
202 res->flags |= rule->flags | IORESOURCE_DMA; 218 res->flags |= rule->flags | IORESOURCE_DMA;
203 res->flags &= ~IORESOURCE_UNSET; 219 res->flags &= ~IORESOURCE_UNSET;
204 220