summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c85
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
179static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, 179static 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
690static 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
714static int gk20a_init_error_notifier(struct channel_gk20a *ch, 716static 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)
2613int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority) 2601int 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
2646static int gk20a_channel_zcull_bind(struct channel_gk20a *ch, 2631static 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;