xref: /freebsd/sys/dev/qat/qat_common/adf_pfvf_vf_msg.c (revision ded037e65e5239671b1292ec987a2e0894b217b5)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2025 Intel Corporation */
3 #include <linux/bitfield.h>
4 #include "adf_accel_devices.h"
5 #include "adf_common_drv.h"
6 #include "adf_pfvf_msg.h"
7 #include "adf_pfvf_vf_msg.h"
8 #include "adf_pfvf_vf_proto.h"
9 
10 /**
11  * adf_vf2pf_notify_init() - send init msg to PF
12  * @accel_dev:  Pointer to acceleration VF device.
13  *
14  * Function sends an init message from the VF to a PF
15  *
16  * Return: 0 on success, error code otherwise.
17  */
18 int
adf_vf2pf_notify_init(struct adf_accel_dev * accel_dev)19 adf_vf2pf_notify_init(struct adf_accel_dev *accel_dev)
20 {
21 	struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_INIT };
22 
23 	if (adf_send_vf2pf_msg(accel_dev, msg)) {
24 		device_printf(GET_DEV(accel_dev),
25 			      "Failed to send Init event to PF\n");
26 		return -EFAULT;
27 	}
28 	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
29 	return 0;
30 }
31 
32 /**
33  * adf_vf2pf_notify_shutdown() - send shutdown msg to PF
34  * @accel_dev:  Pointer to acceleration VF device.
35  *
36  * Function sends a shutdown message from the VF to a PF
37  *
38  * Return: void
39  */
40 void
adf_vf2pf_notify_shutdown(struct adf_accel_dev * accel_dev)41 adf_vf2pf_notify_shutdown(struct adf_accel_dev *accel_dev)
42 {
43 	struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_SHUTDOWN };
44 
45 	if (test_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status))
46 		if (adf_send_vf2pf_msg(accel_dev, msg))
47 			device_printf(GET_DEV(accel_dev),
48 				      "Failed to send Shutdown event to PF\n");
49 }
50 
51 int
adf_vf2pf_request_version(struct adf_accel_dev * accel_dev)52 adf_vf2pf_request_version(struct adf_accel_dev *accel_dev)
53 {
54 	u8 pf_version;
55 	int compat;
56 	int ret;
57 	struct pfvf_message resp;
58 	struct pfvf_message msg = {
59 		.type = ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ,
60 		.data = ADF_PFVF_COMPAT_THIS_VERSION,
61 	};
62 
63 	BUILD_BUG_ON(ADF_PFVF_COMPAT_THIS_VERSION > 255);
64 
65 	ret = adf_send_vf2pf_req(accel_dev, msg, &resp);
66 	if (ret) {
67 		device_printf(
68 		    GET_DEV(accel_dev),
69 		    "Failed to send Compatibility Version Request.\n");
70 		return ret;
71 	}
72 
73 	pf_version = FIELD_GET(ADF_PF2VF_VERSION_RESP_VERS_MASK, resp.data);
74 	compat = FIELD_GET(ADF_PF2VF_VERSION_RESP_RESULT_MASK, resp.data);
75 
76 	/* Response from PF received, check compatibility */
77 	switch (compat) {
78 	case ADF_PF2VF_VF_COMPATIBLE:
79 		break;
80 	case ADF_PF2VF_VF_COMPAT_UNKNOWN:
81 		/* VF is newer than PF - compatible for now */
82 		break;
83 	case ADF_PF2VF_VF_INCOMPATIBLE:
84 		device_printf(
85 		    GET_DEV(accel_dev),
86 		    "PF (vers %d) and VF (vers %d) are not compatible\n",
87 		    pf_version,
88 		    ADF_PFVF_COMPAT_THIS_VERSION);
89 		return -EINVAL;
90 	default:
91 		device_printf(
92 		    GET_DEV(accel_dev),
93 		    "Invalid response from PF; assume not compatible\n");
94 		return -EINVAL;
95 	}
96 
97 	accel_dev->u1.vf.pf_compat_ver = pf_version;
98 	return 0;
99 }
100 
101 void
adf_vf2pf_restarting_complete(struct adf_accel_dev * accel_dev)102 adf_vf2pf_restarting_complete(struct adf_accel_dev *accel_dev)
103 {
104 	struct pfvf_message msg = { .type =
105 					ADF_VF2PF_MSGTYPE_RESTARTING_COMPLETE };
106 
107 	if (accel_dev->u1.vf.pf_compat_ver < ADF_PFVF_COMPAT_FALLBACK)
108 		return;
109 
110 	if (adf_send_vf2pf_msg(accel_dev, msg)) {
111 		device_printf(
112 		    GET_DEV(accel_dev),
113 		    "Failed to send Restarting complete event to PF\n");
114 	}
115 }
116 
117 int
adf_vf2pf_get_capabilities(struct adf_accel_dev * accel_dev)118 adf_vf2pf_get_capabilities(struct adf_accel_dev *accel_dev)
119 {
120 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
121 	struct capabilities_v3 cap_msg = { 0 };
122 	unsigned int len = sizeof(cap_msg);
123 
124 	if (accel_dev->u1.vf.pf_compat_ver < ADF_PFVF_COMPAT_CAPABILITIES)
125 		/* The PF is too old to support the extended capabilities */
126 		return 0;
127 
128 	if (adf_send_vf2pf_blkmsg_req(accel_dev,
129 				      ADF_VF2PF_BLKMSG_REQ_CAP_SUMMARY,
130 				      (u8 *)&cap_msg,
131 				      &len)) {
132 		device_printf(GET_DEV(accel_dev),
133 			      "QAT: Failed to get block message response\n");
134 		return -EFAULT;
135 	}
136 
137 	switch (cap_msg.hdr.version) {
138 	default:
139 		/* Newer version received, handle only the know parts */
140 		fallthrough;
141 	case ADF_PFVF_CAPABILITIES_V3_VERSION:
142 		if (likely(len >= sizeof(struct capabilities_v3)))
143 			hw_data->clock_frequency = cap_msg.frequency;
144 		else
145 			device_printf(GET_DEV(accel_dev),
146 				      "Could not get frequency");
147 		fallthrough;
148 	case ADF_PFVF_CAPABILITIES_V2_VERSION:
149 		if (likely(len >= sizeof(struct capabilities_v2))) {
150 			hw_data->accel_capabilities_mask = cap_msg.capabilities;
151 		} else {
152 			device_printf(GET_DEV(accel_dev),
153 				      "Could not get capabilities");
154 		}
155 		fallthrough;
156 	case ADF_PFVF_CAPABILITIES_V1_VERSION:
157 		if (likely(len >= sizeof(struct capabilities_v1))) {
158 			hw_data->extended_dc_capabilities = cap_msg.ext_dc_caps;
159 		} else {
160 			device_printf(
161 			    GET_DEV(accel_dev),
162 			    "Capabilities message truncated to %d bytes\n",
163 			    len);
164 			return -EFAULT;
165 		}
166 	}
167 
168 	return 0;
169 }
170 
171 int
adf_vf2pf_get_ring_to_svc(struct adf_accel_dev * accel_dev)172 adf_vf2pf_get_ring_to_svc(struct adf_accel_dev *accel_dev)
173 {
174 	struct ring_to_svc_map_v1 rts_map_msg = { 0 };
175 	unsigned int len = sizeof(rts_map_msg);
176 
177 	if (accel_dev->u1.vf.pf_compat_ver < ADF_PFVF_COMPAT_RING_TO_SVC_MAP)
178 		/* Use already set default mappings */
179 		return 0;
180 
181 	if (adf_send_vf2pf_blkmsg_req(accel_dev,
182 				      ADF_VF2PF_BLKMSG_REQ_RING_SVC_MAP,
183 				      (u8 *)&rts_map_msg,
184 				      &len)) {
185 		device_printf(GET_DEV(accel_dev),
186 			      "QAT: Failed to get block message response\n");
187 		return -EFAULT;
188 	}
189 
190 	if (unlikely(len < sizeof(struct ring_to_svc_map_v1))) {
191 		device_printf(GET_DEV(accel_dev),
192 			      "RING_TO_SVC message truncated to %d bytes\n",
193 			      len);
194 		return -EFAULT;
195 	}
196 
197 	/* Only v1 at present */
198 	accel_dev->hw_device->ring_to_svc_map = rts_map_msg.map;
199 	accel_dev->hw_device->get_ring_to_svc_done = true;
200 
201 	return 0;
202 }
203