xref: /freebsd/sys/dev/qat/qat_common/adf_cfg_sysctl.c (revision 8aa51e6d7de0a828020de64560d1385e15955a1c)
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