vfio/pci-core: Add capability for AtomicOp completer support
authorAlex Williamson <alex.williamson@redhat.com>
Fri, 19 May 2023 21:47:48 +0000 (15:47 -0600)
committerAlex Williamson <alex.williamson@redhat.com>
Fri, 16 Jun 2023 18:22:18 +0000 (12:22 -0600)
Test and enable PCIe AtomicOp completer support of various widths and
report via device-info capability to userspace.

Reviewed-by: Cédric Le Goater <clg@redhat.com>
Reviewed-by: Robin Voetter <robin@streamhpc.com>
Tested-by: Robin Voetter <robin@streamhpc.com>
Link: https://lore.kernel.org/r/20230519214748.402003-1-alex.williamson@redhat.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
drivers/vfio/pci/vfio_pci_core.c
include/uapi/linux/vfio.h

index ec7e662..20d7b69 100644 (file)
@@ -885,6 +885,37 @@ int vfio_pci_core_register_dev_region(struct vfio_pci_core_device *vdev,
 }
 EXPORT_SYMBOL_GPL(vfio_pci_core_register_dev_region);
 
+static int vfio_pci_info_atomic_cap(struct vfio_pci_core_device *vdev,
+                                   struct vfio_info_cap *caps)
+{
+       struct vfio_device_info_cap_pci_atomic_comp cap = {
+               .header.id = VFIO_DEVICE_INFO_CAP_PCI_ATOMIC_COMP,
+               .header.version = 1
+       };
+       struct pci_dev *pdev = pci_physfn(vdev->pdev);
+       u32 devcap2;
+
+       pcie_capability_read_dword(pdev, PCI_EXP_DEVCAP2, &devcap2);
+
+       if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP32) &&
+           !pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP32))
+               cap.flags |= VFIO_PCI_ATOMIC_COMP32;
+
+       if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP64) &&
+           !pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP64))
+               cap.flags |= VFIO_PCI_ATOMIC_COMP64;
+
+       if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP128) &&
+           !pci_enable_atomic_ops_to_root(pdev,
+                                          PCI_EXP_DEVCAP2_ATOMIC_COMP128))
+               cap.flags |= VFIO_PCI_ATOMIC_COMP128;
+
+       if (!cap.flags)
+               return -ENODEV;
+
+       return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
+}
+
 static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev,
                                   struct vfio_device_info __user *arg)
 {
@@ -923,6 +954,13 @@ static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev,
                return ret;
        }
 
+       ret = vfio_pci_info_atomic_cap(vdev, &caps);
+       if (ret && ret != -ENODEV) {
+               pci_warn(vdev->pdev,
+                        "Failed to setup AtomicOps info capability\n");
+               return ret;
+       }
+
        if (caps.size) {
                info.flags |= VFIO_DEVICE_FLAGS_CAPS;
                if (info.argsz < sizeof(info) + caps.size) {
index 1a36134..4f48bad 100644 (file)
@@ -240,6 +240,20 @@ struct vfio_device_info {
 #define VFIO_DEVICE_INFO_CAP_ZPCI_UTIL         3
 #define VFIO_DEVICE_INFO_CAP_ZPCI_PFIP         4
 
+/*
+ * The following VFIO_DEVICE_INFO capability reports support for PCIe AtomicOp
+ * completion to the root bus with supported widths provided via flags.
+ */
+#define VFIO_DEVICE_INFO_CAP_PCI_ATOMIC_COMP   5
+struct vfio_device_info_cap_pci_atomic_comp {
+       struct vfio_info_cap_header header;
+       __u32 flags;
+#define VFIO_PCI_ATOMIC_COMP32 (1 << 0)
+#define VFIO_PCI_ATOMIC_COMP64 (1 << 1)
+#define VFIO_PCI_ATOMIC_COMP128        (1 << 2)
+       __u32 reserved;
+};
+
 /**
  * VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8,
  *                                    struct vfio_region_info)