|
20 | 20 | #include <linux/pci-doe.h> |
21 | 21 | #include <linux/workqueue.h> |
22 | 22 |
|
| 23 | +#include "pci.h" |
| 24 | + |
23 | 25 | #define PCI_DOE_PROTOCOL_DISCOVERY 0 |
24 | 26 |
|
25 | 27 | /* Timeout of 1 second from 6.30.2 Operation, PCI Spec r6.0 */ |
@@ -658,3 +660,74 @@ int pci_doe(struct pci_doe_mb *doe_mb, u16 vendor, u8 type, |
658 | 660 | return task.rv; |
659 | 661 | } |
660 | 662 | EXPORT_SYMBOL_GPL(pci_doe); |
| 663 | + |
| 664 | +/** |
| 665 | + * pci_find_doe_mailbox() - Find Data Object Exchange mailbox |
| 666 | + * |
| 667 | + * @pdev: PCI device |
| 668 | + * @vendor: Vendor ID |
| 669 | + * @type: Data Object Type |
| 670 | + * |
| 671 | + * Find first DOE mailbox of a PCI device which supports the given protocol. |
| 672 | + * |
| 673 | + * RETURNS: Pointer to the DOE mailbox or NULL if none was found. |
| 674 | + */ |
| 675 | +struct pci_doe_mb *pci_find_doe_mailbox(struct pci_dev *pdev, u16 vendor, |
| 676 | + u8 type) |
| 677 | +{ |
| 678 | + struct pci_doe_mb *doe_mb; |
| 679 | + unsigned long index; |
| 680 | + |
| 681 | + xa_for_each(&pdev->doe_mbs, index, doe_mb) |
| 682 | + if (pci_doe_supports_prot(doe_mb, vendor, type)) |
| 683 | + return doe_mb; |
| 684 | + |
| 685 | + return NULL; |
| 686 | +} |
| 687 | +EXPORT_SYMBOL_GPL(pci_find_doe_mailbox); |
| 688 | + |
| 689 | +void pci_doe_init(struct pci_dev *pdev) |
| 690 | +{ |
| 691 | + struct pci_doe_mb *doe_mb; |
| 692 | + u16 offset = 0; |
| 693 | + int rc; |
| 694 | + |
| 695 | + xa_init(&pdev->doe_mbs); |
| 696 | + |
| 697 | + while ((offset = pci_find_next_ext_capability(pdev, offset, |
| 698 | + PCI_EXT_CAP_ID_DOE))) { |
| 699 | + doe_mb = pci_doe_create_mb(pdev, offset); |
| 700 | + if (IS_ERR(doe_mb)) { |
| 701 | + pci_err(pdev, "[%x] failed to create mailbox: %ld\n", |
| 702 | + offset, PTR_ERR(doe_mb)); |
| 703 | + continue; |
| 704 | + } |
| 705 | + |
| 706 | + rc = xa_insert(&pdev->doe_mbs, offset, doe_mb, GFP_KERNEL); |
| 707 | + if (rc) { |
| 708 | + pci_err(pdev, "[%x] failed to insert mailbox: %d\n", |
| 709 | + offset, rc); |
| 710 | + pci_doe_destroy_mb(doe_mb); |
| 711 | + } |
| 712 | + } |
| 713 | +} |
| 714 | + |
| 715 | +void pci_doe_destroy(struct pci_dev *pdev) |
| 716 | +{ |
| 717 | + struct pci_doe_mb *doe_mb; |
| 718 | + unsigned long index; |
| 719 | + |
| 720 | + xa_for_each(&pdev->doe_mbs, index, doe_mb) |
| 721 | + pci_doe_destroy_mb(doe_mb); |
| 722 | + |
| 723 | + xa_destroy(&pdev->doe_mbs); |
| 724 | +} |
| 725 | + |
| 726 | +void pci_doe_disconnected(struct pci_dev *pdev) |
| 727 | +{ |
| 728 | + struct pci_doe_mb *doe_mb; |
| 729 | + unsigned long index; |
| 730 | + |
| 731 | + xa_for_each(&pdev->doe_mbs, index, doe_mb) |
| 732 | + pci_doe_cancel_tasks(doe_mb); |
| 733 | +} |
0 commit comments