1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 #include <sys/types.h>
4 #include <sys/sysctl.h>
5 #include <sys/systm.h>
6 #include "adf_accel_devices.h"
7 #include "adf_cfg.h"
8 #include "adf_cfg_sysctl.h"
9 #include "adf_cfg_device.h"
10 #include "adf_common_drv.h"
11 #include <sys/mutex.h>
12 #include <sys/sbuf.h>
13
14 #define ADF_CFG_SYSCTL_BUF_SZ ADF_CFG_MAX_VAL
15 #define ADF_CFG_UP_STR "up"
16 #define ADF_CFG_DOWN_STR "down"
17
18 #define ADF_CFG_MAX_USER_PROCESSES 64
19
20 static int
adf_cfg_down(struct adf_accel_dev * accel_dev)21 adf_cfg_down(struct adf_accel_dev *accel_dev)
22 {
23 int ret = 0;
24
25 if (!adf_dev_started(accel_dev)) {
26 device_printf(GET_DEV(accel_dev),
27 "Device qat_dev%d already down\n",
28 accel_dev->accel_id);
29 return 0;
30 }
31
32 if (adf_dev_in_use(accel_dev)) {
33 pr_err("QAT: Device %d in use\n", accel_dev->accel_id);
34 goto out;
35 }
36
37 if (adf_dev_stop(accel_dev)) {
38 device_printf(GET_DEV(accel_dev),
39 "Failed to stop qat_dev%d\n",
40 accel_dev->accel_id);
41 ret = EFAULT;
42 goto out;
43 }
44
45 adf_dev_shutdown(accel_dev);
46
47 out:
48 return ret;
49 }
50
51 static int
adf_cfg_up(struct adf_accel_dev * accel_dev)52 adf_cfg_up(struct adf_accel_dev *accel_dev)
53 {
54 int ret;
55
56 if (adf_dev_started(accel_dev))
57 return 0;
58
59 if (NULL == accel_dev->hw_device->config_device)
60 return ENXIO;
61
62 ret = accel_dev->hw_device->config_device(accel_dev);
63 if (ret) {
64 device_printf(GET_DEV(accel_dev),
65 "Failed to start qat_dev%d\n",
66 accel_dev->accel_id);
67 return ret;
68 }
69
70 ret = adf_dev_init(accel_dev);
71 if (!ret)
72 ret = adf_dev_start(accel_dev);
73
74 if (ret) {
75 device_printf(GET_DEV(accel_dev),
76 "Failed to start qat_dev%d\n",
77 accel_dev->accel_id);
78 adf_dev_stop(accel_dev);
79 adf_dev_shutdown(accel_dev);
80 }
81
82 if (!ret) {
83 struct adf_cfg_device *cfg_dev = NULL;
84
85 cfg_dev = accel_dev->cfg->dev;
86 adf_cfg_device_clear(cfg_dev, accel_dev);
87 free(cfg_dev, M_QAT);
88 accel_dev->cfg->dev = NULL;
89 }
90
91 return 0;
92 }
93
94 static const char *const cfg_serv[] =
95 { "sym;asym", "sym", "asym", "dc", "sym;dc", "asym;dc", "cy", "cy;dc" };
96
97 static const char *const cfg_mode[] = { "ks;us", "us", "ks" };
98
adf_cfg_sysctl_services_handle(SYSCTL_HANDLER_ARGS)99 static int adf_cfg_sysctl_services_handle(SYSCTL_HANDLER_ARGS)
100 {
101 struct adf_cfg_device_data *dev_cfg_data;
102 struct adf_accel_dev *accel_dev;
103 char buf[ADF_CFG_SYSCTL_BUF_SZ];
104 unsigned int len;
105 int ret = 0;
106 int i = 0;
107
108 accel_dev = arg1;
109 if (!accel_dev)
110 return ENXIO;
111
112 dev_cfg_data = accel_dev->cfg;
113 if (!dev_cfg_data)
114 return ENXIO;
115
116 strlcpy(buf, dev_cfg_data->cfg_services, sizeof(buf));
117
118 ret = sysctl_handle_string(oidp, buf, sizeof(buf), req);
119 if (ret != 0 || req->newptr == NULL)
120 return ret;
121
122 /* Handle config change */
123 if (adf_dev_started(accel_dev)) {
124 device_printf(
125 GET_DEV(accel_dev),
126 "QAT: configuration could be changed in down state only\n");
127 return EINVAL;
128 }
129
130 len = strlen(buf);
131
132 for (i = 0; i < ARRAY_SIZE(cfg_serv); i++) {
133 if ((len > 0 && strncasecmp(cfg_serv[i], buf, len) == 0)) {
134 strlcpy(dev_cfg_data->cfg_services,
135 buf,
136 ADF_CFG_MAX_VAL);
137 break;
138 }
139 }
140
141 if (i == ARRAY_SIZE(cfg_serv)) {
142 device_printf(GET_DEV(accel_dev),
143 "Unknown service configuration\n");
144 ret = EINVAL;
145 }
146
147 return ret;
148 }
149
adf_cfg_sysctl_mode_handle(SYSCTL_HANDLER_ARGS)150 static int adf_cfg_sysctl_mode_handle(SYSCTL_HANDLER_ARGS)
151 {
152 struct adf_cfg_device_data *dev_cfg_data;
153 struct adf_accel_dev *accel_dev;
154 char buf[ADF_CFG_SYSCTL_BUF_SZ];
155 unsigned int len;
156 int ret = 0;
157 int i = 0;
158
159 accel_dev = arg1;
160 if (!accel_dev)
161 return ENXIO;
162
163 dev_cfg_data = accel_dev->cfg;
164 if (!dev_cfg_data)
165 return ENXIO;
166
167 strlcpy(buf, dev_cfg_data->cfg_mode, sizeof(buf));
168
169 ret = sysctl_handle_string(oidp, buf, sizeof(buf), req);
170 if (ret != 0 || req->newptr == NULL)
171 return ret;
172
173 /* Handle config change */
174 if (adf_dev_started(accel_dev)) {
175 device_printf(
176 GET_DEV(accel_dev),
177 "QAT: configuration could be changed in down state only\n");
178 return EBUSY;
179 }
180
181 len = strlen(buf);
182
183 for (i = 0; i < ARRAY_SIZE(cfg_mode); i++) {
184 if ((len > 0 && strncasecmp(cfg_mode[i], buf, len) == 0)) {
185 strlcpy(dev_cfg_data->cfg_mode, buf, ADF_CFG_MAX_VAL);
186 break;
187 }
188 }
189
190 if (i == ARRAY_SIZE(cfg_mode)) {
191 device_printf(GET_DEV(accel_dev),
192 "Unknown configuration mode\n");
193 ret = EINVAL;
194 }
195
196 return ret;
197 }
198
adf_cfg_sysctl_handle(SYSCTL_HANDLER_ARGS)199 static int adf_cfg_sysctl_handle(SYSCTL_HANDLER_ARGS)
200 {
201 struct adf_cfg_device_data *dev_cfg_data;
202 struct adf_accel_dev *accel_dev;
203 char buf[ADF_CFG_SYSCTL_BUF_SZ] = { 0 };
204 unsigned int len;
205 int ret = 0;
206
207 accel_dev = arg1;
208 if (!accel_dev)
209 return ENXIO;
210
211 dev_cfg_data = accel_dev->cfg;
212 if (!dev_cfg_data)
213 return ENXIO;
214
215 if (adf_dev_started(accel_dev)) {
216 strlcpy(buf, ADF_CFG_UP_STR, sizeof(buf));
217 } else {
218 strlcpy(buf, ADF_CFG_DOWN_STR, sizeof(buf));
219 }
220
221 ret = sysctl_handle_string(oidp, buf, sizeof(buf), req);
222 if (ret != 0 || req->newptr == NULL)
223 return ret;
224
225 len = strlen(buf);
226
227 if ((len > 0 && strncasecmp(ADF_CFG_UP_STR, buf, len) == 0)) {
228 ret = adf_cfg_up(accel_dev);
229
230 } else if (len > 0 && strncasecmp(ADF_CFG_DOWN_STR, buf, len) == 0) {
231 ret = adf_cfg_down(accel_dev);
232
233 } else {
234 device_printf(GET_DEV(accel_dev), "QAT: Invalid operation\n");
235 ret = EINVAL;
236 }
237
238 return ret;
239 }
240
adf_cfg_sysctl_num_processes_handle(SYSCTL_HANDLER_ARGS)241 static int adf_cfg_sysctl_num_processes_handle(SYSCTL_HANDLER_ARGS)
242 {
243 struct adf_cfg_device_data *dev_cfg_data;
244 struct adf_accel_dev *accel_dev;
245 uint32_t num_user_processes = 0;
246 int ret = 0;
247
248 accel_dev = arg1;
249 if (!accel_dev)
250 return ENXIO;
251
252 dev_cfg_data = accel_dev->cfg;
253 if (!dev_cfg_data)
254 return ENXIO;
255
256 num_user_processes = dev_cfg_data->num_user_processes;
257
258 ret = sysctl_handle_int(oidp, &num_user_processes, 0, req);
259 if (ret != 0 || req->newptr == NULL)
260 return ret;
261
262 if (adf_dev_started(accel_dev)) {
263 device_printf(
264 GET_DEV(accel_dev),
265 "QAT: configuration could be changed in down state only\n");
266 return EBUSY;
267 }
268
269 if (num_user_processes > ADF_CFG_MAX_USER_PROCESSES) {
270 return EINVAL;
271 }
272
273 dev_cfg_data->num_user_processes = num_user_processes;
274
275 return ret;
276 }
277
278 int
adf_cfg_sysctl_add(struct adf_accel_dev * accel_dev)279 adf_cfg_sysctl_add(struct adf_accel_dev *accel_dev)
280 {
281 struct sysctl_ctx_list *qat_sysctl_ctx;
282 struct sysctl_oid *qat_sysctl_tree;
283
284 if (!accel_dev)
285 return EINVAL;
286
287 qat_sysctl_ctx =
288 device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev);
289 qat_sysctl_tree =
290 device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev);
291
292 SYSCTL_ADD_PROC(qat_sysctl_ctx,
293 SYSCTL_CHILDREN(qat_sysctl_tree),
294 OID_AUTO,
295 "state",
296 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
297 accel_dev,
298 0,
299 adf_cfg_sysctl_handle,
300 "A",
301 "QAT State");
302
303 SYSCTL_ADD_PROC(qat_sysctl_ctx,
304 SYSCTL_CHILDREN(qat_sysctl_tree),
305 OID_AUTO,
306 "cfg_services",
307 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
308 accel_dev,
309 0,
310 adf_cfg_sysctl_services_handle,
311 "A",
312 "QAT services confguration");
313
314 SYSCTL_ADD_PROC(qat_sysctl_ctx,
315 SYSCTL_CHILDREN(qat_sysctl_tree),
316 OID_AUTO,
317 "cfg_mode",
318 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
319 accel_dev,
320 0,
321 adf_cfg_sysctl_mode_handle,
322 "A",
323 "QAT mode configuration");
324
325 SYSCTL_ADD_PROC(qat_sysctl_ctx,
326 SYSCTL_CHILDREN(qat_sysctl_tree),
327 OID_AUTO,
328 "num_user_processes",
329 CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
330 accel_dev,
331 0,
332 adf_cfg_sysctl_num_processes_handle,
333 "I",
334 "QAT user processes number ");
335
336 return 0;
337 }
338
339 void
adf_cfg_sysctl_remove(struct adf_accel_dev * accel_dev)340 adf_cfg_sysctl_remove(struct adf_accel_dev *accel_dev)
341 {
342 }
343