On Thu, 13 Aug 2026 15:06:10 +0530
<[email protected]> wrote:

> From: Manish Honap <[email protected]>
> 
> 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 <[email protected]>
> ---
>  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);
> +

Use guards to simplify these, especially the registration path where we
can then just return -EBUSY.

I see the get function stores a per-vdev cxl_ops pointer with module
reference held for the life of the device, so the serialization on the
mutex is only per-device at probe time, but it might still be
worthwhile to preempt that with a rwsem here where both these paths are
writers and the get is a reader.

>  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;
> +};

To mirror vfio_device_ops, should these drop _device and just become
.init and .release?  I think that better reflects their actual usage
while the eventual .open_device and .close_device already reflect the
mapping into vfio_device_ops sequencing.  Thanks,

Alex

> +
> +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,


Reply via email to