File Index
Files and directories
Sign in
FILE

intel_pxp_session.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/i915/pxp/intel_pxp_session.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright(c) 2020, Intel Corporation. All rights reserved.
  4 */
  5
  6#include <drm/drm_print.h>
  7
  8#include "i915_drv.h"
  9
 10#include "intel_pxp.h"
 11#include "intel_pxp_cmd.h"
 12#include "intel_pxp_gsccs.h"
 13#include "intel_pxp_session.h"
 14#include "intel_pxp_tee.h"
 15#include "intel_pxp_types.h"
 16#include "intel_pxp_regs.h"
 17
 18#define ARB_SESSION I915_PROTECTED_CONTENT_DEFAULT_SESSION /* shorter define */
 19
 20static bool intel_pxp_session_is_in_play(struct intel_pxp *pxp, u32 id)
 21{
 22	struct intel_uncore *uncore = pxp->ctrl_gt->uncore;
 23	intel_wakeref_t wakeref;
 24	u32 sip = 0;
 25
 26	/* if we're suspended the session is considered off */
 27	with_intel_runtime_pm_if_in_use(uncore->rpm, wakeref)
 28		sip = intel_uncore_read(uncore, KCR_SIP(pxp->kcr_base));
 29
 30	return sip & BIT(id);
 31}
 32
 33static int pxp_wait_for_session_state(struct intel_pxp *pxp, u32 id, bool in_play)
 34{
 35	struct intel_uncore *uncore = pxp->ctrl_gt->uncore;
 36	intel_wakeref_t wakeref;
 37	u32 mask = BIT(id);
 38	int ret;
 39
 40	/* if we're suspended the session is considered off */
 41	wakeref = intel_runtime_pm_get_if_in_use(uncore->rpm);
 42	if (!wakeref)
 43		return in_play ? -ENODEV : 0;
 44
 45	ret = intel_wait_for_register(uncore,
 46				      KCR_SIP(pxp->kcr_base),
 47				      mask,
 48				      in_play ? mask : 0,
 49				      250);
 50
 51	intel_runtime_pm_put(uncore->rpm, wakeref);
 52
 53	return ret;
 54}
 55
 56static int pxp_create_arb_session(struct intel_pxp *pxp)
 57{
 58	struct intel_gt *gt = pxp->ctrl_gt;
 59	int ret;
 60
 61	pxp->arb_is_valid = false;
 62
 63	if (intel_pxp_session_is_in_play(pxp, ARB_SESSION)) {
 64		drm_err(&gt->i915->drm, "arb session already in play at creation time\n");
 65		return -EEXIST;
 66	}
 67
 68	if (HAS_ENGINE(pxp->ctrl_gt, GSC0))
 69		ret = intel_pxp_gsccs_create_session(pxp, ARB_SESSION);
 70	else
 71		ret = intel_pxp_tee_cmd_create_arb_session(pxp, ARB_SESSION);
 72	if (ret) {
 73		drm_err(&gt->i915->drm, "tee cmd for arb session creation failed\n");
 74		return ret;
 75	}
 76
 77	ret = pxp_wait_for_session_state(pxp, ARB_SESSION, true);
 78	if (ret) {
 79		drm_dbg(&gt->i915->drm, "arb session failed to go in play\n");
 80		return ret;
 81	}
 82	drm_dbg(&gt->i915->drm, "PXP ARB session is alive\n");
 83
 84	if (!++pxp->key_instance)
 85		++pxp->key_instance;
 86
 87	pxp->arb_is_valid = true;
 88
 89	return 0;
 90}
 91
 92static int pxp_terminate_arb_session_and_global(struct intel_pxp *pxp)
 93{
 94	int ret;
 95	struct intel_gt *gt = pxp->ctrl_gt;
 96
 97	/* must mark termination in progress calling this function */
 98	GEM_WARN_ON(pxp->arb_is_valid);
 99
100	/* terminate the hw sessions */
101	ret = intel_pxp_terminate_session(pxp, ARB_SESSION);
102	if (ret) {
103		drm_err(&gt->i915->drm, "Failed to submit session termination\n");
104		return ret;
105	}
106
107	ret = pxp_wait_for_session_state(pxp, ARB_SESSION, false);
108	if (ret) {
109		drm_err(&gt->i915->drm, "Session state did not clear\n");
110		return ret;
111	}
112
113	intel_uncore_write(gt->uncore, KCR_GLOBAL_TERMINATE(pxp->kcr_base), 1);
114
115	if (HAS_ENGINE(gt, GSC0))
116		intel_pxp_gsccs_end_arb_fw_session(pxp, ARB_SESSION);
117	else
118		intel_pxp_tee_end_arb_fw_session(pxp, ARB_SESSION);
119
120	return ret;
121}
122
123void intel_pxp_terminate(struct intel_pxp *pxp, bool post_invalidation_needs_restart)
124{
125	int ret;
126
127	pxp->hw_state_invalidated = post_invalidation_needs_restart;
128
129	/*
130	 * if we fail to submit the termination there is no point in waiting for
131	 * it to complete. PXP will be marked as non-active until the next
132	 * termination is issued.
133	 */
134	ret = pxp_terminate_arb_session_and_global(pxp);
135	if (ret)
136		complete_all(&pxp->termination);
137}
138
139static void pxp_terminate_complete(struct intel_pxp *pxp)
140{
141	/* Re-create the arb session after teardown handle complete */
142	if (fetch_and_zero(&pxp->hw_state_invalidated)) {
143		drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: creating arb_session after invalidation");
144		pxp_create_arb_session(pxp);
145	}
146
147	complete_all(&pxp->termination);
148}
149
150static void pxp_session_work(struct work_struct *work)
151{
152	struct intel_pxp *pxp = container_of(work, typeof(*pxp), session_work);
153	struct intel_gt *gt = pxp->ctrl_gt;
154	intel_wakeref_t wakeref;
155	u32 events = 0;
156
157	spin_lock_irq(gt->irq_lock);
158	events = fetch_and_zero(&pxp->session_events);
159	spin_unlock_irq(gt->irq_lock);
160
161	if (!events)
162		return;
163
164	drm_dbg(&gt->i915->drm, "PXP: processing event-flags 0x%08x", events);
165
166	if (events & PXP_INVAL_REQUIRED)
167		intel_pxp_invalidate(pxp);
168
169	/*
170	 * If we're processing an event while suspending then don't bother,
171	 * we're going to re-init everything on resume anyway.
172	 */
173	wakeref = intel_runtime_pm_get_if_in_use(gt->uncore->rpm);
174	if (!wakeref)
175		return;
176
177	if (events & PXP_TERMINATION_REQUEST) {
178		events &= ~PXP_TERMINATION_COMPLETE;
179		intel_pxp_terminate(pxp, true);
180	}
181
182	if (events & PXP_TERMINATION_COMPLETE)
183		pxp_terminate_complete(pxp);
184
185	intel_runtime_pm_put(gt->uncore->rpm, wakeref);
186}
187
188void intel_pxp_session_management_init(struct intel_pxp *pxp)
189{
190	mutex_init(&pxp->arb_mutex);
191	INIT_WORK(&pxp->session_work, pxp_session_work);
192}
~/ Read-only file preview.