24
24
/* Device specification max LOAD size */
25
25
#define MAX_LOAD_SIZE (BIT_ULL(__mlx5_bit_sz(load_vhca_state_in, size)) - 1)
26
26
27
+ #define MAX_CHUNK_SIZE SZ_8M
28
+
27
29
static struct mlx5vf_pci_core_device * mlx5vf_drvdata (struct pci_dev * pdev )
28
30
{
29
31
struct vfio_pci_core_device * core_device = dev_get_drvdata (& pdev -> dev );
@@ -304,7 +306,8 @@ static void mlx5vf_mark_err(struct mlx5_vf_migration_file *migf)
304
306
wake_up_interruptible (& migf -> poll_wait );
305
307
}
306
308
307
- static int mlx5vf_add_stop_copy_header (struct mlx5_vf_migration_file * migf )
309
+ static int mlx5vf_add_stop_copy_header (struct mlx5_vf_migration_file * migf ,
310
+ bool track )
308
311
{
309
312
size_t size = sizeof (struct mlx5_vf_migration_header ) +
310
313
sizeof (struct mlx5_vf_migration_tag_stop_copy_data );
@@ -331,7 +334,7 @@ static int mlx5vf_add_stop_copy_header(struct mlx5_vf_migration_file *migf)
331
334
to_buff = kmap_local_page (page );
332
335
memcpy (to_buff , & header , sizeof (header ));
333
336
header_buf -> length = sizeof (header );
334
- data .stop_copy_size = cpu_to_le64 (migf -> buf -> allocated_length );
337
+ data .stop_copy_size = cpu_to_le64 (migf -> buf [ 0 ] -> allocated_length );
335
338
memcpy (to_buff + sizeof (header ), & data , sizeof (data ));
336
339
header_buf -> length += sizeof (data );
337
340
kunmap_local (to_buff );
@@ -340,48 +343,83 @@ static int mlx5vf_add_stop_copy_header(struct mlx5_vf_migration_file *migf)
340
343
spin_lock_irqsave (& migf -> list_lock , flags );
341
344
list_add_tail (& header_buf -> buf_elm , & migf -> buf_list );
342
345
spin_unlock_irqrestore (& migf -> list_lock , flags );
343
- migf -> pre_copy_initial_bytes = size ;
346
+ if (track )
347
+ migf -> pre_copy_initial_bytes = size ;
344
348
return 0 ;
345
349
err :
346
350
mlx5vf_put_data_buffer (header_buf );
347
351
return ret ;
348
352
}
349
353
350
- static int mlx5vf_prep_stop_copy (struct mlx5_vf_migration_file * migf ,
351
- size_t state_size )
354
+ static int mlx5vf_prep_stop_copy (struct mlx5vf_pci_core_device * mvdev ,
355
+ struct mlx5_vf_migration_file * migf ,
356
+ size_t state_size , u64 full_size ,
357
+ bool track )
352
358
{
353
359
struct mlx5_vhca_data_buffer * buf ;
354
360
size_t inc_state_size ;
361
+ int num_chunks ;
355
362
int ret ;
363
+ int i ;
356
364
357
- /* let's be ready for stop_copy size that might grow by 10 percents */
358
- if (check_add_overflow (state_size , state_size / 10 , & inc_state_size ))
359
- inc_state_size = state_size ;
365
+ if (mvdev -> chunk_mode ) {
366
+ size_t chunk_size = min_t (size_t , MAX_CHUNK_SIZE , full_size );
360
367
361
- buf = mlx5vf_get_data_buffer (migf , inc_state_size , DMA_FROM_DEVICE );
362
- if (IS_ERR (buf ))
363
- return PTR_ERR (buf );
368
+ /* from firmware perspective at least 'state_size' buffer should be set */
369
+ inc_state_size = max (state_size , chunk_size );
370
+ } else {
371
+ if (track ) {
372
+ /* let's be ready for stop_copy size that might grow by 10 percents */
373
+ if (check_add_overflow (state_size , state_size / 10 , & inc_state_size ))
374
+ inc_state_size = state_size ;
375
+ } else {
376
+ inc_state_size = state_size ;
377
+ }
378
+ }
364
379
365
- migf -> buf = buf ;
366
- buf = mlx5vf_get_data_buffer (migf ,
367
- sizeof (struct mlx5_vf_migration_header ), DMA_NONE );
368
- if (IS_ERR (buf )) {
369
- ret = PTR_ERR (buf );
370
- goto err ;
380
+ /* let's not overflow the device specification max SAVE size */
381
+ inc_state_size = min_t (size_t , inc_state_size ,
382
+ (BIT_ULL (__mlx5_bit_sz (save_vhca_state_in , size )) - PAGE_SIZE ));
383
+
384
+ num_chunks = mvdev -> chunk_mode ? MAX_NUM_CHUNKS : 1 ;
385
+ for (i = 0 ; i < num_chunks ; i ++ ) {
386
+ buf = mlx5vf_get_data_buffer (migf , inc_state_size , DMA_FROM_DEVICE );
387
+ if (IS_ERR (buf )) {
388
+ ret = PTR_ERR (buf );
389
+ goto err ;
390
+ }
391
+
392
+ migf -> buf [i ] = buf ;
393
+ buf = mlx5vf_get_data_buffer (migf ,
394
+ sizeof (struct mlx5_vf_migration_header ), DMA_NONE );
395
+ if (IS_ERR (buf )) {
396
+ ret = PTR_ERR (buf );
397
+ goto err ;
398
+ }
399
+ migf -> buf_header [i ] = buf ;
400
+ if (mvdev -> chunk_mode ) {
401
+ migf -> buf [i ]-> stop_copy_chunk_num = i + 1 ;
402
+ migf -> buf_header [i ]-> stop_copy_chunk_num = i + 1 ;
403
+ }
371
404
}
372
405
373
- migf -> buf_header = buf ;
374
- ret = mlx5vf_add_stop_copy_header (migf );
406
+ ret = mlx5vf_add_stop_copy_header (migf , track );
375
407
if (ret )
376
- goto err_header ;
408
+ goto err ;
377
409
return 0 ;
378
410
379
- err_header :
380
- mlx5vf_put_data_buffer (migf -> buf_header );
381
- migf -> buf_header = NULL ;
382
411
err :
383
- mlx5vf_put_data_buffer (migf -> buf );
384
- migf -> buf = NULL ;
412
+ for (i = 0 ; i < num_chunks ; i ++ ) {
413
+ if (migf -> buf [i ]) {
414
+ mlx5vf_put_data_buffer (migf -> buf [i ]);
415
+ migf -> buf [i ] = NULL ;
416
+ }
417
+ if (migf -> buf_header [i ]) {
418
+ mlx5vf_put_data_buffer (migf -> buf_header [i ]);
419
+ migf -> buf_header [i ] = NULL ;
420
+ }
421
+ }
422
+
385
423
return ret ;
386
424
}
387
425
@@ -511,9 +549,9 @@ static int mlx5vf_pci_save_device_inc_data(struct mlx5vf_pci_core_device *mvdev)
511
549
goto err ;
512
550
513
551
/* Checking whether we have a matching pre-allocated buffer that can fit */
514
- if (migf -> buf && migf -> buf -> allocated_length >= length ) {
515
- buf = migf -> buf ;
516
- migf -> buf = NULL ;
552
+ if (migf -> buf [ 0 ] -> allocated_length >= length ) {
553
+ buf = migf -> buf [ 0 ] ;
554
+ migf -> buf [ 0 ] = NULL ;
517
555
} else {
518
556
buf = mlx5vf_get_data_buffer (migf , length , DMA_FROM_DEVICE );
519
557
if (IS_ERR (buf )) {
@@ -541,6 +579,7 @@ mlx5vf_pci_save_device_data(struct mlx5vf_pci_core_device *mvdev, bool track)
541
579
struct mlx5_vf_migration_file * migf ;
542
580
struct mlx5_vhca_data_buffer * buf ;
543
581
size_t length ;
582
+ u64 full_size ;
544
583
int ret ;
545
584
546
585
migf = kzalloc (sizeof (* migf ), GFP_KERNEL_ACCOUNT );
@@ -574,20 +613,25 @@ mlx5vf_pci_save_device_data(struct mlx5vf_pci_core_device *mvdev, bool track)
574
613
INIT_LIST_HEAD (& migf -> buf_list );
575
614
INIT_LIST_HEAD (& migf -> avail_list );
576
615
spin_lock_init (& migf -> list_lock );
577
- ret = mlx5vf_cmd_query_vhca_migration_state (mvdev , & length , NULL , 0 );
616
+ ret = mlx5vf_cmd_query_vhca_migration_state (mvdev , & length , & full_size , 0 );
617
+ if (ret )
618
+ goto out_pd ;
619
+
620
+ ret = mlx5vf_prep_stop_copy (mvdev , migf , length , full_size , track );
578
621
if (ret )
579
622
goto out_pd ;
580
623
581
624
if (track ) {
582
- ret = mlx5vf_prep_stop_copy (migf , length );
583
- if (ret )
625
+ /* leave the allocated buffer ready for the stop-copy phase */
626
+ buf = mlx5vf_alloc_data_buffer (migf ,
627
+ migf -> buf [0 ]-> allocated_length , DMA_FROM_DEVICE );
628
+ if (IS_ERR (buf )) {
629
+ ret = PTR_ERR (buf );
584
630
goto out_pd ;
585
- }
586
-
587
- buf = mlx5vf_alloc_data_buffer (migf , length , DMA_FROM_DEVICE );
588
- if (IS_ERR (buf )) {
589
- ret = PTR_ERR (buf );
590
- goto out_pd ;
631
+ }
632
+ } else {
633
+ buf = migf -> buf [0 ];
634
+ migf -> buf [0 ] = NULL ;
591
635
}
592
636
593
637
ret = mlx5vf_cmd_save_vhca_state (mvdev , migf , buf , false, track );
@@ -820,8 +864,8 @@ static ssize_t mlx5vf_resume_write(struct file *filp, const char __user *buf,
820
864
size_t len , loff_t * pos )
821
865
{
822
866
struct mlx5_vf_migration_file * migf = filp -> private_data ;
823
- struct mlx5_vhca_data_buffer * vhca_buf = migf -> buf ;
824
- struct mlx5_vhca_data_buffer * vhca_buf_header = migf -> buf_header ;
867
+ struct mlx5_vhca_data_buffer * vhca_buf = migf -> buf [ 0 ] ;
868
+ struct mlx5_vhca_data_buffer * vhca_buf_header = migf -> buf_header [ 0 ] ;
825
869
loff_t requested_length ;
826
870
bool has_work = false;
827
871
ssize_t done = 0 ;
@@ -856,15 +900,15 @@ static ssize_t mlx5vf_resume_write(struct file *filp, const char __user *buf,
856
900
if (vhca_buf_header -> allocated_length < migf -> record_size ) {
857
901
mlx5vf_free_data_buffer (vhca_buf_header );
858
902
859
- migf -> buf_header = mlx5vf_alloc_data_buffer (migf ,
903
+ migf -> buf_header [ 0 ] = mlx5vf_alloc_data_buffer (migf ,
860
904
migf -> record_size , DMA_NONE );
861
- if (IS_ERR (migf -> buf_header )) {
862
- ret = PTR_ERR (migf -> buf_header );
863
- migf -> buf_header = NULL ;
905
+ if (IS_ERR (migf -> buf_header [ 0 ] )) {
906
+ ret = PTR_ERR (migf -> buf_header [ 0 ] );
907
+ migf -> buf_header [ 0 ] = NULL ;
864
908
goto out_unlock ;
865
909
}
866
910
867
- vhca_buf_header = migf -> buf_header ;
911
+ vhca_buf_header = migf -> buf_header [ 0 ] ;
868
912
}
869
913
870
914
vhca_buf_header -> start_pos = migf -> max_pos ;
@@ -884,15 +928,15 @@ static ssize_t mlx5vf_resume_write(struct file *filp, const char __user *buf,
884
928
if (vhca_buf -> allocated_length < size ) {
885
929
mlx5vf_free_data_buffer (vhca_buf );
886
930
887
- migf -> buf = mlx5vf_alloc_data_buffer (migf ,
931
+ migf -> buf [ 0 ] = mlx5vf_alloc_data_buffer (migf ,
888
932
size , DMA_TO_DEVICE );
889
- if (IS_ERR (migf -> buf )) {
890
- ret = PTR_ERR (migf -> buf );
891
- migf -> buf = NULL ;
933
+ if (IS_ERR (migf -> buf [ 0 ] )) {
934
+ ret = PTR_ERR (migf -> buf [ 0 ] );
935
+ migf -> buf [ 0 ] = NULL ;
892
936
goto out_unlock ;
893
937
}
894
938
895
- vhca_buf = migf -> buf ;
939
+ vhca_buf = migf -> buf [ 0 ] ;
896
940
}
897
941
898
942
vhca_buf -> start_pos = migf -> max_pos ;
@@ -974,7 +1018,7 @@ mlx5vf_pci_resume_device_data(struct mlx5vf_pci_core_device *mvdev)
974
1018
goto out_pd ;
975
1019
}
976
1020
977
- migf -> buf = buf ;
1021
+ migf -> buf [ 0 ] = buf ;
978
1022
if (MLX5VF_PRE_COPY_SUPP (mvdev )) {
979
1023
buf = mlx5vf_alloc_data_buffer (migf ,
980
1024
sizeof (struct mlx5_vf_migration_header ), DMA_NONE );
@@ -983,7 +1027,7 @@ mlx5vf_pci_resume_device_data(struct mlx5vf_pci_core_device *mvdev)
983
1027
goto out_buf ;
984
1028
}
985
1029
986
- migf -> buf_header = buf ;
1030
+ migf -> buf_header [ 0 ] = buf ;
987
1031
migf -> load_state = MLX5_VF_LOAD_STATE_READ_HEADER ;
988
1032
} else {
989
1033
/* Initial state will be to read the image */
@@ -997,7 +1041,7 @@ mlx5vf_pci_resume_device_data(struct mlx5vf_pci_core_device *mvdev)
997
1041
spin_lock_init (& migf -> list_lock );
998
1042
return migf ;
999
1043
out_buf :
1000
- mlx5vf_free_data_buffer (migf -> buf );
1044
+ mlx5vf_free_data_buffer (migf -> buf [ 0 ] );
1001
1045
out_pd :
1002
1046
mlx5vf_cmd_dealloc_pd (migf );
1003
1047
out_free :
@@ -1101,7 +1145,7 @@ mlx5vf_pci_step_device_state_locked(struct mlx5vf_pci_core_device *mvdev,
1101
1145
if (!MLX5VF_PRE_COPY_SUPP (mvdev )) {
1102
1146
ret = mlx5vf_cmd_load_vhca_state (mvdev ,
1103
1147
mvdev -> resuming_migf ,
1104
- mvdev -> resuming_migf -> buf );
1148
+ mvdev -> resuming_migf -> buf [ 0 ] );
1105
1149
if (ret )
1106
1150
return ERR_PTR (ret );
1107
1151
}
0 commit comments