1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright(c) 2022 Intel Corporation. */ 3 4 #include <linux/cpu.h> 5 #include <linux/delay.h> 6 #include <linux/fs.h> 7 #include <linux/nmi.h> 8 #include <linux/slab.h> 9 #include <linux/stop_machine.h> 10 11 #include "ifs.h" 12 13 /* 14 * Note all code and data in this file is protected by 15 * ifs_sem. On HT systems all threads on a core will 16 * execute together, but only the first thread on the 17 * core will update results of the test. 18 */ 19 20 #define CREATE_TRACE_POINTS 21 #include <trace/events/intel_ifs.h> 22 23 /* Max retries on the same chunk */ 24 #define MAX_IFS_RETRIES 5 25 26 struct run_params { 27 struct ifs_data *ifsd; 28 union ifs_scan *activate; 29 union ifs_status status; 30 }; 31 32 struct sbaf_run_params { 33 struct ifs_data *ifsd; 34 int *retry_cnt; 35 union ifs_sbaf *activate; 36 union ifs_sbaf_status status; 37 }; 38 39 /* 40 * Number of TSC cycles that a logical CPU will wait for the other 41 * logical CPU on the core in the WRMSR(ACTIVATE_SCAN). 42 */ 43 #define IFS_THREAD_WAIT 100000 44 45 enum ifs_status_err_code { 46 IFS_NO_ERROR = 0, 47 IFS_OTHER_THREAD_COULD_NOT_JOIN = 1, 48 IFS_INTERRUPTED_BEFORE_RENDEZVOUS = 2, 49 IFS_POWER_MGMT_INADEQUATE_FOR_SCAN = 3, 50 IFS_INVALID_CHUNK_RANGE = 4, 51 IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS = 5, 52 IFS_CORE_NOT_CAPABLE_CURRENTLY = 6, 53 IFS_UNASSIGNED_ERROR_CODE = 7, 54 IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT = 8, 55 IFS_INTERRUPTED_DURING_EXECUTION = 9, 56 IFS_UNASSIGNED_ERROR_CODE_0xA = 0xA, 57 IFS_CORRUPTED_CHUNK = 0xB, 58 }; 59 60 static const char * const scan_test_status[] = { 61 [IFS_NO_ERROR] = "SCAN no error", 62 [IFS_OTHER_THREAD_COULD_NOT_JOIN] = "Other thread could not join.", 63 [IFS_INTERRUPTED_BEFORE_RENDEZVOUS] = "Interrupt occurred prior to SCAN coordination.", 64 [IFS_POWER_MGMT_INADEQUATE_FOR_SCAN] = 65 "Core Abort SCAN Response due to power management condition.", 66 [IFS_INVALID_CHUNK_RANGE] = "Non valid chunks in the range", 67 [IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS] = "Mismatch in arguments between threads T0/T1.", 68 [IFS_CORE_NOT_CAPABLE_CURRENTLY] = "Core not capable of performing SCAN currently", 69 [IFS_UNASSIGNED_ERROR_CODE] = "Unassigned error code 0x7", 70 [IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT] = 71 "Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently", 72 [IFS_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SCAN start", 73 [IFS_UNASSIGNED_ERROR_CODE_0xA] = "Unassigned error code 0xA", 74 [IFS_CORRUPTED_CHUNK] = "Scan operation aborted due to corrupted image. Try reloading", 75 }; 76 77 static void message_not_tested(struct device *dev, int cpu, union ifs_status status) 78 { 79 struct ifs_data *ifsd = ifs_get_data(dev); 80 81 /* 82 * control_error is set when the microcode runs into a problem 83 * loading the image from the reserved BIOS memory, or it has 84 * been corrupted. Reloading the image may fix this issue. 85 */ 86 if (status.control_error) { 87 dev_warn(dev, "CPU(s) %*pbl: Scan controller error. Batch: %02x version: 0x%x\n", 88 cpumask_pr_args(cpu_smt_mask(cpu)), ifsd->cur_batch, ifsd->loaded_version); 89 return; 90 } 91 92 if (status.error_code < ARRAY_SIZE(scan_test_status)) { 93 dev_info(dev, "CPU(s) %*pbl: SCAN operation did not start. %s\n", 94 cpumask_pr_args(cpu_smt_mask(cpu)), 95 scan_test_status[status.error_code]); 96 } else if (status.error_code == IFS_SW_TIMEOUT) { 97 dev_info(dev, "CPU(s) %*pbl: software timeout during scan\n", 98 cpumask_pr_args(cpu_smt_mask(cpu))); 99 } else if (status.error_code == IFS_SW_PARTIAL_COMPLETION) { 100 dev_info(dev, "CPU(s) %*pbl: %s\n", 101 cpumask_pr_args(cpu_smt_mask(cpu)), 102 "Not all scan chunks were executed. Maximum forward progress retries exceeded"); 103 } else { 104 dev_info(dev, "CPU(s) %*pbl: SCAN unknown status %llx\n", 105 cpumask_pr_args(cpu_smt_mask(cpu)), status.data); 106 } 107 } 108 109 static void message_fail(struct device *dev, int cpu, union ifs_status status) 110 { 111 struct ifs_data *ifsd = ifs_get_data(dev); 112 113 /* 114 * signature_error is set when the output from the scan chains does not 115 * match the expected signature. This might be a transient problem (e.g. 116 * due to a bit flip from an alpha particle or neutron). If the problem 117 * repeats on a subsequent test, then it indicates an actual problem in 118 * the core being tested. 119 */ 120 if (status.signature_error) { 121 dev_err(dev, "CPU(s) %*pbl: test signature incorrect. Batch: %02x version: 0x%x\n", 122 cpumask_pr_args(cpu_smt_mask(cpu)), ifsd->cur_batch, ifsd->loaded_version); 123 } 124 } 125 126 static bool can_restart(union ifs_status status) 127 { 128 enum ifs_status_err_code err_code = status.error_code; 129 130 /* Signature for chunk is bad, or scan test failed */ 131 if (status.signature_error || status.control_error) 132 return false; 133 134 switch (err_code) { 135 case IFS_NO_ERROR: 136 case IFS_OTHER_THREAD_COULD_NOT_JOIN: 137 case IFS_INTERRUPTED_BEFORE_RENDEZVOUS: 138 case IFS_POWER_MGMT_INADEQUATE_FOR_SCAN: 139 case IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT: 140 case IFS_INTERRUPTED_DURING_EXECUTION: 141 return true; 142 case IFS_INVALID_CHUNK_RANGE: 143 case IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS: 144 case IFS_CORE_NOT_CAPABLE_CURRENTLY: 145 case IFS_UNASSIGNED_ERROR_CODE: 146 case IFS_UNASSIGNED_ERROR_CODE_0xA: 147 case IFS_CORRUPTED_CHUNK: 148 break; 149 } 150 return false; 151 } 152 153 #define SPINUNIT 100 /* 100 nsec */ 154 static atomic_t array_cpus_in; 155 static atomic_t scan_cpus_in; 156 static atomic_t sbaf_cpus_in; 157 158 /* 159 * Simplified cpu sibling rendezvous loop based on microcode loader __wait_for_cpus() 160 */ 161 static void wait_for_sibling_cpu(atomic_t *t, long long timeout) 162 { 163 int cpu = smp_processor_id(); 164 const struct cpumask *smt_mask = cpu_smt_mask(cpu); 165 int all_cpus = cpumask_weight(smt_mask); 166 167 atomic_inc(t); 168 while (atomic_read(t) < all_cpus) { 169 if (timeout < SPINUNIT) 170 return; 171 ndelay(SPINUNIT); 172 timeout -= SPINUNIT; 173 touch_nmi_watchdog(); 174 } 175 } 176 177 /* 178 * Execute the scan. Called "simultaneously" on all threads of a core 179 * at high priority using the stop_cpus mechanism. 180 */ 181 static int doscan(void *data) 182 { 183 int cpu = smp_processor_id(), start, stop; 184 struct run_params *params = data; 185 union ifs_status status; 186 struct ifs_data *ifsd; 187 int first; 188 189 ifsd = params->ifsd; 190 191 if (ifsd->generation) { 192 start = params->activate->gen2.start; 193 stop = params->activate->gen2.stop; 194 } else { 195 start = params->activate->gen0.start; 196 stop = params->activate->gen0.stop; 197 } 198 199 /* Only the first logical CPU on a core reports result */ 200 first = cpumask_first(cpu_smt_mask(cpu)); 201 202 wait_for_sibling_cpu(&scan_cpus_in, NSEC_PER_SEC); 203 204 /* 205 * This WRMSR will wait for other HT threads to also write 206 * to this MSR (at most for activate.delay cycles). Then it 207 * starts scan of each requested chunk. The core scan happens 208 * during the "execution" of the WRMSR. This instruction can 209 * take up to 200 milliseconds (in the case where all chunks 210 * are processed in a single pass) before it retires. 211 */ 212 wrmsrl(MSR_ACTIVATE_SCAN, params->activate->data); 213 rdmsrl(MSR_SCAN_STATUS, status.data); 214 215 trace_ifs_status(ifsd->cur_batch, start, stop, status.data); 216 217 /* Pass back the result of the scan */ 218 if (cpu == first) 219 params->status = status; 220 221 return 0; 222 } 223 224 /* 225 * Use stop_core_cpuslocked() to synchronize writing to MSR_ACTIVATE_SCAN 226 * on all threads of the core to be tested. Loop if necessary to complete 227 * run of all chunks. Include some defensive tests to make sure forward 228 * progress is made, and that the whole test completes in a reasonable time. 229 */ 230 static void ifs_test_core(int cpu, struct device *dev) 231 { 232 union ifs_status status = {}; 233 union ifs_scan activate; 234 unsigned long timeout; 235 struct ifs_data *ifsd; 236 int to_start, to_stop; 237 int status_chunk; 238 struct run_params params; 239 int retries; 240 241 ifsd = ifs_get_data(dev); 242 243 activate.gen0.rsvd = 0; 244 activate.delay = IFS_THREAD_WAIT; 245 activate.sigmce = 0; 246 to_start = 0; 247 to_stop = ifsd->valid_chunks - 1; 248 249 params.ifsd = ifs_get_data(dev); 250 251 if (ifsd->generation) { 252 activate.gen2.start = to_start; 253 activate.gen2.stop = to_stop; 254 } else { 255 activate.gen0.start = to_start; 256 activate.gen0.stop = to_stop; 257 } 258 259 timeout = jiffies + HZ / 2; 260 retries = MAX_IFS_RETRIES; 261 262 while (to_start <= to_stop) { 263 if (time_after(jiffies, timeout)) { 264 status.error_code = IFS_SW_TIMEOUT; 265 break; 266 } 267 268 params.activate = &activate; 269 atomic_set(&scan_cpus_in, 0); 270 stop_core_cpuslocked(cpu, doscan, ¶ms); 271 272 status = params.status; 273 274 /* Some cases can be retried, give up for others */ 275 if (!can_restart(status)) 276 break; 277 278 status_chunk = ifsd->generation ? status.gen2.chunk_num : status.gen0.chunk_num; 279 if (status_chunk == to_start) { 280 /* Check for forward progress */ 281 if (--retries == 0) { 282 if (status.error_code == IFS_NO_ERROR) 283 status.error_code = IFS_SW_PARTIAL_COMPLETION; 284 break; 285 } 286 } else { 287 retries = MAX_IFS_RETRIES; 288 if (ifsd->generation) 289 activate.gen2.start = status_chunk; 290 else 291 activate.gen0.start = status_chunk; 292 to_start = status_chunk; 293 } 294 } 295 296 /* Update status for this core */ 297 ifsd->scan_details = status.data; 298 299 if (status.signature_error) { 300 ifsd->status = SCAN_TEST_FAIL; 301 message_fail(dev, cpu, status); 302 } else if (status.control_error || status.error_code) { 303 ifsd->status = SCAN_NOT_TESTED; 304 message_not_tested(dev, cpu, status); 305 } else { 306 ifsd->status = SCAN_TEST_PASS; 307 } 308 } 309 310 static int do_array_test(void *data) 311 { 312 union ifs_array *command = data; 313 int cpu = smp_processor_id(); 314 int first; 315 316 wait_for_sibling_cpu(&array_cpus_in, NSEC_PER_SEC); 317 318 /* 319 * Only one logical CPU on a core needs to trigger the Array test via MSR write. 320 */ 321 first = cpumask_first(cpu_smt_mask(cpu)); 322 323 if (cpu == first) { 324 wrmsrl(MSR_ARRAY_BIST, command->data); 325 /* Pass back the result of the test */ 326 rdmsrl(MSR_ARRAY_BIST, command->data); 327 } 328 329 return 0; 330 } 331 332 static void ifs_array_test_core(int cpu, struct device *dev) 333 { 334 union ifs_array command = {}; 335 bool timed_out = false; 336 struct ifs_data *ifsd; 337 unsigned long timeout; 338 339 ifsd = ifs_get_data(dev); 340 341 command.array_bitmask = ~0U; 342 timeout = jiffies + HZ / 2; 343 344 do { 345 if (time_after(jiffies, timeout)) { 346 timed_out = true; 347 break; 348 } 349 atomic_set(&array_cpus_in, 0); 350 stop_core_cpuslocked(cpu, do_array_test, &command); 351 352 if (command.ctrl_result) 353 break; 354 } while (command.array_bitmask); 355 356 ifsd->scan_details = command.data; 357 358 if (command.ctrl_result) 359 ifsd->status = SCAN_TEST_FAIL; 360 else if (timed_out || command.array_bitmask) 361 ifsd->status = SCAN_NOT_TESTED; 362 else 363 ifsd->status = SCAN_TEST_PASS; 364 } 365 366 #define ARRAY_GEN1_TEST_ALL_ARRAYS 0x0ULL 367 #define ARRAY_GEN1_STATUS_FAIL 0x1ULL 368 369 static int do_array_test_gen1(void *status) 370 { 371 int cpu = smp_processor_id(); 372 int first; 373 374 first = cpumask_first(cpu_smt_mask(cpu)); 375 376 if (cpu == first) { 377 wrmsrl(MSR_ARRAY_TRIGGER, ARRAY_GEN1_TEST_ALL_ARRAYS); 378 rdmsrl(MSR_ARRAY_STATUS, *((u64 *)status)); 379 } 380 381 return 0; 382 } 383 384 static void ifs_array_test_gen1(int cpu, struct device *dev) 385 { 386 struct ifs_data *ifsd = ifs_get_data(dev); 387 u64 status = 0; 388 389 stop_core_cpuslocked(cpu, do_array_test_gen1, &status); 390 ifsd->scan_details = status; 391 392 if (status & ARRAY_GEN1_STATUS_FAIL) 393 ifsd->status = SCAN_TEST_FAIL; 394 else 395 ifsd->status = SCAN_TEST_PASS; 396 } 397 398 #define SBAF_STATUS_PASS 0 399 #define SBAF_STATUS_SIGN_FAIL 1 400 #define SBAF_STATUS_INTR 2 401 #define SBAF_STATUS_TEST_FAIL 3 402 403 enum sbaf_status_err_code { 404 IFS_SBAF_NO_ERROR = 0, 405 IFS_SBAF_OTHER_THREAD_COULD_NOT_JOIN = 1, 406 IFS_SBAF_INTERRUPTED_BEFORE_RENDEZVOUS = 2, 407 IFS_SBAF_UNASSIGNED_ERROR_CODE3 = 3, 408 IFS_SBAF_INVALID_BUNDLE_INDEX = 4, 409 IFS_SBAF_MISMATCH_ARGS_BETWEEN_THREADS = 5, 410 IFS_SBAF_CORE_NOT_CAPABLE_CURRENTLY = 6, 411 IFS_SBAF_UNASSIGNED_ERROR_CODE7 = 7, 412 IFS_SBAF_EXCEED_NUMBER_OF_THREADS_CONCURRENT = 8, 413 IFS_SBAF_INTERRUPTED_DURING_EXECUTION = 9, 414 IFS_SBAF_INVALID_PROGRAM_INDEX = 0xA, 415 IFS_SBAF_CORRUPTED_CHUNK = 0xB, 416 IFS_SBAF_DID_NOT_START = 0xC, 417 }; 418 419 static const char * const sbaf_test_status[] = { 420 [IFS_SBAF_NO_ERROR] = "SBAF no error", 421 [IFS_SBAF_OTHER_THREAD_COULD_NOT_JOIN] = "Other thread could not join.", 422 [IFS_SBAF_INTERRUPTED_BEFORE_RENDEZVOUS] = "Interrupt occurred prior to SBAF coordination.", 423 [IFS_SBAF_UNASSIGNED_ERROR_CODE3] = "Unassigned error code 0x3", 424 [IFS_SBAF_INVALID_BUNDLE_INDEX] = "Non-valid sbaf bundles. Reload test image", 425 [IFS_SBAF_MISMATCH_ARGS_BETWEEN_THREADS] = "Mismatch in arguments between threads T0/T1.", 426 [IFS_SBAF_CORE_NOT_CAPABLE_CURRENTLY] = "Core not capable of performing SBAF currently", 427 [IFS_SBAF_UNASSIGNED_ERROR_CODE7] = "Unassigned error code 0x7", 428 [IFS_SBAF_EXCEED_NUMBER_OF_THREADS_CONCURRENT] = "Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently", 429 [IFS_SBAF_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SBAF start", 430 [IFS_SBAF_INVALID_PROGRAM_INDEX] = "SBAF program index not valid", 431 [IFS_SBAF_CORRUPTED_CHUNK] = "SBAF operation aborted due to corrupted chunk", 432 [IFS_SBAF_DID_NOT_START] = "SBAF operation did not start", 433 }; 434 435 static void sbaf_message_not_tested(struct device *dev, int cpu, u64 status_data) 436 { 437 union ifs_sbaf_status status = (union ifs_sbaf_status)status_data; 438 439 if (status.error_code < ARRAY_SIZE(sbaf_test_status)) { 440 dev_info(dev, "CPU(s) %*pbl: SBAF operation did not start. %s\n", 441 cpumask_pr_args(cpu_smt_mask(cpu)), 442 sbaf_test_status[status.error_code]); 443 } else if (status.error_code == IFS_SW_TIMEOUT) { 444 dev_info(dev, "CPU(s) %*pbl: software timeout during scan\n", 445 cpumask_pr_args(cpu_smt_mask(cpu))); 446 } else if (status.error_code == IFS_SW_PARTIAL_COMPLETION) { 447 dev_info(dev, "CPU(s) %*pbl: %s\n", 448 cpumask_pr_args(cpu_smt_mask(cpu)), 449 "Not all SBAF bundles executed. Maximum forward progress retries exceeded"); 450 } else { 451 dev_info(dev, "CPU(s) %*pbl: SBAF unknown status %llx\n", 452 cpumask_pr_args(cpu_smt_mask(cpu)), status.data); 453 } 454 } 455 456 static void sbaf_message_fail(struct device *dev, int cpu, union ifs_sbaf_status status) 457 { 458 /* Failed signature check is set when SBAF signature did not match the expected value */ 459 if (status.sbaf_status == SBAF_STATUS_SIGN_FAIL) { 460 dev_err(dev, "CPU(s) %*pbl: Failed signature check\n", 461 cpumask_pr_args(cpu_smt_mask(cpu))); 462 } 463 464 /* Failed to reach end of test */ 465 if (status.sbaf_status == SBAF_STATUS_TEST_FAIL) { 466 dev_err(dev, "CPU(s) %*pbl: Failed to complete test\n", 467 cpumask_pr_args(cpu_smt_mask(cpu))); 468 } 469 } 470 471 static bool sbaf_bundle_completed(union ifs_sbaf_status status) 472 { 473 return !(status.sbaf_status || status.error_code); 474 } 475 476 static bool sbaf_can_restart(union ifs_sbaf_status status) 477 { 478 enum sbaf_status_err_code err_code = status.error_code; 479 480 /* Signature for chunk is bad, or scan test failed */ 481 if (status.sbaf_status == SBAF_STATUS_SIGN_FAIL || 482 status.sbaf_status == SBAF_STATUS_TEST_FAIL) 483 return false; 484 485 switch (err_code) { 486 case IFS_SBAF_NO_ERROR: 487 case IFS_SBAF_OTHER_THREAD_COULD_NOT_JOIN: 488 case IFS_SBAF_INTERRUPTED_BEFORE_RENDEZVOUS: 489 case IFS_SBAF_EXCEED_NUMBER_OF_THREADS_CONCURRENT: 490 case IFS_SBAF_INTERRUPTED_DURING_EXECUTION: 491 return true; 492 case IFS_SBAF_UNASSIGNED_ERROR_CODE3: 493 case IFS_SBAF_INVALID_BUNDLE_INDEX: 494 case IFS_SBAF_MISMATCH_ARGS_BETWEEN_THREADS: 495 case IFS_SBAF_CORE_NOT_CAPABLE_CURRENTLY: 496 case IFS_SBAF_UNASSIGNED_ERROR_CODE7: 497 case IFS_SBAF_INVALID_PROGRAM_INDEX: 498 case IFS_SBAF_CORRUPTED_CHUNK: 499 case IFS_SBAF_DID_NOT_START: 500 break; 501 } 502 return false; 503 } 504 505 /* 506 * Execute the SBAF test. Called "simultaneously" on all threads of a core 507 * at high priority using the stop_cpus mechanism. 508 */ 509 static int dosbaf(void *data) 510 { 511 struct sbaf_run_params *run_params = data; 512 int cpu = smp_processor_id(); 513 union ifs_sbaf_status status; 514 struct ifs_data *ifsd; 515 int first; 516 517 ifsd = run_params->ifsd; 518 519 /* Only the first logical CPU on a core reports result */ 520 first = cpumask_first(cpu_smt_mask(cpu)); 521 wait_for_sibling_cpu(&sbaf_cpus_in, NSEC_PER_SEC); 522 523 /* 524 * This WRMSR will wait for other HT threads to also write 525 * to this MSR (at most for activate.delay cycles). Then it 526 * starts scan of each requested bundle. The core test happens 527 * during the "execution" of the WRMSR. 528 */ 529 wrmsrl(MSR_ACTIVATE_SBAF, run_params->activate->data); 530 rdmsrl(MSR_SBAF_STATUS, status.data); 531 trace_ifs_sbaf(ifsd->cur_batch, *run_params->activate, status); 532 533 /* Pass back the result of the test */ 534 if (cpu == first) 535 run_params->status = status; 536 537 return 0; 538 } 539 540 static void ifs_sbaf_test_core(int cpu, struct device *dev) 541 { 542 struct sbaf_run_params run_params; 543 union ifs_sbaf_status status = {}; 544 union ifs_sbaf activate; 545 unsigned long timeout; 546 struct ifs_data *ifsd; 547 int stop_bundle; 548 int retries; 549 550 ifsd = ifs_get_data(dev); 551 552 activate.data = 0; 553 activate.delay = IFS_THREAD_WAIT; 554 555 timeout = jiffies + 2 * HZ; 556 retries = MAX_IFS_RETRIES; 557 activate.bundle_idx = 0; 558 stop_bundle = ifsd->max_bundle; 559 560 while (activate.bundle_idx <= stop_bundle) { 561 if (time_after(jiffies, timeout)) { 562 status.error_code = IFS_SW_TIMEOUT; 563 break; 564 } 565 566 atomic_set(&sbaf_cpus_in, 0); 567 568 run_params.ifsd = ifsd; 569 run_params.activate = &activate; 570 run_params.retry_cnt = &retries; 571 stop_core_cpuslocked(cpu, dosbaf, &run_params); 572 573 status = run_params.status; 574 575 if (sbaf_bundle_completed(status)) { 576 activate.bundle_idx = status.bundle_idx + 1; 577 activate.pgm_idx = 0; 578 retries = MAX_IFS_RETRIES; 579 continue; 580 } 581 582 /* Some cases can be retried, give up for others */ 583 if (!sbaf_can_restart(status)) 584 break; 585 586 if (status.pgm_idx == activate.pgm_idx) { 587 /* If no progress retry */ 588 if (--retries == 0) { 589 if (status.error_code == IFS_NO_ERROR) 590 status.error_code = IFS_SW_PARTIAL_COMPLETION; 591 break; 592 } 593 } else { 594 /* if some progress, more pgms remaining in bundle, reset retries */ 595 retries = MAX_IFS_RETRIES; 596 activate.bundle_idx = status.bundle_idx; 597 activate.pgm_idx = status.pgm_idx; 598 } 599 } 600 601 /* Update status for this core */ 602 ifsd->scan_details = status.data; 603 604 if (status.sbaf_status == SBAF_STATUS_SIGN_FAIL || 605 status.sbaf_status == SBAF_STATUS_TEST_FAIL) { 606 ifsd->status = SCAN_TEST_FAIL; 607 sbaf_message_fail(dev, cpu, status); 608 } else if (status.error_code || status.sbaf_status == SBAF_STATUS_INTR || 609 (activate.bundle_idx < stop_bundle)) { 610 ifsd->status = SCAN_NOT_TESTED; 611 sbaf_message_not_tested(dev, cpu, status.data); 612 } else { 613 ifsd->status = SCAN_TEST_PASS; 614 } 615 } 616 617 /* 618 * Initiate per core test. It wakes up work queue threads on the target cpu and 619 * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and 620 * wait for all sibling threads to finish the scan test. 621 */ 622 int do_core_test(int cpu, struct device *dev) 623 { 624 const struct ifs_test_caps *test = ifs_get_test_caps(dev); 625 struct ifs_data *ifsd = ifs_get_data(dev); 626 int ret = 0; 627 628 /* Prevent CPUs from being taken offline during the scan test */ 629 cpus_read_lock(); 630 631 if (!cpu_online(cpu)) { 632 dev_info(dev, "cannot test on the offline cpu %d\n", cpu); 633 ret = -EINVAL; 634 goto out; 635 } 636 637 switch (test->test_num) { 638 case IFS_TYPE_SAF: 639 if (!ifsd->loaded) 640 ret = -EPERM; 641 else 642 ifs_test_core(cpu, dev); 643 break; 644 case IFS_TYPE_ARRAY_BIST: 645 if (ifsd->array_gen == ARRAY_GEN0) 646 ifs_array_test_core(cpu, dev); 647 else 648 ifs_array_test_gen1(cpu, dev); 649 break; 650 case IFS_TYPE_SBAF: 651 if (!ifsd->loaded) 652 ret = -EPERM; 653 else 654 ifs_sbaf_test_core(cpu, dev); 655 break; 656 default: 657 ret = -EINVAL; 658 } 659 out: 660 cpus_read_unlock(); 661 return ret; 662 } 663