xref: /freebsd/sys/dev/qat/qat_common/adf_cfg_sysctl.c (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #include <sys/types.h>
5 #include <sys/sysctl.h>
6 #include <sys/systm.h>
7 #include "adf_accel_devices.h"
8 #include "adf_cfg.h"
9 #include "adf_cfg_sysctl.h"
10 #include "adf_cfg_device.h"
11 #include "adf_common_drv.h"
12 #include <sys/mutex.h>
13 #include <sys/sbuf.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
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
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 
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 	accel_dev = arg1;
110 	if (!accel_dev)
111 		return ENXIO;
112 
113 	dev_cfg_data = accel_dev->cfg;
114 	if (!dev_cfg_data)
115 		return ENXIO;
116 
117 	strlcpy(buf, dev_cfg_data->cfg_services, sizeof(buf));
118 
119 	ret = sysctl_handle_string(oidp, buf, sizeof(buf), req);
120 	if (ret != 0 || req->newptr == NULL)
121 		return ret;
122 
123 	/* Handle config change */
124 	if (adf_dev_started(accel_dev)) {
125 		device_printf(
126 		    GET_DEV(accel_dev),
127 		    "QAT: configuration could be changed in down state only\n");
128 		return EINVAL;
129 	}
130 
131 	len = strlen(buf);
132 
133 	for (i = 0; i < ARRAY_SIZE(cfg_serv); i++) {
134 		if ((len > 0 && strncasecmp(cfg_serv[i], buf, len) == 0)) {
135 			strlcpy(dev_cfg_data->cfg_services,
136 				buf,
137 				ADF_CFG_MAX_VAL);
138 			break;
139 		}
140 	}
141 
142 	if (i == ARRAY_SIZE(cfg_serv)) {
143 		device_printf(GET_DEV(accel_dev),
144 			      "Unknown service configuration\n");
145 		ret = EINVAL;
146 	}
147 
148 	return ret;
149 }
150 
151 static int adf_cfg_sysctl_mode_handle(SYSCTL_HANDLER_ARGS)
152 {
153 	struct adf_cfg_device_data *dev_cfg_data;
154 	struct adf_accel_dev *accel_dev;
155 	char buf[ADF_CFG_SYSCTL_BUF_SZ];
156 	unsigned int len;
157 	int ret = 0;
158 	int i = 0;
159 
160 	accel_dev = arg1;
161 	if (!accel_dev)
162 		return ENXIO;
163 
164 	dev_cfg_data = accel_dev->cfg;
165 	if (!dev_cfg_data)
166 		return ENXIO;
167 
168 	strlcpy(buf, dev_cfg_data->cfg_mode, sizeof(buf));
169 
170 	ret = sysctl_handle_string(oidp, buf, sizeof(buf), req);
171 	if (ret != 0 || req->newptr == NULL)
172 		return ret;
173 
174 	/* Handle config change */
175 	if (adf_dev_started(accel_dev)) {
176 		device_printf(
177 		    GET_DEV(accel_dev),
178 		    "QAT: configuration could be changed in down state only\n");
179 		return EBUSY;
180 	}
181 
182 	len = strlen(buf);
183 
184 	for (i = 0; i < ARRAY_SIZE(cfg_mode); i++) {
185 		if ((len > 0 && strncasecmp(cfg_mode[i], buf, len) == 0)) {
186 			strlcpy(dev_cfg_data->cfg_mode, buf, ADF_CFG_MAX_VAL);
187 			break;
188 		}
189 	}
190 
191 	if (i == ARRAY_SIZE(cfg_mode)) {
192 		device_printf(GET_DEV(accel_dev),
193 			      "Unknown configuration mode\n");
194 		ret = EINVAL;
195 	}
196 
197 	return ret;
198 }
199 
200 static int adf_cfg_sysctl_handle(SYSCTL_HANDLER_ARGS)
201 {
202 	struct adf_cfg_device_data *dev_cfg_data;
203 	struct adf_accel_dev *accel_dev;
204 	char buf[ADF_CFG_SYSCTL_BUF_SZ] = { 0 };
205 	unsigned int len;
206 	int ret = 0;
207 
208 	accel_dev = arg1;
209 	if (!accel_dev)
210 		return ENXIO;
211 
212 	dev_cfg_data = accel_dev->cfg;
213 	if (!dev_cfg_data)
214 		return ENXIO;
215 
216 	if (adf_dev_started(accel_dev)) {
217 		strlcpy(buf, ADF_CFG_UP_STR, sizeof(buf));
218 	} else {
219 		strlcpy(buf, ADF_CFG_DOWN_STR, sizeof(buf));
220 	}
221 
222 	ret = sysctl_handle_string(oidp, buf, sizeof(buf), req);
223 	if (ret != 0 || req->newptr == NULL)
224 		return ret;
225 
226 	len = strlen(buf);
227 
228 	if ((len > 0 && strncasecmp(ADF_CFG_UP_STR, buf, len) == 0)) {
229 		ret = adf_cfg_up(accel_dev);
230 
231 	} else if (len > 0 && strncasecmp(ADF_CFG_DOWN_STR, buf, len) == 0) {
232 		ret = adf_cfg_down(accel_dev);
233 
234 	} else {
235 		device_printf(GET_DEV(accel_dev), "QAT: Invalid operation\n");
236 		ret = EINVAL;
237 	}
238 
239 	return ret;
240 }
241 
242 static int adf_cfg_sysctl_num_processes_handle(SYSCTL_HANDLER_ARGS)
243 {
244 	struct adf_cfg_device_data *dev_cfg_data;
245 	struct adf_accel_dev *accel_dev;
246 	uint32_t num_user_processes = 0;
247 	int ret = 0;
248 
249 	accel_dev = arg1;
250 	if (!accel_dev)
251 		return ENXIO;
252 
253 	dev_cfg_data = accel_dev->cfg;
254 	if (!dev_cfg_data)
255 		return ENXIO;
256 
257 	num_user_processes = dev_cfg_data->num_user_processes;
258 
259 	ret = sysctl_handle_int(oidp, &num_user_processes, 0, req);
260 	if (ret != 0 || req->newptr == NULL)
261 		return ret;
262 
263 	if (adf_dev_started(accel_dev)) {
264 		device_printf(
265 		    GET_DEV(accel_dev),
266 		    "QAT: configuration could be changed in down state only\n");
267 		return EBUSY;
268 	}
269 
270 	if (num_user_processes > ADF_CFG_MAX_USER_PROCESSES) {
271 		return EINVAL;
272 	}
273 
274 	dev_cfg_data->num_user_processes = num_user_processes;
275 
276 	return ret;
277 }
278 
279 int
280 adf_cfg_sysctl_add(struct adf_accel_dev *accel_dev)
281 {
282 	struct sysctl_ctx_list *qat_sysctl_ctx;
283 	struct sysctl_oid *qat_sysctl_tree;
284 
285 	if (!accel_dev)
286 		return EINVAL;
287 
288 	qat_sysctl_ctx =
289 	    device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev);
290 	qat_sysctl_tree =
291 	    device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev);
292 
293 	SYSCTL_ADD_PROC(qat_sysctl_ctx,
294 			SYSCTL_CHILDREN(qat_sysctl_tree),
295 			OID_AUTO,
296 			"state",
297 			CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
298 			accel_dev,
299 			0,
300 			adf_cfg_sysctl_handle,
301 			"A",
302 			"QAT State");
303 
304 	SYSCTL_ADD_PROC(qat_sysctl_ctx,
305 			SYSCTL_CHILDREN(qat_sysctl_tree),
306 			OID_AUTO,
307 			"cfg_services",
308 			CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
309 			accel_dev,
310 			0,
311 			adf_cfg_sysctl_services_handle,
312 			"A",
313 			"QAT services confguration");
314 
315 	SYSCTL_ADD_PROC(qat_sysctl_ctx,
316 			SYSCTL_CHILDREN(qat_sysctl_tree),
317 			OID_AUTO,
318 			"cfg_mode",
319 			CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
320 			accel_dev,
321 			0,
322 			adf_cfg_sysctl_mode_handle,
323 			"A",
324 			"QAT mode configuration");
325 
326 	SYSCTL_ADD_PROC(qat_sysctl_ctx,
327 			SYSCTL_CHILDREN(qat_sysctl_tree),
328 			OID_AUTO,
329 			"num_user_processes",
330 			CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
331 			accel_dev,
332 			0,
333 			adf_cfg_sysctl_num_processes_handle,
334 			"I",
335 			"QAT user processes number ");
336 
337 	return 0;
338 }
339 
340 void
341 adf_cfg_sysctl_remove(struct adf_accel_dev *accel_dev)
342 {
343 }
344