|
@@ -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);
|