diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | 148 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h | 4 |
2 files changed, 57 insertions, 95 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c index a0b0ac1e..16898593 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | |||
@@ -51,6 +51,39 @@ struct gk20a_channel_syncpt { | |||
51 | struct nvgpu_mem syncpt_buf; | 51 | struct nvgpu_mem syncpt_buf; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | int gk20a_channel_gen_syncpt_wait_cmd(struct channel_gk20a *c, | ||
55 | u32 id, u32 thresh, struct priv_cmd_entry *wait_cmd, | ||
56 | u32 wait_cmd_size, int pos, bool preallocated) | ||
57 | { | ||
58 | int err = 0; | ||
59 | bool is_expired = nvgpu_nvhost_syncpt_is_expired_ext( | ||
60 | c->g->nvhost_dev, id, thresh); | ||
61 | |||
62 | if (is_expired) { | ||
63 | if (preallocated) { | ||
64 | nvgpu_memset(c->g, wait_cmd->mem, | ||
65 | (wait_cmd->off + pos * wait_cmd_size) * sizeof(u32), | ||
66 | 0, wait_cmd_size * sizeof(u32)); | ||
67 | } | ||
68 | } else { | ||
69 | if (!preallocated) { | ||
70 | err = gk20a_channel_alloc_priv_cmdbuf(c, | ||
71 | c->g->ops.fifo.get_syncpt_wait_cmd_size(), wait_cmd); | ||
72 | if (err) { | ||
73 | nvgpu_err(c->g, "not enough priv cmd buffer space"); | ||
74 | return err; | ||
75 | } | ||
76 | } | ||
77 | nvgpu_log(c->g, gpu_dbg_info, "sp->id %d gpu va %llx", | ||
78 | id, c->vm->syncpt_ro_map_gpu_va); | ||
79 | c->g->ops.fifo.add_syncpt_wait_cmd(c->g, wait_cmd, | ||
80 | pos * wait_cmd_size, id, thresh, | ||
81 | c->vm->syncpt_ro_map_gpu_va); | ||
82 | } | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
54 | static int gk20a_channel_syncpt_wait_syncpt(struct gk20a_channel_sync *s, | 87 | static int gk20a_channel_syncpt_wait_syncpt(struct gk20a_channel_sync *s, |
55 | u32 id, u32 thresh, struct priv_cmd_entry *wait_cmd) | 88 | u32 id, u32 thresh, struct priv_cmd_entry *wait_cmd) |
56 | { | 89 | { |
@@ -58,108 +91,36 @@ static int gk20a_channel_syncpt_wait_syncpt(struct gk20a_channel_sync *s, | |||
58 | container_of(s, struct gk20a_channel_syncpt, ops); | 91 | container_of(s, struct gk20a_channel_syncpt, ops); |
59 | struct channel_gk20a *c = sp->c; | 92 | struct channel_gk20a *c = sp->c; |
60 | int err = 0; | 93 | int err = 0; |
94 | u32 wait_cmd_size = c->g->ops.fifo.get_syncpt_wait_cmd_size(); | ||
61 | 95 | ||
62 | if (!nvgpu_nvhost_syncpt_is_valid_pt_ext(sp->nvhost_dev, id)) | 96 | if (!nvgpu_nvhost_syncpt_is_valid_pt_ext(sp->nvhost_dev, id)) |
63 | return -EINVAL; | 97 | return -EINVAL; |
64 | 98 | ||
65 | if (nvgpu_nvhost_syncpt_is_expired_ext(sp->nvhost_dev, id, thresh)) | 99 | err = gk20a_channel_gen_syncpt_wait_cmd(c, id, thresh, |
66 | return 0; | 100 | wait_cmd, wait_cmd_size, 0, false); |
67 | 101 | ||
68 | err = gk20a_channel_alloc_priv_cmdbuf(c, | 102 | return err; |
69 | c->g->ops.fifo.get_syncpt_wait_cmd_size(), wait_cmd); | ||
70 | if (err) { | ||
71 | nvgpu_err(c->g, | ||
72 | "not enough priv cmd buffer space"); | ||
73 | return err; | ||
74 | } | ||
75 | |||
76 | nvgpu_log(c->g, gpu_dbg_info, "sp->id %d gpu va %llx", | ||
77 | id, sp->c->vm->syncpt_ro_map_gpu_va); | ||
78 | c->g->ops.fifo.add_syncpt_wait_cmd(c->g, wait_cmd, 0, id, | ||
79 | thresh, c->vm->syncpt_ro_map_gpu_va); | ||
80 | |||
81 | return 0; | ||
82 | } | 103 | } |
83 | 104 | ||
84 | static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd, | 105 | static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd, |
85 | struct priv_cmd_entry *wait_cmd, int max_wait_cmds) | 106 | struct priv_cmd_entry *wait_cmd, int max_wait_cmds) |
86 | { | 107 | { |
87 | #ifdef CONFIG_SYNC | 108 | struct nvgpu_os_fence os_fence = {0}; |
88 | int i; | ||
89 | int num_wait_cmds; | ||
90 | struct sync_fence *sync_fence; | ||
91 | struct sync_pt *pt; | ||
92 | struct gk20a_channel_syncpt *sp = | 109 | struct gk20a_channel_syncpt *sp = |
93 | container_of(s, struct gk20a_channel_syncpt, ops); | 110 | container_of(s, struct gk20a_channel_syncpt, ops); |
94 | struct channel_gk20a *c = sp->c; | 111 | struct channel_gk20a *c = sp->c; |
95 | u32 wait_id; | ||
96 | int err = 0; | 112 | int err = 0; |
97 | u32 wait_cmd_size = 0; | ||
98 | |||
99 | sync_fence = nvgpu_nvhost_sync_fdget(fd); | ||
100 | if (!sync_fence) | ||
101 | return -EINVAL; | ||
102 | 113 | ||
103 | if (max_wait_cmds && sync_fence->num_fences > max_wait_cmds) { | 114 | err = nvgpu_os_fence_fdget(&os_fence, c, fd); |
104 | sync_fence_put(sync_fence); | 115 | if (err) |
105 | return -EINVAL; | 116 | return -EINVAL; |
106 | } | ||
107 | |||
108 | /* validate syncpt ids */ | ||
109 | for (i = 0; i < sync_fence->num_fences; i++) { | ||
110 | pt = sync_pt_from_fence(sync_fence->cbs[i].sync_pt); | ||
111 | wait_id = nvgpu_nvhost_sync_pt_id(pt); | ||
112 | if (!wait_id || !nvgpu_nvhost_syncpt_is_valid_pt_ext( | ||
113 | sp->nvhost_dev, wait_id)) { | ||
114 | sync_fence_put(sync_fence); | ||
115 | return -EINVAL; | ||
116 | } | ||
117 | } | ||
118 | 117 | ||
119 | num_wait_cmds = nvgpu_nvhost_sync_num_pts(sync_fence); | 118 | err = os_fence.ops->program_waits(&os_fence, |
120 | if (num_wait_cmds == 0) { | 119 | wait_cmd, c, max_wait_cmds); |
121 | sync_fence_put(sync_fence); | ||
122 | return 0; | ||
123 | } | ||
124 | wait_cmd_size = c->g->ops.fifo.get_syncpt_wait_cmd_size(); | ||
125 | err = gk20a_channel_alloc_priv_cmdbuf(c, | ||
126 | wait_cmd_size * num_wait_cmds, | ||
127 | wait_cmd); | ||
128 | if (err) { | ||
129 | nvgpu_err(c->g, | ||
130 | "not enough priv cmd buffer space"); | ||
131 | sync_fence_put(sync_fence); | ||
132 | return err; | ||
133 | } | ||
134 | |||
135 | i = 0; | ||
136 | for (i = 0; i < sync_fence->num_fences; i++) { | ||
137 | struct fence *f = sync_fence->cbs[i].sync_pt; | ||
138 | struct sync_pt *pt = sync_pt_from_fence(f); | ||
139 | u32 wait_id = nvgpu_nvhost_sync_pt_id(pt); | ||
140 | u32 wait_value = nvgpu_nvhost_sync_pt_thresh(pt); | ||
141 | |||
142 | if (nvgpu_nvhost_syncpt_is_expired_ext(sp->nvhost_dev, | ||
143 | wait_id, wait_value)) { | ||
144 | nvgpu_memset(c->g, wait_cmd->mem, | ||
145 | (wait_cmd->off + i * wait_cmd_size) * sizeof(u32), | ||
146 | 0, wait_cmd_size * sizeof(u32)); | ||
147 | } else { | ||
148 | nvgpu_log(c->g, gpu_dbg_info, "sp->id %d gpu va %llx", | ||
149 | wait_id, sp->syncpt_buf.gpu_va); | ||
150 | c->g->ops.fifo.add_syncpt_wait_cmd(c->g, wait_cmd, | ||
151 | i * wait_cmd_size, wait_id, wait_value, | ||
152 | c->vm->syncpt_ro_map_gpu_va); | ||
153 | } | ||
154 | } | ||
155 | 120 | ||
156 | WARN_ON(i != num_wait_cmds); | 121 | os_fence.ops->drop_ref(&os_fence); |
157 | sync_fence_put(sync_fence); | ||
158 | 122 | ||
159 | return 0; | 123 | return err; |
160 | #else | ||
161 | return -ENODEV; | ||
162 | #endif | ||
163 | } | 124 | } |
164 | 125 | ||
165 | static void gk20a_channel_syncpt_update(void *priv, int nr_completed) | 126 | static void gk20a_channel_syncpt_update(void *priv, int nr_completed) |
@@ -185,6 +146,7 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, | |||
185 | container_of(s, struct gk20a_channel_syncpt, ops); | 146 | container_of(s, struct gk20a_channel_syncpt, ops); |
186 | struct channel_gk20a *c = sp->c; | 147 | struct channel_gk20a *c = sp->c; |
187 | struct sync_fence *sync_fence = NULL; | 148 | struct sync_fence *sync_fence = NULL; |
149 | struct nvgpu_os_fence os_fence = {0}; | ||
188 | 150 | ||
189 | err = gk20a_channel_alloc_priv_cmdbuf(c, | 151 | err = gk20a_channel_alloc_priv_cmdbuf(c, |
190 | c->g->ops.fifo.get_syncpt_incr_cmd_size(wfi_cmd), | 152 | c->g->ops.fifo.get_syncpt_incr_cmd_size(wfi_cmd), |
@@ -226,26 +188,22 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, | |||
226 | } | 188 | } |
227 | } | 189 | } |
228 | 190 | ||
229 | #ifdef CONFIG_SYNC | ||
230 | if (need_sync_fence) { | 191 | if (need_sync_fence) { |
231 | sync_fence = nvgpu_nvhost_sync_create_fence(sp->nvhost_dev, | 192 | err = nvgpu_os_fence_syncpt_create(&os_fence, c, sp->nvhost_dev, |
232 | sp->id, thresh, "fence"); | 193 | sp->id, thresh); |
233 | 194 | ||
234 | if (IS_ERR(sync_fence)) { | 195 | if (err) |
235 | err = PTR_ERR(sync_fence); | ||
236 | goto clean_up_priv_cmd; | 196 | goto clean_up_priv_cmd; |
237 | } | 197 | |
198 | sync_fence = (struct sync_fence *)os_fence.priv; | ||
238 | } | 199 | } |
239 | #endif | ||
240 | 200 | ||
241 | err = gk20a_fence_from_syncpt(fence, sp->nvhost_dev, | 201 | err = gk20a_fence_from_syncpt(fence, sp->nvhost_dev, |
242 | sp->id, thresh, sync_fence); | 202 | sp->id, thresh, sync_fence); |
243 | 203 | ||
244 | if (err) { | 204 | if (err) { |
245 | #ifdef CONFIG_SYNC | 205 | if (nvgpu_os_fence_is_initialized(&os_fence)) |
246 | if (sync_fence) | 206 | os_fence.ops->drop_ref(&os_fence); |
247 | sync_fence_put(sync_fence); | ||
248 | #endif | ||
249 | goto clean_up_priv_cmd; | 207 | goto clean_up_priv_cmd; |
250 | } | 208 | } |
251 | 209 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h index 565b4f86..5c6e91c9 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h | |||
@@ -108,6 +108,10 @@ void gk20a_channel_gen_sema_wait_cmd(struct channel_gk20a *c, | |||
108 | struct nvgpu_semaphore *sema, struct priv_cmd_entry *wait_cmd, | 108 | struct nvgpu_semaphore *sema, struct priv_cmd_entry *wait_cmd, |
109 | u32 wait_cmd_size, int pos); | 109 | u32 wait_cmd_size, int pos); |
110 | 110 | ||
111 | int gk20a_channel_gen_syncpt_wait_cmd(struct channel_gk20a *c, | ||
112 | u32 id, u32 thresh, struct priv_cmd_entry *wait_cmd, | ||
113 | u32 wait_cmd_size, int pos, bool preallocated); | ||
114 | |||
111 | void gk20a_channel_sync_destroy(struct gk20a_channel_sync *sync, | 115 | void gk20a_channel_sync_destroy(struct gk20a_channel_sync *sync, |
112 | bool set_safe_state); | 116 | bool set_safe_state); |
113 | struct gk20a_channel_sync *gk20a_channel_sync_create(struct channel_gk20a *c, | 117 | struct gk20a_channel_sync *gk20a_channel_sync_create(struct channel_gk20a *c, |