@@ -184,6 +184,12 @@ static const char *control_bit_to_string(enum xe_gt_sriov_control_bits bit)
184184 CASE2STR (PAUSE_SAVE_GUC );
185185 CASE2STR (PAUSE_FAILED );
186186 CASE2STR (PAUSED );
187+ CASE2STR (SAVE_WIP );
188+ CASE2STR (SAVE_FAILED );
189+ CASE2STR (SAVED );
190+ CASE2STR (RESTORE_WIP );
191+ CASE2STR (RESTORE_FAILED );
192+ CASE2STR (RESTORED );
187193 CASE2STR (RESUME_WIP );
188194 CASE2STR (RESUME_SEND_RESUME );
189195 CASE2STR (RESUME_FAILED );
@@ -208,6 +214,8 @@ static unsigned long pf_get_default_timeout(enum xe_gt_sriov_control_bits bit)
208214 case XE_GT_SRIOV_STATE_FLR_WIP :
209215 case XE_GT_SRIOV_STATE_FLR_RESET_CONFIG :
210216 return 5 * HZ ;
217+ case XE_GT_SRIOV_STATE_RESTORE_WIP :
218+ return 20 * HZ ;
211219 default :
212220 return HZ ;
213221 }
@@ -329,6 +337,8 @@ static void pf_exit_vf_mismatch(struct xe_gt *gt, unsigned int vfid)
329337 pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSE_FAILED );
330338 pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESUME_FAILED );
331339 pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_FLR_FAILED );
340+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVE_FAILED );
341+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORE_FAILED );
332342}
333343
334344#define pf_enter_vf_state_machine_bug (gt , vfid ) ({ \
@@ -359,6 +369,8 @@ static void pf_queue_vf(struct xe_gt *gt, unsigned int vfid)
359369
360370static void pf_exit_vf_flr_wip (struct xe_gt * gt , unsigned int vfid );
361371static void pf_exit_vf_stop_wip (struct xe_gt * gt , unsigned int vfid );
372+ static void pf_exit_vf_save_wip (struct xe_gt * gt , unsigned int vfid );
373+ static void pf_exit_vf_restore_wip (struct xe_gt * gt , unsigned int vfid );
362374static void pf_exit_vf_pause_wip (struct xe_gt * gt , unsigned int vfid );
363375static void pf_exit_vf_resume_wip (struct xe_gt * gt , unsigned int vfid );
364376
@@ -380,6 +392,8 @@ static void pf_exit_vf_wip(struct xe_gt *gt, unsigned int vfid)
380392
381393 pf_exit_vf_flr_wip (gt , vfid );
382394 pf_exit_vf_stop_wip (gt , vfid );
395+ pf_exit_vf_save_wip (gt , vfid );
396+ pf_exit_vf_restore_wip (gt , vfid );
383397 pf_exit_vf_pause_wip (gt , vfid );
384398 pf_exit_vf_resume_wip (gt , vfid );
385399
@@ -399,6 +413,8 @@ static void pf_enter_vf_ready(struct xe_gt *gt, unsigned int vfid)
399413 pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSED );
400414 pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_STOPPED );
401415 pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESUMED );
416+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVED );
417+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORED );
402418 pf_exit_vf_mismatch (gt , vfid );
403419 pf_exit_vf_wip (gt , vfid );
404420}
@@ -675,6 +691,8 @@ static void pf_enter_vf_resumed(struct xe_gt *gt, unsigned int vfid)
675691{
676692 pf_enter_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESUMED );
677693 pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSED );
694+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVED );
695+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORED );
678696 pf_exit_vf_mismatch (gt , vfid );
679697 pf_exit_vf_wip (gt , vfid );
680698}
@@ -753,6 +771,16 @@ int xe_gt_sriov_pf_control_resume_vf(struct xe_gt *gt, unsigned int vfid)
753771 return - EPERM ;
754772 }
755773
774+ if (pf_check_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVE_WIP )) {
775+ xe_gt_sriov_dbg (gt , "VF%u save is in progress!\n" , vfid );
776+ return - EBUSY ;
777+ }
778+
779+ if (pf_check_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORE_WIP )) {
780+ xe_gt_sriov_dbg (gt , "VF%u restore is in progress!\n" , vfid );
781+ return - EBUSY ;
782+ }
783+
756784 if (!pf_enter_vf_resume_wip (gt , vfid )) {
757785 xe_gt_sriov_dbg (gt , "VF%u resume already in progress!\n" , vfid );
758786 return - EALREADY ;
@@ -776,6 +804,218 @@ int xe_gt_sriov_pf_control_resume_vf(struct xe_gt *gt, unsigned int vfid)
776804 return - ECANCELED ;
777805}
778806
807+ static void pf_exit_vf_save_wip (struct xe_gt * gt , unsigned int vfid )
808+ {
809+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVE_WIP );
810+ }
811+
812+ static void pf_enter_vf_saved (struct xe_gt * gt , unsigned int vfid )
813+ {
814+ if (!pf_enter_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVED ))
815+ pf_enter_vf_state_machine_bug (gt , vfid );
816+
817+ xe_gt_sriov_dbg (gt , "VF%u saved!\n" , vfid );
818+
819+ pf_expect_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSED );
820+ pf_exit_vf_mismatch (gt , vfid );
821+ pf_exit_vf_wip (gt , vfid );
822+ }
823+
824+ static bool pf_handle_vf_save (struct xe_gt * gt , unsigned int vfid )
825+ {
826+ if (!pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVE_WIP ))
827+ return false;
828+
829+ pf_enter_vf_saved (gt , vfid );
830+
831+ return true;
832+ }
833+
834+ static bool pf_enter_vf_save_wip (struct xe_gt * gt , unsigned int vfid )
835+ {
836+ if (pf_enter_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVE_WIP )) {
837+ pf_enter_vf_wip (gt , vfid );
838+ pf_queue_vf (gt , vfid );
839+ return true;
840+ }
841+
842+ return false;
843+ }
844+
845+ /**
846+ * xe_gt_sriov_pf_control_trigger_save_vf() - Start an SR-IOV VF migration data save sequence.
847+ * @gt: the &xe_gt
848+ * @vfid: the VF identifier
849+ *
850+ * This function is for PF only.
851+ *
852+ * Return: 0 on success or a negative error code on failure.
853+ */
854+ int xe_gt_sriov_pf_control_trigger_save_vf (struct xe_gt * gt , unsigned int vfid )
855+ {
856+ if (pf_check_vf_state (gt , vfid , XE_GT_SRIOV_STATE_STOPPED )) {
857+ xe_gt_sriov_dbg (gt , "VF%u is stopped!\n" , vfid );
858+ return - EPERM ;
859+ }
860+
861+ if (!pf_check_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSED )) {
862+ xe_gt_sriov_dbg (gt , "VF%u is not paused!\n" , vfid );
863+ return - EPERM ;
864+ }
865+
866+ if (pf_check_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORE_WIP )) {
867+ xe_gt_sriov_dbg (gt , "VF%u restore is in progress!\n" , vfid );
868+ return - EBUSY ;
869+ }
870+
871+ if (!pf_enter_vf_save_wip (gt , vfid )) {
872+ xe_gt_sriov_dbg (gt , "VF%u save already in progress!\n" , vfid );
873+ return - EALREADY ;
874+ }
875+
876+ return 0 ;
877+ }
878+
879+ /**
880+ * xe_gt_sriov_pf_control_finish_save_vf() - Complete a VF migration data save sequence.
881+ * @gt: the &xe_gt
882+ * @vfid: the VF identifier
883+ *
884+ * This function is for PF only.
885+ *
886+ * Return: 0 on success or a negative error code on failure.
887+ */
888+ int xe_gt_sriov_pf_control_finish_save_vf (struct xe_gt * gt , unsigned int vfid )
889+ {
890+ if (!pf_expect_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVED )) {
891+ pf_enter_vf_mismatch (gt , vfid );
892+ return - EIO ;
893+ }
894+
895+ pf_expect_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSED );
896+
897+ return 0 ;
898+ }
899+
900+ static void pf_exit_vf_restore_wip (struct xe_gt * gt , unsigned int vfid )
901+ {
902+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORE_WIP );
903+ }
904+
905+ static void pf_enter_vf_restored (struct xe_gt * gt , unsigned int vfid )
906+ {
907+ if (!pf_enter_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORED ))
908+ pf_enter_vf_state_machine_bug (gt , vfid );
909+
910+ xe_gt_sriov_dbg (gt , "VF%u restored!\n" , vfid );
911+
912+ pf_expect_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSED );
913+ pf_exit_vf_mismatch (gt , vfid );
914+ pf_exit_vf_wip (gt , vfid );
915+ }
916+
917+ static bool pf_handle_vf_restore (struct xe_gt * gt , unsigned int vfid )
918+ {
919+ if (!pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORE_WIP ))
920+ return false;
921+
922+ pf_enter_vf_restored (gt , vfid );
923+
924+ return true;
925+ }
926+
927+ static bool pf_enter_vf_restore_wip (struct xe_gt * gt , unsigned int vfid )
928+ {
929+ if (pf_enter_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORE_WIP )) {
930+ pf_enter_vf_wip (gt , vfid );
931+ pf_queue_vf (gt , vfid );
932+ return true;
933+ }
934+
935+ return false;
936+ }
937+
938+ /**
939+ * xe_gt_sriov_pf_control_trigger restore_vf() - Start an SR-IOV VF migration data restore sequence.
940+ * @gt: the &xe_gt
941+ * @vfid: the VF identifier
942+ *
943+ * This function is for PF only.
944+ *
945+ * Return: 0 on success or a negative error code on failure.
946+ */
947+ int xe_gt_sriov_pf_control_trigger_restore_vf (struct xe_gt * gt , unsigned int vfid )
948+ {
949+ if (pf_check_vf_state (gt , vfid , XE_GT_SRIOV_STATE_STOPPED )) {
950+ xe_gt_sriov_dbg (gt , "VF%u is stopped!\n" , vfid );
951+ return - EPERM ;
952+ }
953+
954+ if (!pf_check_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSED )) {
955+ xe_gt_sriov_dbg (gt , "VF%u is not paused!\n" , vfid );
956+ return - EPERM ;
957+ }
958+
959+ if (pf_check_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVE_WIP )) {
960+ xe_gt_sriov_dbg (gt , "VF%u save is in progress!\n" , vfid );
961+ return - EBUSY ;
962+ }
963+
964+ if (!pf_enter_vf_restore_wip (gt , vfid )) {
965+ xe_gt_sriov_dbg (gt , "VF%u restore already in progress!\n" , vfid );
966+ return - EALREADY ;
967+ }
968+
969+ return 0 ;
970+ }
971+
972+ static int pf_wait_vf_restore_done (struct xe_gt * gt , unsigned int vfid )
973+ {
974+ unsigned long timeout = pf_get_default_timeout (XE_GT_SRIOV_STATE_RESTORE_WIP );
975+ int err ;
976+
977+ err = pf_wait_vf_wip_done (gt , vfid , timeout );
978+ if (err ) {
979+ xe_gt_sriov_notice (gt , "VF%u RESTORE didn't finish in %u ms (%pe)\n" ,
980+ vfid , jiffies_to_msecs (timeout ), ERR_PTR (err ));
981+ return err ;
982+ }
983+
984+ if (!pf_expect_vf_not_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORE_FAILED ))
985+ return - EIO ;
986+
987+ return 0 ;
988+ }
989+
990+ /**
991+ * xe_gt_sriov_pf_control_finish_restore_vf() - Complete a VF migration data restore sequence.
992+ * @gt: the &xe_gt
993+ * @vfid: the VF identifier
994+ *
995+ * This function is for PF only.
996+ *
997+ * Return: 0 on success or a negative error code on failure.
998+ */
999+ int xe_gt_sriov_pf_control_finish_restore_vf (struct xe_gt * gt , unsigned int vfid )
1000+ {
1001+ int ret ;
1002+
1003+ if (pf_check_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORE_WIP )) {
1004+ ret = pf_wait_vf_restore_done (gt , vfid );
1005+ if (ret )
1006+ return ret ;
1007+ }
1008+
1009+ if (!pf_expect_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORED )) {
1010+ pf_enter_vf_mismatch (gt , vfid );
1011+ return - EIO ;
1012+ }
1013+
1014+ pf_expect_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSED );
1015+
1016+ return 0 ;
1017+ }
1018+
7791019/**
7801020 * DOC: The VF STOP state machine
7811021 *
@@ -817,6 +1057,8 @@ static void pf_enter_vf_stopped(struct xe_gt *gt, unsigned int vfid)
8171057
8181058 pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESUMED );
8191059 pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_PAUSED );
1060+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_SAVED );
1061+ pf_exit_vf_state (gt , vfid , XE_GT_SRIOV_STATE_RESTORED );
8201062 pf_exit_vf_mismatch (gt , vfid );
8211063 pf_exit_vf_wip (gt , vfid );
8221064}
@@ -1463,6 +1705,12 @@ static bool pf_process_vf_state_machine(struct xe_gt *gt, unsigned int vfid)
14631705 if (pf_exit_vf_pause_save_guc (gt , vfid ))
14641706 return true;
14651707
1708+ if (pf_handle_vf_save (gt , vfid ))
1709+ return true;
1710+
1711+ if (pf_handle_vf_restore (gt , vfid ))
1712+ return true;
1713+
14661714 if (pf_exit_vf_resume_send_resume (gt , vfid ))
14671715 return true;
14681716
0 commit comments