diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2016-01-06 03:12:23 -0500 |
---|---|---|
committer | Sachin Nikam <snikam@nvidia.com> | 2016-01-13 02:23:43 -0500 |
commit | e153458aad399eedc2c05692226afb000dff4d58 (patch) | |
tree | 16fd705a75920f1659b76f14a6fe3ff60560da2b /drivers | |
parent | f7285577d7948115ff38c83982eb3b126302b195 (diff) |
gpu: nvgpu: return ENOSPC if no private command buffer space
If we run out of gpfifo space or private command
buffer space, we currently return EAGAIN as error code
Instead of EAGAIN, return ENOSPC as error code so
that caller (user space) can read the error code
and do some re-trials
As the jobs are processed, it is possible to free up
some space. And hence such re-trials could succeed
Bug 1715291
Change-Id: I9a2ed7134d2496b383899b3c02c0e70452b26115
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/929402
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Tested-by: Sachin Nikam <snikam@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | 38 |
2 files changed, 22 insertions, 20 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 2ec1ffe4..f34df520 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -1327,7 +1327,7 @@ int gk20a_channel_alloc_priv_cmdbuf(struct channel_gk20a *c, u32 orig_size, | |||
1327 | free_count = (q->size - (q->put - q->get) - 1) % q->size; | 1327 | free_count = (q->size - (q->put - q->get) - 1) % q->size; |
1328 | 1328 | ||
1329 | if (size > free_count) | 1329 | if (size > free_count) |
1330 | return -EAGAIN; | 1330 | return -ENOSPC; |
1331 | 1331 | ||
1332 | e = kzalloc(sizeof(struct priv_cmd_entry), GFP_KERNEL); | 1332 | e = kzalloc(sizeof(struct priv_cmd_entry), GFP_KERNEL); |
1333 | if (!e) { | 1333 | if (!e) { |
@@ -2022,7 +2022,7 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | |||
2022 | 2022 | ||
2023 | if (err) { | 2023 | if (err) { |
2024 | gk20a_err(d, "timeout waiting for gpfifo space"); | 2024 | gk20a_err(d, "timeout waiting for gpfifo space"); |
2025 | err = -EAGAIN; | 2025 | err = -ENOSPC; |
2026 | goto clean_up; | 2026 | goto clean_up; |
2027 | } | 2027 | } |
2028 | 2028 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c index c0c8ec6d..952e6e6a 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * GK20A Channel Synchronization Abstraction | 4 | * GK20A Channel Synchronization Abstraction |
5 | * | 5 | * |
6 | * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. | 6 | * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms and conditions of the GNU General Public License, | 9 | * under the terms and conditions of the GNU General Public License, |
@@ -60,6 +60,7 @@ static int gk20a_channel_syncpt_wait_syncpt(struct gk20a_channel_sync *s, | |||
60 | struct gk20a_channel_syncpt *sp = | 60 | struct gk20a_channel_syncpt *sp = |
61 | container_of(s, struct gk20a_channel_syncpt, ops); | 61 | container_of(s, struct gk20a_channel_syncpt, ops); |
62 | struct priv_cmd_entry *wait_cmd = NULL; | 62 | struct priv_cmd_entry *wait_cmd = NULL; |
63 | int err = 0; | ||
63 | 64 | ||
64 | if (!nvhost_syncpt_is_valid_pt_ext(sp->host1x_pdev, id)) { | 65 | if (!nvhost_syncpt_is_valid_pt_ext(sp->host1x_pdev, id)) { |
65 | dev_warn(dev_from_gk20a(sp->c->g), | 66 | dev_warn(dev_from_gk20a(sp->c->g), |
@@ -70,11 +71,11 @@ static int gk20a_channel_syncpt_wait_syncpt(struct gk20a_channel_sync *s, | |||
70 | if (nvhost_syncpt_is_expired_ext(sp->host1x_pdev, id, thresh)) | 71 | if (nvhost_syncpt_is_expired_ext(sp->host1x_pdev, id, thresh)) |
71 | return 0; | 72 | return 0; |
72 | 73 | ||
73 | gk20a_channel_alloc_priv_cmdbuf(sp->c, 4, &wait_cmd); | 74 | err = gk20a_channel_alloc_priv_cmdbuf(sp->c, 4, &wait_cmd); |
74 | if (wait_cmd == NULL) { | 75 | if (err) { |
75 | gk20a_err(dev_from_gk20a(sp->c->g), | 76 | gk20a_err(dev_from_gk20a(sp->c->g), |
76 | "not enough priv cmd buffer space"); | 77 | "not enough priv cmd buffer space"); |
77 | return -EAGAIN; | 78 | return err; |
78 | } | 79 | } |
79 | 80 | ||
80 | add_wait_cmd(&wait_cmd->ptr[0], id, thresh); | 81 | add_wait_cmd(&wait_cmd->ptr[0], id, thresh); |
@@ -96,6 +97,7 @@ static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd, | |||
96 | struct gk20a_channel_syncpt *sp = | 97 | struct gk20a_channel_syncpt *sp = |
97 | container_of(s, struct gk20a_channel_syncpt, ops); | 98 | container_of(s, struct gk20a_channel_syncpt, ops); |
98 | struct channel_gk20a *c = sp->c; | 99 | struct channel_gk20a *c = sp->c; |
100 | int err = 0; | ||
99 | 101 | ||
100 | sync_fence = nvhost_sync_fdget(fd); | 102 | sync_fence = nvhost_sync_fdget(fd); |
101 | if (!sync_fence) | 103 | if (!sync_fence) |
@@ -116,12 +118,12 @@ static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd, | |||
116 | if (num_wait_cmds == 0) | 118 | if (num_wait_cmds == 0) |
117 | return 0; | 119 | return 0; |
118 | 120 | ||
119 | gk20a_channel_alloc_priv_cmdbuf(c, 4 * num_wait_cmds, &wait_cmd); | 121 | err = gk20a_channel_alloc_priv_cmdbuf(c, 4 * num_wait_cmds, &wait_cmd); |
120 | if (wait_cmd == NULL) { | 122 | if (err) { |
121 | gk20a_err(dev_from_gk20a(c->g), | 123 | gk20a_err(dev_from_gk20a(c->g), |
122 | "not enough priv cmd buffer space"); | 124 | "not enough priv cmd buffer space"); |
123 | sync_fence_put(sync_fence); | 125 | sync_fence_put(sync_fence); |
124 | return -EAGAIN; | 126 | return err; |
125 | } | 127 | } |
126 | 128 | ||
127 | i = 0; | 129 | i = 0; |
@@ -182,11 +184,11 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, | |||
182 | if (wfi_cmd) | 184 | if (wfi_cmd) |
183 | incr_cmd_size += 2; | 185 | incr_cmd_size += 2; |
184 | 186 | ||
185 | gk20a_channel_alloc_priv_cmdbuf(c, incr_cmd_size, &incr_cmd); | 187 | err = gk20a_channel_alloc_priv_cmdbuf(c, incr_cmd_size, &incr_cmd); |
186 | if (incr_cmd == NULL) { | 188 | if (err) { |
187 | gk20a_err(dev_from_gk20a(c->g), | 189 | gk20a_err(dev_from_gk20a(c->g), |
188 | "not enough priv cmd buffer space"); | 190 | "not enough priv cmd buffer space"); |
189 | return -EAGAIN; | 191 | return err; |
190 | } | 192 | } |
191 | 193 | ||
192 | /* WAR for hw bug 1491360: syncpt needs to be incremented twice */ | 194 | /* WAR for hw bug 1491360: syncpt needs to be incremented twice */ |
@@ -471,18 +473,17 @@ static int gk20a_channel_semaphore_wait_fd( | |||
471 | w->sema = gk20a_semaphore_alloc(sema->pool); | 473 | w->sema = gk20a_semaphore_alloc(sema->pool); |
472 | if (!w->sema) { | 474 | if (!w->sema) { |
473 | gk20a_err(dev_from_gk20a(c->g), "ran out of semaphores"); | 475 | gk20a_err(dev_from_gk20a(c->g), "ran out of semaphores"); |
474 | err = -EAGAIN; | 476 | err = -ENOMEM; |
475 | goto fail; | 477 | goto fail; |
476 | } | 478 | } |
477 | 479 | ||
478 | /* worker takes one reference */ | 480 | /* worker takes one reference */ |
479 | gk20a_semaphore_get(w->sema); | 481 | gk20a_semaphore_get(w->sema); |
480 | 482 | ||
481 | gk20a_channel_alloc_priv_cmdbuf(c, 8, &wait_cmd); | 483 | err = gk20a_channel_alloc_priv_cmdbuf(c, 8, &wait_cmd); |
482 | if (wait_cmd == NULL) { | 484 | if (err) { |
483 | gk20a_err(dev_from_gk20a(c->g), | 485 | gk20a_err(dev_from_gk20a(c->g), |
484 | "not enough priv cmd buffer space"); | 486 | "not enough priv cmd buffer space"); |
485 | err = -EAGAIN; | ||
486 | goto fail; | 487 | goto fail; |
487 | } | 488 | } |
488 | 489 | ||
@@ -527,21 +528,22 @@ static int __gk20a_channel_semaphore_incr( | |||
527 | container_of(s, struct gk20a_channel_semaphore, ops); | 528 | container_of(s, struct gk20a_channel_semaphore, ops); |
528 | struct channel_gk20a *c = sp->c; | 529 | struct channel_gk20a *c = sp->c; |
529 | struct gk20a_semaphore *semaphore; | 530 | struct gk20a_semaphore *semaphore; |
531 | int err = 0; | ||
530 | 532 | ||
531 | semaphore = gk20a_semaphore_alloc(sp->pool); | 533 | semaphore = gk20a_semaphore_alloc(sp->pool); |
532 | if (!semaphore) { | 534 | if (!semaphore) { |
533 | gk20a_err(dev_from_gk20a(c->g), | 535 | gk20a_err(dev_from_gk20a(c->g), |
534 | "ran out of semaphores"); | 536 | "ran out of semaphores"); |
535 | return -EAGAIN; | 537 | return -ENOMEM; |
536 | } | 538 | } |
537 | 539 | ||
538 | incr_cmd_size = 10; | 540 | incr_cmd_size = 10; |
539 | gk20a_channel_alloc_priv_cmdbuf(c, incr_cmd_size, &incr_cmd); | 541 | err = gk20a_channel_alloc_priv_cmdbuf(c, incr_cmd_size, &incr_cmd); |
540 | if (incr_cmd == NULL) { | 542 | if (err) { |
541 | gk20a_err(dev_from_gk20a(c->g), | 543 | gk20a_err(dev_from_gk20a(c->g), |
542 | "not enough priv cmd buffer space"); | 544 | "not enough priv cmd buffer space"); |
543 | gk20a_semaphore_put(semaphore); | 545 | gk20a_semaphore_put(semaphore); |
544 | return -EAGAIN; | 546 | return err; |
545 | } | 547 | } |
546 | 548 | ||
547 | /* Release the completion semaphore. */ | 549 | /* Release the completion semaphore. */ |