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