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 } 575