diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/nvhost.c | 19 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 18 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | 19 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h | 10 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/nvhost.h | 2 |
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 | ||
169 | void 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 | |||
169 | int nvgpu_nvhost_create_symlink(struct gk20a *g) | 188 | int 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); |
1212 | clean_up_sync: | 1221 | clean_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 | } |
1217 | clean_up_unmap: | 1226 | clean_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 | ||
283 | static 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 | |||
283 | static void gk20a_channel_syncpt_signal_timeline( | 290 | static 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 | ||
645 | static void gk20a_channel_semaphore_set_safe_state(struct gk20a_channel_sync *s) | ||
646 | { | ||
647 | /* Nothing to do. */ | ||
648 | } | ||
649 | |||
637 | static void gk20a_channel_semaphore_signal_timeline( | 650 | static 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 | ||
714 | void gk20a_channel_sync_destroy(struct gk20a_channel_sync *sync) | 728 | void 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 | ||
104 | void gk20a_channel_sync_destroy(struct gk20a_channel_sync *sync); | 111 | void gk20a_channel_sync_destroy(struct gk20a_channel_sync *sync, |
112 | bool set_safe_state); | ||
105 | struct gk20a_channel_sync *gk20a_channel_sync_create(struct channel_gk20a *c, | 113 | struct gk20a_channel_sync *gk20a_channel_sync_create(struct channel_gk20a *c, |
106 | bool user_managed); | 114 | bool user_managed); |
107 | bool gk20a_channel_sync_needs_sync_framework(struct gk20a *g); | 115 | bool 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); |
53 | u32 nvgpu_nvhost_syncpt_read_maxval(struct nvgpu_nvhost_dev *nvhost_dev, | 53 | u32 nvgpu_nvhost_syncpt_read_maxval(struct nvgpu_nvhost_dev *nvhost_dev, |
54 | u32 id); | 54 | u32 id); |
55 | void nvgpu_nvhost_syncpt_set_safe_state( | ||
56 | struct nvgpu_nvhost_dev *nvhost_dev, u32 id); | ||
55 | 57 | ||
56 | int nvgpu_nvhost_intr_register_notifier(struct nvgpu_nvhost_dev *nvhost_dev, | 58 | int 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); |