Skip to content

Commit 3b506d7

Browse files
committed
drm/xe/pxp: Handle the PXP termination interrupt
When something happen to the session, the HW generates a termination interrupt. In reply to this, the driver is required to submit an inline session termination via the VCS, trigger the global termination and notify the GSC FW that the session is now invalid. v2: rename ARB define to make it cleaner to move it to uapi (John) v3: fix parameter name in documentation Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: John Harrison <John.C.Harrison@Intel.com> Reviewed-by: John Harrison <John.C.Harrison@Intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-6-daniele.ceraolospurio@intel.com
1 parent 96e84a2 commit 3b506d7

File tree

6 files changed

+189
-4
lines changed

6 files changed

+189
-4
lines changed

drivers/gpu/drm/xe/regs/xe_irq_regs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#define ENGINE1_MASK REG_GENMASK(31, 16)
4545
#define ENGINE0_MASK REG_GENMASK(15, 0)
4646
#define GPM_WGBOXPERF_INTR_ENABLE XE_REG(0x19003c, XE_REG_OPTION_VF)
47+
#define CRYPTO_RSVD_INTR_ENABLE XE_REG(0x190040)
4748
#define GUNIT_GSC_INTR_ENABLE XE_REG(0x190044, XE_REG_OPTION_VF)
4849
#define CCS_RSVD_INTR_ENABLE XE_REG(0x190048, XE_REG_OPTION_VF)
4950

@@ -54,6 +55,7 @@
5455
#define INTR_ENGINE_INTR(x) REG_FIELD_GET(GENMASK(15, 0), x)
5556
#define OTHER_GUC_INSTANCE 0
5657
#define OTHER_GSC_HECI2_INSTANCE 3
58+
#define OTHER_KCR_INSTANCE 4
5759
#define OTHER_GSC_INSTANCE 6
5860

5961
#define IIR_REG_SELECTOR(x) XE_REG(0x190070 + ((x) * 4), XE_REG_OPTION_VF)
@@ -65,6 +67,7 @@
6567
#define HECI2_RSVD_INTR_MASK XE_REG(0x1900e4)
6668
#define GUC_SG_INTR_MASK XE_REG(0x1900e8, XE_REG_OPTION_VF)
6769
#define GPM_WGBOXPERF_INTR_MASK XE_REG(0x1900ec, XE_REG_OPTION_VF)
70+
#define CRYPTO_RSVD_INTR_MASK XE_REG(0x1900f0)
6871
#define GUNIT_GSC_INTR_MASK XE_REG(0x1900f4, XE_REG_OPTION_VF)
6972
#define CCS0_CCS1_INTR_MASK XE_REG(0x190100)
7073
#define CCS2_CCS3_INTR_MASK XE_REG(0x190104)
@@ -79,4 +82,9 @@
7982
#define GT_CS_MASTER_ERROR_INTERRUPT REG_BIT(3)
8083
#define GT_RENDER_USER_INTERRUPT REG_BIT(0)
8184

85+
/* irqs for OTHER_KCR_INSTANCE */
86+
#define KCR_PXP_STATE_TERMINATED_INTERRUPT REG_BIT(1)
87+
#define KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT REG_BIT(2)
88+
#define KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT REG_BIT(3)
89+
8290
#endif

drivers/gpu/drm/xe/regs/xe_pxp_regs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,10 @@
1414
#define KCR_INIT XE_REG(0x3860f0)
1515
#define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14)
1616

17+
/* KCR hwdrm session in play status 0-31 */
18+
#define KCR_SIP XE_REG(0x386260)
19+
20+
/* PXP global terminate register for session termination */
21+
#define KCR_GLOBAL_TERMINATE XE_REG(0x3860f8)
22+
1723
#endif /* __XE_PXP_REGS_H__ */

drivers/gpu/drm/xe/xe_irq.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "xe_hw_engine.h"
2121
#include "xe_memirq.h"
2222
#include "xe_mmio.h"
23+
#include "xe_pxp.h"
2324
#include "xe_sriov.h"
2425

2526
/*
@@ -208,6 +209,15 @@ void xe_irq_enable_hwe(struct xe_gt *gt)
208209
}
209210
if (heci_mask)
210211
xe_mmio_write32(mmio, HECI2_RSVD_INTR_MASK, ~(heci_mask << 16));
212+
213+
if (xe_pxp_is_supported(xe)) {
214+
u32 kcr_mask = KCR_PXP_STATE_TERMINATED_INTERRUPT |
215+
KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT |
216+
KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT;
217+
218+
xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_ENABLE, kcr_mask << 16);
219+
xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_MASK, ~(kcr_mask << 16));
220+
}
211221
}
212222
}
213223

@@ -330,9 +340,15 @@ static void gt_irq_handler(struct xe_tile *tile,
330340
}
331341

332342
if (class == XE_ENGINE_CLASS_OTHER) {
333-
/* HECI GSCFI interrupts come from outside of GT */
343+
/*
344+
* HECI GSCFI interrupts come from outside of GT.
345+
* KCR irqs come from inside GT but are handled
346+
* by the global PXP subsystem.
347+
*/
334348
if (xe->info.has_heci_gscfi && instance == OTHER_GSC_INSTANCE)
335349
xe_heci_gsc_irq_handler(xe, intr_vec);
350+
else if (instance == OTHER_KCR_INSTANCE)
351+
xe_pxp_irq_handler(xe, intr_vec);
336352
else
337353
gt_other_irq_handler(engine_gt, instance, intr_vec);
338354
}
@@ -510,6 +526,8 @@ static void gt_irq_reset(struct xe_tile *tile)
510526
xe_mmio_write32(mmio, GUNIT_GSC_INTR_ENABLE, 0);
511527
xe_mmio_write32(mmio, GUNIT_GSC_INTR_MASK, ~0);
512528
xe_mmio_write32(mmio, HECI2_RSVD_INTR_MASK, ~0);
529+
xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_ENABLE, 0);
530+
xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_MASK, ~0);
513531
}
514532

515533
xe_mmio_write32(mmio, GPM_WGBOXPERF_INTR_ENABLE, 0);

drivers/gpu/drm/xe/xe_pxp.c

Lines changed: 136 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
#include "xe_gt.h"
1313
#include "xe_gt_types.h"
1414
#include "xe_mmio.h"
15+
#include "xe_pm.h"
1516
#include "xe_pxp_submit.h"
1617
#include "xe_pxp_types.h"
1718
#include "xe_uc_fw.h"
19+
#include "regs/xe_irq_regs.h"
1820
#include "regs/xe_pxp_regs.h"
1921

2022
/**
@@ -25,11 +27,132 @@
2527
* integrated parts.
2628
*/
2729

28-
static bool pxp_is_supported(const struct xe_device *xe)
30+
#define ARB_SESSION DRM_XE_PXP_HWDRM_DEFAULT_SESSION /* shorter define */
31+
32+
bool xe_pxp_is_supported(const struct xe_device *xe)
2933
{
3034
return xe->info.has_pxp && IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY);
3135
}
3236

37+
static bool pxp_is_enabled(const struct xe_pxp *pxp)
38+
{
39+
return pxp;
40+
}
41+
42+
static int pxp_wait_for_session_state(struct xe_pxp *pxp, u32 id, bool in_play)
43+
{
44+
struct xe_gt *gt = pxp->gt;
45+
u32 mask = BIT(id);
46+
47+
return xe_mmio_wait32(&gt->mmio, KCR_SIP, mask, in_play ? mask : 0,
48+
250, NULL, false);
49+
}
50+
51+
static void pxp_terminate(struct xe_pxp *pxp)
52+
{
53+
int ret = 0;
54+
struct xe_device *xe = pxp->xe;
55+
struct xe_gt *gt = pxp->gt;
56+
unsigned int fw_ref;
57+
58+
drm_dbg(&xe->drm, "Terminating PXP\n");
59+
60+
fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
61+
if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) {
62+
ret = -EIO;
63+
goto out;
64+
}
65+
66+
/* terminate the hw session */
67+
ret = xe_pxp_submit_session_termination(pxp, ARB_SESSION);
68+
if (ret)
69+
goto out;
70+
71+
ret = pxp_wait_for_session_state(pxp, ARB_SESSION, false);
72+
if (ret)
73+
goto out;
74+
75+
/* Trigger full HW cleanup */
76+
xe_mmio_write32(&gt->mmio, KCR_GLOBAL_TERMINATE, 1);
77+
78+
/* now we can tell the GSC to clean up its own state */
79+
ret = xe_pxp_submit_session_invalidation(&pxp->gsc_res, ARB_SESSION);
80+
81+
out:
82+
xe_force_wake_put(gt_to_fw(gt), fw_ref);
83+
84+
if (ret)
85+
drm_err(&xe->drm, "PXP termination failed: %pe\n", ERR_PTR(ret));
86+
}
87+
88+
static void pxp_terminate_complete(struct xe_pxp *pxp)
89+
{
90+
/* TODO mark the session as ready to start */
91+
}
92+
93+
static void pxp_irq_work(struct work_struct *work)
94+
{
95+
struct xe_pxp *pxp = container_of(work, typeof(*pxp), irq.work);
96+
struct xe_device *xe = pxp->xe;
97+
u32 events = 0;
98+
99+
spin_lock_irq(&xe->irq.lock);
100+
events = pxp->irq.events;
101+
pxp->irq.events = 0;
102+
spin_unlock_irq(&xe->irq.lock);
103+
104+
if (!events)
105+
return;
106+
107+
/*
108+
* If we're processing a termination irq while suspending then don't
109+
* bother, we're going to re-init everything on resume anyway.
110+
*/
111+
if ((events & PXP_TERMINATION_REQUEST) && !xe_pm_runtime_get_if_active(xe))
112+
return;
113+
114+
if (events & PXP_TERMINATION_REQUEST) {
115+
events &= ~PXP_TERMINATION_COMPLETE;
116+
pxp_terminate(pxp);
117+
}
118+
119+
if (events & PXP_TERMINATION_COMPLETE)
120+
pxp_terminate_complete(pxp);
121+
122+
if (events & PXP_TERMINATION_REQUEST)
123+
xe_pm_runtime_put(xe);
124+
}
125+
126+
/**
127+
* xe_pxp_irq_handler - Handles PXP interrupts.
128+
* @xe: the xe_device structure
129+
* @iir: interrupt vector
130+
*/
131+
void xe_pxp_irq_handler(struct xe_device *xe, u16 iir)
132+
{
133+
struct xe_pxp *pxp = xe->pxp;
134+
135+
if (!pxp_is_enabled(pxp)) {
136+
drm_err(&xe->drm, "PXP irq 0x%x received with PXP disabled!\n", iir);
137+
return;
138+
}
139+
140+
lockdep_assert_held(&xe->irq.lock);
141+
142+
if (unlikely(!iir))
143+
return;
144+
145+
if (iir & (KCR_PXP_STATE_TERMINATED_INTERRUPT |
146+
KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT))
147+
pxp->irq.events |= PXP_TERMINATION_REQUEST;
148+
149+
if (iir & KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT)
150+
pxp->irq.events |= PXP_TERMINATION_COMPLETE;
151+
152+
if (pxp->irq.events)
153+
queue_work(pxp->irq.wq, &pxp->irq.work);
154+
}
155+
33156
static int kcr_pxp_set_status(const struct xe_pxp *pxp, bool enable)
34157
{
35158
u32 val = enable ? _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES) :
@@ -60,6 +183,7 @@ static void pxp_fini(void *arg)
60183
{
61184
struct xe_pxp *pxp = arg;
62185

186+
destroy_workqueue(pxp->irq.wq);
63187
xe_pxp_destroy_execution_resources(pxp);
64188

65189
/* no need to explicitly disable KCR since we're going to do an FLR */
@@ -83,7 +207,7 @@ int xe_pxp_init(struct xe_device *xe)
83207
struct xe_pxp *pxp;
84208
int err;
85209

86-
if (!pxp_is_supported(xe))
210+
if (!xe_pxp_is_supported(xe))
87211
return -EOPNOTSUPP;
88212

89213
/* we only support PXP on single tile devices with a media GT */
@@ -105,12 +229,19 @@ int xe_pxp_init(struct xe_device *xe)
105229
if (!pxp)
106230
return -ENOMEM;
107231

232+
INIT_WORK(&pxp->irq.work, pxp_irq_work);
108233
pxp->xe = xe;
109234
pxp->gt = gt;
110235

236+
pxp->irq.wq = alloc_ordered_workqueue("pxp-wq", 0);
237+
if (!pxp->irq.wq) {
238+
err = -ENOMEM;
239+
goto out_free;
240+
}
241+
111242
err = kcr_pxp_enable(pxp);
112243
if (err)
113-
goto out_free;
244+
goto out_wq;
114245

115246
err = xe_pxp_allocate_execution_resources(pxp);
116247
if (err)
@@ -122,6 +253,8 @@ int xe_pxp_init(struct xe_device *xe)
122253

123254
out_kcr_disable:
124255
kcr_pxp_disable(pxp);
256+
out_wq:
257+
destroy_workqueue(pxp->irq.wq);
125258
out_free:
126259
drmm_kfree(&xe->drm, pxp);
127260
return err;

drivers/gpu/drm/xe/xe_pxp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@
66
#ifndef __XE_PXP_H__
77
#define __XE_PXP_H__
88

9+
#include <linux/types.h>
10+
911
struct xe_device;
1012

13+
#define DRM_XE_PXP_HWDRM_DEFAULT_SESSION 0xF /* TODO: move to uapi */
14+
15+
bool xe_pxp_is_supported(const struct xe_device *xe);
16+
1117
int xe_pxp_init(struct xe_device *xe);
18+
void xe_pxp_irq_handler(struct xe_device *xe, u16 iir);
1219

1320
#endif /* __XE_PXP_H__ */

drivers/gpu/drm/xe/xe_pxp_types.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <linux/iosys-map.h>
1010
#include <linux/types.h>
11+
#include <linux/workqueue.h>
1112

1213
struct xe_bo;
1314
struct xe_exec_queue;
@@ -69,6 +70,18 @@ struct xe_pxp {
6970

7071
/** @gsc_res: kernel-owned objects for PXP submissions to the GSCCS */
7172
struct xe_pxp_gsc_client_resources gsc_res;
73+
74+
/** @irq: wrapper for the worker and queue used for PXP irq support */
75+
struct {
76+
/** @irq.work: worker that manages irq events. */
77+
struct work_struct work;
78+
/** @irq.wq: workqueue on which to queue the irq work. */
79+
struct workqueue_struct *wq;
80+
/** @irq.events: pending events, protected with xe->irq.lock. */
81+
u32 events;
82+
#define PXP_TERMINATION_REQUEST BIT(0)
83+
#define PXP_TERMINATION_COMPLETE BIT(1)
84+
} irq;
7285
};
7386

7487
#endif /* __XE_PXP_TYPES_H__ */

0 commit comments

Comments
 (0)