diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/iomap.c | 53 |
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) | |||
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); | ||