diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2014-10-01 11:53:49 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:12:10 -0400 |
commit | f8f6b298848ed05ad83ce107ff8a4fff0b37dd2d (patch) | |
tree | 554d121fbbc47745556cd6a99c6b5d6258951b80 /drivers/gpu/nvgpu | |
parent | 6275bbb33bb0f72cc03c7e68d8186b36c96ee854 (diff) |
gpu: nvgpu: support config of TPC FUSE dynamically
Follow steps below to config active TPC number:
echo 1 > /sys/devices/platform/host1x/gpu.0/force_idle
echo 0x1/0x2/0x3 > /sys/devices/platform/host1x/gpu.0/tpc_fs_mask
echo 0 > /sys/devices/platform/host1x/gpu.0/force_idle
where,
0x1 : disable TPC1
0x2 : disable TPC0
0x3 : both TPCs active
Also, add API set_gpc_tpc_mask to update the TPCs and call this
API after update to sysfs "tpc_fs_mask"
Once fuses are updated for new TPC settings, we need to
reconfigure GR and golden_image. Hence disable gr->sw_ready
and golden_image_initialized flags.
Also, initialize gr->tpc_count = 0 each time in
gr_gk20a_init_gr_config(), otherwise it goes on adding tpc count
Bug 1513685
Change-Id: Ib50bafef08664262f8426ac0d6cbad74b32c5909
Signed-off-by: Kevin Huang <kevinh@nvidia.com>
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/552606
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | 18 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/gr_gm20b.c | 23 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/gr_gm20b.h | 11 |
5 files changed, 53 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 3f070a58..49038a0f 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -125,6 +125,7 @@ struct gpu_ops { | |||
125 | u32 reg_offset); | 125 | u32 reg_offset); |
126 | int (*load_ctxsw_ucode)(struct gk20a *g); | 126 | int (*load_ctxsw_ucode)(struct gk20a *g); |
127 | u32 (*get_gpc_tpc_mask)(struct gk20a *g, u32 gpc_index); | 127 | u32 (*get_gpc_tpc_mask)(struct gk20a *g, u32 gpc_index); |
128 | void (*set_gpc_tpc_mask)(struct gk20a *g, u32 gpc_index); | ||
128 | void (*free_channel_ctx)(struct channel_gk20a *c); | 129 | void (*free_channel_ctx)(struct channel_gk20a *c); |
129 | int (*alloc_obj_ctx)(struct channel_gk20a *c, | 130 | int (*alloc_obj_ctx)(struct channel_gk20a *c, |
130 | struct nvgpu_alloc_obj_ctx_args *args); | 131 | struct nvgpu_alloc_obj_ctx_args *args); |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c index 1f32ac6d..42720307 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | |||
@@ -607,9 +607,18 @@ static ssize_t tpc_fs_mask_store(struct device *device, | |||
607 | if (kstrtoul(buf, 10, &val) < 0) | 607 | if (kstrtoul(buf, 10, &val) < 0) |
608 | return -EINVAL; | 608 | return -EINVAL; |
609 | 609 | ||
610 | if (val) | 610 | if (val && val != g->gr.gpc_tpc_mask[0] && g->ops.gr.set_gpc_tpc_mask) { |
611 | g->gr.gpc_tpc_mask[0] = val; | 611 | g->gr.gpc_tpc_mask[0] = val; |
612 | 612 | ||
613 | g->ops.gr.set_gpc_tpc_mask(g, 0); | ||
614 | |||
615 | kfree(g->gr.ctx_vars.local_golden_image); | ||
616 | g->gr.ctx_vars.local_golden_image = NULL; | ||
617 | g->gr.ctx_vars.golden_image_initialized = false; | ||
618 | g->gr.ctx_vars.golden_image_size = 0; | ||
619 | g->gr.sw_ready = false; | ||
620 | } | ||
621 | |||
613 | return count; | 622 | return count; |
614 | } | 623 | } |
615 | 624 | ||
@@ -621,6 +630,11 @@ static ssize_t tpc_fs_mask_read(struct device *device, | |||
621 | struct gr_gk20a *gr = &g->gr; | 630 | struct gr_gk20a *gr = &g->gr; |
622 | u32 gpc_index; | 631 | u32 gpc_index; |
623 | u32 tpc_fs_mask = 0; | 632 | u32 tpc_fs_mask = 0; |
633 | int err = 0; | ||
634 | |||
635 | err = gk20a_busy(g->dev); | ||
636 | if (err) | ||
637 | return err; | ||
624 | 638 | ||
625 | for (gpc_index = 0; gpc_index < gr->gpc_count; gpc_index++) { | 639 | for (gpc_index = 0; gpc_index < gr->gpc_count; gpc_index++) { |
626 | if (g->ops.gr.get_gpc_tpc_mask) | 640 | if (g->ops.gr.get_gpc_tpc_mask) |
@@ -629,6 +643,8 @@ static ssize_t tpc_fs_mask_read(struct device *device, | |||
629 | (gr->max_tpc_per_gpc_count * gpc_index); | 643 | (gr->max_tpc_per_gpc_count * gpc_index); |
630 | } | 644 | } |
631 | 645 | ||
646 | gk20a_idle(g->dev); | ||
647 | |||
632 | return sprintf(buf, "0x%x\n", tpc_fs_mask); | 648 | return sprintf(buf, "0x%x\n", tpc_fs_mask); |
633 | } | 649 | } |
634 | 650 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index da257cd4..3cf5845c 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c | |||
@@ -3084,6 +3084,7 @@ static int gr_gk20a_init_gr_config(struct gk20a *g, struct gr_gk20a *gr) | |||
3084 | goto clean_up; | 3084 | goto clean_up; |
3085 | 3085 | ||
3086 | gr->ppc_count = 0; | 3086 | gr->ppc_count = 0; |
3087 | gr->tpc_count = 0; | ||
3087 | for (gpc_index = 0; gpc_index < gr->gpc_count; gpc_index++) { | 3088 | for (gpc_index = 0; gpc_index < gr->gpc_count; gpc_index++) { |
3088 | tmp = gk20a_readl(g, gr_gpc0_fs_gpc_r()); | 3089 | tmp = gk20a_readl(g, gr_gpc0_fs_gpc_r()); |
3089 | 3090 | ||
diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c index 8f056181..a6b54ea5 100644 --- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c | |||
@@ -15,6 +15,8 @@ | |||
15 | 15 | ||
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/delay.h> /* for mdelay */ | 17 | #include <linux/delay.h> /* for mdelay */ |
18 | #include <linux/io.h> | ||
19 | #include <linux/tegra-fuse.h> | ||
18 | 20 | ||
19 | #include "gk20a/gk20a.h" | 21 | #include "gk20a/gk20a.h" |
20 | #include "gk20a/gr_gk20a.h" | 22 | #include "gk20a/gr_gk20a.h" |
@@ -492,6 +494,26 @@ static u32 gr_gm20b_get_gpc_tpc_mask(struct gk20a *g, u32 gpc_index) | |||
492 | return (~val) & ((0x1 << gr->max_tpc_per_gpc_count) - 1); | 494 | return (~val) & ((0x1 << gr->max_tpc_per_gpc_count) - 1); |
493 | } | 495 | } |
494 | 496 | ||
497 | static void gr_gm20b_set_gpc_tpc_mask(struct gk20a *g, u32 gpc_index) | ||
498 | { | ||
499 | tegra_clk_writel(CLK_RST_CONTROLLER_MISC_CLK_ENB_0_ALL_VISIBLE, | ||
500 | CLK_RST_CONTROLLER_MISC_CLK_ENB_0); | ||
501 | |||
502 | tegra_fuse_writel(0x1, FUSE_FUSEBYPASS_0); | ||
503 | tegra_fuse_writel(0x0, FUSE_WRITE_ACCESS_SW_0); | ||
504 | |||
505 | if (g->gr.gpc_tpc_mask[gpc_index] == 0x1) { | ||
506 | tegra_fuse_writel(0x0, FUSE_OPT_GPU_TPC0_DISABLE_0); | ||
507 | tegra_fuse_writel(0x1, FUSE_OPT_GPU_TPC1_DISABLE_0); | ||
508 | } else if (g->gr.gpc_tpc_mask[gpc_index] == 0x2) { | ||
509 | tegra_fuse_writel(0x1, FUSE_OPT_GPU_TPC0_DISABLE_0); | ||
510 | tegra_fuse_writel(0x0, FUSE_OPT_GPU_TPC1_DISABLE_0); | ||
511 | } else { | ||
512 | tegra_fuse_writel(0x0, FUSE_OPT_GPU_TPC0_DISABLE_0); | ||
513 | tegra_fuse_writel(0x0, FUSE_OPT_GPU_TPC1_DISABLE_0); | ||
514 | } | ||
515 | } | ||
516 | |||
495 | static int gr_gm20b_ctx_state_floorsweep(struct gk20a *g) | 517 | static int gr_gm20b_ctx_state_floorsweep(struct gk20a *g) |
496 | { | 518 | { |
497 | struct gr_gk20a *gr = &g->gr; | 519 | struct gr_gk20a *gr = &g->gr; |
@@ -785,6 +807,7 @@ void gm20b_init_gr(struct gpu_ops *gops) | |||
785 | gops->gr.load_ctxsw_ucode = gr_gm20b_load_ctxsw_ucode; | 807 | gops->gr.load_ctxsw_ucode = gr_gm20b_load_ctxsw_ucode; |
786 | else | 808 | else |
787 | gops->gr.load_ctxsw_ucode = gr_gk20a_load_ctxsw_ucode; | 809 | gops->gr.load_ctxsw_ucode = gr_gk20a_load_ctxsw_ucode; |
810 | gops->gr.set_gpc_tpc_mask = gr_gm20b_set_gpc_tpc_mask; | ||
788 | gops->gr.get_gpc_tpc_mask = gr_gm20b_get_gpc_tpc_mask; | 811 | gops->gr.get_gpc_tpc_mask = gr_gm20b_get_gpc_tpc_mask; |
789 | gops->gr.free_channel_ctx = gk20a_free_channel_ctx; | 812 | gops->gr.free_channel_ctx = gk20a_free_channel_ctx; |
790 | gops->gr.alloc_obj_ctx = gk20a_alloc_obj_ctx; | 813 | gops->gr.alloc_obj_ctx = gk20a_alloc_obj_ctx; |
diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.h b/drivers/gpu/nvgpu/gm20b/gr_gm20b.h index 470e5bae..fd109eec 100644 --- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.h | |||
@@ -25,6 +25,17 @@ enum { | |||
25 | MAXWELL_CHANNEL_GPFIFO_A= 0xB06F, | 25 | MAXWELL_CHANNEL_GPFIFO_A= 0xB06F, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | #define tegra_clk_writel(value, offset) \ | ||
29 | writel(value, IO_ADDRESS(0x60006000 + offset)) | ||
30 | |||
31 | #define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 0x48 | ||
32 | #define CLK_RST_CONTROLLER_MISC_CLK_ENB_0_ALL_VISIBLE BIT(28) | ||
33 | |||
34 | #define FUSE_FUSEBYPASS_0 0x24 | ||
35 | #define FUSE_WRITE_ACCESS_SW_0 0x30 | ||
36 | #define FUSE_OPT_GPU_TPC0_DISABLE_0 0x30C | ||
37 | #define FUSE_OPT_GPU_TPC1_DISABLE_0 0x33C | ||
38 | |||
28 | #define NVB197_SET_ALPHA_CIRCULAR_BUFFER_SIZE 0x02dc | 39 | #define NVB197_SET_ALPHA_CIRCULAR_BUFFER_SIZE 0x02dc |
29 | #define NVB197_SET_CIRCULAR_BUFFER_SIZE 0x1280 | 40 | #define NVB197_SET_CIRCULAR_BUFFER_SIZE 0x1280 |
30 | #define NVB197_SET_SHADER_EXCEPTIONS 0x1528 | 41 | #define NVB197_SET_SHADER_EXCEPTIONS 0x1528 |