diff options
-rw-r--r-- | include/linux/io.h | 2 | ||||
-rw-r--r-- | lib/iomap.c | 53 |
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); | |||
45 | void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr); | 45 | void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr); |
46 | void __iomem * const * pcim_iomap_table(struct pci_dev *pdev); | 46 | void __iomem * const * pcim_iomap_table(struct pci_dev *pdev); |
47 | 47 | ||
48 | int 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 | } |
500 | EXPORT_SYMBOL(pcim_iounmap); | 500 | EXPORT_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 | */ | ||
510 | int 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 | } | ||
553 | EXPORT_SYMBOL(pcim_iomap_regions); | ||