aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/io.h2
-rw-r--r--lib/iomap.c53
2 files changed, 55 insertions, 0 deletions
diff --git a/include/linux/io.h b/include/linux/io.h
index f5edf9c5de0a..45a9c944cb0a 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -45,6 +45,8 @@ void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
45void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr); 45void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
46void __iomem * const * pcim_iomap_table(struct pci_dev *pdev); 46void __iomem * const * pcim_iomap_table(struct pci_dev *pdev);
47 47
48int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name);
49
48/** 50/**
49 * check_signature - find BIOS signatures 51 * check_signature - find BIOS signatures
50 * @io_addr: mmio address to check 52 * @io_addr: mmio address to check
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)
498 WARN_ON(1); 498 WARN_ON(1);
499} 499}
500EXPORT_SYMBOL(pcim_iounmap); 500EXPORT_SYMBOL(pcim_iounmap);
501
502/**
503 * pcim_iomap_regions - Request and iomap PCI BARs
504 * @pdev: PCI device to map IO resources for
505 * @mask: Mask of BARs to request and iomap
506 * @name: Name used when requesting regions
507 *
508 * Request and iomap regions specified by @mask.
509 */
510int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name)
511{
512 void __iomem * const *iomap;
513 int i, rc;
514
515 iomap = pcim_iomap_table(pdev);
516 if (!iomap)
517 return -ENOMEM;
518
519 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
520 unsigned long len;
521
522 if (!(mask & (1 << i)))
523 continue;
524
525 rc = -EINVAL;
526 len = pci_resource_len(pdev, i);
527 if (!len)
528 goto err_inval;
529
530 rc = pci_request_region(pdev, i, name);
531 if (rc)
532 goto err_region;
533
534 rc = -ENOMEM;
535 if (!pcim_iomap(pdev, i, 0))
536 goto err_iomap;
537 }
538
539 return 0;
540
541 err_iomap:
542 pcim_iounmap(pdev, iomap[i]);
543 err_region:
544 pci_release_region(pdev, i);
545 err_inval:
546 while (--i >= 0) {
547 pcim_iounmap(pdev, iomap[i]);
548 pci_release_region(pdev, i);
549 }
550
551 return rc;
552}
553EXPORT_SYMBOL(pcim_iomap_regions);