diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/cde_gk20a.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 132 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 1 |
3 files changed, 97 insertions, 38 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c index 01fca058..e1edec2a 100644 --- a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c | |||
@@ -723,7 +723,7 @@ static int gk20a_cde_execute_buffer(struct gk20a_cde_ctx *cde_ctx, | |||
723 | return -ENOSYS; | 723 | return -ENOSYS; |
724 | } | 724 | } |
725 | 725 | ||
726 | return gk20a_submit_channel_gpfifo(cde_ctx->ch, gpfifo, | 726 | return gk20a_submit_channel_gpfifo(cde_ctx->ch, gpfifo, NULL, |
727 | num_entries, flags, fence, fence_out); | 727 | num_entries, flags, fence, fence_out); |
728 | } | 728 | } |
729 | 729 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 4cf3beec..0b84b7da 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -1551,14 +1551,42 @@ static void trace_write_pushbuffer(struct channel_gk20a *c, | |||
1551 | 1551 | ||
1552 | static void trace_write_pushbuffer_range(struct channel_gk20a *c, | 1552 | static void trace_write_pushbuffer_range(struct channel_gk20a *c, |
1553 | struct nvgpu_gpfifo *g, | 1553 | struct nvgpu_gpfifo *g, |
1554 | struct nvgpu_submit_gpfifo_args *args, | ||
1555 | int offset, | ||
1554 | int count) | 1556 | int count) |
1555 | { | 1557 | { |
1556 | if (gk20a_debug_trace_cmdbuf) { | 1558 | u32 size; |
1557 | int i; | 1559 | int i; |
1558 | struct nvgpu_gpfifo *gp = g; | 1560 | struct nvgpu_gpfifo *gp; |
1559 | for (i = 0; i < count; i++, gp++) | 1561 | bool gpfifo_allocated = false; |
1560 | trace_write_pushbuffer(c, gp); | 1562 | |
1563 | if (!gk20a_debug_trace_cmdbuf) | ||
1564 | return; | ||
1565 | |||
1566 | if (!g && !args) | ||
1567 | return; | ||
1568 | |||
1569 | if (!g) { | ||
1570 | size = args->num_entries * sizeof(struct nvgpu_gpfifo); | ||
1571 | if (size) { | ||
1572 | g = nvgpu_alloc(size, false); | ||
1573 | if (!g) | ||
1574 | return; | ||
1575 | |||
1576 | if (copy_from_user(g, | ||
1577 | (void __user *)(uintptr_t)args->gpfifo, size)) { | ||
1578 | return; | ||
1579 | } | ||
1580 | } | ||
1581 | gpfifo_allocated = true; | ||
1561 | } | 1582 | } |
1583 | |||
1584 | gp = g + offset; | ||
1585 | for (i = 0; i < count; i++, gp++) | ||
1586 | trace_write_pushbuffer(c, gp); | ||
1587 | |||
1588 | if (gpfifo_allocated) | ||
1589 | nvgpu_free(g); | ||
1562 | } | 1590 | } |
1563 | 1591 | ||
1564 | static void gk20a_channel_timeout_start(struct channel_gk20a *ch, | 1592 | static void gk20a_channel_timeout_start(struct channel_gk20a *ch, |
@@ -1810,6 +1838,7 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) | |||
1810 | 1838 | ||
1811 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | 1839 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, |
1812 | struct nvgpu_gpfifo *gpfifo, | 1840 | struct nvgpu_gpfifo *gpfifo, |
1841 | struct nvgpu_submit_gpfifo_args *args, | ||
1813 | u32 num_entries, | 1842 | u32 num_entries, |
1814 | u32 flags, | 1843 | u32 flags, |
1815 | struct nvgpu_fence *fence, | 1844 | struct nvgpu_fence *fence, |
@@ -1842,6 +1871,9 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | |||
1842 | return -ENOMEM; | 1871 | return -ENOMEM; |
1843 | } | 1872 | } |
1844 | 1873 | ||
1874 | if (!gpfifo && !args) | ||
1875 | return -EINVAL; | ||
1876 | |||
1845 | if ((flags & (NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_WAIT | | 1877 | if ((flags & (NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_WAIT | |
1846 | NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET)) && | 1878 | NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET)) && |
1847 | !fence) | 1879 | !fence) |
@@ -1986,24 +2018,69 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | |||
1986 | start = c->gpfifo.put; | 2018 | start = c->gpfifo.put; |
1987 | end = start + num_entries; | 2019 | end = start + num_entries; |
1988 | 2020 | ||
1989 | if (end > c->gpfifo.entry_num) { | 2021 | if (gpfifo) { |
1990 | int length0 = c->gpfifo.entry_num - start; | 2022 | if (end > c->gpfifo.entry_num) { |
1991 | int length1 = num_entries - length0; | 2023 | int length0 = c->gpfifo.entry_num - start; |
2024 | int length1 = num_entries - length0; | ||
1992 | 2025 | ||
1993 | memcpy(gpfifo_mem + start, gpfifo, | 2026 | memcpy(gpfifo_mem + start, gpfifo, |
1994 | length0 * sizeof(*gpfifo)); | 2027 | length0 * sizeof(*gpfifo)); |
1995 | 2028 | ||
1996 | memcpy(gpfifo_mem, gpfifo + length0, | 2029 | memcpy(gpfifo_mem, gpfifo + length0, |
1997 | length1 * sizeof(*gpfifo)); | 2030 | length1 * sizeof(*gpfifo)); |
2031 | |||
2032 | trace_write_pushbuffer_range(c, gpfifo, NULL, | ||
2033 | 0, length0); | ||
2034 | trace_write_pushbuffer_range(c, gpfifo, NULL, | ||
2035 | length0, length1); | ||
2036 | } else { | ||
2037 | memcpy(gpfifo_mem + start, gpfifo, | ||
2038 | num_entries * sizeof(*gpfifo)); | ||
1998 | 2039 | ||
1999 | trace_write_pushbuffer_range(c, gpfifo, length0); | 2040 | trace_write_pushbuffer_range(c, gpfifo, NULL, |
2000 | trace_write_pushbuffer_range(c, gpfifo + length0, length1); | 2041 | 0, num_entries); |
2042 | } | ||
2001 | } else { | 2043 | } else { |
2002 | memcpy(gpfifo_mem + start, gpfifo, | 2044 | struct nvgpu_gpfifo __user *user_gpfifo = |
2003 | num_entries * sizeof(*gpfifo)); | 2045 | (struct nvgpu_gpfifo __user *)(uintptr_t)args->gpfifo; |
2046 | if (end > c->gpfifo.entry_num) { | ||
2047 | int length0 = c->gpfifo.entry_num - start; | ||
2048 | int length1 = num_entries - length0; | ||
2049 | |||
2050 | err = copy_from_user(gpfifo_mem + start, | ||
2051 | user_gpfifo, | ||
2052 | length0 * sizeof(*user_gpfifo)); | ||
2053 | if (err) { | ||
2054 | mutex_unlock(&c->submit_lock); | ||
2055 | goto clean_up; | ||
2056 | } | ||
2057 | |||
2058 | err = copy_from_user(gpfifo_mem, | ||
2059 | user_gpfifo + length0, | ||
2060 | length1 * sizeof(*user_gpfifo)); | ||
2061 | if (err) { | ||
2062 | mutex_unlock(&c->submit_lock); | ||
2063 | goto clean_up; | ||
2064 | } | ||
2004 | 2065 | ||
2005 | trace_write_pushbuffer_range(c, gpfifo, num_entries); | 2066 | trace_write_pushbuffer_range(c, NULL, args, |
2067 | 0, length0); | ||
2068 | trace_write_pushbuffer_range(c, NULL, args, | ||
2069 | length0, length1); | ||
2070 | } else { | ||
2071 | err = copy_from_user(gpfifo_mem + start, | ||
2072 | user_gpfifo, | ||
2073 | num_entries * sizeof(*user_gpfifo)); | ||
2074 | if (err) { | ||
2075 | mutex_unlock(&c->submit_lock); | ||
2076 | goto clean_up; | ||
2077 | } | ||
2078 | |||
2079 | trace_write_pushbuffer_range(c, NULL, args, | ||
2080 | 0, num_entries); | ||
2081 | } | ||
2006 | } | 2082 | } |
2083 | |||
2007 | c->gpfifo.put = (c->gpfifo.put + num_entries) & | 2084 | c->gpfifo.put = (c->gpfifo.put + num_entries) & |
2008 | (c->gpfifo.entry_num - 1); | 2085 | (c->gpfifo.entry_num - 1); |
2009 | 2086 | ||
@@ -2501,8 +2578,6 @@ static int gk20a_ioctl_channel_submit_gpfifo( | |||
2501 | struct nvgpu_submit_gpfifo_args *args) | 2578 | struct nvgpu_submit_gpfifo_args *args) |
2502 | { | 2579 | { |
2503 | struct gk20a_fence *fence_out; | 2580 | struct gk20a_fence *fence_out; |
2504 | void *gpfifo = NULL; | ||
2505 | u32 size; | ||
2506 | int ret = 0; | 2581 | int ret = 0; |
2507 | 2582 | ||
2508 | gk20a_dbg_fn(""); | 2583 | gk20a_dbg_fn(""); |
@@ -2510,23 +2585,7 @@ static int gk20a_ioctl_channel_submit_gpfifo( | |||
2510 | if (ch->has_timedout) | 2585 | if (ch->has_timedout) |
2511 | return -ETIMEDOUT; | 2586 | return -ETIMEDOUT; |
2512 | 2587 | ||
2513 | /* zero-sized submits are allowed, since they can be used for | 2588 | ret = gk20a_submit_channel_gpfifo(ch, NULL, args, args->num_entries, |
2514 | * synchronization; we might still wait and do an increment */ | ||
2515 | size = args->num_entries * sizeof(struct nvgpu_gpfifo); | ||
2516 | if (size) { | ||
2517 | gpfifo = nvgpu_alloc(size, false); | ||
2518 | if (!gpfifo) | ||
2519 | return -ENOMEM; | ||
2520 | |||
2521 | if (copy_from_user(gpfifo, | ||
2522 | (void __user *)(uintptr_t)args->gpfifo, | ||
2523 | size)) { | ||
2524 | ret = -EINVAL; | ||
2525 | goto clean_up; | ||
2526 | } | ||
2527 | } | ||
2528 | |||
2529 | ret = gk20a_submit_channel_gpfifo(ch, gpfifo, args->num_entries, | ||
2530 | args->flags, &args->fence, | 2589 | args->flags, &args->fence, |
2531 | &fence_out); | 2590 | &fence_out); |
2532 | 2591 | ||
@@ -2549,7 +2608,6 @@ static int gk20a_ioctl_channel_submit_gpfifo( | |||
2549 | gk20a_fence_put(fence_out); | 2608 | gk20a_fence_put(fence_out); |
2550 | 2609 | ||
2551 | clean_up: | 2610 | clean_up: |
2552 | nvgpu_free(gpfifo); | ||
2553 | return ret; | 2611 | return ret; |
2554 | } | 2612 | } |
2555 | 2613 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index e7809daa..d5f5e6a2 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h | |||
@@ -237,6 +237,7 @@ void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a); | |||
237 | 237 | ||
238 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | 238 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, |
239 | struct nvgpu_gpfifo *gpfifo, | 239 | struct nvgpu_gpfifo *gpfifo, |
240 | struct nvgpu_submit_gpfifo_args *args, | ||
240 | u32 num_entries, | 241 | u32 num_entries, |
241 | u32 flags, | 242 | u32 flags, |
242 | struct nvgpu_fence *fence, | 243 | struct nvgpu_fence *fence, |