• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright(c) 2020 Intel Corporation.
4  */
5 
6 #include <linux/component.h>
7 
8 #include <drm/i915_pxp_tee_interface.h>
9 #include <drm/i915_component.h>
10 
11 #include "i915_drv.h"
12 #include "intel_pxp.h"
13 #include "intel_pxp_session.h"
14 #include "intel_pxp_tee.h"
15 #include "intel_pxp_tee_interface.h"
16 
i915_dev_to_pxp(struct device * i915_kdev)17 static inline struct intel_pxp *i915_dev_to_pxp(struct device *i915_kdev)
18 {
19 	struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
20 
21 	return &to_gt(i915)->pxp;
22 }
23 
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)24 static int intel_pxp_tee_io_message(struct intel_pxp *pxp,
25 				    void *msg_in, u32 msg_in_size,
26 				    void *msg_out, u32 msg_out_max_size,
27 				    u32 *msg_out_rcv_size)
28 {
29 	struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
30 	struct i915_pxp_component *pxp_component = pxp->pxp_component;
31 	int ret = 0;
32 
33 	mutex_lock(&pxp->tee_mutex);
34 
35 	/*
36 	 * The binding of the component is asynchronous from i915 probe, so we
37 	 * can't be sure it has happened.
38 	 */
39 	if (!pxp_component) {
40 		ret = -ENODEV;
41 		goto unlock;
42 	}
43 
44 	ret = pxp_component->ops->send(pxp_component->tee_dev, msg_in, msg_in_size);
45 	if (ret) {
46 		drm_err(&i915->drm, "Failed to send PXP TEE message\n");
47 		goto unlock;
48 	}
49 
50 	ret = pxp_component->ops->recv(pxp_component->tee_dev, msg_out, msg_out_max_size);
51 	if (ret < 0) {
52 		drm_err(&i915->drm, "Failed to receive PXP TEE message\n");
53 		goto unlock;
54 	}
55 
56 	if (ret > msg_out_max_size) {
57 		drm_err(&i915->drm,
58 			"Failed to receive PXP TEE message due to unexpected output size\n");
59 		ret = -ENOSPC;
60 		goto unlock;
61 	}
62 
63 	if (msg_out_rcv_size)
64 		*msg_out_rcv_size = ret;
65 
66 	ret = 0;
67 unlock:
68 	mutex_unlock(&pxp->tee_mutex);
69 	return ret;
70 }
71 
72 /**
73  * i915_pxp_tee_component_bind - bind function to pass the function pointers to pxp_tee
74  * @i915_kdev: pointer to i915 kernel device
75  * @tee_kdev: pointer to tee kernel device
76  * @data: pointer to pxp_tee_master containing the function pointers
77  *
78  * This bind function is called during the system boot or resume from system sleep.
79  *
80  * Return: return 0 if successful.
81  */
i915_pxp_tee_component_bind(struct device * i915_kdev,struct device * tee_kdev,void * data)82 static int i915_pxp_tee_component_bind(struct device *i915_kdev,
83 				       struct device *tee_kdev, void *data)
84 {
85 	struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
86 	struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
87 	intel_wakeref_t wakeref;
88 
89 	mutex_lock(&pxp->tee_mutex);
90 	pxp->pxp_component = data;
91 	pxp->pxp_component->tee_dev = tee_kdev;
92 	mutex_unlock(&pxp->tee_mutex);
93 
94 	/* if we are suspended, the HW will be re-initialized on resume */
95 	wakeref = intel_runtime_pm_get_if_in_use(&i915->runtime_pm);
96 	if (!wakeref)
97 		return 0;
98 
99 	/* the component is required to fully start the PXP HW */
100 	intel_pxp_init_hw(pxp);
101 
102 	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
103 
104 	return 0;
105 }
106 
i915_pxp_tee_component_unbind(struct device * i915_kdev,struct device * tee_kdev,void * data)107 static void i915_pxp_tee_component_unbind(struct device *i915_kdev,
108 					  struct device *tee_kdev, void *data)
109 {
110 	struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
111 	struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
112 	intel_wakeref_t wakeref;
113 
114 	with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref)
115 		intel_pxp_fini_hw(pxp);
116 
117 	mutex_lock(&pxp->tee_mutex);
118 	pxp->pxp_component = NULL;
119 	mutex_unlock(&pxp->tee_mutex);
120 }
121 
122 static const struct component_ops i915_pxp_tee_component_ops = {
123 	.bind   = i915_pxp_tee_component_bind,
124 	.unbind = i915_pxp_tee_component_unbind,
125 };
126 
intel_pxp_tee_component_init(struct intel_pxp * pxp)127 int intel_pxp_tee_component_init(struct intel_pxp *pxp)
128 {
129 	int ret;
130 	struct intel_gt *gt = pxp_to_gt(pxp);
131 	struct drm_i915_private *i915 = gt->i915;
132 
133 	ret = component_add_typed(i915->drm.dev, &i915_pxp_tee_component_ops,
134 				  I915_COMPONENT_PXP);
135 	if (ret < 0) {
136 		drm_err(&i915->drm, "Failed to add PXP component (%d)\n", ret);
137 		return ret;
138 	}
139 
140 	pxp->pxp_component_added = true;
141 
142 	return 0;
143 }
144 
intel_pxp_tee_component_fini(struct intel_pxp * pxp)145 void intel_pxp_tee_component_fini(struct intel_pxp *pxp)
146 {
147 	struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
148 
149 	if (!pxp->pxp_component_added)
150 		return;
151 
152 	component_del(i915->drm.dev, &i915_pxp_tee_component_ops);
153 	pxp->pxp_component_added = false;
154 }
155 
intel_pxp_tee_cmd_create_arb_session(struct intel_pxp * pxp,int arb_session_id)156 int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp,
157 					 int arb_session_id)
158 {
159 	struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
160 	struct pxp_tee_create_arb_in msg_in = {0};
161 	struct pxp_tee_create_arb_out msg_out = {0};
162 	int ret;
163 
164 	msg_in.header.api_version = PXP_TEE_APIVER;
165 	msg_in.header.command_id = PXP_TEE_ARB_CMDID;
166 	msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header);
167 	msg_in.protection_mode = PXP_TEE_ARB_PROTECTION_MODE;
168 	msg_in.session_id = arb_session_id;
169 
170 	ret = intel_pxp_tee_io_message(pxp,
171 				       &msg_in, sizeof(msg_in),
172 				       &msg_out, sizeof(msg_out),
173 				       NULL);
174 
175 	if (ret)
176 		drm_err(&i915->drm, "Failed to send tee msg ret=[%d]\n", ret);
177 
178 	return ret;
179 }
180