1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include "gt/intel_engine_pm.h"
7 #include "gt/intel_gpu_commands.h"
8 #include "gt/intel_gt.h"
9 #include "gt/intel_gt_print.h"
10 #include "gt/intel_ring.h"
11 #include "intel_gsc_fw.h"
12 
13 #define GSC_FW_STATUS_REG			_MMIO(0x116C40)
14 #define GSC_FW_CURRENT_STATE			REG_GENMASK(3, 0)
15 #define   GSC_FW_CURRENT_STATE_RESET		0
16 #define GSC_FW_INIT_COMPLETE_BIT		REG_BIT(9)
17 
18 static bool gsc_is_in_reset(struct intel_uncore *uncore)
19 {
20 	u32 fw_status = intel_uncore_read(uncore, GSC_FW_STATUS_REG);
21 
22 	return REG_FIELD_GET(GSC_FW_CURRENT_STATE, fw_status) ==
23 	       GSC_FW_CURRENT_STATE_RESET;
24 }
25 
26 bool intel_gsc_uc_fw_init_done(struct intel_gsc_uc *gsc)
27 {
28 	struct intel_uncore *uncore = gsc_uc_to_gt(gsc)->uncore;
29 	u32 fw_status = intel_uncore_read(uncore, GSC_FW_STATUS_REG);
30 
31 	return fw_status & GSC_FW_INIT_COMPLETE_BIT;
32 }
33 
34 static int emit_gsc_fw_load(struct i915_request *rq, struct intel_gsc_uc *gsc)
35 {
36 	u32 offset = i915_ggtt_offset(gsc->local);
37 	u32 *cs;
38 
39 	cs = intel_ring_begin(rq, 4);
40 	if (IS_ERR(cs))
41 		return PTR_ERR(cs);
42 
43 	*cs++ = GSC_FW_LOAD;
44 	*cs++ = lower_32_bits(offset);
45 	*cs++ = upper_32_bits(offset);
46 	*cs++ = (gsc->local->size / SZ_4K) | HECI1_FW_LIMIT_VALID;
47 
48 	intel_ring_advance(rq, cs);
49 
50 	return 0;
51 }
52 
53 static int gsc_fw_load(struct intel_gsc_uc *gsc)
54 {
55 	struct intel_context *ce = gsc->ce;
56 	struct i915_request *rq;
57 	int err;
58 
59 	if (!ce)
60 		return -ENODEV;
61 
62 	rq = i915_request_create(ce);
63 	if (IS_ERR(rq))
64 		return PTR_ERR(rq);
65 
66 	if (ce->engine->emit_init_breadcrumb) {
67 		err = ce->engine->emit_init_breadcrumb(rq);
68 		if (err)
69 			goto out_rq;
70 	}
71 
72 	err = emit_gsc_fw_load(rq, gsc);
73 	if (err)
74 		goto out_rq;
75 
76 	err = ce->engine->emit_flush(rq, 0);
77 
78 out_rq:
79 	i915_request_get(rq);
80 
81 	if (unlikely(err))
82 		i915_request_set_error_once(rq, err);
83 
84 	i915_request_add(rq);
85 
86 	if (!err && i915_request_wait(rq, 0, msecs_to_jiffies(500)) < 0)
87 		err = -ETIME;
88 
89 	i915_request_put(rq);
90 
91 	if (err)
92 		gt_err(gsc_uc_to_gt(gsc), "Request submission for GSC load failed %pe\n",
93 		       ERR_PTR(err));
94 
95 	return err;
96 }
97 
98 static int gsc_fw_load_prepare(struct intel_gsc_uc *gsc)
99 {
100 	struct intel_gt *gt = gsc_uc_to_gt(gsc);
101 	struct drm_i915_private *i915 = gt->i915;
102 	struct drm_i915_gem_object *obj;
103 	void *src, *dst;
104 
105 	if (!gsc->local)
106 		return -ENODEV;
107 
108 	obj = gsc->local->obj;
109 
110 	if (obj->base.size < gsc->fw.size)
111 		return -ENOSPC;
112 
113 	dst = i915_gem_object_pin_map_unlocked(obj,
114 					       i915_coherent_map_type(i915, obj, true));
115 	if (IS_ERR(dst))
116 		return PTR_ERR(dst);
117 
118 	src = i915_gem_object_pin_map_unlocked(gsc->fw.obj,
119 					       i915_coherent_map_type(i915, gsc->fw.obj, true));
120 	if (IS_ERR(src)) {
121 		i915_gem_object_unpin_map(obj);
122 		return PTR_ERR(src);
123 	}
124 
125 	memset(dst, 0, obj->base.size);
126 	memcpy(dst, src, gsc->fw.size);
127 
128 	i915_gem_object_unpin_map(gsc->fw.obj);
129 	i915_gem_object_unpin_map(obj);
130 
131 	return 0;
132 }
133 
134 static int gsc_fw_wait(struct intel_gt *gt)
135 {
136 	return intel_wait_for_register(gt->uncore,
137 				       GSC_FW_STATUS_REG,
138 				       GSC_FW_INIT_COMPLETE_BIT,
139 				       GSC_FW_INIT_COMPLETE_BIT,
140 				       500);
141 }
142 
143 int intel_gsc_uc_fw_upload(struct intel_gsc_uc *gsc)
144 {
145 	struct intel_gt *gt = gsc_uc_to_gt(gsc);
146 	struct intel_uc_fw *gsc_fw = &gsc->fw;
147 	int err;
148 
149 	/* check current fw status */
150 	if (intel_gsc_uc_fw_init_done(gsc)) {
151 		if (GEM_WARN_ON(!intel_uc_fw_is_loaded(gsc_fw)))
152 			intel_uc_fw_change_status(gsc_fw, INTEL_UC_FIRMWARE_TRANSFERRED);
153 		return -EEXIST;
154 	}
155 
156 	if (!intel_uc_fw_is_loadable(gsc_fw))
157 		return -ENOEXEC;
158 
159 	/* FW blob is ok, so clean the status */
160 	intel_uc_fw_sanitize(&gsc->fw);
161 
162 	if (!gsc_is_in_reset(gt->uncore))
163 		return -EIO;
164 
165 	err = gsc_fw_load_prepare(gsc);
166 	if (err)
167 		goto fail;
168 
169 	/*
170 	 * GSC is only killed by an FLR, so we need to trigger one on unload to
171 	 * make sure we stop it. This is because we assign a chunk of memory to
172 	 * the GSC as part of the FW load , so we need to make sure it stops
173 	 * using it when we release it to the system on driver unload. Note that
174 	 * this is not a problem of the unload per-se, because the GSC will not
175 	 * touch that memory unless there are requests for it coming from the
176 	 * driver; therefore, no accesses will happen while i915 is not loaded,
177 	 * but if we re-load the driver then the GSC might wake up and try to
178 	 * access that old memory location again.
179 	 * Given that an FLR is a very disruptive action (see the FLR function
180 	 * for details), we want to do it as the last action before releasing
181 	 * the access to the MMIO bar, which means we need to do it as part of
182 	 * the primary uncore cleanup.
183 	 * An alternative approach to the FLR would be to use a memory location
184 	 * that survives driver unload, like e.g. stolen memory, and keep the
185 	 * GSC loaded across reloads. However, this requires us to make sure we
186 	 * preserve that memory location on unload and then determine and
187 	 * reserve its offset on each subsequent load, which is not trivial, so
188 	 * it is easier to just kill everything and start fresh.
189 	 */
190 	intel_uncore_set_flr_on_fini(&gt->i915->uncore);
191 
192 	err = gsc_fw_load(gsc);
193 	if (err)
194 		goto fail;
195 
196 	err = gsc_fw_wait(gt);
197 	if (err)
198 		goto fail;
199 
200 	/* FW is not fully operational until we enable SW proxy */
201 	intel_uc_fw_change_status(gsc_fw, INTEL_UC_FIRMWARE_TRANSFERRED);
202 
203 	gt_info(gt, "Loaded GSC firmware %s\n", gsc_fw->file_selected.path);
204 
205 	return 0;
206 
207 fail:
208 	return intel_uc_fw_mark_load_failed(gsc_fw, err);
209 }
210