devres: implement pcim_iomap_regions()
[safe/jmp/linux-2.6] / lib / iomap.c
index 3214028..4990c73 100644 (file)
@@ -498,3 +498,56 @@ void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
        WARN_ON(1);
 }
 EXPORT_SYMBOL(pcim_iounmap);
+
+/**
+ * pcim_iomap_regions - Request and iomap PCI BARs
+ * @pdev: PCI device to map IO resources for
+ * @mask: Mask of BARs to request and iomap
+ * @name: Name used when requesting regions
+ *
+ * Request and iomap regions specified by @mask.
+ */
+int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name)
+{
+       void __iomem * const *iomap;
+       int i, rc;
+
+       iomap = pcim_iomap_table(pdev);
+       if (!iomap)
+               return -ENOMEM;
+
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+               unsigned long len;
+
+               if (!(mask & (1 << i)))
+                       continue;
+
+               rc = -EINVAL;
+               len = pci_resource_len(pdev, i);
+               if (!len)
+                       goto err_inval;
+
+               rc = pci_request_region(pdev, i, name);
+               if (rc)
+                       goto err_region;
+
+               rc = -ENOMEM;
+               if (!pcim_iomap(pdev, i, 0))
+                       goto err_iomap;
+       }
+
+       return 0;
+
+ err_iomap:
+       pcim_iounmap(pdev, iomap[i]);
+ err_region:
+       pci_release_region(pdev, i);
+ err_inval:
+       while (--i >= 0) {
+               pcim_iounmap(pdev, iomap[i]);
+               pci_release_region(pdev, i);
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL(pcim_iomap_regions);