diff options
Diffstat (limited to 'drivers/vfio/pci/vfio_pci_config.c')
-rw-r--r-- | drivers/vfio/pci/vfio_pci_config.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 91335e6de88a..115a36f6f403 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c | |||
@@ -808,6 +808,7 @@ static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos, | |||
808 | { | 808 | { |
809 | __le16 *ctrl = (__le16 *)(vdev->vconfig + pos - | 809 | __le16 *ctrl = (__le16 *)(vdev->vconfig + pos - |
810 | offset + PCI_EXP_DEVCTL); | 810 | offset + PCI_EXP_DEVCTL); |
811 | int readrq = le16_to_cpu(*ctrl) & PCI_EXP_DEVCTL_READRQ; | ||
811 | 812 | ||
812 | count = vfio_default_config_write(vdev, pos, count, perm, offset, val); | 813 | count = vfio_default_config_write(vdev, pos, count, perm, offset, val); |
813 | if (count < 0) | 814 | if (count < 0) |
@@ -833,6 +834,27 @@ static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos, | |||
833 | pci_try_reset_function(vdev->pdev); | 834 | pci_try_reset_function(vdev->pdev); |
834 | } | 835 | } |
835 | 836 | ||
837 | /* | ||
838 | * MPS is virtualized to the user, writes do not change the physical | ||
839 | * register since determining a proper MPS value requires a system wide | ||
840 | * device view. The MRRS is largely independent of MPS, but since the | ||
841 | * user does not have that system-wide view, they might set a safe, but | ||
842 | * inefficiently low value. Here we allow writes through to hardware, | ||
843 | * but we set the floor to the physical device MPS setting, so that | ||
844 | * we can at least use full TLPs, as defined by the MPS value. | ||
845 | * | ||
846 | * NB, if any devices actually depend on an artificially low MRRS | ||
847 | * setting, this will need to be revisited, perhaps with a quirk | ||
848 | * though pcie_set_readrq(). | ||
849 | */ | ||
850 | if (readrq != (le16_to_cpu(*ctrl) & PCI_EXP_DEVCTL_READRQ)) { | ||
851 | readrq = 128 << | ||
852 | ((le16_to_cpu(*ctrl) & PCI_EXP_DEVCTL_READRQ) >> 12); | ||
853 | readrq = max(readrq, pcie_get_mps(vdev->pdev)); | ||
854 | |||
855 | pcie_set_readrq(vdev->pdev, readrq); | ||
856 | } | ||
857 | |||
836 | return count; | 858 | return count; |
837 | } | 859 | } |
838 | 860 | ||
@@ -851,11 +873,12 @@ static int __init init_pci_cap_exp_perm(struct perm_bits *perm) | |||
851 | * Allow writes to device control fields, except devctl_phantom, | 873 | * Allow writes to device control fields, except devctl_phantom, |
852 | * which could confuse IOMMU, MPS, which can break communication | 874 | * which could confuse IOMMU, MPS, which can break communication |
853 | * with other physical devices, and the ARI bit in devctl2, which | 875 | * with other physical devices, and the ARI bit in devctl2, which |
854 | * is set at probe time. FLR gets virtualized via our writefn. | 876 | * is set at probe time. FLR and MRRS get virtualized via our |
877 | * writefn. | ||
855 | */ | 878 | */ |
856 | p_setw(perm, PCI_EXP_DEVCTL, | 879 | p_setw(perm, PCI_EXP_DEVCTL, |
857 | PCI_EXP_DEVCTL_BCR_FLR | PCI_EXP_DEVCTL_PAYLOAD, | 880 | PCI_EXP_DEVCTL_BCR_FLR | PCI_EXP_DEVCTL_PAYLOAD | |
858 | ~PCI_EXP_DEVCTL_PHANTOM); | 881 | PCI_EXP_DEVCTL_READRQ, ~PCI_EXP_DEVCTL_PHANTOM); |
859 | p_setw(perm, PCI_EXP_DEVCTL2, NO_VIRT, ~PCI_EXP_DEVCTL2_ARI); | 882 | p_setw(perm, PCI_EXP_DEVCTL2, NO_VIRT, ~PCI_EXP_DEVCTL2_ARI); |
860 | return 0; | 883 | return 0; |
861 | } | 884 | } |