summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c113
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;
450static u32 gen_ecc_hash_key(char *str) 450static 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
523int gp10b_ecc_stat_create(struct device *dev, 539int 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}