diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gv100/nvlink_gv100.c | 242 |
1 files changed, 164 insertions, 78 deletions
diff --git a/drivers/gpu/nvgpu/gv100/nvlink_gv100.c b/drivers/gpu/nvgpu/gv100/nvlink_gv100.c index 9d99242f..10e7b149 100644 --- a/drivers/gpu/nvgpu/gv100/nvlink_gv100.c +++ b/drivers/gpu/nvgpu/gv100/nvlink_gv100.c | |||
@@ -95,19 +95,6 @@ | |||
95 | minion_falcon_irqdest_target_swgen0_host_normal_f() | \ | 95 | minion_falcon_irqdest_target_swgen0_host_normal_f() | \ |
96 | minion_falcon_irqdest_target_swgen1_host_normal_f()) | 96 | minion_falcon_irqdest_target_swgen1_host_normal_f()) |
97 | 97 | ||
98 | /* Minion FW header format */ | ||
99 | union gv100_minion_hdr { | ||
100 | struct { | ||
101 | u32 os_code_offset; | ||
102 | u32 os_code_size; | ||
103 | u32 os_data_offset; | ||
104 | u32 os_data_size; | ||
105 | u32 num_apps; | ||
106 | u32 app_0_code_start; | ||
107 | }; | ||
108 | u8 raw_data[256]; | ||
109 | }; | ||
110 | |||
111 | struct __nvlink_reginit { | 98 | struct __nvlink_reginit { |
112 | u32 addr; | 99 | u32 addr; |
113 | u32 value; | 100 | u32 value; |
@@ -443,20 +430,35 @@ static bool gv100_nvlink_minion_isr(struct gk20a *g) { | |||
443 | return (intr == 0); | 430 | return (intr == 0); |
444 | } | 431 | } |
445 | 432 | ||
433 | /* Extract a WORD from the MINION ucode */ | ||
434 | static inline u32 minion_extract_word(struct nvgpu_firmware *fw, u32 idx) | ||
435 | { | ||
436 | u32 out_data = 0; | ||
437 | u8 byte = 0; | ||
438 | u32 i = 0; | ||
439 | |||
440 | for (i = 0; i < 4; i++) { | ||
441 | byte = fw->data[idx + i]; | ||
442 | out_data |= ((u32)byte) << (8 * i); | ||
443 | } | ||
444 | |||
445 | return out_data; | ||
446 | } | ||
447 | |||
446 | /* | 448 | /* |
447 | * Load minion FW and set up bootstrap | 449 | * Load minion FW and set up bootstrap |
448 | */ | 450 | */ |
449 | static u32 gv100_nvlink_minion_load(struct gk20a *g) | 451 | static u32 gv100_nvlink_minion_load(struct gk20a *g) |
450 | { | 452 | { |
451 | struct bin_hdr *hdr = NULL; | ||
452 | struct nvgpu_firmware *minion_fw = NULL; | ||
453 | union gv100_minion_hdr *minion_hdr; | ||
454 | u32 *minion_ucode = NULL; | ||
455 | u32 err = 0; | 453 | u32 err = 0; |
454 | struct nvlink_device *ndev = (struct nvlink_device *) g->nvlink.priv; | ||
455 | struct nvgpu_firmware *nvgpu_minion_fw = NULL; | ||
456 | struct minion_hdr *minion_hdr = &ndev->minion_hdr; | ||
457 | u32 data_idx = 0; | ||
458 | u32 app = 0; | ||
456 | struct nvgpu_timeout timeout; | 459 | struct nvgpu_timeout timeout; |
457 | u32 delay = GR_IDLE_CHECK_DEFAULT; | 460 | u32 delay = GR_IDLE_CHECK_DEFAULT; |
458 | u32 reg; | 461 | u32 reg; |
459 | u32 app; | ||
460 | 462 | ||
461 | nvgpu_log_fn(g, " "); | 463 | nvgpu_log_fn(g, " "); |
462 | 464 | ||
@@ -464,8 +466,8 @@ static u32 gv100_nvlink_minion_load(struct gk20a *g) | |||
464 | return 0; | 466 | return 0; |
465 | 467 | ||
466 | /* get mem unlock ucode binary */ | 468 | /* get mem unlock ucode binary */ |
467 | minion_fw = nvgpu_request_firmware(g, "minion.bin", 0); | 469 | nvgpu_minion_fw = nvgpu_request_firmware(g, "minion.bin", 0); |
468 | if (!minion_fw) { | 470 | if (!nvgpu_minion_fw) { |
469 | nvgpu_err(g, "minion ucode get fail"); | 471 | nvgpu_err(g, "minion ucode get fail"); |
470 | err = -ENOENT; | 472 | err = -ENOENT; |
471 | goto exit; | 473 | goto exit; |
@@ -474,24 +476,125 @@ static u32 gv100_nvlink_minion_load(struct gk20a *g) | |||
474 | /* nvdec falcon reset */ | 476 | /* nvdec falcon reset */ |
475 | nvgpu_flcn_reset(&g->minion_flcn); | 477 | nvgpu_flcn_reset(&g->minion_flcn); |
476 | 478 | ||
477 | hdr = (struct bin_hdr *) minion_fw->data; | 479 | /* Read ucode header */ |
478 | 480 | minion_hdr->os_code_offset = minion_extract_word(nvgpu_minion_fw, | |
479 | minion_hdr = (union gv100_minion_hdr *) (minion_fw->data + | 481 | data_idx); |
480 | hdr->header_offset); | 482 | data_idx += 4; |
481 | minion_ucode = (u32 *) (minion_fw->data + hdr->data_offset); | 483 | minion_hdr->os_code_size = minion_extract_word(nvgpu_minion_fw, |
484 | data_idx); | ||
485 | data_idx += 4; | ||
486 | minion_hdr->os_data_offset = minion_extract_word(nvgpu_minion_fw, | ||
487 | data_idx); | ||
488 | data_idx += 4; | ||
489 | minion_hdr->os_data_size = minion_extract_word(nvgpu_minion_fw, | ||
490 | data_idx); | ||
491 | data_idx += 4; | ||
492 | minion_hdr->num_apps = minion_extract_word(nvgpu_minion_fw, | ||
493 | data_idx); | ||
494 | data_idx += 4; | ||
482 | 495 | ||
483 | nvgpu_log(g, gpu_dbg_nvlink, | 496 | nvgpu_log(g, gpu_dbg_nvlink, |
484 | "os_code_offset: 0x%x", minion_hdr->os_code_offset); | 497 | "MINION Ucode Header Info:"); |
498 | nvgpu_log(g, gpu_dbg_nvlink, | ||
499 | "-------------------------"); | ||
485 | nvgpu_log(g, gpu_dbg_nvlink, | 500 | nvgpu_log(g, gpu_dbg_nvlink, |
486 | "os_code_size: 0x%x", minion_hdr->os_code_size); | 501 | " - OS Code Offset = %u", minion_hdr->os_code_offset); |
487 | nvgpu_log(g, gpu_dbg_nvlink, | 502 | nvgpu_log(g, gpu_dbg_nvlink, |
488 | "os_data_offset: 0x%x", minion_hdr->os_data_offset); | 503 | " - OS Code Size = %u", minion_hdr->os_code_size); |
504 | nvgpu_log(g, gpu_dbg_nvlink, | ||
505 | " - OS Data Offset = %u", minion_hdr->os_data_offset); | ||
506 | nvgpu_log(g, gpu_dbg_nvlink, | ||
507 | " - OS Data Size = %u", minion_hdr->os_data_size); | ||
508 | nvgpu_log(g, gpu_dbg_nvlink, | ||
509 | " - Num Apps = %u", minion_hdr->num_apps); | ||
510 | |||
511 | /* Allocate offset/size arrays for all the ucode apps */ | ||
512 | minion_hdr->app_code_offsets = nvgpu_kcalloc(g, | ||
513 | minion_hdr->num_apps, | ||
514 | sizeof(u32)); | ||
515 | if (!minion_hdr->app_code_offsets) { | ||
516 | nvgpu_err(g, "Couldn't allocate MINION app_code_offsets array"); | ||
517 | err = -ENOMEM; | ||
518 | goto exit; | ||
519 | } | ||
520 | |||
521 | minion_hdr->app_code_sizes = nvgpu_kcalloc(g, | ||
522 | minion_hdr->num_apps, | ||
523 | sizeof(u32)); | ||
524 | if (!minion_hdr->app_code_sizes) { | ||
525 | nvgpu_err(g, "Couldn't allocate MINION app_code_sizes array"); | ||
526 | err = -ENOMEM; | ||
527 | goto exit; | ||
528 | } | ||
529 | |||
530 | minion_hdr->app_data_offsets = nvgpu_kcalloc(g, | ||
531 | minion_hdr->num_apps, | ||
532 | sizeof(u32)); | ||
533 | if (!minion_hdr->app_data_offsets) { | ||
534 | nvgpu_err(g, "Couldn't allocate MINION app_data_offsets array"); | ||
535 | err = -ENOMEM; | ||
536 | goto exit; | ||
537 | } | ||
538 | |||
539 | minion_hdr->app_data_sizes = nvgpu_kcalloc(g, | ||
540 | minion_hdr->num_apps, | ||
541 | sizeof(u32)); | ||
542 | if (!minion_hdr->app_data_sizes) { | ||
543 | nvgpu_err(g, "Couldn't allocate MINION app_data_sizes array"); | ||
544 | err = -ENOMEM; | ||
545 | goto exit; | ||
546 | } | ||
547 | |||
548 | /* Get app code offsets and sizes */ | ||
549 | for (app = 0; app < minion_hdr->num_apps; app++) { | ||
550 | minion_hdr->app_code_offsets[app] = | ||
551 | minion_extract_word(nvgpu_minion_fw, data_idx); | ||
552 | data_idx += 4; | ||
553 | minion_hdr->app_code_sizes[app] = | ||
554 | minion_extract_word(nvgpu_minion_fw, data_idx); | ||
555 | data_idx += 4; | ||
556 | |||
557 | nvgpu_log(g, gpu_dbg_nvlink, | ||
558 | " - App Code:"); | ||
559 | nvgpu_log(g, gpu_dbg_nvlink, | ||
560 | " - App #%d: Code Offset = %u, Code Size = %u", | ||
561 | app, | ||
562 | minion_hdr->app_code_offsets[app], | ||
563 | minion_hdr->app_code_sizes[app]); | ||
564 | } | ||
565 | |||
566 | /* Get app data offsets and sizes */ | ||
567 | for (app = 0; app < minion_hdr->num_apps; app++) { | ||
568 | minion_hdr->app_data_offsets[app] = | ||
569 | minion_extract_word(nvgpu_minion_fw, data_idx); | ||
570 | data_idx += 4; | ||
571 | minion_hdr->app_data_sizes[app] = | ||
572 | minion_extract_word(nvgpu_minion_fw, data_idx); | ||
573 | data_idx += 4; | ||
574 | |||
575 | nvgpu_log(g, gpu_dbg_nvlink, | ||
576 | " - App Data:"); | ||
577 | nvgpu_log(g, gpu_dbg_nvlink, | ||
578 | " - App #%d: Data Offset = %u, Data Size = %u", | ||
579 | app, | ||
580 | minion_hdr->app_data_offsets[app], | ||
581 | minion_hdr->app_data_sizes[app]); | ||
582 | } | ||
583 | |||
584 | minion_hdr->ovl_offset = minion_extract_word(nvgpu_minion_fw, data_idx); | ||
585 | data_idx += 4; | ||
586 | minion_hdr->ovl_size = minion_extract_word(nvgpu_minion_fw, data_idx); | ||
587 | data_idx += 4; | ||
588 | |||
589 | ndev->minion_img = &(nvgpu_minion_fw->data[data_idx]); | ||
590 | minion_hdr->ucode_data_size = nvgpu_minion_fw->size - data_idx; | ||
591 | |||
489 | nvgpu_log(g, gpu_dbg_nvlink, | 592 | nvgpu_log(g, gpu_dbg_nvlink, |
490 | "os_data_size: 0x%x", minion_hdr->os_data_size); | 593 | " - Overlay Offset = %u", minion_hdr->ovl_offset); |
491 | nvgpu_log(g, gpu_dbg_nvlink, | 594 | nvgpu_log(g, gpu_dbg_nvlink, |
492 | "num_apps: 0x%x", minion_hdr->num_apps); | 595 | " - Overlay Size = %u", minion_hdr->ovl_size); |
493 | nvgpu_log(g, gpu_dbg_nvlink, | 596 | nvgpu_log(g, gpu_dbg_nvlink, |
494 | "app_0_code_start: 0x%x", minion_hdr->app_0_code_start); | 597 | " - Ucode Data Size = %u", minion_hdr->ucode_data_size); |
495 | 598 | ||
496 | /* Clear interrupts */ | 599 | /* Clear interrupts */ |
497 | nvgpu_flcn_set_irq(&g->minion_flcn, true, MINION_FALCON_INTR_MASK, | 600 | nvgpu_flcn_set_irq(&g->minion_flcn, true, MINION_FALCON_INTR_MASK, |
@@ -499,58 +602,34 @@ static u32 gv100_nvlink_minion_load(struct gk20a *g) | |||
499 | 602 | ||
500 | /* Copy Non Secure IMEM code */ | 603 | /* Copy Non Secure IMEM code */ |
501 | nvgpu_flcn_copy_to_imem(&g->minion_flcn, 0, | 604 | nvgpu_flcn_copy_to_imem(&g->minion_flcn, 0, |
502 | (u8 *)&minion_ucode[minion_hdr->os_code_offset >> 2], | 605 | (u8 *)&ndev->minion_img[minion_hdr->os_code_offset], |
503 | minion_hdr->os_code_size, 0, false, | 606 | minion_hdr->os_code_size, 0, false, |
504 | GET_IMEM_TAG(minion_hdr->os_code_offset)); | 607 | GET_IMEM_TAG(minion_hdr->os_code_offset)); |
505 | 608 | ||
506 | /* Copy Non Secure DMEM code */ | 609 | /* Copy Non Secure DMEM code */ |
507 | nvgpu_flcn_copy_to_dmem(&g->minion_flcn, 0, | 610 | nvgpu_flcn_copy_to_dmem(&g->minion_flcn, 0, |
508 | (u8 *)&minion_ucode[minion_hdr->os_data_offset >> 2], | 611 | (u8 *)&ndev->minion_img[minion_hdr->os_data_offset], |
509 | minion_hdr->os_data_size, 0); | 612 | minion_hdr->os_data_size, 0); |
510 | 613 | ||
511 | /* If apps are there load them securely */ | 614 | /* Load the apps securely */ |
512 | if (minion_hdr->num_apps) { | 615 | for (app = 0; app < minion_hdr->num_apps; app++) { |
513 | for (app = 0; app < minion_hdr->num_apps; app++) { | 616 | u32 app_code_start = minion_hdr->app_code_offsets[app]; |
514 | u32 app_code_start, app_code_size; | 617 | u32 app_code_size = minion_hdr->app_code_sizes[app]; |
515 | u32 app_data_start, app_data_size; | 618 | u32 app_data_start = minion_hdr->app_data_offsets[app]; |
516 | 619 | u32 app_data_size = minion_hdr->app_data_sizes[app]; | |
517 | app_code_start = | 620 | |
518 | *((u32 *) &minion_hdr->app_0_code_start + | 621 | if (app_code_size) |
519 | 2*app); | 622 | nvgpu_flcn_copy_to_imem(&g->minion_flcn, |
520 | app_code_size = | 623 | app_code_start, |
521 | *((u32 *) &minion_hdr->app_0_code_start + | 624 | (u8 *)&ndev->minion_img[app_code_start], |
522 | 2*app + 1); | 625 | app_code_size, 0, true, |
523 | app_data_start = | 626 | GET_IMEM_TAG(app_code_start)); |
524 | *((u32 *) &minion_hdr->app_0_code_start + | 627 | |
525 | 2*minion_hdr->num_apps + 2*app); | 628 | if (app_data_size) |
526 | app_data_size = | 629 | nvgpu_flcn_copy_to_dmem(&g->minion_flcn, |
527 | *((u32 *) &minion_hdr->app_0_code_start + | 630 | app_data_start, |
528 | 2*minion_hdr->num_apps + 2*app + 1); | 631 | (u8 *)&ndev->minion_img[app_data_start], |
529 | 632 | app_data_size, 0); | |
530 | nvgpu_log(g, gpu_dbg_nvlink, | ||
531 | " app %d code_offset 0x%x", app, app_code_start); | ||
532 | nvgpu_log(g, gpu_dbg_nvlink, | ||
533 | " app %d code_size 0x%x", app, app_code_size); | ||
534 | nvgpu_log(g, gpu_dbg_nvlink, | ||
535 | " app %d data_offset 0x%x", app, app_data_start); | ||
536 | nvgpu_log(g, gpu_dbg_nvlink, | ||
537 | " app %d data_size 0x%x", app, app_data_size); | ||
538 | |||
539 | if (app_code_size) | ||
540 | nvgpu_flcn_copy_to_imem(&g->minion_flcn, | ||
541 | app_code_start, | ||
542 | (u8 *)&minion_ucode[ | ||
543 | app_code_start >> 2], | ||
544 | app_code_size, 0, true, | ||
545 | GET_IMEM_TAG(app_code_start)); | ||
546 | |||
547 | if (app_data_size) | ||
548 | nvgpu_flcn_copy_to_dmem(&g->minion_flcn, | ||
549 | app_data_start, | ||
550 | (u8 *)&minion_ucode[ | ||
551 | app_data_start >> 2], | ||
552 | app_data_size, 0); | ||
553 | } | ||
554 | } | 633 | } |
555 | 634 | ||
556 | /* set BOOTVEC to start of non-secure code */ | 635 | /* set BOOTVEC to start of non-secure code */ |
@@ -595,8 +674,15 @@ static u32 gv100_nvlink_minion_load(struct gk20a *g) | |||
595 | gv100_nvlink_initialize_minion(g); | 674 | gv100_nvlink_initialize_minion(g); |
596 | 675 | ||
597 | exit: | 676 | exit: |
598 | if (minion_fw) | 677 | nvgpu_kfree(g, minion_hdr->app_code_offsets); |
599 | nvgpu_release_firmware(g, minion_fw); | 678 | nvgpu_kfree(g, minion_hdr->app_code_sizes); |
679 | nvgpu_kfree(g, minion_hdr->app_data_offsets); | ||
680 | nvgpu_kfree(g, minion_hdr->app_data_sizes); | ||
681 | |||
682 | if (nvgpu_minion_fw) { | ||
683 | nvgpu_release_firmware(g, nvgpu_minion_fw); | ||
684 | ndev->minion_img = NULL; | ||
685 | } | ||
600 | 686 | ||
601 | return err; | 687 | return err; |
602 | } | 688 | } |