diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2015-03-16 13:00:32 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-04-04 22:00:44 -0400 |
commit | 78d8f8fe366d521e1acb62a96ca5f0d72e15c8f5 (patch) | |
tree | e061e1aa42b10bd0bb3b1293770626106edea765 /drivers/gpu/nvgpu/gk20a | |
parent | 1eded552869f6957bec7695554752e26391daaee (diff) |
gpu: nvgpu: Cache channel state before dumping
Split channel debug dump into two phases. In first phase we just copy
the data to a temporary buffer, and in second phase we dump the state
from the temporary buffer.
Change-Id: I2578b9fdaaa76f1230df7badbca9fcb5f3854e56
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/717886
Reviewed-by: Konsta Holtta <kholtta@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/debug_gk20a.c | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/debug_gk20a.c b/drivers/gpu/nvgpu/gk20a/debug_gk20a.c index ace05c07..2c37d22d 100644 --- a/drivers/gpu/nvgpu/gk20a/debug_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/debug_gk20a.c | |||
@@ -34,6 +34,11 @@ | |||
34 | unsigned int gk20a_debug_trace_cmdbuf; | 34 | unsigned int gk20a_debug_trace_cmdbuf; |
35 | static struct platform_device *gk20a_device; | 35 | static struct platform_device *gk20a_device; |
36 | 36 | ||
37 | struct ch_state { | ||
38 | int pid; | ||
39 | u8 inst_block[0]; | ||
40 | }; | ||
41 | |||
37 | static const char * const ccsr_chan_status_str[] = { | 42 | static const char * const ccsr_chan_status_str[] = { |
38 | "idle", | 43 | "idle", |
39 | "pending", | 44 | "pending", |
@@ -97,23 +102,25 @@ void gk20a_debug_output(struct gk20a_debug_output *o, | |||
97 | 102 | ||
98 | static void gk20a_debug_show_channel(struct gk20a *g, | 103 | static void gk20a_debug_show_channel(struct gk20a *g, |
99 | struct gk20a_debug_output *o, | 104 | struct gk20a_debug_output *o, |
100 | struct channel_gk20a *ch) | 105 | u32 hw_chid, |
106 | struct ch_state *ch_state) | ||
101 | { | 107 | { |
102 | u32 channel = gk20a_readl(g, ccsr_channel_r(ch->hw_chid)); | 108 | u32 channel = gk20a_readl(g, ccsr_channel_r(hw_chid)); |
103 | u32 status = ccsr_channel_status_v(channel); | 109 | u32 status = ccsr_channel_status_v(channel); |
104 | u32 syncpointa, syncpointb; | 110 | u32 syncpointa, syncpointb; |
105 | void *inst_ptr; | 111 | void *inst_ptr; |
106 | 112 | ||
107 | inst_ptr = ch->inst_block.cpu_va; | 113 | if (!ch_state) |
108 | if (!inst_ptr) | ||
109 | return; | 114 | return; |
110 | 115 | ||
116 | inst_ptr = &ch_state->inst_block[0]; | ||
117 | |||
111 | syncpointa = gk20a_mem_rd32(inst_ptr, ram_fc_syncpointa_w()); | 118 | syncpointa = gk20a_mem_rd32(inst_ptr, ram_fc_syncpointa_w()); |
112 | syncpointb = gk20a_mem_rd32(inst_ptr, ram_fc_syncpointb_w()); | 119 | syncpointb = gk20a_mem_rd32(inst_ptr, ram_fc_syncpointb_w()); |
113 | 120 | ||
114 | gk20a_debug_output(o, "%d-%s, pid %d: ", ch->hw_chid, | 121 | gk20a_debug_output(o, "%d-%s, pid %d: ", hw_chid, |
115 | ch->g->dev->name, | 122 | g->dev->name, |
116 | ch->pid); | 123 | ch_state->pid); |
117 | gk20a_debug_output(o, "%s in use %s %s\n", | 124 | gk20a_debug_output(o, "%s in use %s %s\n", |
118 | ccsr_channel_enable_v(channel) ? "" : "not", | 125 | ccsr_channel_enable_v(channel) ? "" : "not", |
119 | ccsr_chan_status_str[status], | 126 | ccsr_chan_status_str[status], |
@@ -160,6 +167,8 @@ void gk20a_debug_show_dump(struct gk20a *g, struct gk20a_debug_output *o) | |||
160 | u32 chid; | 167 | u32 chid; |
161 | int i, err; | 168 | int i, err; |
162 | 169 | ||
170 | struct ch_state **ch_state; | ||
171 | |||
163 | err = gk20a_busy(g->dev); | 172 | err = gk20a_busy(g->dev); |
164 | if (err) { | 173 | if (err) { |
165 | gk20a_debug_output(o, "failed to power on gpu: %d\n", err); | 174 | gk20a_debug_output(o, "failed to power on gpu: %d\n", err); |
@@ -214,12 +223,34 @@ void gk20a_debug_show_dump(struct gk20a *g, struct gk20a_debug_output *o) | |||
214 | } | 223 | } |
215 | gk20a_debug_output(o, "\n"); | 224 | gk20a_debug_output(o, "\n"); |
216 | 225 | ||
226 | ch_state = kzalloc(sizeof(*ch_state) | ||
227 | * f->num_channels, GFP_KERNEL); | ||
228 | if (!ch_state) { | ||
229 | gk20a_debug_output(o, "cannot alloc memory for channels\n"); | ||
230 | goto done; | ||
231 | } | ||
232 | |||
233 | for (chid = 0; chid < f->num_channels; chid++) { | ||
234 | if (f->channel[chid].in_use) | ||
235 | ch_state[chid] = kmalloc(sizeof(struct ch_state) + ram_in_alloc_size_v(), GFP_KERNEL); | ||
236 | } | ||
237 | |||
238 | for (chid = 0; chid < f->num_channels; chid++) { | ||
239 | if (ch_state[chid] && f->channel[chid].inst_block.cpu_va) { | ||
240 | ch_state[chid]->pid = f->channel[chid].pid; | ||
241 | memcpy(&ch_state[chid]->inst_block[0], | ||
242 | f->channel[chid].inst_block.cpu_va, | ||
243 | ram_in_alloc_size_v()); | ||
244 | } | ||
245 | } | ||
217 | for (chid = 0; chid < f->num_channels; chid++) { | 246 | for (chid = 0; chid < f->num_channels; chid++) { |
218 | if (f->channel[chid].in_use) { | 247 | if (ch_state[chid]) { |
219 | struct channel_gk20a *gpu_ch = &f->channel[chid]; | 248 | gk20a_debug_show_channel(g, o, chid, ch_state[chid]); |
220 | gk20a_debug_show_channel(g, o, gpu_ch); | 249 | kfree(ch_state[chid]); |
221 | } | 250 | } |
222 | } | 251 | } |
252 | kfree(ch_state); | ||
253 | done: | ||
223 | gk20a_idle(g->dev); | 254 | gk20a_idle(g->dev); |
224 | } | 255 | } |
225 | 256 | ||