1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023 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_ring.h"
10 #include "intel_gsc_uc_heci_cmd_submit.h"
11 
12 struct gsc_heci_pkt {
13 	u64 addr_in;
14 	u32 size_in;
15 	u64 addr_out;
16 	u32 size_out;
17 };
18 
19 static int emit_gsc_heci_pkt(struct i915_request *rq, struct gsc_heci_pkt *pkt)
20 {
21 	u32 *cs;
22 
23 	cs = intel_ring_begin(rq, 8);
24 	if (IS_ERR(cs))
25 		return PTR_ERR(cs);
26 
27 	*cs++ = GSC_HECI_CMD_PKT;
28 	*cs++ = lower_32_bits(pkt->addr_in);
29 	*cs++ = upper_32_bits(pkt->addr_in);
30 	*cs++ = pkt->size_in;
31 	*cs++ = lower_32_bits(pkt->addr_out);
32 	*cs++ = upper_32_bits(pkt->addr_out);
33 	*cs++ = pkt->size_out;
34 	*cs++ = 0;
35 
36 	intel_ring_advance(rq, cs);
37 
38 	return 0;
39 }
40 
41 int intel_gsc_uc_heci_cmd_submit_packet(struct intel_gsc_uc *gsc, u64 addr_in,
42 					u32 size_in, u64 addr_out,
43 					u32 size_out)
44 {
45 	struct intel_context *ce = gsc->ce;
46 	struct i915_request *rq;
47 	struct gsc_heci_pkt pkt = {
48 	.addr_in = addr_in,
49 	.size_in = size_in,
50 	.addr_out = addr_out,
51 	.size_out = size_out
52 	};
53 	int err;
54 
55 	if (!ce)
56 		return -ENODEV;
57 
58 	rq = i915_request_create(ce);
59 	if (IS_ERR(rq))
60 		return PTR_ERR(rq);
61 
62 	if (ce->engine->emit_init_breadcrumb) {
63 		err = ce->engine->emit_init_breadcrumb(rq);
64 		if (err)
65 			goto out_rq;
66 	}
67 
68 	err = emit_gsc_heci_pkt(rq, &pkt);
69 
70 	if (err)
71 		goto out_rq;
72 
73 	err = ce->engine->emit_flush(rq, 0);
74 
75 out_rq:
76 	i915_request_get(rq);
77 
78 	if (unlikely(err))
79 		i915_request_set_error_once(rq, err);
80 
81 	i915_request_add(rq);
82 
83 	if (!err && i915_request_wait(rq, 0, msecs_to_jiffies(500)) < 0)
84 		err = -ETIME;
85 
86 	i915_request_put(rq);
87 
88 	if (err)
89 		drm_err(&gsc_uc_to_gt(gsc)->i915->drm,
90 			"Request submission for GSC heci cmd failed (%d)\n",
91 			err);
92 
93 	return err;
94 }
95 
96 void intel_gsc_uc_heci_cmd_emit_mtl_header(struct intel_gsc_mtl_header *header,
97 					   u8 heci_client_id, u32 message_size,
98 					   u64 host_session_id)
99 {
100 	host_session_id &= ~HOST_SESSION_MASK;
101 	if (heci_client_id == HECI_MEADDRESS_PXP)
102 		host_session_id |= HOST_SESSION_PXP_SINGLE;
103 
104 	header->validity_marker = GSC_HECI_VALIDITY_MARKER;
105 	header->heci_client_id = heci_client_id;
106 	header->host_session_handle = host_session_id;
107 	header->header_version = MTL_GSC_HEADER_VERSION;
108 	header->message_size = message_size;
109 }
110