2019-05-27 08:55:21 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2015-03-16 14:08:43 -06:00
/*
* Copyright ( C ) 2013 - Virtual Open Systems
* Author : Antonios Motakis < a . motakis @ virtualopensystems . com >
*/
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/vfio.h>
2022-09-21 18:43:57 +08:00
# include <linux/pm_runtime.h>
2015-03-16 14:08:43 -06:00
# include <linux/platform_device.h>
# include "vfio_platform_private.h"
# define DRIVER_VERSION "0.10"
# define DRIVER_AUTHOR "Antonios Motakis <a.motakis@virtualopensystems.com>"
# define DRIVER_DESC "VFIO for platform devices - User Level meta-driver"
2016-07-19 09:01:47 -04:00
static bool reset_required = true ;
module_param ( reset_required , bool , 0444 ) ;
MODULE_PARM_DESC ( reset_required , " override reset requirement (default: 1) " ) ;
2015-03-16 14:08:43 -06:00
/* probing devices from the linux platform bus */
static struct resource * get_platform_resource ( struct vfio_platform_device * vdev ,
int num )
{
struct platform_device * dev = ( struct platform_device * ) vdev - > opaque ;
2020-12-09 22:36:39 +02:00
return platform_get_mem_or_io ( dev , num ) ;
2015-03-16 14:08:43 -06:00
}
static int get_platform_irq ( struct vfio_platform_device * vdev , int i )
{
struct platform_device * pdev = ( struct platform_device * ) vdev - > opaque ;
2020-03-24 09:26:30 -06:00
return platform_get_irq_optional ( pdev , i ) ;
2015-03-16 14:08:43 -06:00
}
2022-09-21 18:43:57 +08:00
static int vfio_platform_init_dev ( struct vfio_device * core_vdev )
2015-03-16 14:08:43 -06:00
{
2022-09-21 18:43:57 +08:00
struct vfio_platform_device * vdev =
container_of ( core_vdev , struct vfio_platform_device , vdev ) ;
struct platform_device * pdev = to_platform_device ( core_vdev - > dev ) ;
2015-03-16 14:08:43 -06:00
vdev - > opaque = ( void * ) pdev ;
vdev - > name = pdev - > name ;
vdev - > flags = VFIO_DEVICE_FLAGS_PLATFORM ;
vdev - > get_resource = get_platform_resource ;
vdev - > get_irq = get_platform_irq ;
2016-07-19 09:01:47 -04:00
vdev - > reset_required = reset_required ;
2015-03-16 14:08:43 -06:00
2022-09-21 18:43:57 +08:00
return vfio_platform_init_common ( vdev ) ;
}
static const struct vfio_device_ops vfio_platform_ops ;
static int vfio_platform_probe ( struct platform_device * pdev )
{
struct vfio_platform_device * vdev ;
int ret ;
vdev = vfio_alloc_device ( vfio_platform_device , vdev , & pdev - > dev ,
& vfio_platform_ops ) ;
if ( IS_ERR ( vdev ) )
return PTR_ERR ( vdev ) ;
ret = vfio_register_group_dev ( & vdev - > vdev ) ;
if ( ret )
goto out_put_vdev ;
pm_runtime_enable ( & pdev - > dev ) ;
2021-03-30 09:53:06 -06:00
dev_set_drvdata ( & pdev - > dev , vdev ) ;
return 0 ;
2022-09-21 18:43:57 +08:00
out_put_vdev :
vfio_put_device ( & vdev - > vdev ) ;
return ret ;
}
static void vfio_platform_release_dev ( struct vfio_device * core_vdev )
{
struct vfio_platform_device * vdev =
container_of ( core_vdev , struct vfio_platform_device , vdev ) ;
vfio_platform_release_common ( vdev ) ;
2015-03-16 14:08:43 -06:00
}
static int vfio_platform_remove ( struct platform_device * pdev )
{
2021-03-30 09:53:06 -06:00
struct vfio_platform_device * vdev = dev_get_drvdata ( & pdev - > dev ) ;
2015-03-16 14:08:43 -06:00
2022-09-21 18:43:57 +08:00
vfio_unregister_group_dev ( & vdev - > vdev ) ;
pm_runtime_disable ( vdev - > device ) ;
vfio_put_device ( & vdev - > vdev ) ;
2021-03-30 09:53:06 -06:00
return 0 ;
2015-03-16 14:08:43 -06:00
}
2022-09-21 18:43:57 +08:00
static const struct vfio_device_ops vfio_platform_ops = {
. name = " vfio-platform " ,
. init = vfio_platform_init_dev ,
. release = vfio_platform_release_dev ,
. open_device = vfio_platform_open_device ,
. close_device = vfio_platform_close_device ,
. ioctl = vfio_platform_ioctl ,
. read = vfio_platform_read ,
. write = vfio_platform_write ,
. mmap = vfio_platform_mmap ,
2022-11-29 16:31:51 -04:00
. bind_iommufd = vfio_iommufd_physical_bind ,
. unbind_iommufd = vfio_iommufd_physical_unbind ,
. attach_ioas = vfio_iommufd_physical_attach_ioas ,
2022-09-21 18:43:57 +08:00
} ;
2015-03-16 14:08:43 -06:00
static struct platform_driver vfio_platform_driver = {
. probe = vfio_platform_probe ,
. remove = vfio_platform_remove ,
. driver = {
. name = " vfio-platform " ,
} ,
2022-04-18 08:49:56 +08:00
. driver_managed_dma = true ,
2015-03-16 14:08:43 -06:00
} ;
module_platform_driver ( vfio_platform_driver ) ;
MODULE_VERSION ( DRIVER_VERSION ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_AUTHOR ( DRIVER_AUTHOR ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;