PNP: add pnp_resource index for ISAPNP
authorBjorn Helgaas <bjorn.helgaas@hp.com>
Mon, 28 Apr 2008 22:34:32 +0000 (16:34 -0600)
committerLen Brown <len.brown@intel.com>
Tue, 29 Apr 2008 07:22:28 +0000 (03:22 -0400)
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>
drivers/pnp/base.h
drivers/pnp/interface.c
drivers/pnp/isapnp/core.c
drivers/pnp/manager.c

index 49b4138f3476561950470ecd9a6e0cbb3e40687e..78673577068428594d5f1ca8dcc3d04e311e08ec 100644 (file)
@@ -31,6 +31,7 @@ struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
 
 struct pnp_resource {
        struct resource res;
+       unsigned int index;             /* ISAPNP config register index */
 };
 
 struct pnp_resource_table {
index e9e66ed4fa31ebffe75b87f8020b7bcd51fec434..ead151242a643c45d65dff9f87e4bae741aac085 100644 (file)
@@ -320,6 +320,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
                          const char *ubuf, size_t count)
 {
        struct pnp_dev *dev = to_pnp_dev(dmdev);
+       struct pnp_resource *pnp_res;
        struct resource *res;
        char *buf = (void *)ubuf;
        int retval = 0;
@@ -380,10 +381,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
                                buf += 2;
                                while (isspace(*buf))
                                        ++buf;
-                               res = pnp_get_resource(dev, IORESOURCE_IO,
-                                                      nport);
-                               if (!res)
+                               pnp_res = pnp_get_pnp_resource(dev,
+                                               IORESOURCE_IO, nport);
+                               if (!pnp_res)
                                        break;
+                               pnp_res->index = nport;
+                               res = &pnp_res->res;
                                res->start = simple_strtoul(buf, &buf, 0);
                                while (isspace(*buf))
                                        ++buf;
@@ -402,10 +405,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
                                buf += 3;
                                while (isspace(*buf))
                                        ++buf;
-                               res = pnp_get_resource(dev, IORESOURCE_MEM,
-                                                      nmem);
-                               if (!res)
+                               pnp_res = pnp_get_pnp_resource(dev,
+                                               IORESOURCE_MEM, nmem);
+                               if (!pnp_res)
                                        break;
+                               pnp_res->index = nmem;
+                               res = &pnp_res->res;
                                res->start = simple_strtoul(buf, &buf, 0);
                                while (isspace(*buf))
                                        ++buf;
@@ -424,10 +429,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
                                buf += 3;
                                while (isspace(*buf))
                                        ++buf;
-                               res = pnp_get_resource(dev, IORESOURCE_IRQ,
-                                                      nirq);
-                               if (!res)
+                               pnp_res = pnp_get_pnp_resource(dev,
+                                               IORESOURCE_IRQ, nirq);
+                               if (!pnp_res)
                                        break;
+                               pnp_res->index = nirq;
+                               res = &pnp_res->res;
                                res->start = res->end =
                                    simple_strtoul(buf, &buf, 0);
                                res->flags = IORESOURCE_IRQ;
@@ -438,10 +445,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
                                buf += 3;
                                while (isspace(*buf))
                                        ++buf;
-                               res = pnp_get_resource(dev, IORESOURCE_DMA,
-                                                      ndma);
-                               if (!res)
+                               pnp_res = pnp_get_pnp_resource(dev,
+                                               IORESOURCE_DMA, ndma);
+                               if (!pnp_res)
                                        break;
+                               pnp_res->index = ndma;
+                               res = &pnp_res->res;
                                res->start = res->end =
                                    simple_strtoul(buf, &buf, 0);
                                res->flags = IORESOURCE_DMA;
index a62ecc6f13bd5fc253d5903f8a9d5a1d8c4b568a..f949a538ccde4673333dc7ccf6eb7b6d6f80de44 100644 (file)
@@ -931,6 +931,7 @@ EXPORT_SYMBOL(isapnp_write_byte);
 
 static int isapnp_read_resources(struct pnp_dev *dev)
 {
+       struct pnp_resource *pnp_res;
        struct resource *res;
        int tmp, ret;
 
@@ -940,7 +941,9 @@ static int isapnp_read_resources(struct pnp_dev *dev)
                        ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
                        if (!ret)
                                continue;
-                       res = pnp_get_resource(dev, IORESOURCE_IO, tmp);
+                       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp);
+                       pnp_res->index = tmp;
+                       res = &pnp_res->res;
                        res->start = ret;
                        res->flags = IORESOURCE_IO;
                }
@@ -949,7 +952,10 @@ static int isapnp_read_resources(struct pnp_dev *dev)
                            isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8;
                        if (!ret)
                                continue;
-                       res = pnp_get_resource(dev, IORESOURCE_MEM, tmp);
+                       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM,
+                                                      tmp);
+                       pnp_res->index = tmp;
+                       res = &pnp_res->res;
                        res->start = ret;
                        res->flags = IORESOURCE_MEM;
                }
@@ -959,7 +965,10 @@ static int isapnp_read_resources(struct pnp_dev *dev)
                             8);
                        if (!ret)
                                continue;
-                       res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp);
+                       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ,
+                                                      tmp);
+                       pnp_res->index = tmp;
+                       res = &pnp_res->res;
                        res->start = res->end = ret;
                        res->flags = IORESOURCE_IRQ;
                }
@@ -967,7 +976,10 @@ static int isapnp_read_resources(struct pnp_dev *dev)
                        ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
                        if (ret == 4)
                                continue;
-                       res = pnp_get_resource(dev, IORESOURCE_DMA, tmp);
+                       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA,
+                                                      tmp);
+                       pnp_res->index = tmp;
+                       res = &pnp_res->res;
                        res->start = res->end = ret;
                        res->flags = IORESOURCE_DMA;
                }
@@ -989,45 +1001,62 @@ static int isapnp_get_resources(struct pnp_dev *dev)
 
 static int isapnp_set_resources(struct pnp_dev *dev)
 {
+       struct pnp_resource *pnp_res;
        struct resource *res;
-       int tmp;
+       int tmp, index;
 
        dev_dbg(&dev->dev, "set resources\n");
        isapnp_cfg_begin(dev->card->number, dev->number);
        dev->active = 1;
        for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
-               res = pnp_get_resource(dev, IORESOURCE_IO, tmp);
+               pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp);
+               if (!pnp_res)
+                       continue;
+               res = &pnp_res->res;
                if (pnp_resource_valid(res)) {
+                       index = pnp_res->index;
                        dev_dbg(&dev->dev, "  set io  %d to %#llx\n",
-                               tmp, (unsigned long long) res->start);
-                       isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
+                               index, (unsigned long long) res->start);
+                       isapnp_write_word(ISAPNP_CFG_PORT + (index << 1),
                                          res->start);
                }
        }
        for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
-               res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp);
+               pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp);
+               if (!pnp_res)
+                       continue;
+               res = &pnp_res->res;
                if (pnp_resource_valid(res)) {
                        int irq = res->start;
                        if (irq == 2)
                                irq = 9;
-                       dev_dbg(&dev->dev, "  set irq %d to %d\n", tmp, irq);
-                       isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq);
+                       index = pnp_res->index;
+                       dev_dbg(&dev->dev, "  set irq %d to %d\n", index, irq);
+                       isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq);
                }
        }
        for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
-               res = pnp_get_resource(dev, IORESOURCE_DMA, tmp);
+               pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp);
+               if (!pnp_res)
+                       continue;
+               res = &pnp_res->res;
                if (pnp_resource_valid(res)) {
+                       index = pnp_res->index;
                        dev_dbg(&dev->dev, "  set dma %d to %lld\n",
-                               tmp, (unsigned long long) res->start);
-                       isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start);
+                               index, (unsigned long long) res->start);
+                       isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start);
                }
        }
        for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
-               res = pnp_get_resource(dev, IORESOURCE_MEM, tmp);
+               pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp);
+               if (!pnp_res)
+                       continue;
+               res = &pnp_res->res;
                if (pnp_resource_valid(res)) {
+                       index = pnp_res->index;
                        dev_dbg(&dev->dev, "  set mem %d to %#llx\n",
-                               tmp, (unsigned long long) res->start);
-                       isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
+                               index, (unsigned long long) res->start);
+                       isapnp_write_word(ISAPNP_CFG_MEM + (index << 3),
                                          (res->start >> 8) & 0xffff);
                }
        }
index 4823da27e640f87861ec52c807102c0093b7c807..bea0914ff947a337dcf45d2a58bf7b6fc0f38644 100644 (file)
@@ -19,15 +19,18 @@ DEFINE_MUTEX(pnp_res_mutex);
 
 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
 {
+       struct pnp_resource *pnp_res;
        struct resource *res;
 
-       res = pnp_get_resource(dev, IORESOURCE_IO, idx);
-       if (!res) {
+       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx);
+       if (!pnp_res) {
                dev_err(&dev->dev, "too many I/O port resources\n");
                /* pretend we were successful so at least the manager won't try again */
                return 1;
        }
 
+       res = &pnp_res->res;
+
        /* check if this resource has been manually set, if so skip */
        if (!(res->flags & IORESOURCE_AUTO)) {
                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)
        }
 
        /* set the initial values */
+       pnp_res->index = idx;
        res->flags |= rule->flags | IORESOURCE_IO;
        res->flags &= ~IORESOURCE_UNSET;
 
@@ -65,15 +69,18 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
 
 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
 {
+       struct pnp_resource *pnp_res;
        struct resource *res;
 
-       res = pnp_get_resource(dev, IORESOURCE_MEM, idx);
-       if (!res) {
+       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx);
+       if (!pnp_res) {
                dev_err(&dev->dev, "too many memory resources\n");
                /* pretend we were successful so at least the manager won't try again */
                return 1;
        }
 
+       res = &pnp_res->res;
+
        /* check if this resource has been manually set, if so skip */
        if (!(res->flags & IORESOURCE_AUTO)) {
                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)
        }
 
        /* set the initial values */
+       pnp_res->index = idx;
        res->flags |= rule->flags | IORESOURCE_MEM;
        res->flags &= ~IORESOURCE_UNSET;
 
@@ -121,6 +129,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
 
 static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
 {
+       struct pnp_resource *pnp_res;
        struct resource *res;
        int i;
 
@@ -129,13 +138,15 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
                5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
        };
 
-       res = pnp_get_resource(dev, IORESOURCE_IRQ, idx);
-       if (!res) {
+       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx);
+       if (!pnp_res) {
                dev_err(&dev->dev, "too many IRQ resources\n");
                /* pretend we were successful so at least the manager won't try again */
                return 1;
        }
 
+       res = &pnp_res->res;
+
        /* check if this resource has been manually set, if so skip */
        if (!(res->flags & IORESOURCE_AUTO)) {
                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)
        }
 
        /* set the initial values */
+       pnp_res->index = idx;
        res->flags |= rule->flags | IORESOURCE_IRQ;
        res->flags &= ~IORESOURCE_UNSET;
 
@@ -177,6 +189,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
 
 static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
 {
+       struct pnp_resource *pnp_res;
        struct resource *res;
        int i;
 
@@ -185,12 +198,14 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
                1, 3, 5, 6, 7, 0, 2, 4
        };
 
-       res = pnp_get_resource(dev, IORESOURCE_DMA, idx);
-       if (!res) {
+       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx);
+       if (!pnp_res) {
                dev_err(&dev->dev, "too many DMA resources\n");
                return;
        }
 
+       res = &pnp_res->res;
+
        /* check if this resource has been manually set, if so skip */
        if (!(res->flags & IORESOURCE_AUTO)) {
                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)
        }
 
        /* set the initial values */
+       pnp_res->index = idx;
        res->flags |= rule->flags | IORESOURCE_DMA;
        res->flags &= ~IORESOURCE_UNSET;