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