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