summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-01-20 16:00:28 +0900
committerJeff Garzik <jeff@garzik.org>2007-02-09 17:39:37 -0500
commitd24bbbf251e70bf984cbaa9b1fcadc5f56fc3ae9 (patch)
tree3e3c18f9eebe5136e221d5f3219fa3f62badd8b0 /lib
parentb878ca5d37953ad1c4578b225a13a3c3e7e743b7 (diff)
devres: implement pcim_iomap_regions()
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>
Diffstat (limited to 'lib')
-rw-r--r--lib/iomap.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/iomap.c b/lib/iomap.c
index 3214028141da..4990c736bc4b 100644
--- a/lib/iomap.c
+++ b/lib/iomap.c
@@ -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);