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