According to the VFIO migration specifications, userspace must issue a VFIO_DEVICE_RESET ioctl if a vfio device enters an error state or fails a state transition to recover the device and return its migration state to RUNNING. This patch adds a function that is called when a VFIO_DEVICE_RESET is issued that releases the migration files and frees the storage allocated for maintaining the migration state. Signed-off-by: Anthony Krowiak --- drivers/s390/crypto/vfio_ap_migration.c | 54 +++++++++++++++++++++++++ drivers/s390/crypto/vfio_ap_ops.c | 4 ++ drivers/s390/crypto/vfio_ap_private.h | 1 + 3 files changed, 59 insertions(+) diff --git a/drivers/s390/crypto/vfio_ap_migration.c b/drivers/s390/crypto/vfio_ap_migration.c index 9187cfe26da7..45557f433652 100644 --- a/drivers/s390/crypto/vfio_ap_migration.c +++ b/drivers/s390/crypto/vfio_ap_migration.c @@ -150,3 +150,57 @@ void vfio_ap_release_migration_data(struct ap_matrix_mdev *matrix_mdev) kfree(matrix_mdev->mig_data); matrix_mdev->mig_data = NULL; } + +static void vfio_ap_release_mig_files(struct ap_matrix_mdev *matrix_mdev) +{ + struct vfio_ap_migration_data *mig_data; + + /* + * The fput call does not call .release synchronously while the + * mdevs_lock mutex is held, so there is no problem with incurring a + * deadlock situation if fput is executed in this function. + */ + lockdep_assert_held(&matrix_dev->mdevs_lock); + + mig_data = matrix_mdev->mig_data; + if (!mig_data) + return; + + if (mig_data->stop_copy_mig_file.filp) { + fput(mig_data->stop_copy_mig_file.filp); + mig_data->stop_copy_mig_file.filp = NULL; + } + + kfree(mig_data->stop_copy_mig_file.ap_config); + mig_data->stop_copy_mig_file.ap_config = NULL; + mig_data->stop_copy_mig_file.config_sz = 0; + + if (mig_data->resuming_mig_file.filp) { + fput(mig_data->resuming_mig_file.filp); + mig_data->resuming_mig_file.filp = NULL; + } + + kfree(mig_data->resuming_mig_file.ap_config); + mig_data->resuming_mig_file.ap_config = NULL; + mig_data->resuming_mig_file.config_sz = 0; +} + +/** + * vfio_ap_reset_migration_state - Reset the vfio-ap migration state + * + * @matrix_mdev: pointer to the object maintaining the vfio-ap device state + * + * Called during VFIO_DEVICE_RESET to clean up any active migration + * state and reset the device to RUNNING state as required by the VFIO + * migration specification. + */ +void vfio_ap_reset_migration_state(struct ap_matrix_mdev *matrix_mdev) +{ + lockdep_assert_held(&matrix_dev->mdevs_lock); + + if (!matrix_mdev->mig_data) + return; + + vfio_ap_release_mig_files(matrix_mdev); + matrix_mdev->mig_data->mig_state = VFIO_DEVICE_STATE_RUNNING; +} diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index 47aca908701d..678bdd4c82e9 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -2332,6 +2332,10 @@ static ssize_t vfio_ap_mdev_ioctl(struct vfio_device *vdev, break; case VFIO_DEVICE_RESET: ret = vfio_ap_mdev_reset_queues(matrix_mdev); + if (ret == 0) { + /* Reset migration state per VFIO migration spec */ + vfio_ap_reset_migration_state(matrix_mdev); + } break; case VFIO_DEVICE_GET_IRQ_INFO: ret = vfio_ap_get_irq_info(arg); diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h index a2a713f93674..1fbdfcce5a11 100644 --- a/drivers/s390/crypto/vfio_ap_private.h +++ b/drivers/s390/crypto/vfio_ap_private.h @@ -175,5 +175,6 @@ void vfio_ap_on_scan_complete(struct ap_config_info *new_config_info, void vfio_ap_init_migration_capabilities(struct ap_matrix_mdev *matrix_mdev); int vfio_ap_init_migration_data(struct ap_matrix_mdev *matrix_mdev); void vfio_ap_release_migration_data(struct ap_matrix_mdev *matrix_mdev); +void vfio_ap_reset_migration_state(struct ap_matrix_mdev *matrix_mdev); #endif /* _VFIO_AP_PRIVATE_H_ */ -- 2.53.0