@@ -132,6 +132,14 @@ static int pxp_wait_for_session_state(struct xe_pxp *pxp, u32 id, bool in_play)
132
132
133
133
static void pxp_invalidate_queues (struct xe_pxp * pxp );
134
134
135
+ static void pxp_invalidate_state (struct xe_pxp * pxp )
136
+ {
137
+ pxp_invalidate_queues (pxp );
138
+
139
+ if (pxp -> status == XE_PXP_ACTIVE )
140
+ pxp -> key_instance ++ ;
141
+ }
142
+
135
143
static int pxp_terminate_hw (struct xe_pxp * pxp )
136
144
{
137
145
struct xe_gt * gt = pxp -> gt ;
@@ -185,10 +193,16 @@ static void pxp_terminate(struct xe_pxp *pxp)
185
193
186
194
mutex_lock (& pxp -> mutex );
187
195
188
- pxp_invalidate_queues (pxp );
196
+ pxp_invalidate_state (pxp );
189
197
190
- if (pxp -> status == XE_PXP_ACTIVE )
191
- pxp -> key_instance ++ ;
198
+ /*
199
+ * we'll mark the status as needing termination on resume, so no need to
200
+ * emit a termination now.
201
+ */
202
+ if (pxp -> status == XE_PXP_SUSPENDED ) {
203
+ mutex_unlock (& pxp -> mutex );
204
+ return ;
205
+ }
192
206
193
207
/*
194
208
* If we have a termination already in progress, we need to wait for
@@ -219,11 +233,13 @@ static void pxp_terminate(struct xe_pxp *pxp)
219
233
static void pxp_terminate_complete (struct xe_pxp * pxp )
220
234
{
221
235
/*
222
- * We expect PXP to be in one of 2 states when we get here:
236
+ * We expect PXP to be in one of 3 states when we get here:
223
237
* - XE_PXP_TERMINATION_IN_PROGRESS: a single termination event was
224
238
* requested and it is now completing, so we're ready to start.
225
239
* - XE_PXP_NEEDS_ADDITIONAL_TERMINATION: a second termination was
226
240
* requested while the first one was still being processed.
241
+ * - XE_PXP_SUSPENDED: PXP is now suspended, so we defer everything to
242
+ * when we come back on resume.
227
243
*/
228
244
mutex_lock (& pxp -> mutex );
229
245
@@ -234,6 +250,9 @@ static void pxp_terminate_complete(struct xe_pxp *pxp)
234
250
case XE_PXP_NEEDS_ADDITIONAL_TERMINATION :
235
251
pxp -> status = XE_PXP_NEEDS_TERMINATION ;
236
252
break ;
253
+ case XE_PXP_SUSPENDED :
254
+ /* Nothing to do */
255
+ break ;
237
256
default :
238
257
drm_err (& pxp -> xe -> drm ,
239
258
"PXP termination complete while status was %u\n" ,
@@ -391,6 +410,7 @@ int xe_pxp_init(struct xe_device *xe)
391
410
pxp -> gt = gt ;
392
411
393
412
pxp -> key_instance = 1 ;
413
+ pxp -> last_suspend_key_instance = 1 ;
394
414
395
415
/*
396
416
* we'll use the completions to check if there is an action pending,
@@ -574,6 +594,7 @@ int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q)
574
594
XE_WARN_ON (completion_done (& pxp -> termination ));
575
595
mutex_unlock (& pxp -> mutex );
576
596
goto wait_for_idle ;
597
+ case XE_PXP_SUSPENDED :
577
598
default :
578
599
drm_err (& pxp -> xe -> drm , "unexpected state during PXP start: %u\n" , pxp -> status );
579
600
ret = - EIO ;
@@ -779,3 +800,103 @@ int xe_pxp_obj_key_check(struct xe_pxp *pxp, struct drm_gem_object *obj)
779
800
{
780
801
return xe_pxp_bo_key_check (pxp , gem_to_xe_bo (obj ));
781
802
}
803
+
804
+ /**
805
+ * xe_pxp_pm_suspend - prepare PXP for HW suspend
806
+ * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled)
807
+ *
808
+ * Makes sure all PXP actions have completed and invalidates all PXP queues
809
+ * and objects before we go into a suspend state.
810
+ *
811
+ * Returns: 0 if successful, a negative errno value otherwise.
812
+ */
813
+ int xe_pxp_pm_suspend (struct xe_pxp * pxp )
814
+ {
815
+ int ret = 0 ;
816
+
817
+ if (!xe_pxp_is_enabled (pxp ))
818
+ return 0 ;
819
+
820
+ wait_for_activation :
821
+ if (!wait_for_completion_timeout (& pxp -> activation ,
822
+ msecs_to_jiffies (PXP_ACTIVATION_TIMEOUT_MS )))
823
+ ret = - ETIMEDOUT ;
824
+
825
+ mutex_lock (& pxp -> mutex );
826
+
827
+ switch (pxp -> status ) {
828
+ case XE_PXP_ERROR :
829
+ case XE_PXP_READY_TO_START :
830
+ case XE_PXP_SUSPENDED :
831
+ case XE_PXP_TERMINATION_IN_PROGRESS :
832
+ case XE_PXP_NEEDS_ADDITIONAL_TERMINATION :
833
+ /*
834
+ * If PXP is not running there is nothing to cleanup. If there
835
+ * is a termination pending then no need to issue another one.
836
+ */
837
+ break ;
838
+ case XE_PXP_START_IN_PROGRESS :
839
+ mutex_unlock (& pxp -> mutex );
840
+ goto wait_for_activation ;
841
+ case XE_PXP_NEEDS_TERMINATION :
842
+ /* If PXP was never used we can skip the cleanup */
843
+ if (pxp -> key_instance == pxp -> last_suspend_key_instance )
844
+ break ;
845
+ fallthrough ;
846
+ case XE_PXP_ACTIVE :
847
+ pxp_invalidate_state (pxp );
848
+ break ;
849
+ default :
850
+ drm_err (& pxp -> xe -> drm , "unexpected state during PXP suspend: %u" ,
851
+ pxp -> status );
852
+ ret = - EIO ;
853
+ goto out ;
854
+ }
855
+
856
+ /*
857
+ * We set this even if we were in error state, hoping the suspend clears
858
+ * the error. Worse case we fail again and go in error state again.
859
+ */
860
+ pxp -> status = XE_PXP_SUSPENDED ;
861
+
862
+ mutex_unlock (& pxp -> mutex );
863
+
864
+ /*
865
+ * if there is a termination in progress, wait for it.
866
+ * We need to wait outside the lock because the completion is done from
867
+ * within the lock
868
+ */
869
+ if (!wait_for_completion_timeout (& pxp -> termination ,
870
+ msecs_to_jiffies (PXP_TERMINATION_TIMEOUT_MS )))
871
+ ret = - ETIMEDOUT ;
872
+
873
+ pxp -> last_suspend_key_instance = pxp -> key_instance ;
874
+
875
+ out :
876
+ return ret ;
877
+ }
878
+
879
+ /**
880
+ * xe_pxp_pm_resume - re-init PXP after HW suspend
881
+ * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled)
882
+ */
883
+ void xe_pxp_pm_resume (struct xe_pxp * pxp )
884
+ {
885
+ int err ;
886
+
887
+ if (!xe_pxp_is_enabled (pxp ))
888
+ return ;
889
+
890
+ err = kcr_pxp_enable (pxp );
891
+
892
+ mutex_lock (& pxp -> mutex );
893
+
894
+ xe_assert (pxp -> xe , pxp -> status == XE_PXP_SUSPENDED );
895
+
896
+ if (err )
897
+ pxp -> status = XE_PXP_ERROR ;
898
+ else
899
+ pxp -> status = XE_PXP_NEEDS_TERMINATION ;
900
+
901
+ mutex_unlock (& pxp -> mutex );
902
+ }
0 commit comments