summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2018-03-20 07:51:23 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-03-23 11:20:35 -0400
commitb5b4353ca6cc9b6457ddccc00bf87538291870fc (patch)
tree1e2334728031345a3cb042bcc934bb0d9e3b0f82
parent2aead38194fb6f3166a9ccb501467f7b0662f6c1 (diff)
gpu: nvgpu: set safe state for user managed syncpoints
MAX/threshold value of user managed syncpoint is not tracked by nvgpu So if channel is reset by nvgpu there could be waiters still waiting on some user syncpoint fence Fix this by setting a large safe value to user managed syncpoint when aborting the channel and when closing the channel We right now increment the current value by 0x10000 which should be sufficient to release any pending waiter Bug 200326065 Jira NVGPU-179 Change-Id: Ie6432369bb4c21bd922c14b8d5a74c1477116f0b Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1678768 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Konsta Holtta <kholtta@nvidia.com> Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/common/linux/nvhost.c19
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c18
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c19
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h10
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/nvhost.h2
5 files changed, 62 insertions, 6 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/nvhost.c b/drivers/gpu/nvgpu/common/linux/nvhost.c
index a76953e3..fa169cf0 100644
--- a/drivers/gpu/nvgpu/common/linux/nvhost.c
+++ b/drivers/gpu/nvgpu/common/linux/nvhost.c
@@ -166,6 +166,25 @@ u32 nvgpu_nvhost_syncpt_read_maxval(
166 return nvhost_syncpt_read_maxval(nvhost_dev->host1x_pdev, id); 166 return nvhost_syncpt_read_maxval(nvhost_dev->host1x_pdev, id);
167} 167}
168 168
169void nvgpu_nvhost_syncpt_set_safe_state(
170 struct nvgpu_nvhost_dev *nvhost_dev, u32 id)
171{
172 u32 val;
173
174 /*
175 * Add large number of increments to current value
176 * so that all waiters on this syncpoint are released
177 *
178 * We don't expect any case where more than 0x10000 increments
179 * are pending
180 */
181 val = nvhost_syncpt_read_minval(nvhost_dev->host1x_pdev, id);
182 val += 0x10000;
183
184 nvhost_syncpt_set_minval(nvhost_dev->host1x_pdev, id, val);
185 nvhost_syncpt_set_maxval(nvhost_dev->host1x_pdev, id, val);
186}
187
169int nvgpu_nvhost_create_symlink(struct gk20a *g) 188int nvgpu_nvhost_create_symlink(struct gk20a *g)
170{ 189{
171 struct device *dev = dev_from_gk20a(g); 190 struct device *dev = dev_from_gk20a(g);
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index 78953558..65b17304 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -196,6 +196,8 @@ void gk20a_channel_abort_clean_up(struct channel_gk20a *ch)
196 nvgpu_mutex_acquire(&ch->sync_lock); 196 nvgpu_mutex_acquire(&ch->sync_lock);
197 if (ch->sync) 197 if (ch->sync)
198 ch->sync->set_min_eq_max(ch->sync); 198 ch->sync->set_min_eq_max(ch->sync);
199 if (ch->user_sync)
200 ch->user_sync->set_safe_state(ch->user_sync);
199 nvgpu_mutex_release(&ch->sync_lock); 201 nvgpu_mutex_release(&ch->sync_lock);
200 202
201 /* release all job semaphores (applies only to jobs that use 203 /* release all job semaphores (applies only to jobs that use
@@ -435,11 +437,18 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force)
435 /* sync must be destroyed before releasing channel vm */ 437 /* sync must be destroyed before releasing channel vm */
436 nvgpu_mutex_acquire(&ch->sync_lock); 438 nvgpu_mutex_acquire(&ch->sync_lock);
437 if (ch->sync) { 439 if (ch->sync) {
438 gk20a_channel_sync_destroy(ch->sync); 440 gk20a_channel_sync_destroy(ch->sync, false);
439 ch->sync = NULL; 441 ch->sync = NULL;
440 } 442 }
441 if (ch->user_sync) { 443 if (ch->user_sync) {
442 gk20a_channel_sync_destroy(ch->user_sync); 444 /*
445 * Set user managed syncpoint to safe state
446 * But it's already done if channel has timedout
447 */
448 if (ch->has_timedout)
449 gk20a_channel_sync_destroy(ch->user_sync, false);
450 else
451 gk20a_channel_sync_destroy(ch->user_sync, true);
443 ch->user_sync = NULL; 452 ch->user_sync = NULL;
444 } 453 }
445 nvgpu_mutex_release(&ch->sync_lock); 454 nvgpu_mutex_release(&ch->sync_lock);
@@ -1211,7 +1220,7 @@ clean_up_prealloc:
1211 channel_gk20a_free_prealloc_resources(c); 1220 channel_gk20a_free_prealloc_resources(c);
1212clean_up_sync: 1221clean_up_sync:
1213 if (c->sync) { 1222 if (c->sync) {
1214 gk20a_channel_sync_destroy(c->sync); 1223 gk20a_channel_sync_destroy(c->sync, false);
1215 c->sync = NULL; 1224 c->sync = NULL;
1216 } 1225 }
1217clean_up_unmap: 1226clean_up_unmap:
@@ -1905,7 +1914,8 @@ void gk20a_channel_clean_up_jobs(struct channel_gk20a *c,
1905 if (nvgpu_atomic_dec_and_test( 1914 if (nvgpu_atomic_dec_and_test(
1906 &c->sync->refcount) && 1915 &c->sync->refcount) &&
1907 g->aggressive_sync_destroy) { 1916 g->aggressive_sync_destroy) {
1908 gk20a_channel_sync_destroy(c->sync); 1917 gk20a_channel_sync_destroy(c->sync,
1918 false);
1909 c->sync = NULL; 1919 c->sync = NULL;
1910 } 1920 }
1911 nvgpu_mutex_release(&c->sync_lock); 1921 nvgpu_mutex_release(&c->sync_lock);
diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c
index 3c12147f..236ddaaf 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c
@@ -280,6 +280,13 @@ static void gk20a_channel_syncpt_set_min_eq_max(struct gk20a_channel_sync *s)
280 nvgpu_nvhost_syncpt_set_min_eq_max_ext(sp->nvhost_dev, sp->id); 280 nvgpu_nvhost_syncpt_set_min_eq_max_ext(sp->nvhost_dev, sp->id);
281} 281}
282 282
283static void gk20a_channel_syncpt_set_safe_state(struct gk20a_channel_sync *s)
284{
285 struct gk20a_channel_syncpt *sp =
286 container_of(s, struct gk20a_channel_syncpt, ops);
287 nvgpu_nvhost_syncpt_set_safe_state(sp->nvhost_dev, sp->id);
288}
289
283static void gk20a_channel_syncpt_signal_timeline( 290static void gk20a_channel_syncpt_signal_timeline(
284 struct gk20a_channel_sync *s) 291 struct gk20a_channel_sync *s)
285{ 292{
@@ -357,6 +364,7 @@ gk20a_channel_syncpt_create(struct channel_gk20a *c, bool user_managed)
357 sp->ops.incr_wfi = gk20a_channel_syncpt_incr_wfi; 364 sp->ops.incr_wfi = gk20a_channel_syncpt_incr_wfi;
358 sp->ops.incr_user = gk20a_channel_syncpt_incr_user; 365 sp->ops.incr_user = gk20a_channel_syncpt_incr_user;
359 sp->ops.set_min_eq_max = gk20a_channel_syncpt_set_min_eq_max; 366 sp->ops.set_min_eq_max = gk20a_channel_syncpt_set_min_eq_max;
367 sp->ops.set_safe_state = gk20a_channel_syncpt_set_safe_state;
360 sp->ops.signal_timeline = gk20a_channel_syncpt_signal_timeline; 368 sp->ops.signal_timeline = gk20a_channel_syncpt_signal_timeline;
361 sp->ops.syncpt_id = gk20a_channel_syncpt_id; 369 sp->ops.syncpt_id = gk20a_channel_syncpt_id;
362 sp->ops.syncpt_address = gk20a_channel_syncpt_address; 370 sp->ops.syncpt_address = gk20a_channel_syncpt_address;
@@ -634,6 +642,11 @@ static void gk20a_channel_semaphore_set_min_eq_max(struct gk20a_channel_sync *s)
634 /* Nothing to do. */ 642 /* Nothing to do. */
635} 643}
636 644
645static void gk20a_channel_semaphore_set_safe_state(struct gk20a_channel_sync *s)
646{
647 /* Nothing to do. */
648}
649
637static void gk20a_channel_semaphore_signal_timeline( 650static void gk20a_channel_semaphore_signal_timeline(
638 struct gk20a_channel_sync *s) 651 struct gk20a_channel_sync *s)
639{ 652{
@@ -703,6 +716,7 @@ gk20a_channel_semaphore_create(struct channel_gk20a *c, bool user_managed)
703 sema->ops.incr_wfi = gk20a_channel_semaphore_incr_wfi; 716 sema->ops.incr_wfi = gk20a_channel_semaphore_incr_wfi;
704 sema->ops.incr_user = gk20a_channel_semaphore_incr_user; 717 sema->ops.incr_user = gk20a_channel_semaphore_incr_user;
705 sema->ops.set_min_eq_max = gk20a_channel_semaphore_set_min_eq_max; 718 sema->ops.set_min_eq_max = gk20a_channel_semaphore_set_min_eq_max;
719 sema->ops.set_safe_state = gk20a_channel_semaphore_set_safe_state;
706 sema->ops.signal_timeline = gk20a_channel_semaphore_signal_timeline; 720 sema->ops.signal_timeline = gk20a_channel_semaphore_signal_timeline;
707 sema->ops.syncpt_id = gk20a_channel_semaphore_syncpt_id; 721 sema->ops.syncpt_id = gk20a_channel_semaphore_syncpt_id;
708 sema->ops.syncpt_address = gk20a_channel_semaphore_syncpt_address; 722 sema->ops.syncpt_address = gk20a_channel_semaphore_syncpt_address;
@@ -711,8 +725,11 @@ gk20a_channel_semaphore_create(struct channel_gk20a *c, bool user_managed)
711 return &sema->ops; 725 return &sema->ops;
712} 726}
713 727
714void gk20a_channel_sync_destroy(struct gk20a_channel_sync *sync) 728void gk20a_channel_sync_destroy(struct gk20a_channel_sync *sync,
729 bool set_safe_state)
715{ 730{
731 if (set_safe_state)
732 sync->set_safe_state(sync);
716 sync->destroy(sync); 733 sync->destroy(sync);
717} 734}
718 735
diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h
index 3f44b27a..da8cb251 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h
@@ -86,6 +86,13 @@ struct gk20a_channel_sync {
86 /* Reset the channel syncpoint/semaphore. */ 86 /* Reset the channel syncpoint/semaphore. */
87 void (*set_min_eq_max)(struct gk20a_channel_sync *s); 87 void (*set_min_eq_max)(struct gk20a_channel_sync *s);
88 88
89 /*
90 * Set the channel syncpoint/semaphore to safe state
91 * This should be used to reset User managed syncpoint since we don't
92 * track threshold values for those syncpoints
93 */
94 void (*set_safe_state)(struct gk20a_channel_sync *s);
95
89 /* Signals the sync timeline (if owned by the gk20a_channel_sync layer). 96 /* Signals the sync timeline (if owned by the gk20a_channel_sync layer).
90 * This should be called when we notice that a gk20a_fence is 97 * This should be called when we notice that a gk20a_fence is
91 * expired. */ 98 * expired. */
@@ -101,7 +108,8 @@ struct gk20a_channel_sync {
101 void (*destroy)(struct gk20a_channel_sync *s); 108 void (*destroy)(struct gk20a_channel_sync *s);
102}; 109};
103 110
104void gk20a_channel_sync_destroy(struct gk20a_channel_sync *sync); 111void gk20a_channel_sync_destroy(struct gk20a_channel_sync *sync,
112 bool set_safe_state);
105struct gk20a_channel_sync *gk20a_channel_sync_create(struct channel_gk20a *c, 113struct gk20a_channel_sync *gk20a_channel_sync_create(struct channel_gk20a *c,
106 bool user_managed); 114 bool user_managed);
107bool gk20a_channel_sync_needs_sync_framework(struct gk20a *g); 115bool gk20a_channel_sync_needs_sync_framework(struct gk20a *g);
diff --git a/drivers/gpu/nvgpu/include/nvgpu/nvhost.h b/drivers/gpu/nvgpu/include/nvgpu/nvhost.h
index d5b5831a..13de012a 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/nvhost.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/nvhost.h
@@ -52,6 +52,8 @@ int nvgpu_nvhost_syncpt_read_ext_check(struct nvgpu_nvhost_dev *nvhost_dev,
52 u32 id, u32 *val); 52 u32 id, u32 *val);
53u32 nvgpu_nvhost_syncpt_read_maxval(struct nvgpu_nvhost_dev *nvhost_dev, 53u32 nvgpu_nvhost_syncpt_read_maxval(struct nvgpu_nvhost_dev *nvhost_dev,
54 u32 id); 54 u32 id);
55void nvgpu_nvhost_syncpt_set_safe_state(
56 struct nvgpu_nvhost_dev *nvhost_dev, u32 id);
55 57
56int nvgpu_nvhost_intr_register_notifier(struct nvgpu_nvhost_dev *nvhost_dev, 58int nvgpu_nvhost_intr_register_notifier(struct nvgpu_nvhost_dev *nvhost_dev,
57 u32 id, u32 thresh, void (*callback)(void *, int), void *private_data); 59 u32 id, u32 thresh, void (*callback)(void *, int), void *private_data);