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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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