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