10436ac1bSHuang, Sean Z // SPDX-License-Identifier: MIT
20436ac1bSHuang, Sean Z /*
30436ac1bSHuang, Sean Z  * Copyright(c) 2020 Intel Corporation.
40436ac1bSHuang, Sean Z  */
50436ac1bSHuang, Sean Z 
60436ac1bSHuang, Sean Z #include <linux/component.h>
72052287aSJani Nikula 
82052287aSJani Nikula #include <drm/i915_pxp_tee_interface.h>
92052287aSJani Nikula #include <drm/i915_component.h>
102052287aSJani Nikula 
119058f9d7SVitaly Lubart #include "gem/i915_gem_lmem.h"
129058f9d7SVitaly Lubart 
130436ac1bSHuang, Sean Z #include "i915_drv.h"
14*115cdccaSJonathan Cavitt #include "gt/intel_gt.h"
15f67986b0SAlan Previn 
160436ac1bSHuang, Sean Z #include "intel_pxp.h"
1707db5bd2SAlan Previn #include "intel_pxp_cmd_interface_42.h"
18087b6818SDaniele Ceraolo Spurio #include "intel_pxp_huc.h"
19f67986b0SAlan Previn #include "intel_pxp_session.h"
20f67986b0SAlan Previn #include "intel_pxp_tee.h"
21f67986b0SAlan Previn #include "intel_pxp_types.h"
220436ac1bSHuang, Sean Z 
2369e6dd14SAlan Previn static bool
is_fw_err_platform_config(u32 type)2469e6dd14SAlan Previn is_fw_err_platform_config(u32 type)
2569e6dd14SAlan Previn {
2669e6dd14SAlan Previn 	switch (type) {
2769e6dd14SAlan Previn 	case PXP_STATUS_ERROR_API_VERSION:
2869e6dd14SAlan Previn 	case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF:
2969e6dd14SAlan Previn 	case PXP_STATUS_PLATFCONFIG_KF1_BAD:
3069e6dd14SAlan Previn 		return true;
3169e6dd14SAlan Previn 	default:
3269e6dd14SAlan Previn 		break;
3369e6dd14SAlan Previn 	}
3469e6dd14SAlan Previn 	return false;
3569e6dd14SAlan Previn }
3669e6dd14SAlan Previn 
3769e6dd14SAlan Previn static const char *
fw_err_to_string(u32 type)3869e6dd14SAlan Previn fw_err_to_string(u32 type)
3969e6dd14SAlan Previn {
4069e6dd14SAlan Previn 	switch (type) {
4169e6dd14SAlan Previn 	case PXP_STATUS_ERROR_API_VERSION:
4269e6dd14SAlan Previn 		return "ERR_API_VERSION";
4369e6dd14SAlan Previn 	case PXP_STATUS_NOT_READY:
4469e6dd14SAlan Previn 		return "ERR_NOT_READY";
4569e6dd14SAlan Previn 	case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF:
4669e6dd14SAlan Previn 	case PXP_STATUS_PLATFCONFIG_KF1_BAD:
4769e6dd14SAlan Previn 		return "ERR_PLATFORM_CONFIG";
4869e6dd14SAlan Previn 	default:
4969e6dd14SAlan Previn 		break;
5069e6dd14SAlan Previn 	}
5169e6dd14SAlan Previn 	return NULL;
5269e6dd14SAlan Previn }
5369e6dd14SAlan Previn 
intel_pxp_tee_io_message(struct intel_pxp * pxp,void * msg_in,u32 msg_in_size,void * msg_out,u32 msg_out_max_size,u32 * msg_out_rcv_size)54cbbd3764SHuang, Sean Z static int intel_pxp_tee_io_message(struct intel_pxp *pxp,
55cbbd3764SHuang, Sean Z 				    void *msg_in, u32 msg_in_size,
56cbbd3764SHuang, Sean Z 				    void *msg_out, u32 msg_out_max_size,
57cbbd3764SHuang, Sean Z 				    u32 *msg_out_rcv_size)
58cbbd3764SHuang, Sean Z {
59f67986b0SAlan Previn 	struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
60cbbd3764SHuang, Sean Z 	struct i915_pxp_component *pxp_component = pxp->pxp_component;
61cbbd3764SHuang, Sean Z 	int ret = 0;
62cbbd3764SHuang, Sean Z 
63cbbd3764SHuang, Sean Z 	mutex_lock(&pxp->tee_mutex);
64cbbd3764SHuang, Sean Z 
65cbbd3764SHuang, Sean Z 	/*
66cbbd3764SHuang, Sean Z 	 * The binding of the component is asynchronous from i915 probe, so we
67cbbd3764SHuang, Sean Z 	 * can't be sure it has happened.
68cbbd3764SHuang, Sean Z 	 */
69cbbd3764SHuang, Sean Z 	if (!pxp_component) {
70cbbd3764SHuang, Sean Z 		ret = -ENODEV;
71cbbd3764SHuang, Sean Z 		goto unlock;
72cbbd3764SHuang, Sean Z 	}
73cbbd3764SHuang, Sean Z 
74cbbd3764SHuang, Sean Z 	ret = pxp_component->ops->send(pxp_component->tee_dev, msg_in, msg_in_size);
75cbbd3764SHuang, Sean Z 	if (ret) {
76cbbd3764SHuang, Sean Z 		drm_err(&i915->drm, "Failed to send PXP TEE message\n");
77cbbd3764SHuang, Sean Z 		goto unlock;
78cbbd3764SHuang, Sean Z 	}
79cbbd3764SHuang, Sean Z 
80cbbd3764SHuang, Sean Z 	ret = pxp_component->ops->recv(pxp_component->tee_dev, msg_out, msg_out_max_size);
81cbbd3764SHuang, Sean Z 	if (ret < 0) {
82cbbd3764SHuang, Sean Z 		drm_err(&i915->drm, "Failed to receive PXP TEE message\n");
83cbbd3764SHuang, Sean Z 		goto unlock;
84cbbd3764SHuang, Sean Z 	}
85cbbd3764SHuang, Sean Z 
86cbbd3764SHuang, Sean Z 	if (ret > msg_out_max_size) {
87cbbd3764SHuang, Sean Z 		drm_err(&i915->drm,
88cbbd3764SHuang, Sean Z 			"Failed to receive PXP TEE message due to unexpected output size\n");
89cbbd3764SHuang, Sean Z 		ret = -ENOSPC;
90cbbd3764SHuang, Sean Z 		goto unlock;
91cbbd3764SHuang, Sean Z 	}
92cbbd3764SHuang, Sean Z 
93cbbd3764SHuang, Sean Z 	if (msg_out_rcv_size)
94cbbd3764SHuang, Sean Z 		*msg_out_rcv_size = ret;
95cbbd3764SHuang, Sean Z 
96cbbd3764SHuang, Sean Z 	ret = 0;
97cbbd3764SHuang, Sean Z unlock:
98cbbd3764SHuang, Sean Z 	mutex_unlock(&pxp->tee_mutex);
99cbbd3764SHuang, Sean Z 	return ret;
100cbbd3764SHuang, Sean Z }
101cbbd3764SHuang, Sean Z 
intel_pxp_tee_stream_message(struct intel_pxp * pxp,u8 client_id,u32 fence_id,void * msg_in,size_t msg_in_len,void * msg_out,size_t msg_out_len)1029058f9d7SVitaly Lubart int intel_pxp_tee_stream_message(struct intel_pxp *pxp,
1039058f9d7SVitaly Lubart 				 u8 client_id, u32 fence_id,
1049058f9d7SVitaly Lubart 				 void *msg_in, size_t msg_in_len,
1059058f9d7SVitaly Lubart 				 void *msg_out, size_t msg_out_len)
1069058f9d7SVitaly Lubart {
1079058f9d7SVitaly Lubart 	/* TODO: for bigger objects we need to use a sg of 4k pages */
1089058f9d7SVitaly Lubart 	const size_t max_msg_size = PAGE_SIZE;
109f67986b0SAlan Previn 	struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
1109058f9d7SVitaly Lubart 	struct i915_pxp_component *pxp_component = pxp->pxp_component;
1119058f9d7SVitaly Lubart 	unsigned int offset = 0;
1129058f9d7SVitaly Lubart 	struct scatterlist *sg;
1139058f9d7SVitaly Lubart 	int ret;
1149058f9d7SVitaly Lubart 
1159058f9d7SVitaly Lubart 	if (msg_in_len > max_msg_size || msg_out_len > max_msg_size)
1169058f9d7SVitaly Lubart 		return -ENOSPC;
1179058f9d7SVitaly Lubart 
1189058f9d7SVitaly Lubart 	mutex_lock(&pxp->tee_mutex);
1199058f9d7SVitaly Lubart 
1209058f9d7SVitaly Lubart 	if (unlikely(!pxp_component || !pxp_component->ops->gsc_command)) {
1219058f9d7SVitaly Lubart 		ret = -ENODEV;
1229058f9d7SVitaly Lubart 		goto unlock;
1239058f9d7SVitaly Lubart 	}
1249058f9d7SVitaly Lubart 
1259058f9d7SVitaly Lubart 	GEM_BUG_ON(!pxp->stream_cmd.obj);
1269058f9d7SVitaly Lubart 
1279058f9d7SVitaly Lubart 	sg = i915_gem_object_get_sg_dma(pxp->stream_cmd.obj, 0, &offset);
1289058f9d7SVitaly Lubart 
1299058f9d7SVitaly Lubart 	memcpy(pxp->stream_cmd.vaddr, msg_in, msg_in_len);
1309058f9d7SVitaly Lubart 
1319058f9d7SVitaly Lubart 	ret = pxp_component->ops->gsc_command(pxp_component->tee_dev, client_id,
1329058f9d7SVitaly Lubart 					      fence_id, sg, msg_in_len, sg);
1339058f9d7SVitaly Lubart 	if (ret < 0)
1349058f9d7SVitaly Lubart 		drm_err(&i915->drm, "Failed to send PXP TEE gsc command\n");
1359058f9d7SVitaly Lubart 	else
1369058f9d7SVitaly Lubart 		memcpy(msg_out, pxp->stream_cmd.vaddr, msg_out_len);
1379058f9d7SVitaly Lubart 
1389058f9d7SVitaly Lubart unlock:
1399058f9d7SVitaly Lubart 	mutex_unlock(&pxp->tee_mutex);
1409058f9d7SVitaly Lubart 	return ret;
1419058f9d7SVitaly Lubart }
1429058f9d7SVitaly Lubart 
1430436ac1bSHuang, Sean Z /**
1440436ac1bSHuang, Sean Z  * i915_pxp_tee_component_bind - bind function to pass the function pointers to pxp_tee
1450436ac1bSHuang, Sean Z  * @i915_kdev: pointer to i915 kernel device
1460436ac1bSHuang, Sean Z  * @tee_kdev: pointer to tee kernel device
1470436ac1bSHuang, Sean Z  * @data: pointer to pxp_tee_master containing the function pointers
1480436ac1bSHuang, Sean Z  *
1490436ac1bSHuang, Sean Z  * This bind function is called during the system boot or resume from system sleep.
1500436ac1bSHuang, Sean Z  *
1510436ac1bSHuang, Sean Z  * Return: return 0 if successful.
1520436ac1bSHuang, Sean Z  */
i915_pxp_tee_component_bind(struct device * i915_kdev,struct device * tee_kdev,void * data)1530436ac1bSHuang, Sean Z static int i915_pxp_tee_component_bind(struct device *i915_kdev,
1540436ac1bSHuang, Sean Z 				       struct device *tee_kdev, void *data)
1550436ac1bSHuang, Sean Z {
1560cfab4cbSHuang, Sean Z 	struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
157f67986b0SAlan Previn 	struct intel_pxp *pxp = i915->pxp;
158f67986b0SAlan Previn 	struct intel_uc *uc = &pxp->ctrl_gt->uc;
1590cfab4cbSHuang, Sean Z 	intel_wakeref_t wakeref;
160087b6818SDaniele Ceraolo Spurio 	int ret = 0;
1610436ac1bSHuang, Sean Z 
1626e52ced0SAlexander Usyskin 	if (!HAS_HECI_PXP(i915)) {
1636e52ced0SAlexander Usyskin 		pxp->dev_link = device_link_add(i915_kdev, tee_kdev, DL_FLAG_STATELESS);
1646e52ced0SAlexander Usyskin 		if (drm_WARN_ON(&i915->drm, !pxp->dev_link))
1656e52ced0SAlexander Usyskin 			return -ENODEV;
1666e52ced0SAlexander Usyskin 	}
1676e52ced0SAlexander Usyskin 
168cbbd3764SHuang, Sean Z 	mutex_lock(&pxp->tee_mutex);
1690436ac1bSHuang, Sean Z 	pxp->pxp_component = data;
1700436ac1bSHuang, Sean Z 	pxp->pxp_component->tee_dev = tee_kdev;
171cbbd3764SHuang, Sean Z 	mutex_unlock(&pxp->tee_mutex);
1720436ac1bSHuang, Sean Z 
173087b6818SDaniele Ceraolo Spurio 	if (intel_uc_uses_huc(uc) && intel_huc_is_loaded_by_gsc(&uc->huc)) {
174087b6818SDaniele Ceraolo Spurio 		with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
175087b6818SDaniele Ceraolo Spurio 			/* load huc via pxp */
176087b6818SDaniele Ceraolo Spurio 			ret = intel_huc_fw_load_and_auth_via_gsc(&uc->huc);
177087b6818SDaniele Ceraolo Spurio 			if (ret < 0)
178087b6818SDaniele Ceraolo Spurio 				drm_err(&i915->drm, "failed to load huc via gsc %d\n", ret);
179087b6818SDaniele Ceraolo Spurio 		}
180087b6818SDaniele Ceraolo Spurio 	}
181087b6818SDaniele Ceraolo Spurio 
1820cfab4cbSHuang, Sean Z 	/* if we are suspended, the HW will be re-initialized on resume */
1830cfab4cbSHuang, Sean Z 	wakeref = intel_runtime_pm_get_if_in_use(&i915->runtime_pm);
1840cfab4cbSHuang, Sean Z 	if (!wakeref)
1850cfab4cbSHuang, Sean Z 		return 0;
1860cfab4cbSHuang, Sean Z 
187e0111ce0SDaniele Ceraolo Spurio 	/* the component is required to fully start the PXP HW */
188c5be8fc9SDaniele Ceraolo Spurio 	if (intel_pxp_is_enabled(pxp))
189e0111ce0SDaniele Ceraolo Spurio 		intel_pxp_init_hw(pxp);
190cbbd3764SHuang, Sean Z 
1910cfab4cbSHuang, Sean Z 	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
1920cfab4cbSHuang, Sean Z 
193087b6818SDaniele Ceraolo Spurio 	return ret;
1940436ac1bSHuang, Sean Z }
1950436ac1bSHuang, Sean Z 
i915_pxp_tee_component_unbind(struct device * i915_kdev,struct device * tee_kdev,void * data)1960436ac1bSHuang, Sean Z static void i915_pxp_tee_component_unbind(struct device *i915_kdev,
1970436ac1bSHuang, Sean Z 					  struct device *tee_kdev, void *data)
1980436ac1bSHuang, Sean Z {
199f9535d28SJuston Li 	struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
200f67986b0SAlan Previn 	struct intel_pxp *pxp = i915->pxp;
201f9535d28SJuston Li 	intel_wakeref_t wakeref;
2020436ac1bSHuang, Sean Z 
203c5be8fc9SDaniele Ceraolo Spurio 	if (intel_pxp_is_enabled(pxp))
204f9535d28SJuston Li 		with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref)
205e0111ce0SDaniele Ceraolo Spurio 			intel_pxp_fini_hw(pxp);
206e0111ce0SDaniele Ceraolo Spurio 
207cbbd3764SHuang, Sean Z 	mutex_lock(&pxp->tee_mutex);
2080436ac1bSHuang, Sean Z 	pxp->pxp_component = NULL;
209cbbd3764SHuang, Sean Z 	mutex_unlock(&pxp->tee_mutex);
2106e52ced0SAlexander Usyskin 
2116e52ced0SAlexander Usyskin 	if (pxp->dev_link) {
2126e52ced0SAlexander Usyskin 		device_link_del(pxp->dev_link);
2136e52ced0SAlexander Usyskin 		pxp->dev_link = NULL;
2146e52ced0SAlexander Usyskin 	}
2150436ac1bSHuang, Sean Z }
2160436ac1bSHuang, Sean Z 
2170436ac1bSHuang, Sean Z static const struct component_ops i915_pxp_tee_component_ops = {
2180436ac1bSHuang, Sean Z 	.bind   = i915_pxp_tee_component_bind,
2190436ac1bSHuang, Sean Z 	.unbind = i915_pxp_tee_component_unbind,
2200436ac1bSHuang, Sean Z };
2210436ac1bSHuang, Sean Z 
alloc_streaming_command(struct intel_pxp * pxp)2229058f9d7SVitaly Lubart static int alloc_streaming_command(struct intel_pxp *pxp)
2239058f9d7SVitaly Lubart {
224f67986b0SAlan Previn 	struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
2259058f9d7SVitaly Lubart 	struct drm_i915_gem_object *obj = NULL;
2269058f9d7SVitaly Lubart 	void *cmd;
2279058f9d7SVitaly Lubart 	int err;
2289058f9d7SVitaly Lubart 
2299058f9d7SVitaly Lubart 	pxp->stream_cmd.obj = NULL;
2309058f9d7SVitaly Lubart 	pxp->stream_cmd.vaddr = NULL;
2319058f9d7SVitaly Lubart 
2329058f9d7SVitaly Lubart 	if (!IS_DGFX(i915))
2339058f9d7SVitaly Lubart 		return 0;
2349058f9d7SVitaly Lubart 
2359058f9d7SVitaly Lubart 	/* allocate lmem object of one page for PXP command memory and store it */
2369058f9d7SVitaly Lubart 	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, I915_BO_ALLOC_CONTIGUOUS);
2379058f9d7SVitaly Lubart 	if (IS_ERR(obj)) {
2389058f9d7SVitaly Lubart 		drm_err(&i915->drm, "Failed to allocate pxp streaming command!\n");
2399058f9d7SVitaly Lubart 		return PTR_ERR(obj);
2409058f9d7SVitaly Lubart 	}
2419058f9d7SVitaly Lubart 
2429058f9d7SVitaly Lubart 	err = i915_gem_object_pin_pages_unlocked(obj);
2439058f9d7SVitaly Lubart 	if (err) {
2449058f9d7SVitaly Lubart 		drm_err(&i915->drm, "Failed to pin gsc message page!\n");
2459058f9d7SVitaly Lubart 		goto out_put;
2469058f9d7SVitaly Lubart 	}
2479058f9d7SVitaly Lubart 
2489058f9d7SVitaly Lubart 	/* map the lmem into the virtual memory pointer */
249*115cdccaSJonathan Cavitt 	cmd = i915_gem_object_pin_map_unlocked(obj,
250*115cdccaSJonathan Cavitt 					       intel_gt_coherent_map_type(pxp->ctrl_gt,
251*115cdccaSJonathan Cavitt 									  obj, true));
2529058f9d7SVitaly Lubart 	if (IS_ERR(cmd)) {
2539058f9d7SVitaly Lubart 		drm_err(&i915->drm, "Failed to map gsc message page!\n");
2549058f9d7SVitaly Lubart 		err = PTR_ERR(cmd);
2559058f9d7SVitaly Lubart 		goto out_unpin;
2569058f9d7SVitaly Lubart 	}
2579058f9d7SVitaly Lubart 
2589058f9d7SVitaly Lubart 	memset(cmd, 0, obj->base.size);
2599058f9d7SVitaly Lubart 
2609058f9d7SVitaly Lubart 	pxp->stream_cmd.obj = obj;
2619058f9d7SVitaly Lubart 	pxp->stream_cmd.vaddr = cmd;
2629058f9d7SVitaly Lubart 
2639058f9d7SVitaly Lubart 	return 0;
2649058f9d7SVitaly Lubart 
2659058f9d7SVitaly Lubart out_unpin:
2669058f9d7SVitaly Lubart 	i915_gem_object_unpin_pages(obj);
2679058f9d7SVitaly Lubart out_put:
2689058f9d7SVitaly Lubart 	i915_gem_object_put(obj);
2699058f9d7SVitaly Lubart 	return err;
2709058f9d7SVitaly Lubart }
2719058f9d7SVitaly Lubart 
free_streaming_command(struct intel_pxp * pxp)2729058f9d7SVitaly Lubart static void free_streaming_command(struct intel_pxp *pxp)
2739058f9d7SVitaly Lubart {
2749058f9d7SVitaly Lubart 	struct drm_i915_gem_object *obj = fetch_and_zero(&pxp->stream_cmd.obj);
2759058f9d7SVitaly Lubart 
2769058f9d7SVitaly Lubart 	if (!obj)
2779058f9d7SVitaly Lubart 		return;
2789058f9d7SVitaly Lubart 
2799058f9d7SVitaly Lubart 	i915_gem_object_unpin_map(obj);
2809058f9d7SVitaly Lubart 	i915_gem_object_unpin_pages(obj);
2819058f9d7SVitaly Lubart 	i915_gem_object_put(obj);
2829058f9d7SVitaly Lubart }
2839058f9d7SVitaly Lubart 
intel_pxp_tee_component_init(struct intel_pxp * pxp)2840436ac1bSHuang, Sean Z int intel_pxp_tee_component_init(struct intel_pxp *pxp)
2850436ac1bSHuang, Sean Z {
2860436ac1bSHuang, Sean Z 	int ret;
287f67986b0SAlan Previn 	struct intel_gt *gt = pxp->ctrl_gt;
2880436ac1bSHuang, Sean Z 	struct drm_i915_private *i915 = gt->i915;
2890436ac1bSHuang, Sean Z 
2909058f9d7SVitaly Lubart 	ret = alloc_streaming_command(pxp);
2919058f9d7SVitaly Lubart 	if (ret)
2929058f9d7SVitaly Lubart 		return ret;
2939058f9d7SVitaly Lubart 
2940436ac1bSHuang, Sean Z 	ret = component_add_typed(i915->drm.dev, &i915_pxp_tee_component_ops,
2950436ac1bSHuang, Sean Z 				  I915_COMPONENT_PXP);
2960436ac1bSHuang, Sean Z 	if (ret < 0) {
2970436ac1bSHuang, Sean Z 		drm_err(&i915->drm, "Failed to add PXP component (%d)\n", ret);
2989058f9d7SVitaly Lubart 		goto out_free;
2990436ac1bSHuang, Sean Z 	}
3000436ac1bSHuang, Sean Z 
3010436ac1bSHuang, Sean Z 	pxp->pxp_component_added = true;
3020436ac1bSHuang, Sean Z 
3030436ac1bSHuang, Sean Z 	return 0;
3049058f9d7SVitaly Lubart 
3059058f9d7SVitaly Lubart out_free:
3069058f9d7SVitaly Lubart 	free_streaming_command(pxp);
3079058f9d7SVitaly Lubart 	return ret;
3080436ac1bSHuang, Sean Z }
3090436ac1bSHuang, Sean Z 
intel_pxp_tee_component_fini(struct intel_pxp * pxp)3100436ac1bSHuang, Sean Z void intel_pxp_tee_component_fini(struct intel_pxp *pxp)
3110436ac1bSHuang, Sean Z {
312f67986b0SAlan Previn 	struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
3130436ac1bSHuang, Sean Z 
3140436ac1bSHuang, Sean Z 	if (!pxp->pxp_component_added)
3150436ac1bSHuang, Sean Z 		return;
3160436ac1bSHuang, Sean Z 
3170436ac1bSHuang, Sean Z 	component_del(i915->drm.dev, &i915_pxp_tee_component_ops);
3180436ac1bSHuang, Sean Z 	pxp->pxp_component_added = false;
3199058f9d7SVitaly Lubart 
3209058f9d7SVitaly Lubart 	free_streaming_command(pxp);
3210436ac1bSHuang, Sean Z }
322cbbd3764SHuang, Sean Z 
intel_pxp_tee_cmd_create_arb_session(struct intel_pxp * pxp,int arb_session_id)323cbbd3764SHuang, Sean Z int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp,
324cbbd3764SHuang, Sean Z 					 int arb_session_id)
325cbbd3764SHuang, Sean Z {
326f67986b0SAlan Previn 	struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
32707db5bd2SAlan Previn 	struct pxp42_create_arb_in msg_in = {0};
32807db5bd2SAlan Previn 	struct pxp42_create_arb_out msg_out = {0};
329cbbd3764SHuang, Sean Z 	int ret;
330cbbd3764SHuang, Sean Z 
33107db5bd2SAlan Previn 	msg_in.header.api_version = PXP_APIVER(4, 2);
33207db5bd2SAlan Previn 	msg_in.header.command_id = PXP42_CMDID_INIT_SESSION;
333cbbd3764SHuang, Sean Z 	msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header);
33407db5bd2SAlan Previn 	msg_in.protection_mode = PXP42_ARB_SESSION_MODE_HEAVY;
335cbbd3764SHuang, Sean Z 	msg_in.session_id = arb_session_id;
336cbbd3764SHuang, Sean Z 
337cbbd3764SHuang, Sean Z 	ret = intel_pxp_tee_io_message(pxp,
338cbbd3764SHuang, Sean Z 				       &msg_in, sizeof(msg_in),
339cbbd3764SHuang, Sean Z 				       &msg_out, sizeof(msg_out),
340cbbd3764SHuang, Sean Z 				       NULL);
341cbbd3764SHuang, Sean Z 
34269e6dd14SAlan Previn 	if (ret) {
34369e6dd14SAlan Previn 		drm_err(&i915->drm, "Failed to send tee msg init arb session, ret=[%d]\n", ret);
34469e6dd14SAlan Previn 	} else if (msg_out.header.status != 0) {
34569e6dd14SAlan Previn 		if (is_fw_err_platform_config(msg_out.header.status)) {
34669e6dd14SAlan Previn 			drm_info_once(&i915->drm,
34769e6dd14SAlan Previn 				      "PXP init-arb-session-%d failed due to BIOS/SOC:0x%08x:%s\n",
34869e6dd14SAlan Previn 				      arb_session_id, msg_out.header.status,
34969e6dd14SAlan Previn 				      fw_err_to_string(msg_out.header.status));
35069e6dd14SAlan Previn 		} else {
35169e6dd14SAlan Previn 			drm_dbg(&i915->drm, "PXP init-arb-session--%d failed 0x%08x:%st:\n",
35269e6dd14SAlan Previn 				arb_session_id, msg_out.header.status,
35369e6dd14SAlan Previn 				fw_err_to_string(msg_out.header.status));
35469e6dd14SAlan Previn 			drm_dbg(&i915->drm, "     cmd-detail: ID=[0x%08x],API-Ver-[0x%08x]\n",
355b762787bSAlan Previn 				msg_in.header.command_id, msg_in.header.api_version);
35669e6dd14SAlan Previn 		}
35769e6dd14SAlan Previn 	}
358cbbd3764SHuang, Sean Z 
359cbbd3764SHuang, Sean Z 	return ret;
360cbbd3764SHuang, Sean Z }
361d374c047SAlan Previn 
intel_pxp_tee_end_arb_fw_session(struct intel_pxp * pxp,u32 session_id)362d374c047SAlan Previn void intel_pxp_tee_end_arb_fw_session(struct intel_pxp *pxp, u32 session_id)
363d374c047SAlan Previn {
364d374c047SAlan Previn 	struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
365d374c047SAlan Previn 	struct pxp42_inv_stream_key_in msg_in = {0};
366d374c047SAlan Previn 	struct pxp42_inv_stream_key_out msg_out = {0};
367d374c047SAlan Previn 	int ret, trials = 0;
368d374c047SAlan Previn 
369d374c047SAlan Previn try_again:
370d374c047SAlan Previn 	memset(&msg_in, 0, sizeof(msg_in));
371d374c047SAlan Previn 	memset(&msg_out, 0, sizeof(msg_out));
372d374c047SAlan Previn 	msg_in.header.api_version = PXP_APIVER(4, 2);
373d374c047SAlan Previn 	msg_in.header.command_id = PXP42_CMDID_INVALIDATE_STREAM_KEY;
374d374c047SAlan Previn 	msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header);
375d374c047SAlan Previn 
376d374c047SAlan Previn 	msg_in.header.stream_id = FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_VALID, 1);
377d374c047SAlan Previn 	msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_APP_TYPE, 0);
378d374c047SAlan Previn 	msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_ID, session_id);
379d374c047SAlan Previn 
380d374c047SAlan Previn 	ret = intel_pxp_tee_io_message(pxp,
381d374c047SAlan Previn 				       &msg_in, sizeof(msg_in),
382d374c047SAlan Previn 				       &msg_out, sizeof(msg_out),
383d374c047SAlan Previn 				       NULL);
384d374c047SAlan Previn 
385d374c047SAlan Previn 	/* Cleanup coherency between GT and Firmware is critical, so try again if it fails */
386d374c047SAlan Previn 	if ((ret || msg_out.header.status != 0x0) && ++trials < 3)
387d374c047SAlan Previn 		goto try_again;
388d374c047SAlan Previn 
38969e6dd14SAlan Previn 	if (ret) {
39069e6dd14SAlan Previn 		drm_err(&i915->drm, "Failed to send tee msg for inv-stream-key-%u, ret=[%d]\n",
391d374c047SAlan Previn 			session_id, ret);
39269e6dd14SAlan Previn 	} else if (msg_out.header.status != 0) {
39369e6dd14SAlan Previn 		if (is_fw_err_platform_config(msg_out.header.status)) {
39469e6dd14SAlan Previn 			drm_info_once(&i915->drm,
39569e6dd14SAlan Previn 				      "PXP inv-stream-key-%u failed due to BIOS/SOC :0x%08x:%s\n",
39669e6dd14SAlan Previn 				      session_id, msg_out.header.status,
39769e6dd14SAlan Previn 				      fw_err_to_string(msg_out.header.status));
39869e6dd14SAlan Previn 		} else {
39969e6dd14SAlan Previn 			drm_dbg(&i915->drm, "PXP inv-stream-key-%u failed 0x%08x:%s:\n",
40069e6dd14SAlan Previn 				session_id, msg_out.header.status,
40169e6dd14SAlan Previn 				fw_err_to_string(msg_out.header.status));
40269e6dd14SAlan Previn 			drm_dbg(&i915->drm, "     cmd-detail: ID=[0x%08x],API-Ver-[0x%08x]\n",
40369e6dd14SAlan Previn 				msg_in.header.command_id, msg_in.header.api_version);
40469e6dd14SAlan Previn 		}
40569e6dd14SAlan Previn 	}
406d374c047SAlan Previn }
407