diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c | 113 |
1 files changed, 86 insertions, 27 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c index d8bd12d2..8e4cc0a2 100644 --- a/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c +++ b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c | |||
@@ -450,10 +450,11 @@ static struct device_attribute *dev_attr_l2_ecc_ded_count_array; | |||
450 | static u32 gen_ecc_hash_key(char *str) | 450 | static u32 gen_ecc_hash_key(char *str) |
451 | { | 451 | { |
452 | int i = 0; | 452 | int i = 0; |
453 | u32 hash_key = 0; | 453 | u32 hash_key = 0x811c9dc5; |
454 | 454 | ||
455 | while (str[i]) { | 455 | while (str[i]) { |
456 | hash_key += (u32)(str[i]); | 456 | hash_key *= 0x1000193; |
457 | hash_key ^= (u32)(str[i]); | ||
457 | i++; | 458 | i++; |
458 | }; | 459 | }; |
459 | 460 | ||
@@ -467,10 +468,16 @@ static ssize_t ecc_stat_show(struct device *dev, | |||
467 | const char *ecc_stat_full_name = attr->attr.name; | 468 | const char *ecc_stat_full_name = attr->attr.name; |
468 | const char *ecc_stat_base_name; | 469 | const char *ecc_stat_base_name; |
469 | unsigned int hw_unit; | 470 | unsigned int hw_unit; |
471 | unsigned int subunit; | ||
470 | struct gk20a_ecc_stat *ecc_stat; | 472 | struct gk20a_ecc_stat *ecc_stat; |
471 | u32 hash_key; | 473 | u32 hash_key; |
474 | struct gk20a *g = get_gk20a(dev); | ||
472 | 475 | ||
473 | if (sscanf(ecc_stat_full_name, "ltc%u", &hw_unit) == 1) { | 476 | if (sscanf(ecc_stat_full_name, "ltc%u_lts%u", &hw_unit, |
477 | &subunit) == 2) { | ||
478 | ecc_stat_base_name = &(ecc_stat_full_name[strlen("ltc0_lts0_")]); | ||
479 | hw_unit = g->gr.slices_per_ltc * hw_unit + subunit; | ||
480 | } else if (sscanf(ecc_stat_full_name, "ltc%u", &hw_unit) == 1) { | ||
474 | ecc_stat_base_name = &(ecc_stat_full_name[strlen("ltc0_")]); | 481 | ecc_stat_base_name = &(ecc_stat_full_name[strlen("ltc0_")]); |
475 | } else if (sscanf(ecc_stat_full_name, "gpc0_tpc%u", &hw_unit) == 1) { | 482 | } else if (sscanf(ecc_stat_full_name, "gpc0_tpc%u", &hw_unit) == 1) { |
476 | ecc_stat_base_name = &(ecc_stat_full_name[strlen("gpc0_tpc0_")]); | 483 | ecc_stat_base_name = &(ecc_stat_full_name[strlen("gpc0_tpc0_")]); |
@@ -485,10 +492,13 @@ static ssize_t ecc_stat_show(struct device *dev, | |||
485 | } | 492 | } |
486 | 493 | ||
487 | hash_key = gen_ecc_hash_key((char *)ecc_stat_base_name); | 494 | hash_key = gen_ecc_hash_key((char *)ecc_stat_base_name); |
495 | |||
488 | hash_for_each_possible(ecc_hash_table, | 496 | hash_for_each_possible(ecc_hash_table, |
489 | ecc_stat, | 497 | ecc_stat, |
490 | hash_node, | 498 | hash_node, |
491 | hash_key) { | 499 | hash_key) { |
500 | if (hw_unit >= ecc_stat->count) | ||
501 | continue; | ||
492 | if (!strcmp(ecc_stat_full_name, ecc_stat->names[hw_unit])) | 502 | if (!strcmp(ecc_stat_full_name, ecc_stat->names[hw_unit])) |
493 | return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stat->counters[hw_unit]); | 503 | return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stat->counters[hw_unit]); |
494 | } | 504 | } |
@@ -505,16 +515,22 @@ int gr_gp10b_ecc_stat_create(struct device *dev, | |||
505 | struct gk20a *g = get_gk20a(dev); | 515 | struct gk20a *g = get_gk20a(dev); |
506 | char *ltc_unit_name = "ltc"; | 516 | char *ltc_unit_name = "ltc"; |
507 | char *gr_unit_name = "gpc0_tpc"; | 517 | char *gr_unit_name = "gpc0_tpc"; |
518 | char *lts_unit_name = "lts"; | ||
508 | int num_hw_units = 0; | 519 | int num_hw_units = 0; |
520 | int num_subunits = 0; | ||
509 | 521 | ||
510 | if (is_l2) | 522 | if (is_l2 == 1) |
511 | num_hw_units = g->ltc_count; | 523 | num_hw_units = g->ltc_count; |
512 | else | 524 | else if (is_l2 == 2) { |
525 | num_hw_units = g->ltc_count; | ||
526 | num_subunits = g->gr.slices_per_ltc; | ||
527 | } else | ||
513 | num_hw_units = g->gr.tpc_count; | 528 | num_hw_units = g->gr.tpc_count; |
514 | 529 | ||
515 | 530 | ||
516 | return gp10b_ecc_stat_create(dev, num_hw_units, | 531 | return gp10b_ecc_stat_create(dev, num_hw_units, num_subunits, |
517 | is_l2 ? ltc_unit_name : gr_unit_name, | 532 | is_l2 ? ltc_unit_name : gr_unit_name, |
533 | num_subunits ? lts_unit_name: NULL, | ||
518 | ecc_stat_name, | 534 | ecc_stat_name, |
519 | ecc_stat, | 535 | ecc_stat, |
520 | dev_attr_array); | 536 | dev_attr_array); |
@@ -522,7 +538,9 @@ int gr_gp10b_ecc_stat_create(struct device *dev, | |||
522 | 538 | ||
523 | int gp10b_ecc_stat_create(struct device *dev, | 539 | int gp10b_ecc_stat_create(struct device *dev, |
524 | int num_hw_units, | 540 | int num_hw_units, |
541 | int num_subunits, | ||
525 | char *ecc_unit_name, | 542 | char *ecc_unit_name, |
543 | char *ecc_subunit_name, | ||
526 | char *ecc_stat_name, | 544 | char *ecc_stat_name, |
527 | struct gk20a_ecc_stat *ecc_stat, | 545 | struct gk20a_ecc_stat *ecc_stat, |
528 | struct device_attribute **__dev_attr_array) | 546 | struct device_attribute **__dev_attr_array) |
@@ -530,21 +548,56 @@ int gp10b_ecc_stat_create(struct device *dev, | |||
530 | int error = 0; | 548 | int error = 0; |
531 | struct gk20a *g = get_gk20a(dev); | 549 | struct gk20a *g = get_gk20a(dev); |
532 | int hw_unit = 0; | 550 | int hw_unit = 0; |
551 | int subunit = 0; | ||
552 | int element = 0; | ||
533 | u32 hash_key = 0; | 553 | u32 hash_key = 0; |
534 | struct device_attribute *dev_attr_array; | 554 | struct device_attribute *dev_attr_array; |
535 | 555 | ||
556 | int num_elements = num_subunits ? num_subunits*num_hw_units : | ||
557 | num_hw_units; | ||
558 | |||
536 | /* Allocate arrays */ | 559 | /* Allocate arrays */ |
537 | dev_attr_array = nvgpu_kzalloc(g, sizeof(struct device_attribute) * | 560 | dev_attr_array = nvgpu_kzalloc(g, sizeof(struct device_attribute) * |
538 | num_hw_units); | 561 | num_elements); |
539 | ecc_stat->counters = nvgpu_kzalloc(g, sizeof(u32) * num_hw_units); | 562 | ecc_stat->counters = nvgpu_kzalloc(g, sizeof(u32) * num_elements); |
540 | ecc_stat->names = nvgpu_kzalloc(g, sizeof(char *) * num_hw_units); | 563 | ecc_stat->names = nvgpu_kzalloc(g, sizeof(char *) * num_elements); |
541 | for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) { | 564 | for (hw_unit = 0; hw_unit < num_elements; hw_unit++) { |
542 | ecc_stat->names[hw_unit] = nvgpu_kzalloc(g, sizeof(char) * | 565 | ecc_stat->names[hw_unit] = nvgpu_kzalloc(g, sizeof(char) * |
543 | ECC_STAT_NAME_MAX_SIZE); | 566 | ECC_STAT_NAME_MAX_SIZE); |
544 | } | 567 | } |
568 | ecc_stat->count = num_elements; | ||
569 | if (num_subunits) { | ||
570 | for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) { | ||
571 | for (subunit = 0; subunit < num_subunits; subunit++) { | ||
572 | element = hw_unit*num_subunits + subunit; | ||
573 | |||
574 | snprintf(ecc_stat->names[element], | ||
575 | ECC_STAT_NAME_MAX_SIZE, | ||
576 | "%s%d_%s%d_%s", | ||
577 | ecc_unit_name, | ||
578 | hw_unit, | ||
579 | ecc_subunit_name, | ||
580 | subunit, | ||
581 | ecc_stat_name); | ||
582 | |||
583 | sysfs_attr_init(&dev_attr_array[element].attr); | ||
584 | dev_attr_array[element].attr.name = | ||
585 | ecc_stat->names[element]; | ||
586 | dev_attr_array[element].attr.mode = | ||
587 | VERIFY_OCTAL_PERMISSIONS(S_IRUGO); | ||
588 | dev_attr_array[element].show = ecc_stat_show; | ||
589 | dev_attr_array[element].store = NULL; | ||
590 | |||
591 | /* Create sysfs file */ | ||
592 | error |= device_create_file(dev, | ||
593 | &dev_attr_array[element]); | ||
594 | |||
595 | } | ||
596 | } | ||
597 | } else { | ||
598 | for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) { | ||
545 | 599 | ||
546 | for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) { | 600 | /* Fill in struct device_attribute members */ |
547 | /* Fill in struct device_attribute members */ | ||
548 | snprintf(ecc_stat->names[hw_unit], | 601 | snprintf(ecc_stat->names[hw_unit], |
549 | ECC_STAT_NAME_MAX_SIZE, | 602 | ECC_STAT_NAME_MAX_SIZE, |
550 | "%s%d_%s", | 603 | "%s%d_%s", |
@@ -552,14 +605,18 @@ int gp10b_ecc_stat_create(struct device *dev, | |||
552 | hw_unit, | 605 | hw_unit, |
553 | ecc_stat_name); | 606 | ecc_stat_name); |
554 | 607 | ||
555 | sysfs_attr_init(&dev_attr_array[hw_unit].attr); | 608 | sysfs_attr_init(&dev_attr_array[hw_unit].attr); |
556 | dev_attr_array[hw_unit].attr.name = ecc_stat->names[hw_unit]; | 609 | dev_attr_array[hw_unit].attr.name = |
557 | dev_attr_array[hw_unit].attr.mode = VERIFY_OCTAL_PERMISSIONS(S_IRUGO); | 610 | ecc_stat->names[hw_unit]; |
558 | dev_attr_array[hw_unit].show = ecc_stat_show; | 611 | dev_attr_array[hw_unit].attr.mode = |
559 | dev_attr_array[hw_unit].store = NULL; | 612 | VERIFY_OCTAL_PERMISSIONS(S_IRUGO); |
560 | 613 | dev_attr_array[hw_unit].show = ecc_stat_show; | |
561 | /* Create sysfs file */ | 614 | dev_attr_array[hw_unit].store = NULL; |
562 | error |= device_create_file(dev, &dev_attr_array[hw_unit]); | 615 | |
616 | /* Create sysfs file */ | ||
617 | error |= device_create_file(dev, | ||
618 | &dev_attr_array[hw_unit]); | ||
619 | } | ||
563 | } | 620 | } |
564 | 621 | ||
565 | /* Add hash table entry */ | 622 | /* Add hash table entry */ |
@@ -581,8 +638,10 @@ void gr_gp10b_ecc_stat_remove(struct device *dev, | |||
581 | struct gk20a *g = get_gk20a(dev); | 638 | struct gk20a *g = get_gk20a(dev); |
582 | int num_hw_units = 0; | 639 | int num_hw_units = 0; |
583 | 640 | ||
584 | if (is_l2) | 641 | if (is_l2 == 1) |
585 | num_hw_units = g->ltc_count; | 642 | num_hw_units = g->ltc_count; |
643 | else if (is_l2 == 2) | ||
644 | num_hw_units = g->ltc_count * g->gr.slices_per_ltc; | ||
586 | else | 645 | else |
587 | num_hw_units = g->gr.tpc_count; | 646 | num_hw_units = g->gr.tpc_count; |
588 | 647 | ||
@@ -695,13 +754,13 @@ void gr_gp10b_create_sysfs(struct gk20a *g) | |||
695 | &dev_attr_tex_ecc_unique_ded_pipe1_count_array); | 754 | &dev_attr_tex_ecc_unique_ded_pipe1_count_array); |
696 | 755 | ||
697 | error |= gr_gp10b_ecc_stat_create(dev, | 756 | error |= gr_gp10b_ecc_stat_create(dev, |
698 | 1, | 757 | 2, |
699 | "lts0_ecc_sec_count", | 758 | "ecc_sec_count", |
700 | &g->ecc.ltc.l2_sec_count, | 759 | &g->ecc.ltc.l2_sec_count, |
701 | &dev_attr_l2_ecc_sec_count_array); | 760 | &dev_attr_l2_ecc_sec_count_array); |
702 | error |= gr_gp10b_ecc_stat_create(dev, | 761 | error |= gr_gp10b_ecc_stat_create(dev, |
703 | 1, | 762 | 2, |
704 | "lts0_ecc_ded_count", | 763 | "ecc_ded_count", |
705 | &g->ecc.ltc.l2_ded_count, | 764 | &g->ecc.ltc.l2_ded_count, |
706 | &dev_attr_l2_ecc_ded_count_array); | 765 | &dev_attr_l2_ecc_ded_count_array); |
707 | 766 | ||
@@ -769,11 +828,11 @@ static void gr_gp10b_remove_sysfs(struct device *dev) | |||
769 | dev_attr_tex_ecc_unique_ded_pipe1_count_array); | 828 | dev_attr_tex_ecc_unique_ded_pipe1_count_array); |
770 | 829 | ||
771 | gr_gp10b_ecc_stat_remove(dev, | 830 | gr_gp10b_ecc_stat_remove(dev, |
772 | 1, | 831 | 2, |
773 | &g->ecc.ltc.l2_sec_count, | 832 | &g->ecc.ltc.l2_sec_count, |
774 | dev_attr_l2_ecc_sec_count_array); | 833 | dev_attr_l2_ecc_sec_count_array); |
775 | gr_gp10b_ecc_stat_remove(dev, | 834 | gr_gp10b_ecc_stat_remove(dev, |
776 | 1, | 835 | 2, |
777 | &g->ecc.ltc.l2_ded_count, | 836 | &g->ecc.ltc.l2_ded_count, |
778 | dev_attr_l2_ecc_ded_count_array); | 837 | dev_attr_l2_ecc_ded_count_array); |
779 | } | 838 | } |