Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

vfio/mlx5: Let firmware knows upon leaving PRE_COPY back to RUNNING

Let firmware knows upon leaving PRE_COPY back to RUNNING as of some
error in the target/migration cancellation.

This will let firmware cleaning its internal resources that were turned
on upon PRE_COPY.

The flow is based on the device specification in this area.

Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Acked-by: Leon Romanovsky <leon@kernel.org>
Link: https://lore.kernel.org/r/20240205124828.232701-6-yishaih@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

authored by

Yishai Hadas and committed by
Alex Williamson
6de04224 d8d577b5

+45 -12
+10 -4
drivers/vfio/pci/mlx5/cmd.c
··· 108 108 ret = wait_for_completion_interruptible(&mvdev->saving_migf->save_comp); 109 109 if (ret) 110 110 return ret; 111 - if (mvdev->saving_migf->state == 112 - MLX5_MIGF_STATE_PRE_COPY_ERROR) { 111 + /* Upon cleanup, ignore previous pre_copy error state */ 112 + if (mvdev->saving_migf->state == MLX5_MIGF_STATE_PRE_COPY_ERROR && 113 + !(query_flags & MLX5VF_QUERY_CLEANUP)) { 113 114 /* 114 115 * In case we had a PRE_COPY error, only query full 115 116 * image for final image ··· 201 200 /* Must be done outside the lock to let it progress */ 202 201 set_tracker_error(mvdev); 203 202 mutex_lock(&mvdev->state_mutex); 204 - mlx5vf_disable_fds(mvdev); 203 + mlx5vf_disable_fds(mvdev, NULL); 205 204 _mlx5vf_free_page_tracker_resources(mvdev); 206 205 mlx5vf_state_mutex_unlock(mvdev); 207 206 } ··· 640 639 u32 in[MLX5_ST_SZ_DW(save_vhca_state_in)] = {}; 641 640 struct mlx5_vhca_data_buffer *header_buf = NULL; 642 641 struct mlx5vf_async_data *async_data; 642 + bool pre_copy_cleanup = false; 643 643 int err; 644 644 645 645 lockdep_assert_held(&mvdev->state_mutex); ··· 650 648 err = wait_for_completion_interruptible(&migf->save_comp); 651 649 if (err) 652 650 return err; 651 + 652 + if ((migf->state == MLX5_MIGF_STATE_PRE_COPY || 653 + migf->state == MLX5_MIGF_STATE_PRE_COPY_ERROR) && !track && !inc) 654 + pre_copy_cleanup = true; 653 655 654 656 if (migf->state == MLX5_MIGF_STATE_PRE_COPY_ERROR) 655 657 /* ··· 673 667 674 668 async_data = &migf->async_data; 675 669 async_data->buf = buf; 676 - async_data->stop_copy_chunk = !track; 670 + async_data->stop_copy_chunk = (!track && !pre_copy_cleanup); 677 671 async_data->out = kvzalloc(out_size, GFP_KERNEL); 678 672 if (!async_data->out) { 679 673 err = -ENOMEM;
+3 -1
drivers/vfio/pci/mlx5/cmd.h
··· 197 197 enum { 198 198 MLX5VF_QUERY_INC = (1UL << 0), 199 199 MLX5VF_QUERY_FINAL = (1UL << 1), 200 + MLX5VF_QUERY_CLEANUP = (1UL << 2), 200 201 }; 201 202 202 203 int mlx5vf_cmd_suspend_vhca(struct mlx5vf_pci_core_device *mvdev, u16 op_mod); ··· 233 232 struct page *mlx5vf_get_migration_page(struct mlx5_vhca_data_buffer *buf, 234 233 unsigned long offset); 235 234 void mlx5vf_state_mutex_unlock(struct mlx5vf_pci_core_device *mvdev); 236 - void mlx5vf_disable_fds(struct mlx5vf_pci_core_device *mvdev); 235 + void mlx5vf_disable_fds(struct mlx5vf_pci_core_device *mvdev, 236 + enum mlx5_vf_migf_state *last_save_state); 237 237 void mlx5vf_mig_file_cleanup_cb(struct work_struct *_work); 238 238 void mlx5vf_mig_file_set_save_work(struct mlx5_vf_migration_file *migf, 239 239 u8 chunk_num, size_t next_required_umem_size);
+32 -7
drivers/vfio/pci/mlx5/main.c
··· 1146 1146 return ERR_PTR(ret); 1147 1147 } 1148 1148 1149 - void mlx5vf_disable_fds(struct mlx5vf_pci_core_device *mvdev) 1149 + void mlx5vf_disable_fds(struct mlx5vf_pci_core_device *mvdev, 1150 + enum mlx5_vf_migf_state *last_save_state) 1150 1151 { 1151 1152 if (mvdev->resuming_migf) { 1152 1153 mlx5vf_disable_fd(mvdev->resuming_migf); ··· 1158 1157 if (mvdev->saving_migf) { 1159 1158 mlx5_cmd_cleanup_async_ctx(&mvdev->saving_migf->async_ctx); 1160 1159 cancel_work_sync(&mvdev->saving_migf->async_data.work); 1160 + if (last_save_state) 1161 + *last_save_state = mvdev->saving_migf->state; 1161 1162 mlx5vf_disable_fd(mvdev->saving_migf); 1162 1163 wake_up_interruptible(&mvdev->saving_migf->poll_wait); 1163 1164 mlx5fv_cmd_clean_migf_resources(mvdev->saving_migf); ··· 1220 1217 return migf->filp; 1221 1218 } 1222 1219 1223 - if ((cur == VFIO_DEVICE_STATE_STOP_COPY && new == VFIO_DEVICE_STATE_STOP) || 1224 - (cur == VFIO_DEVICE_STATE_PRE_COPY && new == VFIO_DEVICE_STATE_RUNNING) || 1220 + if (cur == VFIO_DEVICE_STATE_STOP_COPY && new == VFIO_DEVICE_STATE_STOP) { 1221 + mlx5vf_disable_fds(mvdev, NULL); 1222 + return NULL; 1223 + } 1224 + 1225 + if ((cur == VFIO_DEVICE_STATE_PRE_COPY && new == VFIO_DEVICE_STATE_RUNNING) || 1225 1226 (cur == VFIO_DEVICE_STATE_PRE_COPY_P2P && 1226 1227 new == VFIO_DEVICE_STATE_RUNNING_P2P)) { 1227 - mlx5vf_disable_fds(mvdev); 1228 - return NULL; 1228 + struct mlx5_vf_migration_file *migf = mvdev->saving_migf; 1229 + struct mlx5_vhca_data_buffer *buf; 1230 + enum mlx5_vf_migf_state state; 1231 + size_t size; 1232 + 1233 + ret = mlx5vf_cmd_query_vhca_migration_state(mvdev, &size, NULL, 1234 + MLX5VF_QUERY_INC | MLX5VF_QUERY_CLEANUP); 1235 + if (ret) 1236 + return ERR_PTR(ret); 1237 + buf = mlx5vf_get_data_buffer(migf, size, DMA_FROM_DEVICE); 1238 + if (IS_ERR(buf)) 1239 + return ERR_CAST(buf); 1240 + /* pre_copy cleanup */ 1241 + ret = mlx5vf_cmd_save_vhca_state(mvdev, migf, buf, false, false); 1242 + if (ret) { 1243 + mlx5vf_put_data_buffer(buf); 1244 + return ERR_PTR(ret); 1245 + } 1246 + mlx5vf_disable_fds(mvdev, &state); 1247 + return (state != MLX5_MIGF_STATE_ERROR) ? NULL : ERR_PTR(-EIO); 1229 1248 } 1230 1249 1231 1250 if (cur == VFIO_DEVICE_STATE_STOP && new == VFIO_DEVICE_STATE_RESUMING) { ··· 1269 1244 if (ret) 1270 1245 return ERR_PTR(ret); 1271 1246 } 1272 - mlx5vf_disable_fds(mvdev); 1247 + mlx5vf_disable_fds(mvdev, NULL); 1273 1248 return NULL; 1274 1249 } 1275 1250 ··· 1314 1289 mvdev->deferred_reset = false; 1315 1290 spin_unlock(&mvdev->reset_lock); 1316 1291 mvdev->mig_state = VFIO_DEVICE_STATE_RUNNING; 1317 - mlx5vf_disable_fds(mvdev); 1292 + mlx5vf_disable_fds(mvdev, NULL); 1318 1293 goto again; 1319 1294 } 1320 1295 mutex_unlock(&mvdev->state_mutex);