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