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_cfg_device.h" 9 #include "adf_cfg_sysctl.h" 10 #include "adf_heartbeat_dbg.h" 11 #include "adf_ver_dbg.h" 12 #include "adf_fw_counters.h" 13 #include "adf_cnvnr_freq_counters.h" 14 15 /** 16 * adf_cfg_dev_add() - Create an acceleration device configuration table. 17 * @accel_dev: Pointer to acceleration device. 18 * 19 * Function creates a configuration table for the given acceleration device. 20 * The table stores device specific config values. 21 * To be used by QAT device specific drivers. 22 * 23 * Return: 0 on success, error code otherwise. 24 */ 25 int 26 adf_cfg_dev_add(struct adf_accel_dev *accel_dev) 27 { 28 struct adf_cfg_device_data *dev_cfg_data; 29 30 dev_cfg_data = malloc(sizeof(*dev_cfg_data), M_QAT, M_WAITOK | M_ZERO); 31 INIT_LIST_HEAD(&dev_cfg_data->sec_list); 32 sx_init(&dev_cfg_data->lock, "qat cfg data"); 33 accel_dev->cfg = dev_cfg_data; 34 35 /* Default device configuration initialization */ 36 if (!accel_dev->is_vf) { 37 38 if (IS_QAT_GEN4(pci_get_device(GET_DEV(accel_dev)))) { 39 dev_cfg_data->num_user_processes = 40 ADF_CFG_STATIC_CONF_USER_PROCESSES_NUM; 41 42 strncpy(dev_cfg_data->cfg_mode, 43 ADF_CFG_KERNEL_USER, 44 ADF_CFG_MAX_VAL); 45 46 if (accel_dev->accel_id % 2 == 0) { 47 strncpy(dev_cfg_data->cfg_services, 48 ADF_CFG_SYM_ASYM, 49 ADF_CFG_MAX_VAL); 50 } else { 51 strncpy(dev_cfg_data->cfg_services, 52 ADF_CFG_DC, 53 ADF_CFG_MAX_VAL); 54 } 55 } else { 56 strncpy(dev_cfg_data->cfg_mode, 57 ADF_CFG_KERNEL, 58 ADF_CFG_MAX_VAL); 59 dev_cfg_data->num_user_processes = 0; 60 strncpy(dev_cfg_data->cfg_services, 61 ADF_CFG_SYM_DC, 62 ADF_CFG_MAX_VAL); 63 } 64 } else { 65 dev_cfg_data->num_user_processes = 66 ADF_CFG_STATIC_CONF_USER_PROCESSES_NUM; 67 68 strncpy(dev_cfg_data->cfg_mode, 69 ADF_CFG_KERNEL, 70 ADF_CFG_MAX_VAL); 71 72 strncpy(dev_cfg_data->cfg_services, 73 "sym;asym", 74 ADF_CFG_MAX_VAL); 75 } 76 77 if (adf_cfg_sysctl_add(accel_dev)) 78 goto err; 79 80 if (adf_cfg_dev_dbg_add(accel_dev)) 81 goto err; 82 83 if (!accel_dev->is_vf) { 84 if (adf_heartbeat_dbg_add(accel_dev)) 85 goto err; 86 87 if (adf_ver_dbg_add(accel_dev)) 88 goto err; 89 90 if (adf_fw_counters_add(accel_dev)) 91 goto err; 92 93 if (adf_cnvnr_freq_counters_add(accel_dev)) 94 goto err; 95 } 96 return 0; 97 98 err: 99 free(dev_cfg_data, M_QAT); 100 accel_dev->cfg = NULL; 101 return EFAULT; 102 } 103 104 static void adf_cfg_section_del_all(struct list_head *head); 105 106 void 107 adf_cfg_del_all(struct adf_accel_dev *accel_dev) 108 { 109 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; 110 111 sx_xlock(&dev_cfg_data->lock); 112 adf_cfg_section_del_all(&dev_cfg_data->sec_list); 113 sx_xunlock(&dev_cfg_data->lock); 114 clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status); 115 } 116 117 void 118 adf_cfg_depot_del_all(struct list_head *head) 119 { 120 adf_cfg_section_del_all(head); 121 } 122 123 /** 124 * adf_cfg_dev_remove() - Clears acceleration device configuration table. 125 * @accel_dev: Pointer to acceleration device. 126 * 127 * Function removes configuration table from the given acceleration device 128 * and frees all allocated memory. 129 * To be used by QAT device specific drivers. 130 * 131 * Return: void 132 */ 133 void 134 adf_cfg_dev_remove(struct adf_accel_dev *accel_dev) 135 { 136 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; 137 138 if (!dev_cfg_data) 139 return; 140 141 sx_xlock(&dev_cfg_data->lock); 142 adf_cfg_section_del_all(&dev_cfg_data->sec_list); 143 sx_xunlock(&dev_cfg_data->lock); 144 145 adf_cfg_sysctl_remove(accel_dev); 146 adf_cfg_dev_dbg_remove(accel_dev); 147 if (!accel_dev->is_vf) { 148 adf_ver_dbg_del(accel_dev); 149 adf_heartbeat_dbg_del(accel_dev); 150 adf_fw_counters_remove(accel_dev); 151 adf_cnvnr_freq_counters_remove(accel_dev); 152 } 153 154 free(dev_cfg_data, M_QAT); 155 accel_dev->cfg = NULL; 156 } 157 158 static void 159 adf_cfg_keyval_add(struct adf_cfg_key_val *new, struct adf_cfg_section *sec) 160 { 161 list_add_tail(&new->list, &sec->param_head); 162 } 163 164 static void 165 adf_cfg_keyval_remove(const char *key, struct adf_cfg_section *sec) 166 { 167 struct list_head *list_ptr, *tmp; 168 struct list_head *head = &sec->param_head; 169 170 list_for_each_prev_safe(list_ptr, tmp, head) 171 { 172 struct adf_cfg_key_val *ptr = 173 list_entry(list_ptr, struct adf_cfg_key_val, list); 174 175 if (strncmp(ptr->key, key, sizeof(ptr->key)) != 0) 176 continue; 177 178 list_del(list_ptr); 179 free(ptr, M_QAT); 180 break; 181 } 182 } 183 184 static int 185 adf_cfg_section_restore_all(struct adf_accel_dev *accel_dev, 186 struct adf_cfg_depot_list *cfg_depot_list) 187 { 188 struct adf_cfg_section *ptr_sec, *iter_sec; 189 struct adf_cfg_key_val *ptr_key; 190 struct list_head *list, *tmp; 191 struct list_head *restore_list = &accel_dev->cfg->sec_list; 192 struct list_head *head = &cfg_depot_list[accel_dev->accel_id].sec_list; 193 194 INIT_LIST_HEAD(restore_list); 195 196 list_for_each_prev_safe(list, tmp, head) 197 { 198 ptr_sec = list_entry(list, struct adf_cfg_section, list); 199 iter_sec = malloc(sizeof(*iter_sec), M_QAT, M_WAITOK | M_ZERO); 200 201 strlcpy(iter_sec->name, ptr_sec->name, sizeof(iter_sec->name)); 202 203 INIT_LIST_HEAD(&iter_sec->param_head); 204 205 /* now we restore all the parameters */ 206 list_for_each_entry(ptr_key, &ptr_sec->param_head, list) 207 { 208 struct adf_cfg_key_val *key_val; 209 210 key_val = 211 malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO); 212 213 memcpy(key_val, ptr_key, sizeof(*key_val)); 214 list_add_tail(&key_val->list, &iter_sec->param_head); 215 } 216 list_add_tail(&iter_sec->list, restore_list); 217 } 218 adf_cfg_section_del_all(head); 219 return 0; 220 } 221 222 int 223 adf_cfg_depot_restore_all(struct adf_accel_dev *accel_dev, 224 struct adf_cfg_depot_list *cfg_depot_list) 225 { 226 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; 227 int ret = 0; 228 229 sx_xlock(&dev_cfg_data->lock); 230 ret = adf_cfg_section_restore_all(accel_dev, cfg_depot_list); 231 sx_xunlock(&dev_cfg_data->lock); 232 233 return ret; 234 } 235 236 /** 237 * adf_cfg_section_del() - Delete config section entry to config table. 238 * @accel_dev: Pointer to acceleration device. 239 * @name: Name of the section 240 * 241 * Function deletes configuration section where key - value entries 242 * will be stored. 243 * To be used by QAT device specific drivers. 244 */ 245 static void 246 adf_cfg_section_del(struct adf_accel_dev *accel_dev, const char *name) 247 { 248 struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name); 249 250 if (!sec) 251 return; 252 adf_cfg_keyval_del_all(&sec->param_head); 253 list_del(&sec->list); 254 free(sec, M_QAT); 255 } 256 257 void 258 adf_cfg_keyval_del_all(struct list_head *head) 259 { 260 struct list_head *list_ptr, *tmp; 261 262 list_for_each_prev_safe(list_ptr, tmp, head) 263 { 264 struct adf_cfg_key_val *ptr = 265 list_entry(list_ptr, struct adf_cfg_key_val, list); 266 list_del(list_ptr); 267 free(ptr, M_QAT); 268 } 269 } 270 271 static void 272 adf_cfg_section_del_all(struct list_head *head) 273 { 274 struct adf_cfg_section *ptr; 275 struct list_head *list, *tmp; 276 277 list_for_each_prev_safe(list, tmp, head) 278 { 279 ptr = list_entry(list, struct adf_cfg_section, list); 280 adf_cfg_keyval_del_all(&ptr->param_head); 281 list_del(list); 282 free(ptr, M_QAT); 283 } 284 } 285 286 static struct adf_cfg_key_val * 287 adf_cfg_key_value_find(struct adf_cfg_section *s, const char *key) 288 { 289 struct list_head *list; 290 291 list_for_each(list, &s->param_head) 292 { 293 struct adf_cfg_key_val *ptr = 294 list_entry(list, struct adf_cfg_key_val, list); 295 if (!strncmp(ptr->key, key, sizeof(ptr->key))) 296 return ptr; 297 } 298 return NULL; 299 } 300 301 struct adf_cfg_section * 302 adf_cfg_sec_find(struct adf_accel_dev *accel_dev, const char *sec_name) 303 { 304 struct adf_cfg_device_data *cfg = accel_dev->cfg; 305 struct list_head *list; 306 307 list_for_each(list, &cfg->sec_list) 308 { 309 struct adf_cfg_section *ptr = 310 list_entry(list, struct adf_cfg_section, list); 311 if (!strncmp(ptr->name, sec_name, sizeof(ptr->name))) 312 return ptr; 313 } 314 return NULL; 315 } 316 317 static int 318 adf_cfg_key_val_get(struct adf_accel_dev *accel_dev, 319 const char *sec_name, 320 const char *key_name, 321 char *val) 322 { 323 struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name); 324 struct adf_cfg_key_val *keyval = NULL; 325 326 if (sec) 327 keyval = adf_cfg_key_value_find(sec, key_name); 328 if (keyval) { 329 memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES); 330 return 0; 331 } 332 return -1; 333 } 334 335 /** 336 * adf_cfg_add_key_value_param() - Add key-value config entry to config table. 337 * @accel_dev: Pointer to acceleration device. 338 * @section_name: Name of the section where the param will be added 339 * @key: The key string 340 * @val: Value pain for the given @key 341 * @type: Type - string, int or address 342 * 343 * Function adds configuration key - value entry in the appropriate section 344 * in the given acceleration device 345 * To be used by QAT device specific drivers. 346 * 347 * Return: 0 on success, error code otherwise. 348 */ 349 int 350 adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, 351 const char *section_name, 352 const char *key, 353 const void *val, 354 enum adf_cfg_val_type type) 355 { 356 char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; 357 struct adf_cfg_device_data *cfg = accel_dev->cfg; 358 struct adf_cfg_key_val *key_val; 359 struct adf_cfg_section *section = 360 adf_cfg_sec_find(accel_dev, section_name); 361 if (!section) 362 return EFAULT; 363 364 key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO); 365 366 INIT_LIST_HEAD(&key_val->list); 367 strlcpy(key_val->key, key, sizeof(key_val->key)); 368 369 if (type == ADF_DEC) { 370 snprintf(key_val->val, 371 ADF_CFG_MAX_VAL_LEN_IN_BYTES, 372 "%ld", 373 (*((const long *)val))); 374 } else if (type == ADF_STR) { 375 strlcpy(key_val->val, (const char *)val, sizeof(key_val->val)); 376 } else if (type == ADF_HEX) { 377 snprintf(key_val->val, 378 ADF_CFG_MAX_VAL_LEN_IN_BYTES, 379 "0x%lx", 380 (unsigned long)val); 381 } else { 382 device_printf(GET_DEV(accel_dev), "Unknown type given.\n"); 383 free(key_val, M_QAT); 384 return -1; 385 } 386 key_val->type = type; 387 388 /* Add the key-value pair as below policy: 389 * 1. If the key doesn't exist, add it, 390 * 2. If the key already exists with a different value 391 * then delete it, 392 * 3. If the key exists with the same value, then return 393 * without doing anything. 394 */ 395 if (adf_cfg_key_val_get(accel_dev, section_name, key, temp_val) == 0) { 396 if (strncmp(temp_val, key_val->val, sizeof(temp_val)) != 0) { 397 adf_cfg_keyval_remove(key, section); 398 } else { 399 free(key_val, M_QAT); 400 return 0; 401 } 402 } 403 404 sx_xlock(&cfg->lock); 405 adf_cfg_keyval_add(key_val, section); 406 sx_xunlock(&cfg->lock); 407 return 0; 408 } 409 410 int 411 adf_cfg_save_section(struct adf_accel_dev *accel_dev, 412 const char *name, 413 struct adf_cfg_section *section) 414 { 415 struct adf_cfg_key_val *ptr; 416 struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name); 417 418 if (!sec) { 419 device_printf(GET_DEV(accel_dev), 420 "Couldn't find section %s\n", 421 name); 422 return EFAULT; 423 } 424 425 strlcpy(section->name, name, sizeof(section->name)); 426 INIT_LIST_HEAD(§ion->param_head); 427 428 /* now we save all the parameters */ 429 list_for_each_entry(ptr, &sec->param_head, list) 430 { 431 struct adf_cfg_key_val *key_val; 432 433 key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO); 434 435 memcpy(key_val, ptr, sizeof(*key_val)); 436 list_add_tail(&key_val->list, §ion->param_head); 437 } 438 return 0; 439 } 440 441 static int 442 adf_cfg_section_save_all(struct adf_accel_dev *accel_dev, 443 struct adf_cfg_depot_list *cfg_depot_list) 444 { 445 struct adf_cfg_section *ptr_sec, *iter_sec; 446 struct list_head *list, *tmp, *save_list; 447 struct list_head *head = &accel_dev->cfg->sec_list; 448 449 save_list = &cfg_depot_list[accel_dev->accel_id].sec_list; 450 451 list_for_each_prev_safe(list, tmp, head) 452 { 453 ptr_sec = list_entry(list, struct adf_cfg_section, list); 454 iter_sec = malloc(sizeof(*iter_sec), M_QAT, M_WAITOK | M_ZERO); 455 456 adf_cfg_save_section(accel_dev, ptr_sec->name, iter_sec); 457 list_add_tail(&iter_sec->list, save_list); 458 } 459 return 0; 460 } 461 462 int 463 adf_cfg_depot_save_all(struct adf_accel_dev *accel_dev, 464 struct adf_cfg_depot_list *cfg_depot_list) 465 { 466 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; 467 int ret = 0; 468 469 sx_xlock(&dev_cfg_data->lock); 470 ret = adf_cfg_section_save_all(accel_dev, cfg_depot_list); 471 sx_xunlock(&dev_cfg_data->lock); 472 473 return ret; 474 } 475 476 /** 477 * adf_cfg_remove_key_param() - remove config entry in config table. 478 * @accel_dev: Pointer to acceleration device. 479 * @section_name: Name of the section where the param will be added 480 * @key: The key string 481 * 482 * Function remove configuration key 483 * To be used by QAT device specific drivers. 484 * 485 * Return: 0 on success, error code otherwise. 486 */ 487 int 488 adf_cfg_remove_key_param(struct adf_accel_dev *accel_dev, 489 const char *section_name, 490 const char *key) 491 { 492 struct adf_cfg_device_data *cfg = accel_dev->cfg; 493 struct adf_cfg_section *section = 494 adf_cfg_sec_find(accel_dev, section_name); 495 if (!section) 496 return EFAULT; 497 498 sx_xlock(&cfg->lock); 499 adf_cfg_keyval_remove(key, section); 500 sx_xunlock(&cfg->lock); 501 return 0; 502 } 503 504 /** 505 * adf_cfg_section_add() - Add config section entry to config table. 506 * @accel_dev: Pointer to acceleration device. 507 * @name: Name of the section 508 * 509 * Function adds configuration section where key - value entries 510 * will be stored. 511 * To be used by QAT device specific drivers. 512 * 513 * Return: 0 on success, error code otherwise. 514 */ 515 int 516 adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name) 517 { 518 struct adf_cfg_device_data *cfg = accel_dev->cfg; 519 struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name); 520 521 if (sec) 522 return 0; 523 524 sec = malloc(sizeof(*sec), M_QAT, M_WAITOK | M_ZERO); 525 526 strlcpy(sec->name, name, sizeof(sec->name)); 527 INIT_LIST_HEAD(&sec->param_head); 528 sx_xlock(&cfg->lock); 529 list_add_tail(&sec->list, &cfg->sec_list); 530 sx_xunlock(&cfg->lock); 531 return 0; 532 } 533 534 /* need to differentiate derived section with the original section */ 535 int 536 adf_cfg_derived_section_add(struct adf_accel_dev *accel_dev, const char *name) 537 { 538 struct adf_cfg_device_data *cfg = accel_dev->cfg; 539 struct adf_cfg_section *sec = NULL; 540 541 if (adf_cfg_section_add(accel_dev, name)) 542 return EFAULT; 543 544 sec = adf_cfg_sec_find(accel_dev, name); 545 if (!sec) 546 return EFAULT; 547 548 sx_xlock(&cfg->lock); 549 sec->is_derived = true; 550 sx_xunlock(&cfg->lock); 551 return 0; 552 } 553 554 static int 555 adf_cfg_restore_key_value_param(struct adf_accel_dev *accel_dev, 556 const char *section_name, 557 const char *key, 558 const char *val, 559 enum adf_cfg_val_type type) 560 { 561 struct adf_cfg_device_data *cfg = accel_dev->cfg; 562 struct adf_cfg_key_val *key_val; 563 struct adf_cfg_section *section = 564 adf_cfg_sec_find(accel_dev, section_name); 565 if (!section) 566 return EFAULT; 567 568 key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO); 569 570 INIT_LIST_HEAD(&key_val->list); 571 572 strlcpy(key_val->key, key, sizeof(key_val->key)); 573 strlcpy(key_val->val, val, sizeof(key_val->val)); 574 key_val->type = type; 575 sx_xlock(&cfg->lock); 576 adf_cfg_keyval_add(key_val, section); 577 sx_xunlock(&cfg->lock); 578 return 0; 579 } 580 581 int 582 adf_cfg_restore_section(struct adf_accel_dev *accel_dev, 583 struct adf_cfg_section *section) 584 { 585 struct adf_cfg_key_val *ptr; 586 int ret = 0; 587 588 ret = adf_cfg_section_add(accel_dev, section->name); 589 if (ret) 590 goto err; 591 592 list_for_each_entry(ptr, §ion->param_head, list) 593 { 594 ret = adf_cfg_restore_key_value_param( 595 accel_dev, section->name, ptr->key, ptr->val, ptr->type); 596 if (ret) 597 goto err_remove_sec; 598 } 599 return 0; 600 601 err_remove_sec: 602 adf_cfg_section_del(accel_dev, section->name); 603 err: 604 device_printf(GET_DEV(accel_dev), 605 "Failed to restore section %s\n", 606 section->name); 607 return ret; 608 } 609 610 int 611 adf_cfg_get_param_value(struct adf_accel_dev *accel_dev, 612 const char *section, 613 const char *name, 614 char *value) 615 { 616 struct adf_cfg_device_data *cfg = accel_dev->cfg; 617 int ret; 618 619 sx_slock(&cfg->lock); 620 ret = adf_cfg_key_val_get(accel_dev, section, name, value); 621 sx_sunlock(&cfg->lock); 622 return ret; 623 } 624