@ -363,21 +363,31 @@ bool vfio_mig_active(void)
static Error * multiple_devices_migration_blocker ;
static Error * multiple_devices_migration_blocker ;
static unsigned int vfio_migratable_device_num ( void )
/*
* Multiple devices migration is allowed only if all devices support P2P
* migration . Single device migration is allowed regardless of P2P migration
* support .
*/
static bool vfio_multiple_devices_migration_is_supported ( void )
{
{
VFIOGroup * group ;
VFIOGroup * group ;
VFIODevice * vbasedev ;
VFIODevice * vbasedev ;
unsigned int device_num = 0 ;
unsigned int device_num = 0 ;
bool all_support_p2p = true ;
QLIST_FOREACH ( group , & vfio_group_list , next ) {
QLIST_FOREACH ( group , & vfio_group_list , next ) {
QLIST_FOREACH ( vbasedev , & group - > device_list , next ) {
QLIST_FOREACH ( vbasedev , & group - > device_list , next ) {
if ( vbasedev - > migration ) {
if ( vbasedev - > migration ) {
device_num + + ;
device_num + + ;
if ( ! ( vbasedev - > migration - > mig_flags & VFIO_MIGRATION_P2P ) ) {
all_support_p2p = false ;
}
}
}
}
}
}
}
return device_num ;
return all_support_p2p | | device_num < = 1 ;
}
}
int vfio_block_multiple_devices_migration ( VFIODevice * vbasedev , Error * * errp )
int vfio_block_multiple_devices_migration ( VFIODevice * vbasedev , Error * * errp )
@ -385,19 +395,19 @@ int vfio_block_multiple_devices_migration(VFIODevice *vbasedev, Error **errp)
int ret ;
int ret ;
if ( multiple_devices_migration_blocker | |
if ( multiple_devices_migration_blocker | |
vfio_migratable_device_num ( ) < = 1 ) {
vfio_multiple_devices_migration_is_supported ( ) ) {
return 0 ;
return 0 ;
}
}
if ( vbasedev - > enable_migration = = ON_OFF_AUTO_ON ) {
if ( vbasedev - > enable_migration = = ON_OFF_AUTO_ON ) {
error_setg ( errp , " Migration is currently not supported with multiple "
error_setg ( errp , " Multiple VFIO devices migration is supported only if "
" VFIO devices " ) ;
" all of them support P2P migration " ) ;
return - EINVAL ;
return - EINVAL ;
}
}
error_setg ( & multiple_devices_migration_blocker ,
error_setg ( & multiple_devices_migration_blocker ,
" Migration is currently not supported with multiple "
" Multiple VFIO devices migration is supported only if all of "
" VFIO devices " ) ;
" them support P2P migration " ) ;
ret = migrate_add_blocker ( multiple_devices_migration_blocker , errp ) ;
ret = migrate_add_blocker ( multiple_devices_migration_blocker , errp ) ;
if ( ret < 0 ) {
if ( ret < 0 ) {
error_free ( multiple_devices_migration_blocker ) ;
error_free ( multiple_devices_migration_blocker ) ;
@ -410,7 +420,7 @@ int vfio_block_multiple_devices_migration(VFIODevice *vbasedev, Error **errp)
void vfio_unblock_multiple_devices_migration ( void )
void vfio_unblock_multiple_devices_migration ( void )
{
{
if ( ! multiple_devices_migration_blocker | |
if ( ! multiple_devices_migration_blocker | |
vfio_migratable_device_num ( ) > 1 ) {
! vfio_multiple_devices_migration_is_supported ( ) ) {
return ;
return ;
}
}