aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/iov.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/iov.c')
-rw-r--r--drivers/pci/iov.c161
1 files changed, 153 insertions, 8 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index b497daab3d4a..e3a87210e947 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>
@@ -110,7 +111,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
110 } 111 }
111 112
112 if (reset) 113 if (reset)
113 pci_execute_reset_function(virtfn); 114 __pci_reset_function(virtfn);
114 115
115 pci_device_add(virtfn, virtfn->bus); 116 pci_device_add(virtfn, virtfn->bus);
116 mutex_unlock(&iov->dev->sriov->lock); 117 mutex_unlock(&iov->dev->sriov->lock);
@@ -164,7 +165,7 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset)
164 165
165 if (reset) { 166 if (reset) {
166 device_release_driver(&virtfn->dev); 167 device_release_driver(&virtfn->dev);
167 pci_execute_reset_function(virtfn); 168 __pci_reset_function(virtfn);
168 } 169 }
169 170
170 sprintf(buf, "virtfn%u", id); 171 sprintf(buf, "virtfn%u", id);
@@ -487,13 +488,15 @@ found:
487 iov->self = dev; 488 iov->self = dev;
488 pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); 489 pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap);
489 pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); 490 pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link);
491 if (dev->pcie_type == PCI_EXP_TYPE_RC_END)
492 iov->link = PCI_DEVFN(PCI_SLOT(dev->devfn), iov->link);
490 493
491 if (pdev) 494 if (pdev)
492 iov->dev = pci_dev_get(pdev); 495 iov->dev = pci_dev_get(pdev);
493 else { 496 else
494 iov->dev = dev; 497 iov->dev = dev;
495 mutex_init(&iov->lock); 498
496 } 499 mutex_init(&iov->lock);
497 500
498 dev->sriov = iov; 501 dev->sriov = iov;
499 dev->is_physfn = 1; 502 dev->is_physfn = 1;
@@ -513,11 +516,11 @@ static void sriov_release(struct pci_dev *dev)
513{ 516{
514 BUG_ON(dev->sriov->nr_virtfn); 517 BUG_ON(dev->sriov->nr_virtfn);
515 518
516 if (dev == dev->sriov->dev) 519 if (dev != dev->sriov->dev)
517 mutex_destroy(&dev->sriov->lock);
518 else
519 pci_dev_put(dev->sriov->dev); 520 pci_dev_put(dev->sriov->dev);
520 521
522 mutex_destroy(&dev->sriov->lock);
523
521 kfree(dev->sriov); 524 kfree(dev->sriov);
522 dev->sriov = NULL; 525 dev->sriov = NULL;
523} 526}
@@ -679,3 +682,145 @@ irqreturn_t pci_sriov_migration(struct pci_dev *dev)
679 return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE; 682 return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE;
680} 683}
681EXPORT_SYMBOL_GPL(pci_sriov_migration); 684EXPORT_SYMBOL_GPL(pci_sriov_migration);
685
686static int ats_alloc_one(struct pci_dev *dev, int ps)
687{
688 int pos;
689 u16 cap;
690 struct pci_ats *ats;
691
692 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
693 if (!pos)
694 return -ENODEV;
695
696 ats = kzalloc(sizeof(*ats), GFP_KERNEL);
697 if (!ats)
698 return -ENOMEM;
699
700 ats->pos = pos;
701 ats->stu = ps;
702 pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
703 ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
704 PCI_ATS_MAX_QDEP;
705 dev->ats = ats;
706
707 return 0;
708}
709
710static void ats_free_one(struct pci_dev *dev)
711{
712 kfree(dev->ats);
713 dev->ats = NULL;
714}
715
716/**
717 * pci_enable_ats - enable the ATS capability
718 * @dev: the PCI device
719 * @ps: the IOMMU page shift
720 *
721 * Returns 0 on success, or negative on failure.
722 */
723int pci_enable_ats(struct pci_dev *dev, int ps)
724{
725 int rc;
726 u16 ctrl;
727
728 BUG_ON(dev->ats && dev->ats->is_enabled);
729
730 if (ps < PCI_ATS_MIN_STU)
731 return -EINVAL;
732
733 if (dev->is_physfn || dev->is_virtfn) {
734 struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
735
736 mutex_lock(&pdev->sriov->lock);
737 if (pdev->ats)
738 rc = pdev->ats->stu == ps ? 0 : -EINVAL;
739 else
740 rc = ats_alloc_one(pdev, ps);
741
742 if (!rc)
743 pdev->ats->ref_cnt++;
744 mutex_unlock(&pdev->sriov->lock);
745 if (rc)
746 return rc;
747 }
748
749 if (!dev->is_physfn) {
750 rc = ats_alloc_one(dev, ps);
751 if (rc)
752 return rc;
753 }
754
755 ctrl = PCI_ATS_CTRL_ENABLE;
756 if (!dev->is_virtfn)
757 ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
758 pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
759
760 dev->ats->is_enabled = 1;
761
762 return 0;
763}
764
765/**
766 * pci_disable_ats - disable the ATS capability
767 * @dev: the PCI device
768 */
769void pci_disable_ats(struct pci_dev *dev)
770{
771 u16 ctrl;
772
773 BUG_ON(!dev->ats || !dev->ats->is_enabled);
774
775 pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
776 ctrl &= ~PCI_ATS_CTRL_ENABLE;
777 pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
778
779 dev->ats->is_enabled = 0;
780
781 if (dev->is_physfn || dev->is_virtfn) {
782 struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
783
784 mutex_lock(&pdev->sriov->lock);
785 pdev->ats->ref_cnt--;
786 if (!pdev->ats->ref_cnt)
787 ats_free_one(pdev);
788 mutex_unlock(&pdev->sriov->lock);
789 }
790
791 if (!dev->is_physfn)
792 ats_free_one(dev);
793}
794
795/**
796 * pci_ats_queue_depth - query the ATS Invalidate Queue Depth
797 * @dev: the PCI device
798 *
799 * Returns the queue depth on success, or negative on failure.
800 *
801 * The ATS spec uses 0 in the Invalidate Queue Depth field to
802 * indicate that the function can accept 32 Invalidate Request.
803 * But here we use the `real' values (i.e. 1~32) for the Queue
804 * Depth; and 0 indicates the function shares the Queue with
805 * other functions (doesn't exclusively own a Queue).
806 */
807int pci_ats_queue_depth(struct pci_dev *dev)
808{
809 int pos;
810 u16 cap;
811
812 if (dev->is_virtfn)
813 return 0;
814
815 if (dev->ats)
816 return dev->ats->qdep;
817
818 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
819 if (!pos)
820 return -ENODEV;
821
822 pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
823
824 return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
825 PCI_ATS_MAX_QDEP;
826}