devres: implement pcim_iomap_regions()
authorTejun Heo <htejun@gmail.com>
Sat, 20 Jan 2007 07:00:28 +0000 (16:00 +0900)
committerJeff Garzik <jeff@garzik.org>
Fri, 9 Feb 2007 22:39:37 +0000 (17:39 -0500)
Implement pcim_iomap_regions().  This function takes mask of BARs to
request and iomap.  No BAR should have length of zero.  BARs are
iomapped using pcim_iomap_table().

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
include/linux/io.h
lib/iomap.c

index f5edf9c5de0a5b8f8799fe62cc7916e146a41e1d..45a9c944cb0ad2b2e49a9d7ba8a389693631e840 100644 (file)
@@ -45,6 +45,8 @@ void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
 void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
 void __iomem * const * pcim_iomap_table(struct pci_dev *pdev);
 
+int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name);
+
 /**
  *     check_signature         -       find BIOS signatures
  *     @io_addr: mmio address to check
index 3214028141daef4f7b0ec7188fa2e298bdd807e6..4990c736bc4b6864df839b45b85dcfa8b3d361e2 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);