diff options
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 47 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 3 |
2 files changed, 37 insertions, 13 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index b126f31a..62092930 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -1592,11 +1592,19 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | |||
1592 | /* Make sure we have enough space for gpfifo entries. If not, | 1592 | /* Make sure we have enough space for gpfifo entries. If not, |
1593 | * wait for signals from completed submits */ | 1593 | * wait for signals from completed submits */ |
1594 | if (gp_free_count(c) < num_entries + extra_entries) { | 1594 | if (gp_free_count(c) < num_entries + extra_entries) { |
1595 | /* we can get here via locked ioctl and other paths too */ | ||
1596 | int locked_path = mutex_is_locked(&c->ioctl_lock); | ||
1597 | if (locked_path) | ||
1598 | mutex_unlock(&c->ioctl_lock); | ||
1599 | |||
1595 | trace_gk20a_gpfifo_submit_wait_for_space(c->g->dev->name); | 1600 | trace_gk20a_gpfifo_submit_wait_for_space(c->g->dev->name); |
1596 | err = wait_event_interruptible(c->submit_wq, | 1601 | err = wait_event_interruptible(c->submit_wq, |
1597 | get_gp_free_count(c) >= num_entries + extra_entries || | 1602 | get_gp_free_count(c) >= num_entries + extra_entries || |
1598 | c->has_timedout); | 1603 | c->has_timedout); |
1599 | trace_gk20a_gpfifo_submit_wait_for_space_done(c->g->dev->name); | 1604 | trace_gk20a_gpfifo_submit_wait_for_space_done(c->g->dev->name); |
1605 | |||
1606 | if (locked_path) | ||
1607 | mutex_lock(&c->ioctl_lock); | ||
1600 | } | 1608 | } |
1601 | 1609 | ||
1602 | if (c->has_timedout) { | 1610 | if (c->has_timedout) { |
@@ -1765,6 +1773,7 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid) | |||
1765 | c->in_use = false; | 1773 | c->in_use = false; |
1766 | c->hw_chid = chid; | 1774 | c->hw_chid = chid; |
1767 | c->bound = false; | 1775 | c->bound = false; |
1776 | mutex_init(&c->ioctl_lock); | ||
1768 | mutex_init(&c->jobs_lock); | 1777 | mutex_init(&c->jobs_lock); |
1769 | mutex_init(&c->submit_lock); | 1778 | mutex_init(&c->submit_lock); |
1770 | INIT_LIST_HEAD(&c->jobs); | 1779 | INIT_LIST_HEAD(&c->jobs); |
@@ -2270,6 +2279,10 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2270 | return -EFAULT; | 2279 | return -EFAULT; |
2271 | } | 2280 | } |
2272 | 2281 | ||
2282 | /* protect our sanity for threaded userspace - most of the channel is | ||
2283 | * not thread safe */ | ||
2284 | mutex_lock(&ch->ioctl_lock); | ||
2285 | |||
2273 | switch (cmd) { | 2286 | switch (cmd) { |
2274 | case NVGPU_IOCTL_CHANNEL_OPEN: | 2287 | case NVGPU_IOCTL_CHANNEL_OPEN: |
2275 | err = gk20a_channel_open_ioctl(ch->g, | 2288 | err = gk20a_channel_open_ioctl(ch->g, |
@@ -2283,7 +2296,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2283 | dev_err(&dev->dev, | 2296 | dev_err(&dev->dev, |
2284 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2297 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2285 | __func__, cmd); | 2298 | __func__, cmd); |
2286 | return err; | 2299 | break; |
2287 | } | 2300 | } |
2288 | err = ch->g->ops.gr.alloc_obj_ctx(ch, | 2301 | err = ch->g->ops.gr.alloc_obj_ctx(ch, |
2289 | (struct nvgpu_alloc_obj_ctx_args *)buf); | 2302 | (struct nvgpu_alloc_obj_ctx_args *)buf); |
@@ -2295,7 +2308,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2295 | dev_err(&dev->dev, | 2308 | dev_err(&dev->dev, |
2296 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2309 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2297 | __func__, cmd); | 2310 | __func__, cmd); |
2298 | return err; | 2311 | break; |
2299 | } | 2312 | } |
2300 | err = ch->g->ops.gr.free_obj_ctx(ch, | 2313 | err = ch->g->ops.gr.free_obj_ctx(ch, |
2301 | (struct nvgpu_free_obj_ctx_args *)buf); | 2314 | (struct nvgpu_free_obj_ctx_args *)buf); |
@@ -2307,7 +2320,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2307 | dev_err(&dev->dev, | 2320 | dev_err(&dev->dev, |
2308 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2321 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2309 | __func__, cmd); | 2322 | __func__, cmd); |
2310 | return err; | 2323 | break; |
2311 | } | 2324 | } |
2312 | err = gk20a_alloc_channel_gpfifo(ch, | 2325 | err = gk20a_alloc_channel_gpfifo(ch, |
2313 | (struct nvgpu_alloc_gpfifo_args *)buf); | 2326 | (struct nvgpu_alloc_gpfifo_args *)buf); |
@@ -2323,10 +2336,18 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2323 | dev_err(&dev->dev, | 2336 | dev_err(&dev->dev, |
2324 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2337 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2325 | __func__, cmd); | 2338 | __func__, cmd); |
2326 | return err; | 2339 | break; |
2327 | } | 2340 | } |
2341 | |||
2342 | /* waiting is thread-safe, not dropping this mutex could | ||
2343 | * deadlock in certain conditions */ | ||
2344 | mutex_unlock(&ch->ioctl_lock); | ||
2345 | |||
2328 | err = gk20a_channel_wait(ch, | 2346 | err = gk20a_channel_wait(ch, |
2329 | (struct nvgpu_wait_args *)buf); | 2347 | (struct nvgpu_wait_args *)buf); |
2348 | |||
2349 | mutex_lock(&ch->ioctl_lock); | ||
2350 | |||
2330 | gk20a_idle(dev); | 2351 | gk20a_idle(dev); |
2331 | break; | 2352 | break; |
2332 | case NVGPU_IOCTL_CHANNEL_ZCULL_BIND: | 2353 | case NVGPU_IOCTL_CHANNEL_ZCULL_BIND: |
@@ -2335,7 +2356,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2335 | dev_err(&dev->dev, | 2356 | dev_err(&dev->dev, |
2336 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2357 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2337 | __func__, cmd); | 2358 | __func__, cmd); |
2338 | return err; | 2359 | break; |
2339 | } | 2360 | } |
2340 | err = gk20a_channel_zcull_bind(ch, | 2361 | err = gk20a_channel_zcull_bind(ch, |
2341 | (struct nvgpu_zcull_bind_args *)buf); | 2362 | (struct nvgpu_zcull_bind_args *)buf); |
@@ -2347,7 +2368,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2347 | dev_err(&dev->dev, | 2368 | dev_err(&dev->dev, |
2348 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2369 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2349 | __func__, cmd); | 2370 | __func__, cmd); |
2350 | return err; | 2371 | break; |
2351 | } | 2372 | } |
2352 | err = gk20a_init_error_notifier(ch, | 2373 | err = gk20a_init_error_notifier(ch, |
2353 | (struct nvgpu_set_error_notifier *)buf); | 2374 | (struct nvgpu_set_error_notifier *)buf); |
@@ -2360,7 +2381,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2360 | dev_err(&dev->dev, | 2381 | dev_err(&dev->dev, |
2361 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2382 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2362 | __func__, cmd); | 2383 | __func__, cmd); |
2363 | return err; | 2384 | break; |
2364 | } | 2385 | } |
2365 | err = gk20a_channel_cycle_stats(ch, | 2386 | err = gk20a_channel_cycle_stats(ch, |
2366 | (struct nvgpu_cycle_stats_args *)buf); | 2387 | (struct nvgpu_cycle_stats_args *)buf); |
@@ -2399,7 +2420,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2399 | dev_err(&dev->dev, | 2420 | dev_err(&dev->dev, |
2400 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2421 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2401 | __func__, cmd); | 2422 | __func__, cmd); |
2402 | return err; | 2423 | break; |
2403 | } | 2424 | } |
2404 | gk20a_channel_set_priority(ch, | 2425 | gk20a_channel_set_priority(ch, |
2405 | ((struct nvgpu_set_priority_args *)buf)->priority); | 2426 | ((struct nvgpu_set_priority_args *)buf)->priority); |
@@ -2411,7 +2432,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2411 | dev_err(&dev->dev, | 2432 | dev_err(&dev->dev, |
2412 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2433 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2413 | __func__, cmd); | 2434 | __func__, cmd); |
2414 | return err; | 2435 | break; |
2415 | } | 2436 | } |
2416 | /* enable channel */ | 2437 | /* enable channel */ |
2417 | gk20a_writel(ch->g, ccsr_channel_r(ch->hw_chid), | 2438 | gk20a_writel(ch->g, ccsr_channel_r(ch->hw_chid), |
@@ -2425,7 +2446,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2425 | dev_err(&dev->dev, | 2446 | dev_err(&dev->dev, |
2426 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2447 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2427 | __func__, cmd); | 2448 | __func__, cmd); |
2428 | return err; | 2449 | break; |
2429 | } | 2450 | } |
2430 | /* disable channel */ | 2451 | /* disable channel */ |
2431 | gk20a_writel(ch->g, ccsr_channel_r(ch->hw_chid), | 2452 | gk20a_writel(ch->g, ccsr_channel_r(ch->hw_chid), |
@@ -2439,7 +2460,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2439 | dev_err(&dev->dev, | 2460 | dev_err(&dev->dev, |
2440 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2461 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2441 | __func__, cmd); | 2462 | __func__, cmd); |
2442 | return err; | 2463 | break; |
2443 | } | 2464 | } |
2444 | err = gk20a_fifo_preempt(ch->g, ch); | 2465 | err = gk20a_fifo_preempt(ch->g, ch); |
2445 | gk20a_idle(dev); | 2466 | gk20a_idle(dev); |
@@ -2450,7 +2471,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2450 | dev_err(&dev->dev, | 2471 | dev_err(&dev->dev, |
2451 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | 2472 | "%s: failed to host gk20a for ioctl cmd: 0x%x", |
2452 | __func__, cmd); | 2473 | __func__, cmd); |
2453 | return err; | 2474 | break; |
2454 | } | 2475 | } |
2455 | err = gk20a_fifo_force_reset_ch(ch, true); | 2476 | err = gk20a_fifo_force_reset_ch(ch, true); |
2456 | gk20a_idle(dev); | 2477 | gk20a_idle(dev); |
@@ -2470,5 +2491,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
2470 | 2491 | ||
2471 | gk20a_dbg_fn("end"); | 2492 | gk20a_dbg_fn("end"); |
2472 | 2493 | ||
2494 | mutex_unlock(&ch->ioctl_lock); | ||
2495 | |||
2473 | return err; | 2496 | return err; |
2474 | } | 2497 | } |
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index c028e3b1..034de53f 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * GK20A graphics channel | 2 | * GK20A graphics channel |
3 | * | 3 | * |
4 | * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
@@ -84,6 +84,7 @@ struct channel_gk20a { | |||
84 | bool first_init; | 84 | bool first_init; |
85 | bool vpr; | 85 | bool vpr; |
86 | pid_t pid; | 86 | pid_t pid; |
87 | struct mutex ioctl_lock; | ||
87 | 88 | ||
88 | int tsgid; | 89 | int tsgid; |
89 | struct list_head ch_entry; /* channel's entry in TSG */ | 90 | struct list_head ch_entry; /* channel's entry in TSG */ |