diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index a5c2efb3..0421c0f6 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -175,7 +175,7 @@ int gk20a_channel_get_timescale_from_timeslice(struct gk20a *g, | |||
175 | } | 175 | } |
176 | 176 | ||
177 | static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, | 177 | static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, |
178 | u32 timeslice_period) | 178 | u32 timeslice_period, bool interleave) |
179 | { | 179 | { |
180 | void *inst_ptr; | 180 | void *inst_ptr; |
181 | int shift = 0, value = 0; | 181 | int shift = 0, value = 0; |
@@ -203,6 +203,30 @@ static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, | |||
203 | gk20a_readl(c->g, ccsr_channel_r(c->hw_chid)) | | 203 | gk20a_readl(c->g, ccsr_channel_r(c->hw_chid)) | |
204 | ccsr_channel_enable_set_true_f()); | 204 | ccsr_channel_enable_set_true_f()); |
205 | 205 | ||
206 | if (c->interleave != interleave) { | ||
207 | mutex_lock(&c->g->interleave_lock); | ||
208 | c->interleave = interleave; | ||
209 | if (interleave) | ||
210 | if (c->g->num_interleaved_channels >= | ||
211 | MAX_INTERLEAVED_CHANNELS) { | ||
212 | gk20a_err(dev_from_gk20a(c->g), | ||
213 | "Change of priority would exceed runlist length, only changing timeslice\n"); | ||
214 | c->interleave = false; | ||
215 | } else | ||
216 | c->g->num_interleaved_channels += 1; | ||
217 | else | ||
218 | c->g->num_interleaved_channels -= 1; | ||
219 | |||
220 | mutex_unlock(&c->g->interleave_lock); | ||
221 | gk20a_dbg_info("Set channel %d to interleave %d", | ||
222 | c->hw_chid, c->interleave); | ||
223 | |||
224 | gk20a_fifo_set_channel_priority( | ||
225 | c->g, 0, c->hw_chid, c->interleave); | ||
226 | c->g->ops.fifo.update_runlist( | ||
227 | c->g, 0, ~0, true, false); | ||
228 | } | ||
229 | |||
206 | return 0; | 230 | return 0; |
207 | } | 231 | } |
208 | 232 | ||
@@ -836,6 +860,17 @@ static void gk20a_free_channel(struct channel_gk20a *ch) | |||
836 | } | 860 | } |
837 | mutex_unlock(&f->deferred_reset_mutex); | 861 | mutex_unlock(&f->deferred_reset_mutex); |
838 | 862 | ||
863 | if (ch->interleave) { | ||
864 | ch->interleave = false; | ||
865 | gk20a_fifo_set_channel_priority( | ||
866 | ch->g, 0, ch->hw_chid, ch->interleave); | ||
867 | |||
868 | mutex_lock(&f->g->interleave_lock); | ||
869 | WARN_ON(f->g->num_interleaved_channels == 0); | ||
870 | f->g->num_interleaved_channels -= 1; | ||
871 | mutex_unlock(&f->g->interleave_lock); | ||
872 | } | ||
873 | |||
839 | if (!ch->bound) | 874 | if (!ch->bound) |
840 | goto release; | 875 | goto release; |
841 | 876 | ||
@@ -1079,6 +1114,10 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) | |||
1079 | ch->timeout_debug_dump = true; | 1114 | ch->timeout_debug_dump = true; |
1080 | ch->has_timedout = false; | 1115 | ch->has_timedout = false; |
1081 | ch->obj_class = 0; | 1116 | ch->obj_class = 0; |
1117 | ch->interleave = false; | ||
1118 | gk20a_fifo_set_channel_priority( | ||
1119 | ch->g, 0, ch->hw_chid, ch->interleave); | ||
1120 | |||
1082 | 1121 | ||
1083 | /* The channel is *not* runnable at this point. It still needs to have | 1122 | /* The channel is *not* runnable at this point. It still needs to have |
1084 | * an address space bound and allocate a gpfifo and grctx. */ | 1123 | * an address space bound and allocate a gpfifo and grctx. */ |
@@ -2458,6 +2497,7 @@ static int gk20a_channel_set_priority(struct channel_gk20a *ch, | |||
2458 | u32 priority) | 2497 | u32 priority) |
2459 | { | 2498 | { |
2460 | u32 timeslice_timeout; | 2499 | u32 timeslice_timeout; |
2500 | bool interleave = false; | ||
2461 | 2501 | ||
2462 | if (gk20a_is_channel_marked_as_tsg(ch)) { | 2502 | if (gk20a_is_channel_marked_as_tsg(ch)) { |
2463 | gk20a_err(dev_from_gk20a(ch->g), | 2503 | gk20a_err(dev_from_gk20a(ch->g), |
@@ -2474,15 +2514,17 @@ static int gk20a_channel_set_priority(struct channel_gk20a *ch, | |||
2474 | timeslice_timeout = ch->g->timeslice_medium_priority_us; | 2514 | timeslice_timeout = ch->g->timeslice_medium_priority_us; |
2475 | break; | 2515 | break; |
2476 | case NVGPU_PRIORITY_HIGH: | 2516 | case NVGPU_PRIORITY_HIGH: |
2517 | if (ch->g->interleave_high_priority) | ||
2518 | interleave = true; | ||
2477 | timeslice_timeout = ch->g->timeslice_high_priority_us; | 2519 | timeslice_timeout = ch->g->timeslice_high_priority_us; |
2478 | break; | 2520 | break; |
2479 | default: | 2521 | default: |
2480 | pr_err("Unsupported priority"); | 2522 | pr_err("Unsupported priority"); |
2481 | return -EINVAL; | 2523 | return -EINVAL; |
2482 | } | 2524 | } |
2483 | channel_gk20a_set_schedule_params(ch, | 2525 | |
2484 | timeslice_timeout); | 2526 | return channel_gk20a_set_schedule_params(ch, |
2485 | return 0; | 2527 | timeslice_timeout, interleave); |
2486 | } | 2528 | } |
2487 | 2529 | ||
2488 | static int gk20a_channel_zcull_bind(struct channel_gk20a *ch, | 2530 | static int gk20a_channel_zcull_bind(struct channel_gk20a *ch, |