PNP: make pnp_{port,mem,etc}_start(), et al work for invalid resources
authorBjorn Helgaas <bjorn.helgaas@hp.com>
Fri, 27 Jun 2008 22:56:56 +0000 (16:56 -0600)
committerAndi Kleen <andi@basil.nowhere.org>
Wed, 16 Jul 2008 21:27:05 +0000 (23:27 +0200)
Some callers use pnp_port_start() and similar functions without
making sure the resource is valid.  This patch makes us fall
back to returning the initial values if the resource is not
valid or not even present.

This mostly preserves the previous behavior, where we would just
return the initial values set by pnp_init_resource_table().  The
original 2.6.25 code didn't range-check the "bar", so it would
return garbage if the bar exceeded the table size.  This code
returns sensible values instead.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
include/linux/pnp.h

index 63b128d512fb5f413085b8b13d144d97cf41477f..8b607aecd959e07c1f5d3fd2f87a788378491def 100644 (file)
@@ -40,19 +40,31 @@ static inline resource_size_t pnp_resource_len(struct resource *res)
 static inline resource_size_t pnp_port_start(struct pnp_dev *dev,
                                             unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_IO, bar)->start;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar);
+
+       if (pnp_resource_valid(res))
+               return res->start;
+       return 0;
 }
 
 static inline resource_size_t pnp_port_end(struct pnp_dev *dev,
                                           unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_IO, bar)->end;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar);
+
+       if (pnp_resource_valid(res))
+               return res->end;
+       return 0;
 }
 
 static inline unsigned long pnp_port_flags(struct pnp_dev *dev,
                                           unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_IO, bar)->flags;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar);
+
+       if (pnp_resource_valid(res))
+               return res->flags;
+       return IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
 }
 
 static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar)
@@ -63,25 +75,41 @@ static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar)
 static inline resource_size_t pnp_port_len(struct pnp_dev *dev,
                                           unsigned int bar)
 {
-       return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_IO, bar));
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar);
+
+       if (pnp_resource_valid(res))
+               return pnp_resource_len(res);
+       return 0;
 }
 
 
 static inline resource_size_t pnp_mem_start(struct pnp_dev *dev,
                                            unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_MEM, bar)->start;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar);
+
+       if (pnp_resource_valid(res))
+               return res->start;
+       return 0;
 }
 
 static inline resource_size_t pnp_mem_end(struct pnp_dev *dev,
                                          unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_MEM, bar)->end;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar);
+
+       if (pnp_resource_valid(res))
+               return res->end;
+       return 0;
 }
 
 static inline unsigned long pnp_mem_flags(struct pnp_dev *dev, unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_MEM, bar)->flags;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar);
+
+       if (pnp_resource_valid(res))
+               return res->flags;
+       return IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
 }
 
 static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar)
@@ -92,18 +120,30 @@ static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar)
 static inline resource_size_t pnp_mem_len(struct pnp_dev *dev,
                                          unsigned int bar)
 {
-       return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_MEM, bar));
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar);
+
+       if (pnp_resource_valid(res))
+               return pnp_resource_len(res);
+       return 0;
 }
 
 
 static inline resource_size_t pnp_irq(struct pnp_dev *dev, unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->start;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_IRQ, bar);
+
+       if (pnp_resource_valid(res))
+               return res->start;
+       return -1;
 }
 
 static inline unsigned long pnp_irq_flags(struct pnp_dev *dev, unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->flags;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_IRQ, bar);
+
+       if (pnp_resource_valid(res))
+               return res->flags;
+       return IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
 }
 
 static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar)
@@ -114,12 +154,20 @@ static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar)
 
 static inline resource_size_t pnp_dma(struct pnp_dev *dev, unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_DMA, bar)->start;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_DMA, bar);
+
+       if (pnp_resource_valid(res))
+               return res->start;
+       return -1;
 }
 
 static inline unsigned long pnp_dma_flags(struct pnp_dev *dev, unsigned int bar)
 {
-       return pnp_get_resource(dev, IORESOURCE_DMA, bar)->flags;
+       struct resource *res = pnp_get_resource(dev, IORESOURCE_DMA, bar);
+
+       if (pnp_resource_valid(res))
+               return res->flags;
+       return IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
 }
 
 static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar)