[PATCH v4 06/27] vfio/pci: Add CXL ops registration interface

From: mhonap

Date: Thu Aug 13 2026 - 05:46:27 EST


From: Manish Honap <mhonap@xxxxxxxxxx>

vfio-pci-core must stay free of any CXL header dependency, so CXL
Type-2 handling lives in a separate vfio-cxl module that plugs in a set
of callbacks. Add the registration interface: vfio-cxl registers a
single struct vfio_cxl_ops at module_init, and vfio-pci-core stores it
under a mutex.

The owner field lets a later patch pin vfio-cxl for the lifetime of each
bound CXL device. No caller yet; the detection path is added next.

Signed-off-by: Manish Honap <mhonap@xxxxxxxxxx>
---
drivers/vfio/pci/vfio_pci_core.c | 27 +++++++++++++++++++++++++++
include/linux/vfio_pci_core.h | 10 ++++++++++
2 files changed, 37 insertions(+)

diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 3f11a9624b9c..88e68d43af9a 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -2670,6 +2670,33 @@ static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)
}
}

+static const struct vfio_cxl_ops *vfio_pci_cxl_ops;
+static DEFINE_MUTEX(vfio_pci_cxl_ops_lock);
+
+int vfio_pci_core_register_cxl_ops(const struct vfio_cxl_ops *ops)
+{
+ int ret = 0;
+
+ mutex_lock(&vfio_pci_cxl_ops_lock);
+ if (vfio_pci_cxl_ops)
+ ret = -EBUSY;
+ else
+ vfio_pci_cxl_ops = ops;
+ mutex_unlock(&vfio_pci_cxl_ops_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_register_cxl_ops);
+
+void vfio_pci_core_unregister_cxl_ops(const struct vfio_cxl_ops *ops)
+{
+ mutex_lock(&vfio_pci_cxl_ops_lock);
+ if (vfio_pci_cxl_ops == ops)
+ vfio_pci_cxl_ops = NULL;
+ mutex_unlock(&vfio_pci_cxl_ops_lock);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_unregister_cxl_ops);
+
static void vfio_pci_core_cleanup(void)
{
vfio_pci_uninit_perm_bits();
diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
index 9a1674c152aa..14753972e714 100644
--- a/include/linux/vfio_pci_core.h
+++ b/include/linux/vfio_pci_core.h
@@ -66,6 +66,16 @@ struct vfio_pci_device_ops {
size_t nr_ranges);
};

+struct vfio_cxl_ops {
+ int (*init_device)(struct vfio_pci_core_device *vdev);
+ void (*release_device)(struct vfio_pci_core_device *vdev);
+ /* Pinned per bound CXL device so vfio-cxl cannot unload under usage */
+ struct module *owner;
+};
+
+int vfio_pci_core_register_cxl_ops(const struct vfio_cxl_ops *ops);
+void vfio_pci_core_unregister_cxl_ops(const struct vfio_cxl_ops *ops);
+
#if IS_ENABLED(CONFIG_VFIO_PCI_DMABUF)
int vfio_pci_core_fill_phys_vec(struct phys_vec *phys_vec,
struct vfio_region_dma_range *dma_ranges,
--
2.25.1