From: Manish Honap <[email protected]>

Read the HDM region size from decoder 0, cached in pdev->hdm at
enumeration, and use it to size the accelerator device state. A Type-2
accelerator has no mailbox, so cxl_set_capacity() establishes the
capacity that devm_cxl_probe_mem() then uses to join the device to the
CXL topology and resolve the host physical range.

Everything here is devm-scoped to the PCI device, so it is unwound when
vfio-pci unbinds. If pdev->hdm is not populated yet, defer the bind.

Signed-off-by: Manish Honap <[email protected]>
---
 drivers/vfio/pci/cxl/vfio_cxl_core.c | 53 ++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/drivers/vfio/pci/cxl/vfio_cxl_core.c 
b/drivers/vfio/pci/cxl/vfio_cxl_core.c
index cbec7319452c..125e11354a46 100644
--- a/drivers/vfio/pci/cxl/vfio_cxl_core.c
+++ b/drivers/vfio/pci/cxl/vfio_cxl_core.c
@@ -6,15 +6,67 @@
  */
 
 #include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/range.h>
 #include <linux/vfio_pci_core.h>
+#include <cxl/cxl.h>
+
+/**
+ * struct vfio_cxl_state - per-device state for a vfio-cxl device
+ * @cxlds: CXL device state; kept first for devm_cxl_dev_state_create()
+ * @cxlmd: memory device joined to the CXL topology at bind
+ * @hpa_range: host physical range of the HDM region
+ */
+struct vfio_cxl_state {
+       struct cxl_dev_state cxlds;
+       struct cxl_memdev *cxlmd;
+       struct range hpa_range;
+};
 
 static int vfio_cxl_init_device(struct vfio_pci_core_device *vdev)
 {
+       struct pci_dev *pdev = vdev->pdev;
+       struct vfio_cxl_state *cxl;
+       struct cxl_memdev *cxlmd;
+       u64 hdm_size, serial;
+       u16 dvsec;
+       int ret;
+
+       /* pdev->hdm is populated at PCI enumeration; defer until it is. */
+       if (!pdev->hdm)
+               return -EPROBE_DEFER;
+
+       hdm_size = range_len(&pdev->hdm->settings[0].hpa_range);
+       if (!hdm_size)
+               return -ENXIO;
+
+       dvsec = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,
+                                         PCI_DVSEC_CXL_DEVICE);
+       serial = pci_get_dsn(pdev);
+
+       cxl = devm_cxl_dev_state_create(&pdev->dev, CXL_DEVTYPE_DEVMEM, serial,
+                                       dvsec, struct vfio_cxl_state, cxlds,
+                                       false);
+       if (!cxl)
+               return -ENOMEM;
+
+       ret = cxl_set_capacity(&cxl->cxlds, hdm_size);
+       if (ret)
+               return ret;
+
+       cxlmd = devm_cxl_probe_mem(&cxl->cxlds, &cxl->hpa_range);
+       if (IS_ERR(cxlmd))
+               return PTR_ERR(cxlmd);
+
+       cxl->cxlmd = cxlmd;
+       vdev->cxl = cxl;
+
        return 0;
 }
 
 static void vfio_cxl_release_device(struct vfio_pci_core_device *vdev)
 {
+       vdev->cxl = NULL;
 }
 
 static const struct vfio_cxl_ops vfio_cxl_ops = {
@@ -39,3 +91,4 @@ module_exit(vfio_cxl_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("VFIO support for CXL Type-2 devices");
 MODULE_ALIAS("vfio-cxl");
+MODULE_IMPORT_NS("CXL");
-- 
2.25.1


Reply via email to