1 // SPDX-License-Identifier: GPL-2.0 2 3 /* 4 * Copyright 2020 HabanaLabs, Ltd. 5 * All Rights Reserved. 6 */ 7 8 #include "habanalabs.h" 9 10 static const char * const hl_glbl_error_cause[] = { 11 "Error due to un-priv read", 12 "Error due to un-secure read", 13 "Error due to read from unmapped reg", 14 "Error due to un-priv write", 15 "Error due to un-secure write", 16 "Error due to write to unmapped reg", 17 "N/A", 18 "N/A", 19 "N/A", 20 "N/A", 21 "N/A", 22 "N/A", 23 "N/A", 24 "N/A", 25 "N/A", 26 "N/A", 27 "External I/F write sec violation", 28 "External I/F write to un-mapped reg", 29 "N/A", 30 "N/A", 31 "N/A", 32 "N/A", 33 "N/A", 34 "N/A", 35 "Read to write only", 36 "Write to read only" 37 }; 38 39 /** 40 * hl_get_pb_block - return the relevant block within the block array 41 * 42 * @hdev: pointer to hl_device structure 43 * @mm_reg_addr: register address in the desired block 44 * @pb_blocks: blocks array 45 * @array_size: blocks array size 46 * 47 */ 48 static int hl_get_pb_block(struct hl_device *hdev, u32 mm_reg_addr, 49 const u32 pb_blocks[], int array_size) 50 { 51 int i; 52 u32 start_addr, end_addr; 53 54 for (i = 0 ; i < array_size ; i++) { 55 start_addr = pb_blocks[i]; 56 end_addr = start_addr + HL_BLOCK_SIZE; 57 58 if ((mm_reg_addr >= start_addr) && (mm_reg_addr < end_addr)) 59 return i; 60 } 61 62 dev_err(hdev->dev, "No protection domain was found for 0x%x\n", 63 mm_reg_addr); 64 return -EDOM; 65 } 66 67 /** 68 * hl_unset_pb_in_block - clear a specific protection bit in a block 69 * 70 * @hdev: pointer to hl_device structure 71 * @reg_offset: register offset will be converted to bit offset in pb block 72 * @sgs_entry: pb array 73 * 74 */ 75 static int hl_unset_pb_in_block(struct hl_device *hdev, u32 reg_offset, 76 struct hl_block_glbl_sec *sgs_entry) 77 { 78 if ((reg_offset >= HL_BLOCK_SIZE) || (reg_offset & 0x3)) { 79 dev_err(hdev->dev, 80 "Register offset(%d) is out of range(%d) or invalid\n", 81 reg_offset, HL_BLOCK_SIZE); 82 return -EINVAL; 83 } 84 85 UNSET_GLBL_SEC_BIT(sgs_entry->sec_array, 86 (reg_offset & (HL_BLOCK_SIZE - 1)) >> 2); 87 88 return 0; 89 } 90 91 /** 92 * hl_unsecure_register - locate the relevant block for this register and 93 * remove corresponding protection bit 94 * 95 * @hdev: pointer to hl_device structure 96 * @mm_reg_addr: register address to unsecure 97 * @offset: additional offset to the register address 98 * @pb_blocks: blocks array 99 * @sgs_array: pb array 100 * @array_size: blocks array size 101 * 102 */ 103 int hl_unsecure_register(struct hl_device *hdev, u32 mm_reg_addr, int offset, 104 const u32 pb_blocks[], struct hl_block_glbl_sec sgs_array[], 105 int array_size) 106 { 107 u32 reg_offset; 108 int block_num; 109 110 block_num = hl_get_pb_block(hdev, mm_reg_addr + offset, pb_blocks, 111 array_size); 112 if (block_num < 0) 113 return block_num; 114 115 reg_offset = (mm_reg_addr + offset) - pb_blocks[block_num]; 116 117 return hl_unset_pb_in_block(hdev, reg_offset, &sgs_array[block_num]); 118 } 119 120 /** 121 * hl_unsecure_register_range - locate the relevant block for this register 122 * range and remove corresponding protection bit 123 * 124 * @hdev: pointer to hl_device structure 125 * @mm_reg_range: register address range to unsecure 126 * @offset: additional offset to the register address 127 * @pb_blocks: blocks array 128 * @sgs_array: pb array 129 * @array_size: blocks array size 130 * 131 */ 132 static int hl_unsecure_register_range(struct hl_device *hdev, 133 struct range mm_reg_range, int offset, const u32 pb_blocks[], 134 struct hl_block_glbl_sec sgs_array[], 135 int array_size) 136 { 137 u32 reg_offset; 138 int i, block_num, rc = 0; 139 140 block_num = hl_get_pb_block(hdev, 141 mm_reg_range.start + offset, pb_blocks, 142 array_size); 143 if (block_num < 0) 144 return block_num; 145 146 for (i = mm_reg_range.start ; i <= mm_reg_range.end ; i += 4) { 147 reg_offset = (i + offset) - pb_blocks[block_num]; 148 rc |= hl_unset_pb_in_block(hdev, reg_offset, 149 &sgs_array[block_num]); 150 } 151 152 return rc; 153 } 154 155 /** 156 * hl_unsecure_registers - locate the relevant block for all registers and 157 * remove corresponding protection bit 158 * 159 * @hdev: pointer to hl_device structure 160 * @mm_reg_array: register address array to unsecure 161 * @mm_array_size: register array size 162 * @offset: additional offset to the register address 163 * @pb_blocks: blocks array 164 * @sgs_array: pb array 165 * @blocks_array_size: blocks array size 166 * 167 */ 168 int hl_unsecure_registers(struct hl_device *hdev, const u32 mm_reg_array[], 169 int mm_array_size, int offset, const u32 pb_blocks[], 170 struct hl_block_glbl_sec sgs_array[], int blocks_array_size) 171 { 172 int i, rc = 0; 173 174 for (i = 0 ; i < mm_array_size ; i++) { 175 rc = hl_unsecure_register(hdev, mm_reg_array[i], offset, 176 pb_blocks, sgs_array, blocks_array_size); 177 178 if (rc) 179 return rc; 180 } 181 182 return rc; 183 } 184 185 /** 186 * hl_unsecure_registers_range - locate the relevant block for all register 187 * ranges and remove corresponding protection bit 188 * 189 * @hdev: pointer to hl_device structure 190 * @mm_reg_range_array: register address range array to unsecure 191 * @mm_array_size: register array size 192 * @offset: additional offset to the register address 193 * @pb_blocks: blocks array 194 * @sgs_array: pb array 195 * @blocks_array_size: blocks array size 196 * 197 */ 198 static int hl_unsecure_registers_range(struct hl_device *hdev, 199 const struct range mm_reg_range_array[], int mm_array_size, 200 int offset, const u32 pb_blocks[], 201 struct hl_block_glbl_sec sgs_array[], int blocks_array_size) 202 { 203 int i, rc = 0; 204 205 for (i = 0 ; i < mm_array_size ; i++) { 206 rc = hl_unsecure_register_range(hdev, mm_reg_range_array[i], 207 offset, pb_blocks, sgs_array, blocks_array_size); 208 209 if (rc) 210 return rc; 211 } 212 213 return rc; 214 } 215 216 /** 217 * hl_ack_pb_security_violations - Ack security violation 218 * 219 * @hdev: pointer to hl_device structure 220 * @pb_blocks: blocks array 221 * @block_offset: additional offset to the block 222 * @array_size: blocks array size 223 * 224 */ 225 static void hl_ack_pb_security_violations(struct hl_device *hdev, 226 const u32 pb_blocks[], u32 block_offset, int array_size) 227 { 228 int i; 229 u32 cause, addr, block_base; 230 231 for (i = 0 ; i < array_size ; i++) { 232 block_base = pb_blocks[i] + block_offset; 233 cause = RREG32(block_base + HL_BLOCK_GLBL_ERR_CAUSE); 234 if (cause) { 235 addr = RREG32(block_base + HL_BLOCK_GLBL_ERR_ADDR); 236 hdev->asic_funcs->pb_print_security_errors(hdev, 237 block_base, cause, addr); 238 WREG32(block_base + HL_BLOCK_GLBL_ERR_CAUSE, cause); 239 } 240 } 241 } 242 243 /** 244 * hl_config_glbl_sec - set pb in HW according to given pb array 245 * 246 * @hdev: pointer to hl_device structure 247 * @pb_blocks: blocks array 248 * @sgs_array: pb array 249 * @block_offset: additional offset to the block 250 * @array_size: blocks array size 251 * 252 */ 253 void hl_config_glbl_sec(struct hl_device *hdev, const u32 pb_blocks[], 254 struct hl_block_glbl_sec sgs_array[], u32 block_offset, 255 int array_size) 256 { 257 int i, j; 258 u32 sgs_base; 259 260 if (hdev->pldm) 261 usleep_range(100, 1000); 262 263 for (i = 0 ; i < array_size ; i++) { 264 sgs_base = block_offset + pb_blocks[i] + 265 HL_BLOCK_GLBL_SEC_OFFS; 266 267 for (j = 0 ; j < HL_BLOCK_GLBL_SEC_LEN ; j++) 268 WREG32(sgs_base + j * sizeof(u32), 269 sgs_array[i].sec_array[j]); 270 } 271 } 272 273 /** 274 * hl_secure_block - locally memsets a block to 0 275 * 276 * @hdev: pointer to hl_device structure 277 * @sgs_array: pb array to clear 278 * @array_size: blocks array size 279 * 280 */ 281 void hl_secure_block(struct hl_device *hdev, 282 struct hl_block_glbl_sec sgs_array[], int array_size) 283 { 284 int i; 285 286 for (i = 0 ; i < array_size ; i++) 287 memset((char *)(sgs_array[i].sec_array), 0, 288 HL_BLOCK_GLBL_SEC_SIZE); 289 } 290 291 /** 292 * hl_init_pb_with_mask - set selected pb instances with mask in HW according 293 * to given configuration 294 * 295 * @hdev: pointer to hl_device structure 296 * @num_dcores: number of decores to apply configuration to 297 * set to HL_PB_SHARED if need to apply only once 298 * @dcore_offset: offset between dcores 299 * @num_instances: number of instances to apply configuration to 300 * @instance_offset: offset between instances 301 * @pb_blocks: blocks array 302 * @blocks_array_size: blocks array size 303 * @user_regs_array: unsecured register array 304 * @user_regs_array_size: unsecured register array size 305 * @mask: enabled instances mask: 1- enabled, 0- disabled 306 */ 307 int hl_init_pb_with_mask(struct hl_device *hdev, u32 num_dcores, 308 u32 dcore_offset, u32 num_instances, u32 instance_offset, 309 const u32 pb_blocks[], u32 blocks_array_size, 310 const u32 *user_regs_array, u32 user_regs_array_size, u64 mask) 311 { 312 int i, j; 313 struct hl_block_glbl_sec *glbl_sec; 314 315 glbl_sec = kcalloc(blocks_array_size, 316 sizeof(struct hl_block_glbl_sec), 317 GFP_KERNEL); 318 if (!glbl_sec) 319 return -ENOMEM; 320 321 hl_secure_block(hdev, glbl_sec, blocks_array_size); 322 hl_unsecure_registers(hdev, user_regs_array, user_regs_array_size, 0, 323 pb_blocks, glbl_sec, blocks_array_size); 324 325 /* Fill all blocks with the same configuration */ 326 for (i = 0 ; i < num_dcores ; i++) { 327 for (j = 0 ; j < num_instances ; j++) { 328 int seq = i * num_instances + j; 329 330 if (!(mask & BIT_ULL(seq))) 331 continue; 332 333 hl_config_glbl_sec(hdev, pb_blocks, glbl_sec, 334 i * dcore_offset + j * instance_offset, 335 blocks_array_size); 336 } 337 } 338 339 kfree(glbl_sec); 340 341 return 0; 342 } 343 344 /** 345 * hl_init_pb - set pb in HW according to given configuration 346 * 347 * @hdev: pointer to hl_device structure 348 * @num_dcores: number of decores to apply configuration to 349 * set to HL_PB_SHARED if need to apply only once 350 * @dcore_offset: offset between dcores 351 * @num_instances: number of instances to apply configuration to 352 * @instance_offset: offset between instances 353 * @pb_blocks: blocks array 354 * @blocks_array_size: blocks array size 355 * @user_regs_array: unsecured register array 356 * @user_regs_array_size: unsecured register array size 357 * 358 */ 359 int hl_init_pb(struct hl_device *hdev, u32 num_dcores, u32 dcore_offset, 360 u32 num_instances, u32 instance_offset, 361 const u32 pb_blocks[], u32 blocks_array_size, 362 const u32 *user_regs_array, u32 user_regs_array_size) 363 { 364 return hl_init_pb_with_mask(hdev, num_dcores, dcore_offset, 365 num_instances, instance_offset, pb_blocks, 366 blocks_array_size, user_regs_array, 367 user_regs_array_size, ULLONG_MAX); 368 } 369 370 /** 371 * hl_init_pb_ranges_with_mask - set pb instances using mask in HW according to 372 * given configuration unsecurring registers 373 * ranges instead of specific registers 374 * 375 * @hdev: pointer to hl_device structure 376 * @num_dcores: number of decores to apply configuration to 377 * set to HL_PB_SHARED if need to apply only once 378 * @dcore_offset: offset between dcores 379 * @num_instances: number of instances to apply configuration to 380 * @instance_offset: offset between instances 381 * @pb_blocks: blocks array 382 * @blocks_array_size: blocks array size 383 * @user_regs_range_array: unsecured register range array 384 * @user_regs_range_array_size: unsecured register range array size 385 * @mask: enabled instances mask: 1- enabled, 0- disabled 386 */ 387 int hl_init_pb_ranges_with_mask(struct hl_device *hdev, u32 num_dcores, 388 u32 dcore_offset, u32 num_instances, u32 instance_offset, 389 const u32 pb_blocks[], u32 blocks_array_size, 390 const struct range *user_regs_range_array, 391 u32 user_regs_range_array_size, u64 mask) 392 { 393 int i, j, rc = 0; 394 struct hl_block_glbl_sec *glbl_sec; 395 396 glbl_sec = kcalloc(blocks_array_size, 397 sizeof(struct hl_block_glbl_sec), 398 GFP_KERNEL); 399 if (!glbl_sec) 400 return -ENOMEM; 401 402 hl_secure_block(hdev, glbl_sec, blocks_array_size); 403 rc = hl_unsecure_registers_range(hdev, user_regs_range_array, 404 user_regs_range_array_size, 0, pb_blocks, glbl_sec, 405 blocks_array_size); 406 if (rc) 407 goto free_glbl_sec; 408 409 /* Fill all blocks with the same configuration */ 410 for (i = 0 ; i < num_dcores ; i++) { 411 for (j = 0 ; j < num_instances ; j++) { 412 int seq = i * num_instances + j; 413 414 if (!(mask & BIT_ULL(seq))) 415 continue; 416 417 hl_config_glbl_sec(hdev, pb_blocks, glbl_sec, 418 i * dcore_offset + j * instance_offset, 419 blocks_array_size); 420 } 421 } 422 423 free_glbl_sec: 424 kfree(glbl_sec); 425 426 return rc; 427 } 428 429 /** 430 * hl_init_pb_ranges - set pb in HW according to given configuration unsecurring 431 * registers ranges instead of specific registers 432 * 433 * @hdev: pointer to hl_device structure 434 * @num_dcores: number of decores to apply configuration to 435 * set to HL_PB_SHARED if need to apply only once 436 * @dcore_offset: offset between dcores 437 * @num_instances: number of instances to apply configuration to 438 * @instance_offset: offset between instances 439 * @pb_blocks: blocks array 440 * @blocks_array_size: blocks array size 441 * @user_regs_range_array: unsecured register range array 442 * @user_regs_range_array_size: unsecured register range array size 443 * 444 */ 445 int hl_init_pb_ranges(struct hl_device *hdev, u32 num_dcores, 446 u32 dcore_offset, u32 num_instances, u32 instance_offset, 447 const u32 pb_blocks[], u32 blocks_array_size, 448 const struct range *user_regs_range_array, 449 u32 user_regs_range_array_size) 450 { 451 return hl_init_pb_ranges_with_mask(hdev, num_dcores, dcore_offset, 452 num_instances, instance_offset, pb_blocks, 453 blocks_array_size, user_regs_range_array, 454 user_regs_range_array_size, ULLONG_MAX); 455 } 456 457 /** 458 * hl_init_pb_single_dcore - set pb for a single docre in HW 459 * according to given configuration 460 * 461 * @hdev: pointer to hl_device structure 462 * @dcore_offset: offset from the dcore0 463 * @num_instances: number of instances to apply configuration to 464 * @instance_offset: offset between instances 465 * @pb_blocks: blocks array 466 * @blocks_array_size: blocks array size 467 * @user_regs_array: unsecured register array 468 * @user_regs_array_size: unsecured register array size 469 * 470 */ 471 int hl_init_pb_single_dcore(struct hl_device *hdev, u32 dcore_offset, 472 u32 num_instances, u32 instance_offset, 473 const u32 pb_blocks[], u32 blocks_array_size, 474 const u32 *user_regs_array, u32 user_regs_array_size) 475 { 476 int i, rc = 0; 477 struct hl_block_glbl_sec *glbl_sec; 478 479 glbl_sec = kcalloc(blocks_array_size, 480 sizeof(struct hl_block_glbl_sec), 481 GFP_KERNEL); 482 if (!glbl_sec) 483 return -ENOMEM; 484 485 hl_secure_block(hdev, glbl_sec, blocks_array_size); 486 rc = hl_unsecure_registers(hdev, user_regs_array, user_regs_array_size, 487 0, pb_blocks, glbl_sec, blocks_array_size); 488 if (rc) 489 goto free_glbl_sec; 490 491 /* Fill all blocks with the same configuration */ 492 for (i = 0 ; i < num_instances ; i++) 493 hl_config_glbl_sec(hdev, pb_blocks, glbl_sec, 494 dcore_offset + i * instance_offset, 495 blocks_array_size); 496 497 free_glbl_sec: 498 kfree(glbl_sec); 499 500 return rc; 501 } 502 503 /** 504 * hl_init_pb_ranges_single_dcore - set pb for a single docre in HW according 505 * to given configuration unsecurring 506 * registers ranges instead of specific 507 * registers 508 * 509 * @hdev: pointer to hl_device structure 510 * @dcore_offset: offset from the dcore0 511 * @num_instances: number of instances to apply configuration to 512 * @instance_offset: offset between instances 513 * @pb_blocks: blocks array 514 * @blocks_array_size: blocks array size 515 * @user_regs_range_array: unsecured register range array 516 * @user_regs_range_array_size: unsecured register range array size 517 * 518 */ 519 int hl_init_pb_ranges_single_dcore(struct hl_device *hdev, u32 dcore_offset, 520 u32 num_instances, u32 instance_offset, 521 const u32 pb_blocks[], u32 blocks_array_size, 522 const struct range *user_regs_range_array, u32 user_regs_range_array_size) 523 { 524 int i; 525 struct hl_block_glbl_sec *glbl_sec; 526 527 glbl_sec = kcalloc(blocks_array_size, 528 sizeof(struct hl_block_glbl_sec), 529 GFP_KERNEL); 530 if (!glbl_sec) 531 return -ENOMEM; 532 533 hl_secure_block(hdev, glbl_sec, blocks_array_size); 534 hl_unsecure_registers_range(hdev, user_regs_range_array, 535 user_regs_range_array_size, 0, pb_blocks, glbl_sec, 536 blocks_array_size); 537 538 /* Fill all blocks with the same configuration */ 539 for (i = 0 ; i < num_instances ; i++) 540 hl_config_glbl_sec(hdev, pb_blocks, glbl_sec, 541 dcore_offset + i * instance_offset, 542 blocks_array_size); 543 544 kfree(glbl_sec); 545 546 return 0; 547 } 548 549 /** 550 * hl_ack_pb_with_mask - ack pb with mask in HW according to given configuration 551 * 552 * @hdev: pointer to hl_device structure 553 * @num_dcores: number of decores to apply configuration to 554 * set to HL_PB_SHARED if need to apply only once 555 * @dcore_offset: offset between dcores 556 * @num_instances: number of instances to apply configuration to 557 * @instance_offset: offset between instances 558 * @pb_blocks: blocks array 559 * @blocks_array_size: blocks array size 560 * @mask: enabled instances mask: 1- enabled, 0- disabled 561 * 562 */ 563 void hl_ack_pb_with_mask(struct hl_device *hdev, u32 num_dcores, 564 u32 dcore_offset, u32 num_instances, u32 instance_offset, 565 const u32 pb_blocks[], u32 blocks_array_size, u64 mask) 566 { 567 int i, j; 568 569 /* ack all blocks */ 570 for (i = 0 ; i < num_dcores ; i++) { 571 for (j = 0 ; j < num_instances ; j++) { 572 int seq = i * num_instances + j; 573 574 if (!(mask & BIT_ULL(seq))) 575 continue; 576 577 hl_ack_pb_security_violations(hdev, pb_blocks, 578 i * dcore_offset + j * instance_offset, 579 blocks_array_size); 580 } 581 } 582 } 583 584 /** 585 * hl_ack_pb - ack pb in HW according to given configuration 586 * 587 * @hdev: pointer to hl_device structure 588 * @num_dcores: number of decores to apply configuration to 589 * set to HL_PB_SHARED if need to apply only once 590 * @dcore_offset: offset between dcores 591 * @num_instances: number of instances to apply configuration to 592 * @instance_offset: offset between instances 593 * @pb_blocks: blocks array 594 * @blocks_array_size: blocks array size 595 * 596 */ 597 void hl_ack_pb(struct hl_device *hdev, u32 num_dcores, u32 dcore_offset, 598 u32 num_instances, u32 instance_offset, 599 const u32 pb_blocks[], u32 blocks_array_size) 600 { 601 hl_ack_pb_with_mask(hdev, num_dcores, dcore_offset, num_instances, 602 instance_offset, pb_blocks, blocks_array_size, 603 ULLONG_MAX); 604 } 605 606 /** 607 * hl_ack_pb_single_dcore - ack pb for single docre in HW 608 * according to given configuration 609 * 610 * @hdev: pointer to hl_device structure 611 * @dcore_offset: offset from dcore0 612 * @num_instances: number of instances to apply configuration to 613 * @instance_offset: offset between instances 614 * @pb_blocks: blocks array 615 * @blocks_array_size: blocks array size 616 * 617 */ 618 void hl_ack_pb_single_dcore(struct hl_device *hdev, u32 dcore_offset, 619 u32 num_instances, u32 instance_offset, 620 const u32 pb_blocks[], u32 blocks_array_size) 621 { 622 int i; 623 624 /* ack all blocks */ 625 for (i = 0 ; i < num_instances ; i++) 626 hl_ack_pb_security_violations(hdev, pb_blocks, 627 dcore_offset + i * instance_offset, 628 blocks_array_size); 629 630 } 631 632 static u32 hl_automated_get_block_base_addr(struct hl_device *hdev, 633 struct hl_special_block_info *block_info, 634 u32 major, u32 minor, u32 sub_minor) 635 { 636 u32 fw_block_base_address = block_info->base_addr + 637 major * block_info->major_offset + 638 minor * block_info->minor_offset + 639 sub_minor * block_info->sub_minor_offset; 640 struct asic_fixed_properties *prop = &hdev->asic_prop; 641 642 /* Calculation above returns an address for FW use, and therefore should 643 * be casted for driver use. 644 */ 645 return (fw_block_base_address - lower_32_bits(prop->cfg_base_address)); 646 } 647 648 static bool hl_check_block_type_exclusion(struct hl_skip_blocks_cfg *skip_blocks_cfg, 649 int block_type) 650 { 651 int i; 652 653 /* Check if block type is listed in the exclusion list of block types */ 654 for (i = 0 ; i < skip_blocks_cfg->block_types_len ; i++) 655 if (block_type == skip_blocks_cfg->block_types[i]) 656 return true; 657 658 return false; 659 } 660 661 static bool hl_check_block_range_exclusion(struct hl_device *hdev, 662 struct hl_skip_blocks_cfg *skip_blocks_cfg, 663 struct hl_special_block_info *block_info, 664 u32 major, u32 minor, u32 sub_minor) 665 { 666 u32 blocks_in_range, block_base_addr_in_range, block_base_addr; 667 int i, j; 668 669 block_base_addr = hl_automated_get_block_base_addr(hdev, block_info, 670 major, minor, sub_minor); 671 672 for (i = 0 ; i < skip_blocks_cfg->block_ranges_len ; i++) { 673 blocks_in_range = (skip_blocks_cfg->block_ranges[i].end - 674 skip_blocks_cfg->block_ranges[i].start) / 675 HL_BLOCK_SIZE + 1; 676 for (j = 0 ; j < blocks_in_range ; j++) { 677 block_base_addr_in_range = skip_blocks_cfg->block_ranges[i].start + 678 j * HL_BLOCK_SIZE; 679 if (block_base_addr == block_base_addr_in_range) 680 return true; 681 } 682 } 683 684 return false; 685 } 686 687 static int hl_read_glbl_errors(struct hl_device *hdev, 688 u32 blk_idx, u32 major, u32 minor, u32 sub_minor, void *data) 689 { 690 struct asic_fixed_properties *prop = &hdev->asic_prop; 691 struct hl_special_block_info *special_blocks = prop->special_blocks; 692 struct hl_special_block_info *current_block = &special_blocks[blk_idx]; 693 u32 glbl_err_addr, glbl_err_cause, addr_val, cause_val, block_base, 694 base = current_block->base_addr - lower_32_bits(prop->cfg_base_address); 695 int i; 696 697 block_base = base + major * current_block->major_offset + 698 minor * current_block->minor_offset + 699 sub_minor * current_block->sub_minor_offset; 700 701 glbl_err_cause = block_base + HL_GLBL_ERR_CAUSE_OFFSET; 702 cause_val = RREG32(glbl_err_cause); 703 if (!cause_val) 704 return 0; 705 706 glbl_err_addr = block_base + HL_GLBL_ERR_ADDR_OFFSET; 707 addr_val = RREG32(glbl_err_addr); 708 709 for (i = 0 ; i <= prop->glbl_err_max_cause_num ; i++) { 710 if (cause_val & BIT(i)) 711 dev_err_ratelimited(hdev->dev, 712 "%s, addr %#llx\n", 713 hl_glbl_error_cause[i], 714 prop->cfg_base_address + block_base + 715 FIELD_GET(HL_GLBL_ERR_ADDRESS_MASK, addr_val)); 716 } 717 718 WREG32(glbl_err_cause, cause_val); 719 720 return 0; 721 } 722 723 void hl_check_for_glbl_errors(struct hl_device *hdev) 724 { 725 struct asic_fixed_properties *prop = &hdev->asic_prop; 726 struct hl_special_blocks_cfg special_blocks_cfg; 727 struct iterate_special_ctx glbl_err_iter; 728 int rc; 729 730 memset(&special_blocks_cfg, 0, sizeof(special_blocks_cfg)); 731 special_blocks_cfg.skip_blocks_cfg = &prop->skip_special_blocks_cfg; 732 733 glbl_err_iter.fn = &hl_read_glbl_errors; 734 glbl_err_iter.data = &special_blocks_cfg; 735 736 rc = hl_iterate_special_blocks(hdev, &glbl_err_iter); 737 if (rc) 738 dev_err_ratelimited(hdev->dev, 739 "Could not iterate special blocks, glbl error check failed\n"); 740 } 741 742 int hl_iterate_special_blocks(struct hl_device *hdev, struct iterate_special_ctx *ctx) 743 { 744 struct hl_special_blocks_cfg *special_blocks_cfg = 745 (struct hl_special_blocks_cfg *)ctx->data; 746 struct hl_skip_blocks_cfg *skip_blocks_cfg = 747 special_blocks_cfg->skip_blocks_cfg; 748 u32 major, minor, sub_minor, blk_idx, num_blocks; 749 struct hl_special_block_info *block_info_arr; 750 int rc; 751 752 block_info_arr = hdev->asic_prop.special_blocks; 753 if (!block_info_arr) 754 return -EINVAL; 755 756 num_blocks = hdev->asic_prop.num_of_special_blocks; 757 758 for (blk_idx = 0 ; blk_idx < num_blocks ; blk_idx++, block_info_arr++) { 759 if (hl_check_block_type_exclusion(skip_blocks_cfg, block_info_arr->block_type)) 760 continue; 761 762 for (major = 0 ; major < block_info_arr->major ; major++) { 763 minor = 0; 764 do { 765 sub_minor = 0; 766 do { 767 if ((hl_check_block_range_exclusion(hdev, 768 skip_blocks_cfg, block_info_arr, 769 major, minor, sub_minor)) || 770 (skip_blocks_cfg->skip_block_hook && 771 skip_blocks_cfg->skip_block_hook(hdev, 772 special_blocks_cfg, 773 blk_idx, major, minor, sub_minor))) { 774 sub_minor++; 775 continue; 776 } 777 778 rc = ctx->fn(hdev, blk_idx, major, minor, 779 sub_minor, ctx->data); 780 if (rc) 781 return rc; 782 783 sub_minor++; 784 } while (sub_minor < block_info_arr->sub_minor); 785 786 minor++; 787 } while (minor < block_info_arr->minor); 788 } 789 } 790 791 return 0; 792 } 793