diff options
author | seshendra Gadagottu <sgadagottu@nvidia.com> | 2017-03-17 14:30:57 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-05-26 17:07:12 -0400 |
commit | c0822cb22e13204e06b145ae950a33d45e95918e (patch) | |
tree | 1623fcd5db0d24190e6d93287742c8d2fee14794 /drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | |
parent | e21e6e947b334cd16cc92c41953bf3c0153b1508 (diff) |
gpu: nvgpu: add chip specific sync point support
Added support for chip specific sync point implementation.
Relevant fifo hal functions are added and updated for
legacy chips.
JIRA GPUT19X-2
Change-Id: I9a9c36d71e15c384b5e5af460cd52012f94e0b04
Signed-off-by: seshendra Gadagottu <sgadagottu@nvidia.com>
Reviewed-on: http://git-master/r/1258232
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | 90 |
1 files changed, 35 insertions, 55 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c index eac7dbc3..07157dc9 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | |||
@@ -42,22 +42,9 @@ struct gk20a_channel_syncpt { | |||
42 | struct channel_gk20a *c; | 42 | struct channel_gk20a *c; |
43 | struct platform_device *host1x_pdev; | 43 | struct platform_device *host1x_pdev; |
44 | u32 id; | 44 | u32 id; |
45 | struct nvgpu_mem syncpt_buf; | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | static void add_wait_cmd(struct gk20a *g, struct priv_cmd_entry *cmd, u32 off, | ||
48 | u32 id, u32 thresh) | ||
49 | { | ||
50 | off = cmd->off + off; | ||
51 | /* syncpoint_a */ | ||
52 | nvgpu_mem_wr32(g, cmd->mem, off++, 0x2001001C); | ||
53 | /* payload */ | ||
54 | nvgpu_mem_wr32(g, cmd->mem, off++, thresh); | ||
55 | /* syncpoint_b */ | ||
56 | nvgpu_mem_wr32(g, cmd->mem, off++, 0x2001001D); | ||
57 | /* syncpt_id, switch_en, wait */ | ||
58 | nvgpu_mem_wr32(g, cmd->mem, off++, (id << 8) | 0x10); | ||
59 | } | ||
60 | |||
61 | static int gk20a_channel_syncpt_wait_syncpt(struct gk20a_channel_sync *s, | 48 | static int gk20a_channel_syncpt_wait_syncpt(struct gk20a_channel_sync *s, |
62 | u32 id, u32 thresh, struct priv_cmd_entry *wait_cmd, | 49 | u32 id, u32 thresh, struct priv_cmd_entry *wait_cmd, |
63 | struct gk20a_fence *fence) | 50 | struct gk20a_fence *fence) |
@@ -75,14 +62,18 @@ static int gk20a_channel_syncpt_wait_syncpt(struct gk20a_channel_sync *s, | |||
75 | if (nvhost_syncpt_is_expired_ext(sp->host1x_pdev, id, thresh)) | 62 | if (nvhost_syncpt_is_expired_ext(sp->host1x_pdev, id, thresh)) |
76 | return 0; | 63 | return 0; |
77 | 64 | ||
78 | err = gk20a_channel_alloc_priv_cmdbuf(c, 4, wait_cmd); | 65 | err = gk20a_channel_alloc_priv_cmdbuf(c, |
66 | c->g->ops.fifo.get_syncpt_wait_cmd_size(), wait_cmd); | ||
79 | if (err) { | 67 | if (err) { |
80 | nvgpu_err(c->g, | 68 | nvgpu_err(c->g, |
81 | "not enough priv cmd buffer space"); | 69 | "not enough priv cmd buffer space"); |
82 | return err; | 70 | return err; |
83 | } | 71 | } |
84 | 72 | ||
85 | add_wait_cmd(c->g, wait_cmd, 0, id, thresh); | 73 | nvgpu_log(c->g, gpu_dbg_info, "sp->id %d gpu va %llx", |
74 | id, sp->syncpt_buf.gpu_va); | ||
75 | c->g->ops.fifo.add_syncpt_wait_cmd(c->g, wait_cmd, 0, id, | ||
76 | thresh, sp->syncpt_buf.gpu_va); | ||
86 | 77 | ||
87 | return 0; | 78 | return 0; |
88 | } | 79 | } |
@@ -101,6 +92,7 @@ static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd, | |||
101 | struct channel_gk20a *c = sp->c; | 92 | struct channel_gk20a *c = sp->c; |
102 | u32 wait_id; | 93 | u32 wait_id; |
103 | int err = 0; | 94 | int err = 0; |
95 | u32 wait_cmd_size = 0; | ||
104 | 96 | ||
105 | sync_fence = nvhost_sync_fdget(fd); | 97 | sync_fence = nvhost_sync_fdget(fd); |
106 | if (!sync_fence) | 98 | if (!sync_fence) |
@@ -130,8 +122,10 @@ static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd, | |||
130 | sync_fence_put(sync_fence); | 122 | sync_fence_put(sync_fence); |
131 | return 0; | 123 | return 0; |
132 | } | 124 | } |
133 | 125 | wait_cmd_size = c->g->ops.fifo.get_syncpt_wait_cmd_size(); | |
134 | err = gk20a_channel_alloc_priv_cmdbuf(c, 4 * num_wait_cmds, wait_cmd); | 126 | err = gk20a_channel_alloc_priv_cmdbuf(c, |
127 | wait_cmd_size * num_wait_cmds, | ||
128 | wait_cmd); | ||
135 | if (err) { | 129 | if (err) { |
136 | nvgpu_err(c->g, | 130 | nvgpu_err(c->g, |
137 | "not enough priv cmd buffer space"); | 131 | "not enough priv cmd buffer space"); |
@@ -152,13 +146,16 @@ static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd, | |||
152 | 146 | ||
153 | if (nvhost_syncpt_is_expired_ext(sp->host1x_pdev, | 147 | if (nvhost_syncpt_is_expired_ext(sp->host1x_pdev, |
154 | wait_id, wait_value)) { | 148 | wait_id, wait_value)) { |
155 | /* each wait_cmd is 4 u32s */ | ||
156 | nvgpu_memset(c->g, wait_cmd->mem, | 149 | nvgpu_memset(c->g, wait_cmd->mem, |
157 | (wait_cmd->off + i * 4) * sizeof(u32), | 150 | (wait_cmd->off + i * wait_cmd_size) * sizeof(u32), |
158 | 0, 4 * sizeof(u32)); | 151 | 0, wait_cmd_size * sizeof(u32)); |
159 | } else | 152 | } else { |
160 | add_wait_cmd(c->g, wait_cmd, i * 4, wait_id, | 153 | nvgpu_log(c->g, gpu_dbg_info, "sp->id %d gpu va %llx", |
161 | wait_value); | 154 | wait_id, sp->syncpt_buf.gpu_va); |
155 | c->g->ops.fifo.add_syncpt_wait_cmd(c->g, wait_cmd, | ||
156 | i * wait_cmd_size, wait_id, wait_value, | ||
157 | sp->syncpt_buf.gpu_va); | ||
158 | } | ||
162 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) | 159 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) |
163 | i++; | 160 | i++; |
164 | } | 161 | } |
@@ -193,45 +190,21 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, | |||
193 | bool need_sync_fence) | 190 | bool need_sync_fence) |
194 | { | 191 | { |
195 | u32 thresh; | 192 | u32 thresh; |
196 | size_t incr_cmd_size; | ||
197 | int off; | ||
198 | int err; | 193 | int err; |
199 | struct gk20a_channel_syncpt *sp = | 194 | struct gk20a_channel_syncpt *sp = |
200 | container_of(s, struct gk20a_channel_syncpt, ops); | 195 | container_of(s, struct gk20a_channel_syncpt, ops); |
201 | struct channel_gk20a *c = sp->c; | 196 | struct channel_gk20a *c = sp->c; |
202 | 197 | ||
203 | incr_cmd_size = 6; | 198 | err = gk20a_channel_alloc_priv_cmdbuf(c, |
204 | if (wfi_cmd) | 199 | c->g->ops.fifo.get_syncpt_incr_cmd_size(wfi_cmd), |
205 | incr_cmd_size += 2; | 200 | incr_cmd); |
206 | |||
207 | err = gk20a_channel_alloc_priv_cmdbuf(c, incr_cmd_size, incr_cmd); | ||
208 | if (err) | 201 | if (err) |
209 | return err; | 202 | return err; |
210 | 203 | ||
211 | off = incr_cmd->off; | 204 | nvgpu_log(c->g, gpu_dbg_info, "sp->id %d gpu va %llx", |
212 | 205 | sp->id, sp->syncpt_buf.gpu_va); | |
213 | /* WAR for hw bug 1491360: syncpt needs to be incremented twice */ | 206 | c->g->ops.fifo.add_syncpt_incr_cmd(c->g, wfi_cmd, |
214 | 207 | incr_cmd, sp->id, sp->syncpt_buf.gpu_va); | |
215 | if (wfi_cmd) { | ||
216 | /* wfi */ | ||
217 | nvgpu_mem_wr32(c->g, incr_cmd->mem, off++, 0x2001001E); | ||
218 | /* handle, ignored */ | ||
219 | nvgpu_mem_wr32(c->g, incr_cmd->mem, off++, 0x00000000); | ||
220 | } | ||
221 | /* syncpoint_a */ | ||
222 | nvgpu_mem_wr32(c->g, incr_cmd->mem, off++, 0x2001001C); | ||
223 | /* payload, ignored */ | ||
224 | nvgpu_mem_wr32(c->g, incr_cmd->mem, off++, 0); | ||
225 | /* syncpoint_b */ | ||
226 | nvgpu_mem_wr32(c->g, incr_cmd->mem, off++, 0x2001001D); | ||
227 | /* syncpt_id, incr */ | ||
228 | nvgpu_mem_wr32(c->g, incr_cmd->mem, off++, (sp->id << 8) | 0x1); | ||
229 | /* syncpoint_b */ | ||
230 | nvgpu_mem_wr32(c->g, incr_cmd->mem, off++, 0x2001001D); | ||
231 | /* syncpt_id, incr */ | ||
232 | nvgpu_mem_wr32(c->g, incr_cmd->mem, off++, (sp->id << 8) | 0x1); | ||
233 | |||
234 | WARN_ON(off - incr_cmd->off != incr_cmd_size); | ||
235 | 208 | ||
236 | thresh = nvhost_syncpt_incr_max_ext(sp->host1x_pdev, sp->id, 2); | 209 | thresh = nvhost_syncpt_incr_max_ext(sp->host1x_pdev, sp->id, 2); |
237 | 210 | ||
@@ -337,6 +310,10 @@ static void gk20a_channel_syncpt_destroy(struct gk20a_channel_sync *s) | |||
337 | { | 310 | { |
338 | struct gk20a_channel_syncpt *sp = | 311 | struct gk20a_channel_syncpt *sp = |
339 | container_of(s, struct gk20a_channel_syncpt, ops); | 312 | container_of(s, struct gk20a_channel_syncpt, ops); |
313 | |||
314 | |||
315 | sp->c->g->ops.fifo.free_syncpt_buf(sp->c, &sp->syncpt_buf); | ||
316 | |||
340 | nvhost_syncpt_set_min_eq_max_ext(sp->host1x_pdev, sp->id); | 317 | nvhost_syncpt_set_min_eq_max_ext(sp->host1x_pdev, sp->id); |
341 | nvhost_syncpt_put_ref_ext(sp->host1x_pdev, sp->id); | 318 | nvhost_syncpt_put_ref_ext(sp->host1x_pdev, sp->id); |
342 | nvgpu_kfree(sp->c->g, sp); | 319 | nvgpu_kfree(sp->c->g, sp); |
@@ -366,6 +343,9 @@ gk20a_channel_syncpt_create(struct channel_gk20a *c) | |||
366 | return NULL; | 343 | return NULL; |
367 | } | 344 | } |
368 | 345 | ||
346 | sp->c->g->ops.fifo.alloc_syncpt_buf(sp->c, sp->id, | ||
347 | &sp->syncpt_buf); | ||
348 | |||
369 | nvhost_syncpt_set_min_eq_max_ext(sp->host1x_pdev, sp->id); | 349 | nvhost_syncpt_set_min_eq_max_ext(sp->host1x_pdev, sp->id); |
370 | 350 | ||
371 | atomic_set(&sp->ops.refcount, 0); | 351 | atomic_set(&sp->ops.refcount, 0); |