diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 85 |
1 files changed, 41 insertions, 44 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 2c2850c6..6eecebf5 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -177,7 +177,7 @@ int gk20a_channel_get_timescale_from_timeslice(struct gk20a *g, | |||
177 | } | 177 | } |
178 | 178 | ||
179 | static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, | 179 | static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, |
180 | u32 timeslice_period, bool interleave) | 180 | u32 timeslice_period) |
181 | { | 181 | { |
182 | void *inst_ptr; | 182 | void *inst_ptr; |
183 | int shift = 0, value = 0; | 183 | int shift = 0, value = 0; |
@@ -205,30 +205,6 @@ static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, | |||
205 | gk20a_readl(c->g, ccsr_channel_r(c->hw_chid)) | | 205 | gk20a_readl(c->g, ccsr_channel_r(c->hw_chid)) | |
206 | ccsr_channel_enable_set_true_f()); | 206 | ccsr_channel_enable_set_true_f()); |
207 | 207 | ||
208 | if (c->interleave != interleave) { | ||
209 | mutex_lock(&c->g->interleave_lock); | ||
210 | c->interleave = interleave; | ||
211 | if (interleave) | ||
212 | if (c->g->num_interleaved_channels >= | ||
213 | MAX_INTERLEAVED_CHANNELS) { | ||
214 | gk20a_err(dev_from_gk20a(c->g), | ||
215 | "Change of priority would exceed runlist length, only changing timeslice\n"); | ||
216 | c->interleave = false; | ||
217 | } else | ||
218 | c->g->num_interleaved_channels += 1; | ||
219 | else | ||
220 | c->g->num_interleaved_channels -= 1; | ||
221 | |||
222 | mutex_unlock(&c->g->interleave_lock); | ||
223 | gk20a_dbg_info("Set channel %d to interleave %d", | ||
224 | c->hw_chid, c->interleave); | ||
225 | |||
226 | gk20a_fifo_set_channel_priority( | ||
227 | c->g, 0, c->hw_chid, c->interleave); | ||
228 | c->g->ops.fifo.update_runlist( | ||
229 | c->g, 0, ~0, true, false); | ||
230 | } | ||
231 | |||
232 | return 0; | 208 | return 0; |
233 | } | 209 | } |
234 | 210 | ||
@@ -711,6 +687,32 @@ static int gk20a_channel_set_wdt_status(struct channel_gk20a *ch, | |||
711 | return 0; | 687 | return 0; |
712 | } | 688 | } |
713 | 689 | ||
690 | static int gk20a_channel_set_runlist_interleave(struct channel_gk20a *ch, | ||
691 | u32 level) | ||
692 | { | ||
693 | struct gk20a *g = ch->g; | ||
694 | int ret; | ||
695 | |||
696 | if (gk20a_is_channel_marked_as_tsg(ch)) { | ||
697 | gk20a_err(dev_from_gk20a(g), "invalid operation for TSG!\n"); | ||
698 | return -EINVAL; | ||
699 | } | ||
700 | |||
701 | switch (level) { | ||
702 | case NVGPU_RUNLIST_INTERLEAVE_LEVEL_LOW: | ||
703 | case NVGPU_RUNLIST_INTERLEAVE_LEVEL_MEDIUM: | ||
704 | case NVGPU_RUNLIST_INTERLEAVE_LEVEL_HIGH: | ||
705 | ret = g->ops.fifo.set_runlist_interleave(g, ch->hw_chid, | ||
706 | false, 0, level); | ||
707 | break; | ||
708 | default: | ||
709 | ret = -EINVAL; | ||
710 | break; | ||
711 | } | ||
712 | |||
713 | return ret ? ret : g->ops.fifo.update_runlist(g, 0, ~0, true, true); | ||
714 | } | ||
715 | |||
714 | static int gk20a_init_error_notifier(struct channel_gk20a *ch, | 716 | static int gk20a_init_error_notifier(struct channel_gk20a *ch, |
715 | struct nvgpu_set_error_notifier *args) | 717 | struct nvgpu_set_error_notifier *args) |
716 | { | 718 | { |
@@ -899,17 +901,6 @@ static void gk20a_free_channel(struct channel_gk20a *ch) | |||
899 | } | 901 | } |
900 | mutex_unlock(&f->deferred_reset_mutex); | 902 | mutex_unlock(&f->deferred_reset_mutex); |
901 | 903 | ||
902 | if (ch->interleave) { | ||
903 | ch->interleave = false; | ||
904 | gk20a_fifo_set_channel_priority( | ||
905 | ch->g, 0, ch->hw_chid, ch->interleave); | ||
906 | |||
907 | mutex_lock(&f->g->interleave_lock); | ||
908 | WARN_ON(f->g->num_interleaved_channels == 0); | ||
909 | f->g->num_interleaved_channels -= 1; | ||
910 | mutex_unlock(&f->g->interleave_lock); | ||
911 | } | ||
912 | |||
913 | if (!ch->bound) | 904 | if (!ch->bound) |
914 | goto release; | 905 | goto release; |
915 | 906 | ||
@@ -1154,11 +1145,8 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) | |||
1154 | ch->has_timedout = false; | 1145 | ch->has_timedout = false; |
1155 | ch->wdt_enabled = true; | 1146 | ch->wdt_enabled = true; |
1156 | ch->obj_class = 0; | 1147 | ch->obj_class = 0; |
1157 | ch->interleave = false; | ||
1158 | ch->clean_up.scheduled = false; | 1148 | ch->clean_up.scheduled = false; |
1159 | gk20a_fifo_set_channel_priority( | 1149 | ch->interleave_level = NVGPU_RUNLIST_INTERLEAVE_LEVEL_LOW; |
1160 | ch->g, 0, ch->hw_chid, ch->interleave); | ||
1161 | |||
1162 | 1150 | ||
1163 | /* The channel is *not* runnable at this point. It still needs to have | 1151 | /* The channel is *not* runnable at this point. It still needs to have |
1164 | * an address space bound and allocate a gpfifo and grctx. */ | 1152 | * an address space bound and allocate a gpfifo and grctx. */ |
@@ -2613,7 +2601,6 @@ unsigned int gk20a_channel_poll(struct file *filep, poll_table *wait) | |||
2613 | int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority) | 2601 | int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority) |
2614 | { | 2602 | { |
2615 | u32 timeslice_timeout; | 2603 | u32 timeslice_timeout; |
2616 | bool interleave = false; | ||
2617 | 2604 | ||
2618 | if (gk20a_is_channel_marked_as_tsg(ch)) { | 2605 | if (gk20a_is_channel_marked_as_tsg(ch)) { |
2619 | gk20a_err(dev_from_gk20a(ch->g), | 2606 | gk20a_err(dev_from_gk20a(ch->g), |
@@ -2630,8 +2617,6 @@ int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority) | |||
2630 | timeslice_timeout = ch->g->timeslice_medium_priority_us; | 2617 | timeslice_timeout = ch->g->timeslice_medium_priority_us; |
2631 | break; | 2618 | break; |
2632 | case NVGPU_PRIORITY_HIGH: | 2619 | case NVGPU_PRIORITY_HIGH: |
2633 | if (ch->g->interleave_high_priority) | ||
2634 | interleave = true; | ||
2635 | timeslice_timeout = ch->g->timeslice_high_priority_us; | 2620 | timeslice_timeout = ch->g->timeslice_high_priority_us; |
2636 | break; | 2621 | break; |
2637 | default: | 2622 | default: |
@@ -2640,7 +2625,7 @@ int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority) | |||
2640 | } | 2625 | } |
2641 | 2626 | ||
2642 | return channel_gk20a_set_schedule_params(ch, | 2627 | return channel_gk20a_set_schedule_params(ch, |
2643 | timeslice_timeout, interleave); | 2628 | timeslice_timeout); |
2644 | } | 2629 | } |
2645 | 2630 | ||
2646 | static int gk20a_channel_zcull_bind(struct channel_gk20a *ch, | 2631 | static int gk20a_channel_zcull_bind(struct channel_gk20a *ch, |
@@ -3045,6 +3030,18 @@ long gk20a_channel_ioctl(struct file *filp, | |||
3045 | err = gk20a_channel_set_wdt_status(ch, | 3030 | err = gk20a_channel_set_wdt_status(ch, |
3046 | (struct nvgpu_channel_wdt_args *)buf); | 3031 | (struct nvgpu_channel_wdt_args *)buf); |
3047 | break; | 3032 | break; |
3033 | case NVGPU_IOCTL_CHANNEL_SET_RUNLIST_INTERLEAVE: | ||
3034 | err = gk20a_busy(dev); | ||
3035 | if (err) { | ||
3036 | dev_err(&dev->dev, | ||
3037 | "%s: failed to host gk20a for ioctl cmd: 0x%x", | ||
3038 | __func__, cmd); | ||
3039 | break; | ||
3040 | } | ||
3041 | err = gk20a_channel_set_runlist_interleave(ch, | ||
3042 | ((struct nvgpu_runlist_interleave_args *)buf)->level); | ||
3043 | gk20a_idle(dev); | ||
3044 | break; | ||
3048 | default: | 3045 | default: |
3049 | dev_dbg(&dev->dev, "unrecognized ioctl cmd: 0x%x", cmd); | 3046 | dev_dbg(&dev->dev, "unrecognized ioctl cmd: 0x%x", cmd); |
3050 | err = -ENOTTY; | 3047 | err = -ENOTTY; |