Changeset 745 for GPL/branches/uniaud32-next/lib32/devres.c
- Timestamp:
- Sep 18, 2022, 11:24:34 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GPL/branches/uniaud32-next/lib32/devres.c
r720 r745 9 9 10 10 #include <linux/device.h> 11 #include <linux/pci.h> 11 12 #include <linux/module.h> 12 13 #include <linux/slab.h> … … 310 311 return NULL; 311 312 } 313 314 /** 315 * devres_get - Find devres, if non-existent, add one atomically 316 * @dev: Device to lookup or add devres for 317 * @new_res: Pointer to new initialized devres to add if not found 318 * @match: Match function (optional) 319 * @match_data: Data for the match function 320 * 321 * Find the latest devres of @dev which has the same release function 322 * as @new_res and for which @match return 1. If found, @new_res is 323 * freed; otherwise, @new_res is added atomically. 324 * 325 * RETURNS: 326 * Pointer to found or added devres. 327 */ 328 void * devres_get(struct device *dev, void *new_res, 329 dr_match_t match, void *match_data) 330 { 331 struct devres *new_dr = container_of(new_res, struct devres, data); 332 struct devres *dr; 333 unsigned long flags; 334 335 spin_lock_irqsave(&dev->devres_lock, flags); 336 dr = find_dr(dev, new_dr->node.release, match, match_data); 337 if (!dr) { 338 add_dr(dev, &new_dr->node); 339 dr = new_dr; 340 new_res = NULL; 341 } 342 spin_unlock_irqrestore(&dev->devres_lock, flags); 343 devres_free(new_res); 344 345 return dr->data; 346 } 347 EXPORT_SYMBOL_GPL(devres_get); 312 348 313 349 /* … … 472 508 } 473 509 EXPORT_SYMBOL(devm_ioremap); 510 511 /** 512 * devm_kvasprintf - Allocate resource managed space and format a string 513 * into that. 514 * @dev: Device to allocate memory for 515 * @gfp: the GFP mask used in the devm_kmalloc() call when 516 * allocating memory 517 * @fmt: The printf()-style format string 518 * @ap: Arguments for the format string 519 * RETURNS: 520 * Pointer to allocated string on success, NULL on failure. 521 */ 522 char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt, 523 va_list ap) 524 { 525 unsigned int len; 526 char *p; 527 va_list aq; 528 529 va_copy(aq, ap); 530 len = vsnprintf(NULL, 0, fmt, aq); 531 va_end(aq); 532 533 p = devm_kmalloc(dev, len+1, gfp); 534 if (!p) 535 return NULL; 536 537 vsnprintf(p, len+1, fmt, ap); 538 539 return p; 540 } 541 EXPORT_SYMBOL(devm_kvasprintf); 542 /** 543 * devm_kasprintf - Allocate resource managed space and format a string 544 * into that. 545 * @dev: Device to allocate memory for 546 * @gfp: the GFP mask used in the devm_kmalloc() call when 547 * allocating memory 548 * @fmt: The printf()-style format string 549 * @...: Arguments for the format string 550 * RETURNS: 551 * Pointer to allocated string on success, NULL on failure. 552 */ 553 char *devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...) 554 { 555 va_list ap; 556 char *p; 557 558 va_start(ap, fmt); 559 p = devm_kvasprintf(dev, gfp, fmt, ap); 560 va_end(ap); 561 562 return p; 563 } 564 EXPORT_SYMBOL_GPL(devm_kasprintf); 565 566 /* 567 * PCI iomap devres 568 */ 569 #define PCIM_IOMAP_MAX PCI_STD_NUM_BARS 570 571 struct pcim_iomap_devres { 572 void __iomem *table[PCIM_IOMAP_MAX]; 573 }; 574 575 static void pcim_iomap_release(struct device *gendev, void *res) 576 { 577 struct pci_dev *dev = to_pci_dev(gendev); 578 struct pcim_iomap_devres *this = res; 579 int i; 580 581 for (i = 0; i < PCIM_IOMAP_MAX; i++) 582 if (this->table[i]) 583 pci_iounmap(dev, this->table[i]); 584 } 585 586 /** 587 * pcim_iomap_table - access iomap allocation table 588 * @pdev: PCI device to access iomap table for 589 * 590 * Access iomap allocation table for @dev. If iomap table doesn't 591 * exist and @pdev is managed, it will be allocated. All iomaps 592 * recorded in the iomap table are automatically unmapped on driver 593 * detach. 594 * 595 * This function might sleep when the table is first allocated but can 596 * be safely called without context and guaranteed to succeed once 597 * allocated. 598 */ 599 void __iomem * const *pcim_iomap_table(struct pci_dev *pdev) 600 { 601 struct pcim_iomap_devres *dr, *new_dr; 602 603 dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL); 604 if (dr) 605 return dr->table; 606 607 new_dr = devres_alloc(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL); 608 if (!new_dr) 609 return NULL; 610 dr = devres_get(&pdev->dev, new_dr, NULL, NULL); 611 return dr->table; 612 } 613 EXPORT_SYMBOL(pcim_iomap_table); 614 615 /** 616 * pcim_iomap - Managed pcim_iomap() 617 * @pdev: PCI device to iomap for 618 * @bar: BAR to iomap 619 * @maxlen: Maximum length of iomap 620 * 621 * Managed pci_iomap(). Map is automatically unmapped on driver 622 * detach. 623 */ 624 void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen) 625 { 626 void __iomem **tbl; 627 628 BUG_ON(bar >= PCIM_IOMAP_MAX); 629 630 tbl = (void __iomem **)pcim_iomap_table(pdev); 631 if (!tbl || tbl[bar]) /* duplicate mappings not allowed */ 632 return NULL; 633 634 tbl[bar] = pci_iomap(pdev, bar, maxlen); 635 return tbl[bar]; 636 } 637 EXPORT_SYMBOL(pcim_iomap); 638 639 /** 640 * pcim_iounmap - Managed pci_iounmap() 641 * @pdev: PCI device to iounmap for 642 * @addr: Address to unmap 643 * 644 * Managed pci_iounmap(). @addr must have been mapped using pcim_iomap(). 645 */ 646 void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr) 647 { 648 void __iomem **tbl; 649 int i; 650 651 pci_iounmap(pdev, addr); 652 653 tbl = (void __iomem **)pcim_iomap_table(pdev); 654 BUG_ON(!tbl); 655 656 for (i = 0; i < PCIM_IOMAP_MAX; i++) 657 if (tbl[i] == addr) { 658 tbl[i] = NULL; 659 return; 660 } 661 WARN_ON(1); 662 } 663 EXPORT_SYMBOL(pcim_iounmap); 664 665 /** 666 * pcim_iomap_regions - Request and iomap PCI BARs 667 * @pdev: PCI device to map IO resources for 668 * @mask: Mask of BARs to request and iomap 669 * @name: Name used when requesting regions 670 * 671 * Request and iomap regions specified by @mask. 672 */ 673 int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name) 674 { 675 void __iomem * const *iomap; 676 int i, rc; 677 678 iomap = pcim_iomap_table(pdev); 679 if (!iomap) 680 return -ENOMEM; 681 682 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 683 unsigned long len; 684 685 if (!(mask & (1 << i))) 686 continue; 687 688 rc = -EINVAL; 689 len = pci_resource_len(pdev, i); 690 if (!len) 691 goto err_inval; 692 693 rc = pci_request_region(pdev, i, name); 694 if (rc) 695 goto err_inval; 696 697 rc = -ENOMEM; 698 if (!pcim_iomap(pdev, i, 0)) 699 goto err_region; 700 } 701 702 return 0; 703 704 err_region: 705 pci_release_region(pdev, i); 706 err_inval: 707 while (--i >= 0) { 708 if (!(mask & (1 << i))) 709 continue; 710 pcim_iounmap(pdev, iomap[i]); 711 pci_release_region(pdev, i); 712 } 713 714 return rc; 715 } 716 EXPORT_SYMBOL(pcim_iomap_regions);
Note:
See TracChangeset
for help on using the changeset viewer.