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
adf_cfg_dev_add(struct adf_accel_dev * accel_dev)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
adf_cfg_del_all(struct adf_accel_dev * accel_dev)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
adf_cfg_depot_del_all(struct list_head * head)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
adf_cfg_dev_remove(struct adf_accel_dev * accel_dev)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
adf_cfg_keyval_add(struct adf_cfg_key_val * new,struct adf_cfg_section * sec)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
adf_cfg_keyval_remove(const char * key,struct adf_cfg_section * sec)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
adf_cfg_section_restore_all(struct adf_accel_dev * accel_dev,struct adf_cfg_depot_list * cfg_depot_list)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
adf_cfg_depot_restore_all(struct adf_accel_dev * accel_dev,struct adf_cfg_depot_list * cfg_depot_list)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
adf_cfg_section_del(struct adf_accel_dev * accel_dev,const char * name)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
adf_cfg_keyval_del_all(struct list_head * head)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
adf_cfg_section_del_all(struct list_head * head)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 *
adf_cfg_key_value_find(struct adf_cfg_section * s,const char * key)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 *
adf_cfg_sec_find(struct adf_accel_dev * accel_dev,const char * sec_name)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
adf_cfg_key_val_get(struct adf_accel_dev * accel_dev,const char * sec_name,const char * key_name,char * val)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
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)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
adf_cfg_save_section(struct adf_accel_dev * accel_dev,const char * name,struct adf_cfg_section * section)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(§ion->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, §ion->param_head);
436 }
437 return 0;
438 }
439
440 static int
adf_cfg_section_save_all(struct adf_accel_dev * accel_dev,struct adf_cfg_depot_list * cfg_depot_list)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
adf_cfg_depot_save_all(struct adf_accel_dev * accel_dev,struct adf_cfg_depot_list * cfg_depot_list)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
adf_cfg_remove_key_param(struct adf_accel_dev * accel_dev,const char * section_name,const char * key)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
adf_cfg_section_add(struct adf_accel_dev * accel_dev,const char * name)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
adf_cfg_derived_section_add(struct adf_accel_dev * accel_dev,const char * name)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
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)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
adf_cfg_restore_section(struct adf_accel_dev * accel_dev,struct adf_cfg_section * section)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, §ion->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
adf_cfg_get_param_value(struct adf_accel_dev * accel_dev,const char * section,const char * name,char * value)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