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(§ion->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, §ion->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, §ion->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