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