xref: /linux/drivers/net/ethernet/intel/ixd/ixd_virtchnl.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
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