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