xref: /freebsd/sys/dev/qat/qat_common/adf_pfvf_vf_msg.c (revision 525fe93dc7487a1e63a90f6a2b956abc601963c1)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 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
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
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
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 int
102 adf_vf2pf_get_capabilities(struct adf_accel_dev *accel_dev)
103 {
104 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
105 	struct capabilities_v3 cap_msg = { 0 };
106 	unsigned int len = sizeof(cap_msg);
107 
108 	if (accel_dev->u1.vf.pf_compat_ver < ADF_PFVF_COMPAT_CAPABILITIES)
109 		/* The PF is too old to support the extended capabilities */
110 		return 0;
111 
112 	if (adf_send_vf2pf_blkmsg_req(accel_dev,
113 				      ADF_VF2PF_BLKMSG_REQ_CAP_SUMMARY,
114 				      (u8 *)&cap_msg,
115 				      &len)) {
116 		device_printf(GET_DEV(accel_dev),
117 			      "QAT: Failed to get block message response\n");
118 		return -EFAULT;
119 	}
120 
121 	switch (cap_msg.hdr.version) {
122 	default:
123 		/* Newer version received, handle only the know parts */
124 		fallthrough;
125 	case ADF_PFVF_CAPABILITIES_V3_VERSION:
126 		if (likely(len >= sizeof(struct capabilities_v3)))
127 			hw_data->clock_frequency = cap_msg.frequency;
128 		else
129 			device_printf(GET_DEV(accel_dev),
130 				      "Could not get frequency");
131 		fallthrough;
132 	case ADF_PFVF_CAPABILITIES_V2_VERSION:
133 		if (likely(len >= sizeof(struct capabilities_v2))) {
134 			hw_data->accel_capabilities_mask = cap_msg.capabilities;
135 		} else {
136 			device_printf(GET_DEV(accel_dev),
137 				      "Could not get capabilities");
138 		}
139 		fallthrough;
140 	case ADF_PFVF_CAPABILITIES_V1_VERSION:
141 		if (likely(len >= sizeof(struct capabilities_v1))) {
142 			hw_data->extended_dc_capabilities = cap_msg.ext_dc_caps;
143 		} else {
144 			device_printf(
145 			    GET_DEV(accel_dev),
146 			    "Capabilities message truncated to %d bytes\n",
147 			    len);
148 			return -EFAULT;
149 		}
150 	}
151 
152 	return 0;
153 }
154 
155 int
156 adf_vf2pf_get_ring_to_svc(struct adf_accel_dev *accel_dev)
157 {
158 	struct ring_to_svc_map_v1 rts_map_msg = { 0 };
159 	unsigned int len = sizeof(rts_map_msg);
160 
161 	if (accel_dev->u1.vf.pf_compat_ver < ADF_PFVF_COMPAT_RING_TO_SVC_MAP)
162 		/* Use already set default mappings */
163 		return 0;
164 
165 	if (adf_send_vf2pf_blkmsg_req(accel_dev,
166 				      ADF_VF2PF_BLKMSG_REQ_RING_SVC_MAP,
167 				      (u8 *)&rts_map_msg,
168 				      &len)) {
169 		device_printf(GET_DEV(accel_dev),
170 			      "QAT: Failed to get block message response\n");
171 		return -EFAULT;
172 	}
173 
174 	if (unlikely(len < sizeof(struct ring_to_svc_map_v1))) {
175 		device_printf(GET_DEV(accel_dev),
176 			      "RING_TO_SVC message truncated to %d bytes\n",
177 			      len);
178 		return -EFAULT;
179 	}
180 
181 	/* Only v1 at present */
182 	accel_dev->hw_device->ring_to_svc_map = rts_map_msg.map;
183 	return 0;
184 }
185