diff options
author | Alex Waterman <alexw@nvidia.com> | 2016-07-18 20:18:33 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2016-09-16 00:58:44 -0400 |
commit | c9bb1228762dfbb595057d976f9b08aaead19f47 (patch) | |
tree | 82007c809def616dd2ad26fa80c33d848b00e0e3 /drivers/gpu/nvgpu/gk20a | |
parent | 7b8cbd2be37643e755ccb204e38c20b17aac28bd (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')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 170 |
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 | */ | ||
2092 | static 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 | |||
2175 | fail: | ||
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 | |||
2089 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | 2183 | int 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 | ||