Commit 98823466 authored by Adam Belay's avatar Adam Belay

[PNP] Handle Disabled Resources Properly

Some devices will allow for individual resources to be disabled,
even when the device as a whole is active.  The current PnP
resource manager is not handling this situation properly.  This
patch corrects the issue by detecting disabled resources and then
flagging them. The pnp layer will now skip over any disabled 
resources.  Interface updates have also been included so that we
can properly display resource tables when a resource is disabled.

Also note that a new flag "IORESOURCE_DISABLED" has been added to
linux/ioports.h.
parent b9d6ea3c
...@@ -259,7 +259,10 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) ...@@ -259,7 +259,10 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
for (i = 0; i < PNP_MAX_PORT; i++) { for (i = 0; i < PNP_MAX_PORT; i++) {
if (pnp_port_valid(dev, i)) { if (pnp_port_valid(dev, i)) {
pnp_printf(buffer,"io"); pnp_printf(buffer,"io");
pnp_printf(buffer," 0x%lx-0x%lx \n", if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED)
pnp_printf(buffer," disabled\n");
else
pnp_printf(buffer," 0x%lx-0x%lx\n",
pnp_port_start(dev, i), pnp_port_start(dev, i),
pnp_port_end(dev, i)); pnp_port_end(dev, i));
} }
...@@ -267,7 +270,10 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) ...@@ -267,7 +270,10 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
for (i = 0; i < PNP_MAX_MEM; i++) { for (i = 0; i < PNP_MAX_MEM; i++) {
if (pnp_mem_valid(dev, i)) { if (pnp_mem_valid(dev, i)) {
pnp_printf(buffer,"mem"); pnp_printf(buffer,"mem");
pnp_printf(buffer," 0x%lx-0x%lx \n", if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED)
pnp_printf(buffer," disabled\n");
else
pnp_printf(buffer," 0x%lx-0x%lx\n",
pnp_mem_start(dev, i), pnp_mem_start(dev, i),
pnp_mem_end(dev, i)); pnp_mem_end(dev, i));
} }
...@@ -275,13 +281,21 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) ...@@ -275,13 +281,21 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
for (i = 0; i < PNP_MAX_IRQ; i++) { for (i = 0; i < PNP_MAX_IRQ; i++) {
if (pnp_irq_valid(dev, i)) { if (pnp_irq_valid(dev, i)) {
pnp_printf(buffer,"irq"); pnp_printf(buffer,"irq");
pnp_printf(buffer," %ld \n", pnp_irq(dev, i)); if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED)
pnp_printf(buffer," disabled\n");
else
pnp_printf(buffer," %ld\n",
pnp_irq(dev, i));
} }
} }
for (i = 0; i < PNP_MAX_DMA; i++) { for (i = 0; i < PNP_MAX_DMA; i++) {
if (pnp_dma_valid(dev, i)) { if (pnp_dma_valid(dev, i)) {
pnp_printf(buffer,"dma"); pnp_printf(buffer,"dma");
pnp_printf(buffer," %ld \n", pnp_dma(dev, i)); if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED)
pnp_printf(buffer," disabled\n");
else
pnp_printf(buffer," %ld\n",
pnp_dma(dev, i));
} }
} }
ret = (buffer->curr - buf); ret = (buffer->curr - buf);
......
...@@ -40,6 +40,9 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) ...@@ -40,6 +40,9 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO))
return 1; return 1;
if (!rule->size)
return 1; /* skip disabled resource requests */
start = &dev->res.port_resource[idx].start; start = &dev->res.port_resource[idx].start;
end = &dev->res.port_resource[idx].end; end = &dev->res.port_resource[idx].end;
flags = &dev->res.port_resource[idx].flags; flags = &dev->res.port_resource[idx].flags;
...@@ -76,6 +79,9 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) ...@@ -76,6 +79,9 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO))
return 1; return 1;
if (!rule->size)
return 1; /* skip disabled resource requests */
start = &dev->res.mem_resource[idx].start; start = &dev->res.mem_resource[idx].start;
end = &dev->res.mem_resource[idx].end; end = &dev->res.mem_resource[idx].end;
flags = &dev->res.mem_resource[idx].flags; flags = &dev->res.mem_resource[idx].flags;
...@@ -128,6 +134,9 @@ static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx) ...@@ -128,6 +134,9 @@ static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx)
if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO))
return 1; return 1;
if (!rule->map)
return 1; /* skip disabled resource requests */
start = &dev->res.irq_resource[idx].start; start = &dev->res.irq_resource[idx].start;
end = &dev->res.irq_resource[idx].end; end = &dev->res.irq_resource[idx].end;
flags = &dev->res.irq_resource[idx].flags; flags = &dev->res.irq_resource[idx].flags;
...@@ -168,6 +177,9 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) ...@@ -168,6 +177,9 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO))
return 1; return 1;
if (!rule->map)
return 1; /* skip disabled resource requests */
start = &dev->res.dma_resource[idx].start; start = &dev->res.dma_resource[idx].start;
end = &dev->res.dma_resource[idx].end; end = &dev->res.dma_resource[idx].end;
flags = &dev->res.dma_resource[idx].flags; flags = &dev->res.dma_resource[idx].flags;
......
...@@ -286,6 +286,8 @@ int pnp_check_port(struct pnp_dev * dev, int idx) ...@@ -286,6 +286,8 @@ int pnp_check_port(struct pnp_dev * dev, int idx)
continue; continue;
for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) { if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
if (pnp_port_flags(dev, tmp) & IORESOURCE_DISABLED)
continue;
tport = &tdev->res.port_resource[tmp].start; tport = &tdev->res.port_resource[tmp].start;
tend = &tdev->res.port_resource[tmp].end; tend = &tdev->res.port_resource[tmp].end;
if (ranged_conflict(port,end,tport,tend)) if (ranged_conflict(port,end,tport,tend))
...@@ -340,6 +342,8 @@ int pnp_check_mem(struct pnp_dev * dev, int idx) ...@@ -340,6 +342,8 @@ int pnp_check_mem(struct pnp_dev * dev, int idx)
continue; continue;
for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
if (pnp_mem_flags(dev, tmp) & IORESOURCE_DISABLED)
continue;
taddr = &tdev->res.mem_resource[tmp].start; taddr = &tdev->res.mem_resource[tmp].start;
tend = &tdev->res.mem_resource[tmp].end; tend = &tdev->res.mem_resource[tmp].end;
if (ranged_conflict(addr,end,taddr,tend)) if (ranged_conflict(addr,end,taddr,tend))
...@@ -409,6 +413,8 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) ...@@ -409,6 +413,8 @@ int pnp_check_irq(struct pnp_dev * dev, int idx)
continue; continue;
for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
if (pnp_irq_flags(dev, tmp) & IORESOURCE_DISABLED)
continue;
if ((tdev->res.irq_resource[tmp].start == *irq)) if ((tdev->res.irq_resource[tmp].start == *irq))
return 0; return 0;
} }
...@@ -462,6 +468,8 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) ...@@ -462,6 +468,8 @@ int pnp_check_dma(struct pnp_dev * dev, int idx)
continue; continue;
for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
if (pnp_dma_flags(dev, tmp) & IORESOURCE_DISABLED)
continue;
if ((tdev->res.dma_resource[tmp].start == *dma)) if ((tdev->res.dma_resource[tmp].start == *dma))
return 0; return 0;
} }
......
...@@ -68,9 +68,13 @@ static void current_irqresource(struct pnp_resource_table * res, int irq) ...@@ -68,9 +68,13 @@ static void current_irqresource(struct pnp_resource_table * res, int irq)
int i = 0; int i = 0;
while ((res->irq_resource[i].flags & IORESOURCE_IRQ) && i < PNP_MAX_IRQ) i++; while ((res->irq_resource[i].flags & IORESOURCE_IRQ) && i < PNP_MAX_IRQ) i++;
if (i < PNP_MAX_IRQ) { if (i < PNP_MAX_IRQ) {
res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
if (irq == -1) {
res->irq_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->irq_resource[i].start = res->irq_resource[i].start =
res->irq_resource[i].end = (unsigned long) irq; res->irq_resource[i].end = (unsigned long) irq;
res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
} }
} }
...@@ -79,9 +83,13 @@ static void current_dmaresource(struct pnp_resource_table * res, int dma) ...@@ -79,9 +83,13 @@ static void current_dmaresource(struct pnp_resource_table * res, int dma)
int i = 0; int i = 0;
while ((res->dma_resource[i].flags & IORESOURCE_DMA) && i < PNP_MAX_DMA) i++; while ((res->dma_resource[i].flags & IORESOURCE_DMA) && i < PNP_MAX_DMA) i++;
if (i < PNP_MAX_DMA) { if (i < PNP_MAX_DMA) {
res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
if (dma == -1) {
res->dma_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->dma_resource[i].start = res->dma_resource[i].start =
res->dma_resource[i].end = (unsigned long) dma; res->dma_resource[i].end = (unsigned long) dma;
res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
} }
} }
...@@ -90,9 +98,13 @@ static void current_ioresource(struct pnp_resource_table * res, int io, int len) ...@@ -90,9 +98,13 @@ static void current_ioresource(struct pnp_resource_table * res, int io, int len)
int i = 0; int i = 0;
while ((res->port_resource[i].flags & IORESOURCE_IO) && i < PNP_MAX_PORT) i++; while ((res->port_resource[i].flags & IORESOURCE_IO) && i < PNP_MAX_PORT) i++;
if (i < PNP_MAX_PORT) { if (i < PNP_MAX_PORT) {
res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
if (len <= 0 || (io + len -1) >= 0x10003) {
res->port_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->port_resource[i].start = (unsigned long) io; res->port_resource[i].start = (unsigned long) io;
res->port_resource[i].end = (unsigned long)(io + len - 1); res->port_resource[i].end = (unsigned long)(io + len - 1);
res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
} }
} }
...@@ -101,9 +113,13 @@ static void current_memresource(struct pnp_resource_table * res, int mem, int le ...@@ -101,9 +113,13 @@ static void current_memresource(struct pnp_resource_table * res, int mem, int le
int i = 0; int i = 0;
while ((res->mem_resource[i].flags & IORESOURCE_MEM) && i < PNP_MAX_MEM) i++; while ((res->mem_resource[i].flags & IORESOURCE_MEM) && i < PNP_MAX_MEM) i++;
if (i < PNP_MAX_MEM) { if (i < PNP_MAX_MEM) {
res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag
if (len <= 0) {
res->mem_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
res->mem_resource[i].start = (unsigned long) mem; res->mem_resource[i].start = (unsigned long) mem;
res->mem_resource[i].end = (unsigned long)(mem + len - 1); res->mem_resource[i].end = (unsigned long)(mem + len - 1);
res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag
} }
} }
......
...@@ -43,6 +43,7 @@ struct resource_list { ...@@ -43,6 +43,7 @@ struct resource_list {
#define IORESOURCE_SHADOWABLE 0x00010000 #define IORESOURCE_SHADOWABLE 0x00010000
#define IORESOURCE_BUS_HAS_VGA 0x00080000 #define IORESOURCE_BUS_HAS_VGA 0x00080000
#define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000 #define IORESOURCE_UNSET 0x20000000
#define IORESOURCE_AUTO 0x40000000 #define IORESOURCE_AUTO 0x40000000
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment