1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (C) 2025 Intel Corporation */
3
4 #include "ixd.h"
5 #include "ixd_ctlq.h"
6 #include "ixd_virtchnl.h"
7
8 /**
9 * ixd_vc_recv_event_msg - Handle virtchnl event message
10 * @adapter: The adapter handling the message
11 * @ctlq_msg: Message received
12 */
ixd_vc_recv_event_msg(struct ixd_adapter * adapter,struct libie_ctlq_msg * ctlq_msg)13 void ixd_vc_recv_event_msg(struct ixd_adapter *adapter,
14 struct libie_ctlq_msg *ctlq_msg)
15 {
16 int payload_size = ctlq_msg->data_len;
17 struct virtchnl2_event *v2e;
18
19 if (payload_size < sizeof(*v2e)) {
20 dev_warn_ratelimited(ixd_to_dev(adapter),
21 "Failed to receive valid payload for event msg (op 0x%X len %u)\n",
22 ctlq_msg->chnl_opcode,
23 payload_size);
24 return;
25 }
26
27 v2e = (struct virtchnl2_event *)ctlq_msg->recv_mem.iov_base;
28
29 dev_dbg(ixd_to_dev(adapter), "Got event 0x%X from the CP\n",
30 le32_to_cpu(v2e->event));
31 }
32
33 /**
34 * ixd_vc_can_handle_msg - Decide if an event has to be handled by virtchnl code
35 * @ctlq_msg: Message received
36 *
37 * Return: %true if virtchnl code can handle the event, %false otherwise
38 */
ixd_vc_can_handle_msg(struct libie_ctlq_msg * ctlq_msg)39 bool ixd_vc_can_handle_msg(struct libie_ctlq_msg *ctlq_msg)
40 {
41 return ctlq_msg->chnl_opcode == VIRTCHNL2_OP_EVENT;
42 }
43
44 /**
45 * ixd_handle_caps - Handle VIRTCHNL2_OP_GET_CAPS response
46 * @adapter: The adapter for which the capabilities are being updated
47 * @recv_buff: Buffer containing the response
48 * @recv_size: Response buffer size
49 * @ctx: unused
50 *
51 * Return: %0 if the response format is correct and was handled as expected,
52 * negative error otherwise.
53 */
ixd_handle_caps(struct ixd_adapter * adapter,void * recv_buff,size_t recv_size,void * ctx)54 static int ixd_handle_caps(struct ixd_adapter *adapter, void *recv_buff,
55 size_t recv_size, void *ctx)
56 {
57 if (recv_size < sizeof(adapter->caps))
58 return -EBADMSG;
59
60 adapter->caps = *(typeof(adapter->caps) *)recv_buff;
61
62 return 0;
63 }
64
65 /**
66 * ixd_req_vc_caps - Request and save device capability
67 * @adapter: The adapter to get the capabilities for
68 *
69 * Return: success or error if sending the get capability message fails
70 */
ixd_req_vc_caps(struct ixd_adapter * adapter)71 static int ixd_req_vc_caps(struct ixd_adapter *adapter)
72 {
73 const struct ixd_ctlq_req req = {
74 .opcode = VIRTCHNL2_OP_GET_CAPS,
75 .send_size = sizeof(struct virtchnl2_get_capabilities),
76 .ctx = NULL,
77 .send_buff_init = NULL,
78 .recv_process = ixd_handle_caps,
79 };
80
81 return ixd_ctlq_do_req(adapter, &req);
82 }
83
84 /**
85 * ixd_get_vc_ver - Get version info from adapter
86 *
87 * Return: filled in virtchannel2 version info, ready for sending
88 */
ixd_get_vc_ver(void)89 static struct virtchnl2_version_info ixd_get_vc_ver(void)
90 {
91 return (struct virtchnl2_version_info) {
92 .major = cpu_to_le32(VIRTCHNL2_VERSION_MAJOR_2),
93 .minor = cpu_to_le32(VIRTCHNL2_VERSION_MINOR_0),
94 };
95 }
96
ixd_fill_vc_ver(struct ixd_adapter * adapter,void * send_buff,void * ctx)97 static void ixd_fill_vc_ver(struct ixd_adapter *adapter, void *send_buff,
98 void *ctx)
99 {
100 *(struct virtchnl2_version_info *)send_buff = ixd_get_vc_ver();
101 }
102
103 /**
104 * ixd_handle_vc_ver - Handle VIRTCHNL2_OP_VERSION response
105 * @adapter: The adapter for which the version is being updated
106 * @recv_buff: Buffer containing the response
107 * @recv_size: Response buffer size
108 * @ctx: Unused
109 *
110 * Return: %0 if the response format is correct and was handled as expected,
111 * negative error otherwise.
112 */
ixd_handle_vc_ver(struct ixd_adapter * adapter,void * recv_buff,size_t recv_size,void * ctx)113 static int ixd_handle_vc_ver(struct ixd_adapter *adapter, void *recv_buff,
114 size_t recv_size, void *ctx)
115 {
116 struct virtchnl2_version_info need_ver = ixd_get_vc_ver();
117 struct virtchnl2_version_info *recv_ver;
118
119 if (recv_size < sizeof(need_ver))
120 return -EBADMSG;
121
122 recv_ver = recv_buff;
123 if (le32_to_cpu(need_ver.major) != le32_to_cpu(recv_ver->major) ||
124 le32_to_cpu(need_ver.minor) != le32_to_cpu(recv_ver->minor))
125 dev_warn(ixd_to_dev(adapter),
126 "Virtchnl version does not match (expected %u.%u, received %u.%u)\n",
127 le32_to_cpu(need_ver.major),
128 le32_to_cpu(need_ver.minor),
129 le32_to_cpu(recv_ver->major),
130 le32_to_cpu(recv_ver->minor));
131
132 if (le32_to_cpu(need_ver.major) != le32_to_cpu(recv_ver->major)) {
133 dev_err(ixd_to_dev(adapter),
134 "Device initialization failed due to virtchnl major version mismatch\n");
135 return -EOPNOTSUPP;
136 }
137
138 adapter->vc_ver.major = le32_to_cpu(recv_ver->major);
139 adapter->vc_ver.minor = le32_to_cpu(recv_ver->minor);
140
141 return 0;
142 }
143
144 /**
145 * ixd_req_vc_version - Request and save Virtchannel2 version
146 * @adapter: The adapter to get the version for
147 *
148 * Return: success or error if sending fails or the response was not as expected
149 */
ixd_req_vc_version(struct ixd_adapter * adapter)150 static int ixd_req_vc_version(struct ixd_adapter *adapter)
151 {
152 const struct ixd_ctlq_req req = {
153 .opcode = VIRTCHNL2_OP_VERSION,
154 .send_size = sizeof(struct virtchnl2_version_info),
155 .ctx = NULL,
156 .send_buff_init = ixd_fill_vc_ver,
157 .recv_process = ixd_handle_vc_ver,
158 };
159
160 return ixd_ctlq_do_req(adapter, &req);
161 }
162
163 /**
164 * ixd_vc_dev_init - virtchnl device core initialization
165 * @adapter: device information
166 *
167 * Return: %0 on success or error if any step of the initialization fails
168 */
ixd_vc_dev_init(struct ixd_adapter * adapter)169 int ixd_vc_dev_init(struct ixd_adapter *adapter)
170 {
171 int err;
172
173 err = ixd_req_vc_version(adapter);
174 if (err) {
175 dev_warn(ixd_to_dev(adapter),
176 "Getting virtchnl version failed, error=%pe\n",
177 ERR_PTR(err));
178 return err;
179 }
180
181 err = ixd_req_vc_caps(adapter);
182 if (err) {
183 dev_warn(ixd_to_dev(adapter),
184 "Getting virtchnl capabilities failed, error=%pe\n",
185 ERR_PTR(err));
186 return err;
187 }
188
189 return err;
190 }
191