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(§ion->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, §ion->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, §ion->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 }
Cache object: 50f7dcc47c49f5c891220d1fb1d76a61
|