Skip to content

Commit 5146221

Browse files
committed
drm/xe/pxp: add PXP PM support
The HW suspend flow kills all PXP HWDRM sessions, so we need to mark all the queues and BOs as invalid and do a full termination when PXP is next used. v2: rebase v3: rebase on new status flow, defer termination to next PXP use as it makes things much easier and allows us to use the same function for all types of suspend. v4: fix the documentation of the suspend function (John) Signed-off-by: Daniele Ceraolo Spurio <[email protected]> Cc: John Harrison <[email protected]> Reviewed-by: John Harrison <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 41a97c4 commit 5146221

File tree

4 files changed

+165
-13
lines changed

4 files changed

+165
-13
lines changed

drivers/gpu/drm/xe/xe_pm.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "xe_guc.h"
2323
#include "xe_irq.h"
2424
#include "xe_pcode.h"
25+
#include "xe_pxp.h"
2526
#include "xe_trace.h"
2627
#include "xe_wa.h"
2728

@@ -122,6 +123,10 @@ int xe_pm_suspend(struct xe_device *xe)
122123
drm_dbg(&xe->drm, "Suspending device\n");
123124
trace_xe_pm_suspend(xe, __builtin_return_address(0));
124125

126+
err = xe_pxp_pm_suspend(xe->pxp);
127+
if (err)
128+
goto err;
129+
125130
for_each_gt(gt, xe, id)
126131
xe_gt_suspend_prepare(gt);
127132

@@ -130,14 +135,12 @@ int xe_pm_suspend(struct xe_device *xe)
130135
/* FIXME: Super racey... */
131136
err = xe_bo_evict_all(xe);
132137
if (err)
133-
goto err;
138+
goto err_pxp;
134139

135140
for_each_gt(gt, xe, id) {
136141
err = xe_gt_suspend(gt);
137-
if (err) {
138-
xe_display_pm_resume(xe);
139-
goto err;
140-
}
142+
if (err)
143+
goto err_display;
141144
}
142145

143146
xe_irq_suspend(xe);
@@ -146,6 +149,11 @@ int xe_pm_suspend(struct xe_device *xe)
146149

147150
drm_dbg(&xe->drm, "Device suspended\n");
148151
return 0;
152+
153+
err_display:
154+
xe_display_pm_resume(xe);
155+
err_pxp:
156+
xe_pxp_pm_resume(xe->pxp);
149157
err:
150158
drm_dbg(&xe->drm, "Device suspend failed %d\n", err);
151159
return err;
@@ -195,6 +203,8 @@ int xe_pm_resume(struct xe_device *xe)
195203
if (err)
196204
goto err;
197205

206+
xe_pxp_pm_resume(xe->pxp);
207+
198208
drm_dbg(&xe->drm, "Device resumed\n");
199209
return 0;
200210
err:
@@ -389,6 +399,10 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
389399
*/
390400
xe_rpm_lockmap_acquire(xe);
391401

402+
err = xe_pxp_pm_suspend(xe->pxp);
403+
if (err)
404+
goto out;
405+
392406
/*
393407
* Applying lock for entire list op as xe_ttm_bo_destroy and xe_bo_move_notify
394408
* also checks and deletes bo entry from user fault list.
@@ -404,22 +418,27 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
404418
if (xe->d3cold.allowed) {
405419
err = xe_bo_evict_all(xe);
406420
if (err)
407-
goto out;
421+
goto out_resume;
408422
}
409423

410424
for_each_gt(gt, xe, id) {
411425
err = xe_gt_suspend(gt);
412426
if (err)
413-
goto out;
427+
goto out_resume;
414428
}
415429

416430
xe_irq_suspend(xe);
417431

418432
xe_display_pm_runtime_suspend_late(xe);
419433

434+
xe_rpm_lockmap_release(xe);
435+
xe_pm_write_callback_task(xe, NULL);
436+
return 0;
437+
438+
out_resume:
439+
xe_display_pm_runtime_resume(xe);
440+
xe_pxp_pm_resume(xe->pxp);
420441
out:
421-
if (err)
422-
xe_display_pm_runtime_resume(xe);
423442
xe_rpm_lockmap_release(xe);
424443
xe_pm_write_callback_task(xe, NULL);
425444
return err;
@@ -472,6 +491,8 @@ int xe_pm_runtime_resume(struct xe_device *xe)
472491
goto out;
473492
}
474493

494+
xe_pxp_pm_resume(xe->pxp);
495+
475496
out:
476497
xe_rpm_lockmap_release(xe);
477498
xe_pm_write_callback_task(xe, NULL);

drivers/gpu/drm/xe/xe_pxp.c

Lines changed: 125 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ static int pxp_wait_for_session_state(struct xe_pxp *pxp, u32 id, bool in_play)
132132

133133
static void pxp_invalidate_queues(struct xe_pxp *pxp);
134134

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+
135143
static int pxp_terminate_hw(struct xe_pxp *pxp)
136144
{
137145
struct xe_gt *gt = pxp->gt;
@@ -185,10 +193,16 @@ static void pxp_terminate(struct xe_pxp *pxp)
185193

186194
mutex_lock(&pxp->mutex);
187195

188-
pxp_invalidate_queues(pxp);
196+
pxp_invalidate_state(pxp);
189197

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+
}
192206

193207
/*
194208
* 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)
219233
static void pxp_terminate_complete(struct xe_pxp *pxp)
220234
{
221235
/*
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:
223237
* - XE_PXP_TERMINATION_IN_PROGRESS: a single termination event was
224238
* requested and it is now completing, so we're ready to start.
225239
* - XE_PXP_NEEDS_ADDITIONAL_TERMINATION: a second termination was
226240
* 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.
227243
*/
228244
mutex_lock(&pxp->mutex);
229245

@@ -234,6 +250,9 @@ static void pxp_terminate_complete(struct xe_pxp *pxp)
234250
case XE_PXP_NEEDS_ADDITIONAL_TERMINATION:
235251
pxp->status = XE_PXP_NEEDS_TERMINATION;
236252
break;
253+
case XE_PXP_SUSPENDED:
254+
/* Nothing to do */
255+
break;
237256
default:
238257
drm_err(&pxp->xe->drm,
239258
"PXP termination complete while status was %u\n",
@@ -391,6 +410,7 @@ int xe_pxp_init(struct xe_device *xe)
391410
pxp->gt = gt;
392411

393412
pxp->key_instance = 1;
413+
pxp->last_suspend_key_instance = 1;
394414

395415
/*
396416
* 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)
574594
XE_WARN_ON(completion_done(&pxp->termination));
575595
mutex_unlock(&pxp->mutex);
576596
goto wait_for_idle;
597+
case XE_PXP_SUSPENDED:
577598
default:
578599
drm_err(&pxp->xe->drm, "unexpected state during PXP start: %u\n", pxp->status);
579600
ret = -EIO;
@@ -779,3 +800,103 @@ int xe_pxp_obj_key_check(struct xe_pxp *pxp, struct drm_gem_object *obj)
779800
{
780801
return xe_pxp_bo_key_check(pxp, gem_to_xe_bo(obj));
781802
}
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+
}

drivers/gpu/drm/xe/xe_pxp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ int xe_pxp_get_readiness_status(struct xe_pxp *pxp);
2121
int xe_pxp_init(struct xe_device *xe);
2222
void xe_pxp_irq_handler(struct xe_device *xe, u16 iir);
2323

24+
int xe_pxp_pm_suspend(struct xe_pxp *pxp);
25+
void xe_pxp_pm_resume(struct xe_pxp *pxp);
26+
2427
int xe_pxp_exec_queue_set_type(struct xe_pxp *pxp, struct xe_exec_queue *q, u8 type);
2528
int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q);
2629
void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q);

drivers/gpu/drm/xe/xe_pxp_types.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ enum xe_pxp_status {
2727
XE_PXP_READY_TO_START,
2828
XE_PXP_START_IN_PROGRESS,
2929
XE_PXP_ACTIVE,
30+
XE_PXP_SUSPENDED,
3031
};
3132

3233
/**
@@ -123,6 +124,12 @@ struct xe_pxp {
123124
* that case in the code.
124125
*/
125126
u32 key_instance;
127+
/**
128+
* @last_suspend_key_instance: value of key_instance at the last
129+
* suspend. Used to check if any PXP session has been created between
130+
* suspend cycles.
131+
*/
132+
u32 last_suspend_key_instance;
126133
};
127134

128135
#endif /* __XE_PXP_TYPES_H__ */

0 commit comments

Comments
 (0)