xref: /freebsd/sys/dev/qat/qat_common/adf_cfg.c (revision fe75646a0234a261c0013bf1840fdac4acaf0cec)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 #include "adf_accel_devices.h"
4 #include "adf_cfg.h"
5 #include "adf_common_drv.h"
6 #include "adf_cfg_dev_dbg.h"
7 #include "adf_cfg_device.h"
8 #include "adf_cfg_sysctl.h"
9 #include "adf_heartbeat_dbg.h"
10 #include "adf_ver_dbg.h"
11 #include "adf_fw_counters.h"
12 #include "adf_cnvnr_freq_counters.h"
13 
14 /**
15  * adf_cfg_dev_add() - Create an acceleration device configuration table.
16  * @accel_dev:  Pointer to acceleration device.
17  *
18  * Function creates a configuration table for the given acceleration device.
19  * The table stores device specific config values.
20  * To be used by QAT device specific drivers.
21  *
22  * Return: 0 on success, error code otherwise.
23  */
24 int
25 adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
26 {
27 	struct adf_cfg_device_data *dev_cfg_data;
28 
29 	dev_cfg_data = malloc(sizeof(*dev_cfg_data), M_QAT, M_WAITOK | M_ZERO);
30 	INIT_LIST_HEAD(&dev_cfg_data->sec_list);
31 	sx_init(&dev_cfg_data->lock, "qat cfg data");
32 	accel_dev->cfg = dev_cfg_data;
33 
34 	/* Default device configuration initialization */
35 	if (!accel_dev->is_vf) {
36 
37 		if (IS_QAT_GEN4(pci_get_device(GET_DEV(accel_dev)))) {
38 			dev_cfg_data->num_user_processes =
39 			    ADF_CFG_STATIC_CONF_USER_PROCESSES_NUM;
40 
41 			strncpy(dev_cfg_data->cfg_mode,
42 				ADF_CFG_KERNEL_USER,
43 				ADF_CFG_MAX_VAL);
44 
45 			if (accel_dev->accel_id % 2 == 0) {
46 				strncpy(dev_cfg_data->cfg_services,
47 					ADF_CFG_SYM_ASYM,
48 					ADF_CFG_MAX_VAL);
49 			} else {
50 				strncpy(dev_cfg_data->cfg_services,
51 					ADF_CFG_DC,
52 					ADF_CFG_MAX_VAL);
53 			}
54 		} else {
55 			strncpy(dev_cfg_data->cfg_mode,
56 				ADF_CFG_KERNEL,
57 				ADF_CFG_MAX_VAL);
58 			dev_cfg_data->num_user_processes = 0;
59 			strncpy(dev_cfg_data->cfg_services,
60 				ADF_CFG_SYM_DC,
61 				ADF_CFG_MAX_VAL);
62 		}
63 	} else {
64 		dev_cfg_data->num_user_processes =
65 		    ADF_CFG_STATIC_CONF_USER_PROCESSES_NUM;
66 
67 		strncpy(dev_cfg_data->cfg_mode,
68 			ADF_CFG_KERNEL,
69 			ADF_CFG_MAX_VAL);
70 
71 		strncpy(dev_cfg_data->cfg_services,
72 			"sym;asym",
73 			ADF_CFG_MAX_VAL);
74 	}
75 
76 	if (adf_cfg_sysctl_add(accel_dev))
77 		goto err;
78 
79 	if (adf_cfg_dev_dbg_add(accel_dev))
80 		goto err;
81 
82 	if (!accel_dev->is_vf) {
83 		if (adf_heartbeat_dbg_add(accel_dev))
84 			goto err;
85 
86 		if (adf_ver_dbg_add(accel_dev))
87 			goto err;
88 
89 		if (adf_fw_counters_add(accel_dev))
90 			goto err;
91 
92 		if (adf_cnvnr_freq_counters_add(accel_dev))
93 			goto err;
94 	}
95 	return 0;
96 
97 err:
98 	free(dev_cfg_data, M_QAT);
99 	accel_dev->cfg = NULL;
100 	return EFAULT;
101 }
102 
103 static void adf_cfg_section_del_all(struct list_head *head);
104 
105 void
106 adf_cfg_del_all(struct adf_accel_dev *accel_dev)
107 {
108 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
109 
110 	sx_xlock(&dev_cfg_data->lock);
111 	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
112 	sx_xunlock(&dev_cfg_data->lock);
113 	clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
114 }
115 
116 void
117 adf_cfg_depot_del_all(struct list_head *head)
118 {
119 	adf_cfg_section_del_all(head);
120 }
121 
122 /**
123  * adf_cfg_dev_remove() - Clears acceleration device configuration table.
124  * @accel_dev:  Pointer to acceleration device.
125  *
126  * Function removes configuration table from the given acceleration device
127  * and frees all allocated memory.
128  * To be used by QAT device specific drivers.
129  *
130  * Return: void
131  */
132 void
133 adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
134 {
135 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
136 
137 	if (!dev_cfg_data)
138 		return;
139 
140 	sx_xlock(&dev_cfg_data->lock);
141 	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
142 	sx_xunlock(&dev_cfg_data->lock);
143 
144 	adf_cfg_sysctl_remove(accel_dev);
145 	adf_cfg_dev_dbg_remove(accel_dev);
146 	if (!accel_dev->is_vf) {
147 		adf_ver_dbg_del(accel_dev);
148 		adf_heartbeat_dbg_del(accel_dev);
149 		adf_fw_counters_remove(accel_dev);
150 		adf_cnvnr_freq_counters_remove(accel_dev);
151 	}
152 
153 	free(dev_cfg_data, M_QAT);
154 	accel_dev->cfg = NULL;
155 }
156 
157 static void
158 adf_cfg_keyval_add(struct adf_cfg_key_val *new, struct adf_cfg_section *sec)
159 {
160 	list_add_tail(&new->list, &sec->param_head);
161 }
162 
163 static void
164 adf_cfg_keyval_remove(const char *key, struct adf_cfg_section *sec)
165 {
166 	struct list_head *list_ptr, *tmp;
167 	struct list_head *head = &sec->param_head;
168 
169 	list_for_each_prev_safe(list_ptr, tmp, head)
170 	{
171 		struct adf_cfg_key_val *ptr =
172 		    list_entry(list_ptr, struct adf_cfg_key_val, list);
173 
174 		if (strncmp(ptr->key, key, sizeof(ptr->key)) != 0)
175 			continue;
176 
177 		list_del(list_ptr);
178 		free(ptr, M_QAT);
179 		break;
180 	}
181 }
182 
183 static int
184 adf_cfg_section_restore_all(struct adf_accel_dev *accel_dev,
185 			    struct adf_cfg_depot_list *cfg_depot_list)
186 {
187 	struct adf_cfg_section *ptr_sec, *iter_sec;
188 	struct adf_cfg_key_val *ptr_key;
189 	struct list_head *list, *tmp;
190 	struct list_head *restore_list = &accel_dev->cfg->sec_list;
191 	struct list_head *head = &cfg_depot_list[accel_dev->accel_id].sec_list;
192 
193 	INIT_LIST_HEAD(restore_list);
194 
195 	list_for_each_prev_safe(list, tmp, head)
196 	{
197 		ptr_sec = list_entry(list, struct adf_cfg_section, list);
198 		iter_sec = malloc(sizeof(*iter_sec), M_QAT, M_WAITOK | M_ZERO);
199 
200 		strlcpy(iter_sec->name, ptr_sec->name, sizeof(iter_sec->name));
201 
202 		INIT_LIST_HEAD(&iter_sec->param_head);
203 
204 		/* now we restore all the parameters */
205 		list_for_each_entry(ptr_key, &ptr_sec->param_head, list)
206 		{
207 			struct adf_cfg_key_val *key_val;
208 
209 			key_val =
210 			    malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO);
211 
212 			memcpy(key_val, ptr_key, sizeof(*key_val));
213 			list_add_tail(&key_val->list, &iter_sec->param_head);
214 		}
215 		list_add_tail(&iter_sec->list, restore_list);
216 	}
217 	adf_cfg_section_del_all(head);
218 	return 0;
219 }
220 
221 int
222 adf_cfg_depot_restore_all(struct adf_accel_dev *accel_dev,
223 			  struct adf_cfg_depot_list *cfg_depot_list)
224 {
225 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
226 	int ret = 0;
227 
228 	sx_xlock(&dev_cfg_data->lock);
229 	ret = adf_cfg_section_restore_all(accel_dev, cfg_depot_list);
230 	sx_xunlock(&dev_cfg_data->lock);
231 
232 	return ret;
233 }
234 
235 /**
236  * adf_cfg_section_del() - Delete config section entry to config table.
237  * @accel_dev:  Pointer to acceleration device.
238  * @name: Name of the section
239  *
240  * Function deletes configuration section where key - value entries
241  * will be stored.
242  * To be used by QAT device specific drivers.
243  */
244 static void
245 adf_cfg_section_del(struct adf_accel_dev *accel_dev, const char *name)
246 {
247 	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
248 
249 	if (!sec)
250 		return;
251 	adf_cfg_keyval_del_all(&sec->param_head);
252 	list_del(&sec->list);
253 	free(sec, M_QAT);
254 }
255 
256 void
257 adf_cfg_keyval_del_all(struct list_head *head)
258 {
259 	struct list_head *list_ptr, *tmp;
260 
261 	list_for_each_prev_safe(list_ptr, tmp, head)
262 	{
263 		struct adf_cfg_key_val *ptr =
264 		    list_entry(list_ptr, struct adf_cfg_key_val, list);
265 		list_del(list_ptr);
266 		free(ptr, M_QAT);
267 	}
268 }
269 
270 static void
271 adf_cfg_section_del_all(struct list_head *head)
272 {
273 	struct adf_cfg_section *ptr;
274 	struct list_head *list, *tmp;
275 
276 	list_for_each_prev_safe(list, tmp, head)
277 	{
278 		ptr = list_entry(list, struct adf_cfg_section, list);
279 		adf_cfg_keyval_del_all(&ptr->param_head);
280 		list_del(list);
281 		free(ptr, M_QAT);
282 	}
283 }
284 
285 static struct adf_cfg_key_val *
286 adf_cfg_key_value_find(struct adf_cfg_section *s, const char *key)
287 {
288 	struct list_head *list;
289 
290 	list_for_each(list, &s->param_head)
291 	{
292 		struct adf_cfg_key_val *ptr =
293 		    list_entry(list, struct adf_cfg_key_val, list);
294 		if (!strncmp(ptr->key, key, sizeof(ptr->key)))
295 			return ptr;
296 	}
297 	return NULL;
298 }
299 
300 struct adf_cfg_section *
301 adf_cfg_sec_find(struct adf_accel_dev *accel_dev, const char *sec_name)
302 {
303 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
304 	struct list_head *list;
305 
306 	list_for_each(list, &cfg->sec_list)
307 	{
308 		struct adf_cfg_section *ptr =
309 		    list_entry(list, struct adf_cfg_section, list);
310 		if (!strncmp(ptr->name, sec_name, sizeof(ptr->name)))
311 			return ptr;
312 	}
313 	return NULL;
314 }
315 
316 static int
317 adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
318 		    const char *sec_name,
319 		    const char *key_name,
320 		    char *val)
321 {
322 	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
323 	struct adf_cfg_key_val *keyval = NULL;
324 
325 	if (sec)
326 		keyval = adf_cfg_key_value_find(sec, key_name);
327 	if (keyval) {
328 		memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
329 		return 0;
330 	}
331 	return -1;
332 }
333 
334 /**
335  * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
336  * @accel_dev:  Pointer to acceleration device.
337  * @section_name: Name of the section where the param will be added
338  * @key: The key string
339  * @val: Value pain for the given @key
340  * @type: Type - string, int or address
341  *
342  * Function adds configuration key - value entry in the appropriate section
343  * in the given acceleration device
344  * To be used by QAT device specific drivers.
345  *
346  * Return: 0 on success, error code otherwise.
347  */
348 int
349 adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
350 			    const char *section_name,
351 			    const char *key,
352 			    const void *val,
353 			    enum adf_cfg_val_type type)
354 {
355 	char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
356 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
357 	struct adf_cfg_key_val *key_val;
358 	struct adf_cfg_section *section =
359 	    adf_cfg_sec_find(accel_dev, section_name);
360 	if (!section)
361 		return EFAULT;
362 
363 	key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO);
364 
365 	INIT_LIST_HEAD(&key_val->list);
366 	strlcpy(key_val->key, key, sizeof(key_val->key));
367 
368 	if (type == ADF_DEC) {
369 		snprintf(key_val->val,
370 			 ADF_CFG_MAX_VAL_LEN_IN_BYTES,
371 			 "%ld",
372 			 (*((const long *)val)));
373 	} else if (type == ADF_STR) {
374 		strlcpy(key_val->val, (const char *)val, sizeof(key_val->val));
375 	} else if (type == ADF_HEX) {
376 		snprintf(key_val->val,
377 			 ADF_CFG_MAX_VAL_LEN_IN_BYTES,
378 			 "0x%lx",
379 			 (unsigned long)val);
380 	} else {
381 		device_printf(GET_DEV(accel_dev), "Unknown type given.\n");
382 		free(key_val, M_QAT);
383 		return -1;
384 	}
385 	key_val->type = type;
386 
387 	/* Add the key-value pair as below policy:
388 	 *     1. If the key doesn't exist, add it,
389 	 *     2. If the key already exists with a different value
390 	 *        then delete it,
391 	 *     3. If the key exists with the same value, then return
392 	 *        without doing anything.
393 	 */
394 	if (adf_cfg_key_val_get(accel_dev, section_name, key, temp_val) == 0) {
395 		if (strncmp(temp_val, key_val->val, sizeof(temp_val)) != 0) {
396 			adf_cfg_keyval_remove(key, section);
397 		} else {
398 			free(key_val, M_QAT);
399 			return 0;
400 		}
401 	}
402 
403 	sx_xlock(&cfg->lock);
404 	adf_cfg_keyval_add(key_val, section);
405 	sx_xunlock(&cfg->lock);
406 	return 0;
407 }
408 
409 int
410 adf_cfg_save_section(struct adf_accel_dev *accel_dev,
411 		     const char *name,
412 		     struct adf_cfg_section *section)
413 {
414 	struct adf_cfg_key_val *ptr;
415 	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
416 
417 	if (!sec) {
418 		device_printf(GET_DEV(accel_dev),
419 			      "Couldn't find section %s\n",
420 			      name);
421 		return EFAULT;
422 	}
423 
424 	strlcpy(section->name, name, sizeof(section->name));
425 	INIT_LIST_HEAD(&section->param_head);
426 
427 	/* now we save all the parameters */
428 	list_for_each_entry(ptr, &sec->param_head, list)
429 	{
430 		struct adf_cfg_key_val *key_val;
431 
432 		key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO);
433 
434 		memcpy(key_val, ptr, sizeof(*key_val));
435 		list_add_tail(&key_val->list, &section->param_head);
436 	}
437 	return 0;
438 }
439 
440 static int
441 adf_cfg_section_save_all(struct adf_accel_dev *accel_dev,
442 			 struct adf_cfg_depot_list *cfg_depot_list)
443 {
444 	struct adf_cfg_section *ptr_sec, *iter_sec;
445 	struct list_head *list, *tmp, *save_list;
446 	struct list_head *head = &accel_dev->cfg->sec_list;
447 
448 	save_list = &cfg_depot_list[accel_dev->accel_id].sec_list;
449 
450 	list_for_each_prev_safe(list, tmp, head)
451 	{
452 		ptr_sec = list_entry(list, struct adf_cfg_section, list);
453 		iter_sec = malloc(sizeof(*iter_sec), M_QAT, M_WAITOK | M_ZERO);
454 
455 		adf_cfg_save_section(accel_dev, ptr_sec->name, iter_sec);
456 		list_add_tail(&iter_sec->list, save_list);
457 	}
458 	return 0;
459 }
460 
461 int
462 adf_cfg_depot_save_all(struct adf_accel_dev *accel_dev,
463 		       struct adf_cfg_depot_list *cfg_depot_list)
464 {
465 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
466 	int ret = 0;
467 
468 	sx_xlock(&dev_cfg_data->lock);
469 	ret = adf_cfg_section_save_all(accel_dev, cfg_depot_list);
470 	sx_xunlock(&dev_cfg_data->lock);
471 
472 	return ret;
473 }
474 
475 /**
476  * adf_cfg_remove_key_param() - remove config entry in config table.
477  * @accel_dev:  Pointer to acceleration device.
478  * @section_name: Name of the section where the param will be added
479  * @key: The key string
480  *
481  * Function remove configuration key
482  * To be used by QAT device specific drivers.
483  *
484  * Return: 0 on success, error code otherwise.
485  */
486 int
487 adf_cfg_remove_key_param(struct adf_accel_dev *accel_dev,
488 			 const char *section_name,
489 			 const char *key)
490 {
491 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
492 	struct adf_cfg_section *section =
493 	    adf_cfg_sec_find(accel_dev, section_name);
494 	if (!section)
495 		return EFAULT;
496 
497 	sx_xlock(&cfg->lock);
498 	adf_cfg_keyval_remove(key, section);
499 	sx_xunlock(&cfg->lock);
500 	return 0;
501 }
502 
503 /**
504  * adf_cfg_section_add() - Add config section entry to config table.
505  * @accel_dev:  Pointer to acceleration device.
506  * @name: Name of the section
507  *
508  * Function adds configuration section where key - value entries
509  * will be stored.
510  * To be used by QAT device specific drivers.
511  *
512  * Return: 0 on success, error code otherwise.
513  */
514 int
515 adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
516 {
517 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
518 	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
519 
520 	if (sec)
521 		return 0;
522 
523 	sec = malloc(sizeof(*sec), M_QAT, M_WAITOK | M_ZERO);
524 
525 	strlcpy(sec->name, name, sizeof(sec->name));
526 	INIT_LIST_HEAD(&sec->param_head);
527 	sx_xlock(&cfg->lock);
528 	list_add_tail(&sec->list, &cfg->sec_list);
529 	sx_xunlock(&cfg->lock);
530 	return 0;
531 }
532 
533 /* need to differentiate derived section with the original section */
534 int
535 adf_cfg_derived_section_add(struct adf_accel_dev *accel_dev, const char *name)
536 {
537 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
538 	struct adf_cfg_section *sec = NULL;
539 
540 	if (adf_cfg_section_add(accel_dev, name))
541 		return EFAULT;
542 
543 	sec = adf_cfg_sec_find(accel_dev, name);
544 	if (!sec)
545 		return EFAULT;
546 
547 	sx_xlock(&cfg->lock);
548 	sec->is_derived = true;
549 	sx_xunlock(&cfg->lock);
550 	return 0;
551 }
552 
553 static int
554 adf_cfg_restore_key_value_param(struct adf_accel_dev *accel_dev,
555 				const char *section_name,
556 				const char *key,
557 				const char *val,
558 				enum adf_cfg_val_type type)
559 {
560 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
561 	struct adf_cfg_key_val *key_val;
562 	struct adf_cfg_section *section =
563 	    adf_cfg_sec_find(accel_dev, section_name);
564 	if (!section)
565 		return EFAULT;
566 
567 	key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO);
568 
569 	INIT_LIST_HEAD(&key_val->list);
570 
571 	strlcpy(key_val->key, key, sizeof(key_val->key));
572 	strlcpy(key_val->val, val, sizeof(key_val->val));
573 	key_val->type = type;
574 	sx_xlock(&cfg->lock);
575 	adf_cfg_keyval_add(key_val, section);
576 	sx_xunlock(&cfg->lock);
577 	return 0;
578 }
579 
580 int
581 adf_cfg_restore_section(struct adf_accel_dev *accel_dev,
582 			struct adf_cfg_section *section)
583 {
584 	struct adf_cfg_key_val *ptr;
585 	int ret = 0;
586 
587 	ret = adf_cfg_section_add(accel_dev, section->name);
588 	if (ret)
589 		goto err;
590 
591 	list_for_each_entry(ptr, &section->param_head, list)
592 	{
593 		ret = adf_cfg_restore_key_value_param(
594 		    accel_dev, section->name, ptr->key, ptr->val, ptr->type);
595 		if (ret)
596 			goto err_remove_sec;
597 	}
598 	return 0;
599 
600 err_remove_sec:
601 	adf_cfg_section_del(accel_dev, section->name);
602 err:
603 	device_printf(GET_DEV(accel_dev),
604 		      "Failed to restore section %s\n",
605 		      section->name);
606 	return ret;
607 }
608 
609 int
610 adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
611 			const char *section,
612 			const char *name,
613 			char *value)
614 {
615 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
616 	int ret;
617 
618 	sx_slock(&cfg->lock);
619 	ret = adf_cfg_key_val_get(accel_dev, section, name, value);
620 	sx_sunlock(&cfg->lock);
621 	return ret;
622 }
623