From d89c83bebae011a76e1ca9ec65c973aac0ad5da9 Mon Sep 17 00:00:00 2001 From: Adam Belay Date: Sun, 8 Feb 2004 15:28:23 +0000 Subject: [PATCH] [PNP]: Resource flags update This patch reorganizes resource flags to ensure that manual resource settings are properly recognized. This fix is necessary for many ALSA drivers. It also prevents comparisons between unset resource structures. The bug was discovered by Rene Herman , who also wrote an initial version of this patch. I made further improvements to ensure that the pnp subsystem was compatible with this initial change. --- drivers/pnp/isapnp/core.c | 8 ++++---- drivers/pnp/manager.c | 18 +++++++++--------- drivers/pnp/pnpbios/rsparser.c | 8 ++++---- drivers/pnp/resource.c | 19 +++++++++++-------- include/linux/pnp.h | 16 ++++++++++++---- 5 files changed, 40 insertions(+), 29 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index b5e3e898f8e5..453f69c55967 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -1039,17 +1039,17 @@ static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_resource_table * isapnp_cfg_begin(dev->card->number, dev->number); dev->active = 1; - for (tmp = 0; tmp < PNP_MAX_PORT && res->port_resource[tmp].flags & IORESOURCE_IO; tmp++) + for (tmp = 0; tmp < PNP_MAX_PORT && (res->port_resource[tmp].flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; tmp++) isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), res->port_resource[tmp].start); - for (tmp = 0; tmp < PNP_MAX_IRQ && res->irq_resource[tmp].flags & IORESOURCE_IRQ; tmp++) { + for (tmp = 0; tmp < PNP_MAX_IRQ && (res->irq_resource[tmp].flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; tmp++) { int irq = res->irq_resource[tmp].start; if (irq == 2) irq = 9; isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq); } - for (tmp = 0; tmp < PNP_MAX_DMA && res->dma_resource[tmp].flags & IORESOURCE_DMA; tmp++) + for (tmp = 0; tmp < PNP_MAX_DMA && (res->dma_resource[tmp].flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; tmp++) isapnp_write_byte(ISAPNP_CFG_DMA+tmp, res->dma_resource[tmp].start); - for (tmp = 0; tmp < PNP_MAX_MEM && res->mem_resource[tmp].flags & IORESOURCE_MEM; tmp++) + for (tmp = 0; tmp < PNP_MAX_MEM && (res->mem_resource[tmp].flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; tmp++) isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (res->mem_resource[tmp].start >> 8) & 0xffff); /* FIXME: We aren't handling 32bit mems properly here */ isapnp_activate(dev->number); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 36b6220a6335..bd344233e5e8 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -223,25 +223,25 @@ void pnp_init_resource_table(struct pnp_resource_table *table) table->irq_resource[idx].name = NULL; table->irq_resource[idx].start = -1; table->irq_resource[idx].end = -1; - table->irq_resource[idx].flags = IORESOURCE_AUTO | IORESOURCE_UNSET; + table->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_DMA; idx++) { table->dma_resource[idx].name = NULL; table->dma_resource[idx].start = -1; table->dma_resource[idx].end = -1; - table->dma_resource[idx].flags = IORESOURCE_AUTO | IORESOURCE_UNSET; + table->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_PORT; idx++) { table->port_resource[idx].name = NULL; table->port_resource[idx].start = 0; table->port_resource[idx].end = 0; - table->port_resource[idx].flags = IORESOURCE_AUTO | IORESOURCE_UNSET; + table->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_MEM; idx++) { table->mem_resource[idx].name = NULL; table->mem_resource[idx].start = 0; table->mem_resource[idx].end = 0; - table->mem_resource[idx].flags = IORESOURCE_AUTO | IORESOURCE_UNSET; + table->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; } } @@ -258,28 +258,28 @@ static void pnp_clean_resource_table(struct pnp_resource_table * res) continue; res->irq_resource[idx].start = -1; res->irq_resource[idx].end = -1; - res->irq_resource[idx].flags = IORESOURCE_AUTO | IORESOURCE_UNSET; + res->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_DMA; idx++) { if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) continue; res->dma_resource[idx].start = -1; res->dma_resource[idx].end = -1; - res->dma_resource[idx].flags = IORESOURCE_AUTO | IORESOURCE_UNSET; + res->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_PORT; idx++) { if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) continue; res->port_resource[idx].start = 0; res->port_resource[idx].end = 0; - res->port_resource[idx].flags = IORESOURCE_AUTO | IORESOURCE_UNSET; + res->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_MEM; idx++) { if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) continue; res->mem_resource[idx].start = 0; res->mem_resource[idx].end = 0; - res->mem_resource[idx].flags = IORESOURCE_AUTO | IORESOURCE_UNSET; + res->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; } } @@ -550,7 +550,7 @@ void pnp_resource_change(struct resource *resource, unsigned long start, unsigne { if (resource == NULL) return; - resource->flags &= ~IORESOURCE_AUTO; + resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET); resource->start = start; resource->end = start + size - 1; } diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 7af3cb0ceceb..758d6804f0ff 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -49,7 +49,7 @@ static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table * res, int irq) { int i = 0; - while ((res->irq_resource[i].flags & IORESOURCE_IRQ) && i < PNP_MAX_IRQ) i++; + while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_IRQ) i++; if (i < PNP_MAX_IRQ) { res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag if (irq == -1) { @@ -65,7 +65,7 @@ static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma) { int i = 0; - while ((res->dma_resource[i].flags & IORESOURCE_DMA) && i < PNP_MAX_DMA) i++; + while (!(res->dma_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_DMA) i++; if (i < PNP_MAX_DMA) { res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag if (dma == -1) { @@ -81,7 +81,7 @@ static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table * res, int io, int len) { int i = 0; - while ((res->port_resource[i].flags & IORESOURCE_IO) && i < PNP_MAX_PORT) i++; + while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_PORT) i++; if (i < PNP_MAX_PORT) { res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag if (len <= 0 || (io + len -1) >= 0x10003) { @@ -97,7 +97,7 @@ static void pnpbios_parse_allocated_memresource(struct pnp_resource_table * res, int mem, int len) { int i = 0; - while ((res->mem_resource[i].flags & IORESOURCE_MEM) && i < PNP_MAX_MEM) i++; + while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_MEM) i++; if (i < PNP_MAX_MEM) { res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag if (len <= 0) { diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index dfe565a82ea8..1c1ab31a619f 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -241,6 +241,9 @@ void pnp_free_option(struct pnp_option *option) (*(enda) >= *(startb) && *(enda) <= *(endb)) || \ (*(starta) < *(startb) && *(enda) > *(endb))) +#define cannot_compare(flags) \ +((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) + int pnp_check_port(struct pnp_dev * dev, int idx) { int tmp; @@ -250,7 +253,7 @@ int pnp_check_port(struct pnp_dev * dev, int idx) end = &dev->res.port_resource[idx].end; /* if the resource doesn't exist, don't complain about it */ - if (dev->res.port_resource[idx].flags & IORESOURCE_UNSET) + if (cannot_compare(dev->res.port_resource[idx].flags)) return 1; /* check if the resource is already in use, skip if the @@ -284,7 +287,7 @@ int pnp_check_port(struct pnp_dev * dev, int idx) continue; for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) { - if (pnp_port_flags(dev, tmp) & IORESOURCE_DISABLED) + if (cannot_compare(tdev->res.port_resource[tmp].flags)) continue; tport = &tdev->res.port_resource[tmp].start; tend = &tdev->res.port_resource[tmp].end; @@ -306,7 +309,7 @@ int pnp_check_mem(struct pnp_dev * dev, int idx) end = &dev->res.mem_resource[idx].end; /* if the resource doesn't exist, don't complain about it */ - if (dev->res.mem_resource[idx].flags & IORESOURCE_UNSET) + if (cannot_compare(dev->res.mem_resource[idx].flags)) return 1; /* check if the resource is already in use, skip if the @@ -340,7 +343,7 @@ int pnp_check_mem(struct pnp_dev * dev, int idx) continue; for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { - if (pnp_mem_flags(dev, tmp) & IORESOURCE_DISABLED) + if (cannot_compare(tdev->res.mem_resource[tmp].flags)) continue; taddr = &tdev->res.mem_resource[tmp].start; tend = &tdev->res.mem_resource[tmp].end; @@ -365,7 +368,7 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) unsigned long * irq = &dev->res.irq_resource[idx].start; /* if the resource doesn't exist, don't complain about it */ - if (dev->res.irq_resource[idx].flags & IORESOURCE_UNSET) + if (cannot_compare(dev->res.irq_resource[idx].flags)) return 1; /* check if the resource is valid */ @@ -411,7 +414,7 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) continue; for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { - if (pnp_irq_flags(dev, tmp) & IORESOURCE_DISABLED) + if (cannot_compare(tdev->res.irq_resource[tmp].flags)) continue; if ((tdev->res.irq_resource[tmp].start == *irq)) return 0; @@ -429,7 +432,7 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) unsigned long * dma = &dev->res.dma_resource[idx].start; /* if the resource doesn't exist, don't complain about it */ - if (dev->res.dma_resource[idx].flags & IORESOURCE_UNSET) + if (cannot_compare(dev->res.dma_resource[idx].flags)) return 1; /* check if the resource is valid */ @@ -464,7 +467,7 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) continue; for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { - if (pnp_dma_flags(dev, tmp) & IORESOURCE_DISABLED) + if (cannot_compare(tdev->res.dma_resource[tmp].flags)) continue; if ((tdev->res.dma_resource[tmp].start == *dma)) return 0; diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 1dcef561a280..5aa6df8e1a5a 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -33,7 +33,9 @@ struct pnp_dev; #define pnp_port_start(dev,bar) ((dev)->res.port_resource[(bar)].start) #define pnp_port_end(dev,bar) ((dev)->res.port_resource[(bar)].end) #define pnp_port_flags(dev,bar) ((dev)->res.port_resource[(bar)].flags) -#define pnp_port_valid(dev,bar) (pnp_port_flags((dev),(bar)) & IORESOURCE_IO) +#define pnp_port_valid(dev,bar) \ + ((pnp_port_flags((dev),(bar)) & (IORESOURCE_IO | IORESOURCE_UNSET)) \ + == IORESOURCE_IO) #define pnp_port_len(dev,bar) \ ((pnp_port_start((dev),(bar)) == 0 && \ pnp_port_end((dev),(bar)) == \ @@ -45,7 +47,9 @@ struct pnp_dev; #define pnp_mem_start(dev,bar) ((dev)->res.mem_resource[(bar)].start) #define pnp_mem_end(dev,bar) ((dev)->res.mem_resource[(bar)].end) #define pnp_mem_flags(dev,bar) ((dev)->res.mem_resource[(bar)].flags) -#define pnp_mem_valid(dev,bar) (pnp_mem_flags((dev),(bar)) & IORESOURCE_MEM) +#define pnp_mem_valid(dev,bar) \ + ((pnp_mem_flags((dev),(bar)) & (IORESOURCE_MEM | IORESOURCE_UNSET)) \ + == IORESOURCE_MEM) #define pnp_mem_len(dev,bar) \ ((pnp_mem_start((dev),(bar)) == 0 && \ pnp_mem_end((dev),(bar)) == \ @@ -56,11 +60,15 @@ struct pnp_dev; #define pnp_irq(dev,bar) ((dev)->res.irq_resource[(bar)].start) #define pnp_irq_flags(dev,bar) ((dev)->res.irq_resource[(bar)].flags) -#define pnp_irq_valid(dev,bar) (pnp_irq_flags((dev),(bar)) & IORESOURCE_IRQ) +#define pnp_irq_valid(dev,bar) \ + ((pnp_irq_flags((dev),(bar)) & (IORESOURCE_IRQ | IORESOURCE_UNSET)) \ + == IORESOURCE_IRQ) #define pnp_dma(dev,bar) ((dev)->res.dma_resource[(bar)].start) #define pnp_dma_flags(dev,bar) ((dev)->res.dma_resource[(bar)].flags) -#define pnp_dma_valid(dev,bar) (pnp_dma_flags((dev),(bar)) & IORESOURCE_DMA) +#define pnp_dma_valid(dev,bar) \ + ((pnp_dma_flags((dev),(bar)) & (IORESOURCE_DMA | IORESOURCE_UNSET)) \ + == IORESOURCE_DMA) #define PNP_PORT_FLAG_16BITADDR (1<<0) #define PNP_PORT_FLAG_FIXED (1<<1) -- 2.39.5