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
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 int
adf_vf2pf_get_capabilities(struct adf_accel_dev * accel_dev)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
adf_vf2pf_get_ring_to_svc(struct adf_accel_dev * accel_dev)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