V4L/DVB: v4l2-dev: remove unnecessary lock around atomic clear_bit
[safe/jmp/linux-2.6] / drivers / pnp / resource.c
index d638897..e3446ab 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -210,6 +211,8 @@ int pnp_check_port(struct pnp_dev *dev, struct resource *res)
                        if (tres->flags & IORESOURCE_IO) {
                                if (cannot_compare(tres->flags))
                                        continue;
+                               if (tres->flags & IORESOURCE_WINDOW)
+                                       continue;
                                tport = &tres->start;
                                tend = &tres->end;
                                if (ranged_conflict(port, end, tport, tend))
@@ -270,6 +273,8 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res)
                        if (tres->flags & IORESOURCE_MEM) {
                                if (cannot_compare(tres->flags))
                                        continue;
+                               if (tres->flags & IORESOURCE_WINDOW)
+                                       continue;
                                taddr = &tres->start;
                                tend = &tres->end;
                                if (ranged_conflict(addr, end, taddr, tend))
@@ -286,6 +291,61 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_PCI
+static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
+                           unsigned int irq)
+{
+       u32 class;
+       u8 progif;
+
+       if (pci->irq == irq) {
+               pnp_dbg(&pnp->dev, "  device %s using irq %d\n",
+                       pci_name(pci), irq);
+               return 1;
+       }
+
+       /*
+        * See pci_setup_device() and ata_pci_sff_activate_host() for
+        * similar IDE legacy detection.
+        */
+       pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
+       class >>= 8;            /* discard revision ID */
+       progif = class & 0xff;
+       class >>= 8;
+
+       if (class == PCI_CLASS_STORAGE_IDE) {
+               /*
+                * Unless both channels are native-PCI mode only,
+                * treat the compatibility IRQs as busy.
+                */
+               if ((progif & 0x5) != 0x5)
+                       if (pci_get_legacy_ide_irq(pci, 0) == irq ||
+                           pci_get_legacy_ide_irq(pci, 1) == irq) {
+                               pnp_dbg(&pnp->dev, "  legacy IDE device %s "
+                                       "using irq %d\n", pci_name(pci), irq);
+                               return 1;
+                       }
+       }
+
+       return 0;
+}
+#endif
+
+static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
+{
+#ifdef CONFIG_PCI
+       struct pci_dev *pci = NULL;
+
+       for_each_pci_dev(pci) {
+               if (pci_dev_uses_irq(pnp, pci, irq)) {
+                       pci_dev_put(pci);
+                       return 1;
+               }
+       }
+#endif
+       return 0;
+}
+
 int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
 {
        int i;
@@ -317,18 +377,9 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
                }
        }
 
-#ifdef CONFIG_PCI
        /* check if the resource is being used by a pci device */
-       {
-               struct pci_dev *pci = NULL;
-               for_each_pci_dev(pci) {
-                       if (pci->irq == *irq) {
-                               pci_dev_put(pci);
-                               return 0;
-                       }
-               }
-       }
-#endif
+       if (pci_uses_irq(dev, *irq))
+               return 0;
 
        /* check if the resource is already in use, skip if the
         * device is active because it itself may be in use */
@@ -421,14 +472,15 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
 #endif
 }
 
-int pnp_resource_type(struct resource *res)
+unsigned long pnp_resource_type(struct resource *res)
 {
        return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
-                            IORESOURCE_IRQ | IORESOURCE_DMA);
+                            IORESOURCE_IRQ | IORESOURCE_DMA |
+                            IORESOURCE_BUS);
 }
 
 struct resource *pnp_get_resource(struct pnp_dev *dev,
-                                 unsigned int type, unsigned int num)
+                                 unsigned long type, unsigned int num)
 {
        struct pnp_resource *pnp_res;
        struct resource *res;
@@ -471,7 +523,7 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
        res->start = irq;
        res->end = irq;
 
-       dev_dbg(&dev->dev, "  add irq %d flags %#x\n", irq, flags);
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
        return pnp_res;
 }
 
@@ -492,7 +544,7 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
        res->start = dma;
        res->end = dma;
 
-       dev_dbg(&dev->dev, "  add dma %d flags %#x\n", dma, flags);
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
        return pnp_res;
 }
 
@@ -516,8 +568,7 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
        res->start = start;
        res->end = end;
 
-       dev_dbg(&dev->dev, "  add io  %#llx-%#llx flags %#x\n",
-               (unsigned long long) start, (unsigned long long) end, flags);
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
        return pnp_res;
 }
 
@@ -541,8 +592,31 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
        res->start = start;
        res->end = end;
 
-       dev_dbg(&dev->dev, "  add mem %#llx-%#llx flags %#x\n",
-               (unsigned long long) start, (unsigned long long) end, flags);
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
+       return pnp_res;
+}
+
+struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
+                                         resource_size_t start,
+                                         resource_size_t end)
+{
+       struct pnp_resource *pnp_res;
+       struct resource *res;
+
+       pnp_res = pnp_new_resource(dev);
+       if (!pnp_res) {
+               dev_err(&dev->dev, "can't add resource for BUS %#llx-%#llx\n",
+                       (unsigned long long) start,
+                       (unsigned long long) end);
+               return NULL;
+       }
+
+       res = &pnp_res->res;
+       res->flags = IORESOURCE_BUS;
+       res->start = start;
+       res->end = end;
+
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
        return pnp_res;
 }
 
@@ -592,6 +666,24 @@ int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
 }
 EXPORT_SYMBOL(pnp_possible_config);
 
+int pnp_range_reserved(resource_size_t start, resource_size_t end)
+{
+       struct pnp_dev *dev;
+       struct pnp_resource *pnp_res;
+       resource_size_t *dev_start, *dev_end;
+
+       pnp_for_each_dev(dev) {
+               list_for_each_entry(pnp_res, &dev->resources, list) {
+                       dev_start = &pnp_res->res.start;
+                       dev_end   = &pnp_res->res.end;
+                       if (ranged_conflict(&start, &end, dev_start, dev_end))
+                               return 1;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL(pnp_range_reserved);
+
 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
 static int __init pnp_setup_reserve_irq(char *str)
 {