diff options
Diffstat (limited to 'drivers/pci/iov.c')
| -rw-r--r-- | drivers/pci/iov.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index b497daab3d4a..0a7a1b40286f 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * PCI Express I/O Virtualization (IOV) support. | 6 | * PCI Express I/O Virtualization (IOV) support. |
| 7 | * Single Root IOV 1.0 | 7 | * Single Root IOV 1.0 |
| 8 | * Address Translation Service 1.0 | ||
| 8 | */ | 9 | */ |
| 9 | 10 | ||
| 10 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
| @@ -679,3 +680,107 @@ irqreturn_t pci_sriov_migration(struct pci_dev *dev) | |||
| 679 | return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE; | 680 | return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE; |
| 680 | } | 681 | } |
| 681 | EXPORT_SYMBOL_GPL(pci_sriov_migration); | 682 | EXPORT_SYMBOL_GPL(pci_sriov_migration); |
| 683 | |||
| 684 | static int ats_alloc_one(struct pci_dev *dev, int ps) | ||
| 685 | { | ||
| 686 | int pos; | ||
| 687 | u16 cap; | ||
| 688 | struct pci_ats *ats; | ||
| 689 | |||
| 690 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); | ||
| 691 | if (!pos) | ||
| 692 | return -ENODEV; | ||
| 693 | |||
| 694 | ats = kzalloc(sizeof(*ats), GFP_KERNEL); | ||
| 695 | if (!ats) | ||
| 696 | return -ENOMEM; | ||
| 697 | |||
| 698 | ats->pos = pos; | ||
| 699 | ats->stu = ps; | ||
| 700 | pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap); | ||
| 701 | ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) : | ||
| 702 | PCI_ATS_MAX_QDEP; | ||
| 703 | dev->ats = ats; | ||
| 704 | |||
| 705 | return 0; | ||
| 706 | } | ||
| 707 | |||
| 708 | static void ats_free_one(struct pci_dev *dev) | ||
| 709 | { | ||
| 710 | kfree(dev->ats); | ||
| 711 | dev->ats = NULL; | ||
| 712 | } | ||
| 713 | |||
| 714 | /** | ||
| 715 | * pci_enable_ats - enable the ATS capability | ||
| 716 | * @dev: the PCI device | ||
| 717 | * @ps: the IOMMU page shift | ||
| 718 | * | ||
| 719 | * Returns 0 on success, or negative on failure. | ||
| 720 | */ | ||
| 721 | int pci_enable_ats(struct pci_dev *dev, int ps) | ||
| 722 | { | ||
| 723 | int rc; | ||
| 724 | u16 ctrl; | ||
| 725 | |||
| 726 | BUG_ON(dev->ats); | ||
| 727 | |||
| 728 | if (ps < PCI_ATS_MIN_STU) | ||
| 729 | return -EINVAL; | ||
| 730 | |||
| 731 | rc = ats_alloc_one(dev, ps); | ||
| 732 | if (rc) | ||
| 733 | return rc; | ||
| 734 | |||
| 735 | ctrl = PCI_ATS_CTRL_ENABLE; | ||
| 736 | ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU); | ||
| 737 | pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl); | ||
| 738 | |||
| 739 | return 0; | ||
| 740 | } | ||
| 741 | |||
| 742 | /** | ||
| 743 | * pci_disable_ats - disable the ATS capability | ||
| 744 | * @dev: the PCI device | ||
| 745 | */ | ||
| 746 | void pci_disable_ats(struct pci_dev *dev) | ||
| 747 | { | ||
| 748 | u16 ctrl; | ||
| 749 | |||
| 750 | BUG_ON(!dev->ats); | ||
| 751 | |||
| 752 | pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl); | ||
| 753 | ctrl &= ~PCI_ATS_CTRL_ENABLE; | ||
| 754 | pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl); | ||
| 755 | |||
| 756 | ats_free_one(dev); | ||
| 757 | } | ||
| 758 | |||
| 759 | /** | ||
| 760 | * pci_ats_queue_depth - query the ATS Invalidate Queue Depth | ||
| 761 | * @dev: the PCI device | ||
| 762 | * | ||
| 763 | * Returns the queue depth on success, or negative on failure. | ||
| 764 | * | ||
| 765 | * The ATS spec uses 0 in the Invalidate Queue Depth field to | ||
| 766 | * indicate that the function can accept 32 Invalidate Request. | ||
| 767 | * But here we use the `real' values (i.e. 1~32) for the Queue | ||
| 768 | * Depth. | ||
| 769 | */ | ||
| 770 | int pci_ats_queue_depth(struct pci_dev *dev) | ||
| 771 | { | ||
| 772 | int pos; | ||
| 773 | u16 cap; | ||
| 774 | |||
| 775 | if (dev->ats) | ||
| 776 | return dev->ats->qdep; | ||
| 777 | |||
| 778 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); | ||
| 779 | if (!pos) | ||
| 780 | return -ENODEV; | ||
| 781 | |||
| 782 | pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap); | ||
| 783 | |||
| 784 | return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) : | ||
| 785 | PCI_ATS_MAX_QDEP; | ||
| 786 | } | ||
