summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2016-07-18 20:18:33 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2016-09-16 00:58:44 -0400
commitc9bb1228762dfbb595057d976f9b08aaead19f47 (patch)
tree82007c809def616dd2ad26fa80c33d848b00e0e3 /drivers/gpu/nvgpu/gk20a/channel_gk20a.c
parent7b8cbd2be37643e755ccb204e38c20b17aac28bd (diff)
gpu: nvgpu: Move submit sync code into its own function
Move the submit synchornization code into it's own function. This should help keep the submit code path a little more readable and understandable. Bug 1732449 Reviewed-on: http://git-master/r/1203833 (cherry picked from commit f931c65c166aeca3b8fe2996dba4ea5133febc5a) Change-Id: I4111252d242a4dbffe7f9c31e397a27b66403efc Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/1221043 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c170
1 files changed, 103 insertions, 67 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index 73de900d..c8f8c6ce 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -2086,6 +2086,100 @@ out:
2086 return 0; 2086 return 0;
2087} 2087}
2088 2088
2089/*
2090 * Handle the submit synchronization - pre-fences and post-fences.
2091 */
2092static int gk20a_submit_prepare_syncs(struct channel_gk20a *c,
2093 struct nvgpu_fence *fence,
2094 struct priv_cmd_entry **wait_cmd,
2095 struct priv_cmd_entry **incr_cmd,
2096 struct gk20a_fence **pre_fence,
2097 struct gk20a_fence **post_fence,
2098 bool force_need_sync_fence,
2099 u32 flags)
2100{
2101 struct gk20a *g = c->g;
2102 bool need_sync_fence = false;
2103 bool new_sync_created = false;
2104 int wait_fence_fd = -1;
2105 int err = 0;
2106 bool need_wfi = !(flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SUPPRESS_WFI);
2107
2108 /*
2109 * If user wants to always allocate sync_fence_fds then respect that;
2110 * otherwise, allocate sync_fence_fd based on user flags.
2111 */
2112 if (force_need_sync_fence)
2113 need_sync_fence = true;
2114
2115 mutex_lock(&c->sync_lock);
2116 if (!c->sync) {
2117 c->sync = gk20a_channel_sync_create(c);
2118 if (!c->sync) {
2119 err = -ENOMEM;
2120 mutex_unlock(&c->sync_lock);
2121 goto fail;
2122 }
2123 new_sync_created = true;
2124 }
2125 atomic_inc(&c->sync->refcount);
2126 mutex_unlock(&c->sync_lock);
2127
2128 if (g->ops.fifo.resetup_ramfc && new_sync_created) {
2129 err = g->ops.fifo.resetup_ramfc(c);
2130 if (err)
2131 goto fail;
2132 }
2133
2134 /*
2135 * Optionally insert syncpt wait in the beginning of gpfifo submission
2136 * when user requested and the wait hasn't expired. Validate that the id
2137 * makes sense, elide if not. The only reason this isn't being
2138 * unceremoniously killed is to keep running some tests which trigger
2139 * this condition.
2140 */
2141 if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_WAIT) {
2142 if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SYNC_FENCE) {
2143 wait_fence_fd = fence->id;
2144 err = c->sync->wait_fd(c->sync, wait_fence_fd,
2145 wait_cmd, pre_fence);
2146 } else {
2147 err = c->sync->wait_syncpt(c->sync, fence->id,
2148 fence->value, wait_cmd,
2149 pre_fence);
2150 }
2151 }
2152 if (err)
2153 goto fail;
2154
2155 if ((flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET) &&
2156 (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SYNC_FENCE))
2157 need_sync_fence = true;
2158
2159 /*
2160 * Always generate an increment at the end of a GPFIFO submission. This
2161 * is used to keep track of method completion for idle railgating. The
2162 * sync_pt/semaphore PB is added to the GPFIFO later on in submit.
2163 */
2164 if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET)
2165 err = c->sync->incr_user(c->sync, wait_fence_fd, incr_cmd,
2166 post_fence, need_wfi, need_sync_fence);
2167 else
2168 err = c->sync->incr(c->sync, incr_cmd,
2169 post_fence, need_sync_fence);
2170 if (err)
2171 goto fail;
2172
2173 return 0;
2174
2175fail:
2176 /*
2177 * Cleanup is handled by gk20a_submit_channel_gpfifo() since it is the
2178 * real owner of the objects we make here.
2179 */
2180 return err;
2181}
2182
2089int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, 2183int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
2090 struct nvgpu_gpfifo *gpfifo, 2184 struct nvgpu_gpfifo *gpfifo,
2091 struct nvgpu_submit_gpfifo_args *args, 2185 struct nvgpu_submit_gpfifo_args *args,
@@ -2097,8 +2191,6 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
2097{ 2191{
2098 struct gk20a *g = c->g; 2192 struct gk20a *g = c->g;
2099 struct device *d = dev_from_gk20a(g); 2193 struct device *d = dev_from_gk20a(g);
2100 int err = 0;
2101 int wait_fence_fd = -1;
2102 struct priv_cmd_entry *wait_cmd = NULL; 2194 struct priv_cmd_entry *wait_cmd = NULL;
2103 struct priv_cmd_entry *incr_cmd = NULL; 2195 struct priv_cmd_entry *incr_cmd = NULL;
2104 struct gk20a_fence *pre_fence = NULL; 2196 struct gk20a_fence *pre_fence = NULL;
@@ -2106,21 +2198,12 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
2106 /* we might need two extra gpfifo entries - one for pre fence 2198 /* we might need two extra gpfifo entries - one for pre fence
2107 * and one for post fence. */ 2199 * and one for post fence. */
2108 const int extra_entries = 2; 2200 const int extra_entries = 2;
2109 bool need_wfi = !(flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SUPPRESS_WFI);
2110 bool skip_buffer_refcounting = (flags & 2201 bool skip_buffer_refcounting = (flags &
2111 NVGPU_SUBMIT_GPFIFO_FLAGS_SKIP_BUFFER_REFCOUNTING); 2202 NVGPU_SUBMIT_GPFIFO_FLAGS_SKIP_BUFFER_REFCOUNTING);
2112 bool need_sync_fence = false; 2203 int err = 0;
2113 bool new_sync_created = false;
2114 struct nvgpu_gpfifo __user *user_gpfifo = args ? 2204 struct nvgpu_gpfifo __user *user_gpfifo = args ?
2115 (struct nvgpu_gpfifo __user *)(uintptr_t)args->gpfifo : NULL; 2205 (struct nvgpu_gpfifo __user *)(uintptr_t)args->gpfifo : NULL;
2116 2206
2117 /*
2118 * If user wants to allocate sync_fence_fd always, then respect that;
2119 * otherwise, allocate sync_fence_fd based on user flags only
2120 */
2121 if (force_need_sync_fence)
2122 need_sync_fence = true;
2123
2124 if (c->has_timedout) 2207 if (c->has_timedout)
2125 return -ETIMEDOUT; 2208 return -ETIMEDOUT;
2126 2209
@@ -2192,62 +2275,11 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
2192 } 2275 }
2193 2276
2194 2277
2195 mutex_lock(&c->sync_lock); 2278 err = gk20a_submit_prepare_syncs(c, fence, &wait_cmd, &incr_cmd,
2196 if (!c->sync) { 2279 &pre_fence, &post_fence,
2197 c->sync = gk20a_channel_sync_create(c); 2280 force_need_sync_fence, flags);
2198 if (!c->sync) { 2281 if (err)
2199 err = -ENOMEM;
2200 mutex_unlock(&c->sync_lock);
2201 goto clean_up;
2202 }
2203 new_sync_created = true;
2204 }
2205 atomic_inc(&c->sync->refcount);
2206 mutex_unlock(&c->sync_lock);
2207
2208 if (g->ops.fifo.resetup_ramfc && new_sync_created) {
2209 err = g->ops.fifo.resetup_ramfc(c);
2210 if (err) {
2211 goto clean_up;
2212 }
2213 }
2214
2215 /*
2216 * optionally insert syncpt wait in the beginning of gpfifo submission
2217 * when user requested and the wait hasn't expired.
2218 * validate that the id makes sense, elide if not
2219 * the only reason this isn't being unceremoniously killed is to
2220 * keep running some tests which trigger this condition
2221 */
2222 if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_WAIT) {
2223 if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SYNC_FENCE) {
2224 wait_fence_fd = fence->id;
2225 err = c->sync->wait_fd(c->sync, wait_fence_fd,
2226 &wait_cmd, &pre_fence);
2227 } else {
2228 err = c->sync->wait_syncpt(c->sync, fence->id,
2229 fence->value, &wait_cmd, &pre_fence);
2230 }
2231 }
2232 if (err) {
2233 goto clean_up;
2234 }
2235
2236 if ((flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET) &&
2237 (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SYNC_FENCE))
2238 need_sync_fence = true;
2239
2240 /* always insert syncpt increment at end of gpfifo submission
2241 to keep track of method completion for idle railgating */
2242 if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET)
2243 err = c->sync->incr_user(c->sync, wait_fence_fd, &incr_cmd,
2244 &post_fence, need_wfi, need_sync_fence);
2245 else
2246 err = c->sync->incr(c->sync, &incr_cmd,
2247 &post_fence, need_sync_fence);
2248 if (err) {
2249 goto clean_up; 2282 goto clean_up;
2250 }
2251 2283
2252 if (wait_cmd) 2284 if (wait_cmd)
2253 gk20a_submit_append_priv_cmdbuf(c, wait_cmd); 2285 gk20a_submit_append_priv_cmdbuf(c, wait_cmd);
@@ -2258,6 +2290,10 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
2258 if (err) 2290 if (err)
2259 goto clean_up; 2291 goto clean_up;
2260 2292
2293 /*
2294 * And here's where we add the incr_cmd we generated earlier. It should
2295 * always run!
2296 */
2261 if (incr_cmd) 2297 if (incr_cmd)
2262 gk20a_submit_append_priv_cmdbuf(c, incr_cmd); 2298 gk20a_submit_append_priv_cmdbuf(c, incr_cmd);
2263 2299