Skip to content

Commit

Permalink
PNP: add pnp_resource index for ISAPNP
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bjorn Helgaas authored and Len Brown committed Apr 29, 2008
1 parent 0a977f1 commit 21855d6
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 37 deletions.
1 change: 1 addition & 0 deletions drivers/pnp/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
33 changes: 21 additions & 12 deletions drivers/pnp/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
63 changes: 46 additions & 17 deletions drivers/pnp/isapnp/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -959,15 +965,21 @@ 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;
}
for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
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;
}
Expand All @@ -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);
}
}
Expand Down
32 changes: 24 additions & 8 deletions drivers/pnp/manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand All @@ -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;

Expand Down Expand Up @@ -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 "
Expand All @@ -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;

Expand Down Expand Up @@ -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;

Expand All @@ -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",
Expand All @@ -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;

Expand Down Expand Up @@ -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;

Expand All @@ -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",
Expand All @@ -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;

Expand Down

0 comments on commit 21855d6

Please sign in to comment.