summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
diff options
context:
space:
mode:
authorLakshmanan M <lm@nvidia.com>2016-06-09 01:00:16 -0400
committerTerje Bergstrom <tbergstrom@nvidia.com>2016-06-13 10:45:19 -0400
commita295d90cac87949256b629e29f97fa5e28a1feb3 (patch)
tree7c1a104c0a0594869955074fe8abe86097cacae8 /drivers/gpu/nvgpu/gk20a/channel_gk20a.c
parent987de665838f6b4aceadf52f076b91da4cc633ca (diff)
gpu: nvgpu: Add uapi support for non-graphics engines
Extend the existing NVGPU_GPU_IOCTL_OPEN_CHANNEL interface to allow opening channels for other than the primary (i.e., the graphics) runlists. This is required to push work to dGPU engines that have their own runlists, such as the asynchronous copy engines and the multimedia engines. Minor change - Added active_engines_list allocation and assignment for fifo_vgpu back end. JIRA DNVGPU-25 Change-Id: I3ed377e2c9a2b4dd72e8256463510a62c64e7a8f Signed-off-by: Lakshmanan M <lm@nvidia.com> Reviewed-on: http://git-master/r/1161541 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index 9796d7c6..713c7737 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -328,18 +328,9 @@ static int channel_gk20a_setup_userd(struct channel_gk20a *c)
328static void channel_gk20a_bind(struct channel_gk20a *c) 328static void channel_gk20a_bind(struct channel_gk20a *c)
329{ 329{
330 struct gk20a *g = c->g; 330 struct gk20a *g = c->g;
331 struct fifo_gk20a *f = &g->fifo;
332 u32 engine_id;
333 struct fifo_engine_info_gk20a *engine_info = NULL;
334 u32 inst_ptr = gk20a_mm_inst_block_addr(g, &c->inst_block) 331 u32 inst_ptr = gk20a_mm_inst_block_addr(g, &c->inst_block)
335 >> ram_in_base_shift_v(); 332 >> ram_in_base_shift_v();
336 333
337 /* TODO:Need to handle non GR engine channel bind path */
338 engine_id = gk20a_fifo_get_gr_engine_id(g);
339
340 /* Consider 1st available GR engine */
341 engine_info = (f->engine_info + engine_id);
342
343 gk20a_dbg_info("bind channel %d inst ptr 0x%08x", 334 gk20a_dbg_info("bind channel %d inst ptr 0x%08x",
344 c->hw_chid, inst_ptr); 335 c->hw_chid, inst_ptr);
345 336
@@ -348,7 +339,7 @@ static void channel_gk20a_bind(struct channel_gk20a *c)
348 gk20a_writel(g, ccsr_channel_r(c->hw_chid), 339 gk20a_writel(g, ccsr_channel_r(c->hw_chid),
349 (gk20a_readl(g, ccsr_channel_r(c->hw_chid)) & 340 (gk20a_readl(g, ccsr_channel_r(c->hw_chid)) &
350 ~ccsr_channel_runlist_f(~0)) | 341 ~ccsr_channel_runlist_f(~0)) |
351 ccsr_channel_runlist_f(engine_info->runlist_id)); 342 ccsr_channel_runlist_f(c->runlist_id));
352 343
353 gk20a_writel(g, ccsr_channel_inst_r(c->hw_chid), 344 gk20a_writel(g, ccsr_channel_inst_r(c->hw_chid),
354 ccsr_channel_inst_ptr_f(inst_ptr) | 345 ccsr_channel_inst_ptr_f(inst_ptr) |
@@ -401,7 +392,7 @@ void channel_gk20a_free_inst(struct gk20a *g, struct channel_gk20a *ch)
401 392
402static int channel_gk20a_update_runlist(struct channel_gk20a *c, bool add) 393static int channel_gk20a_update_runlist(struct channel_gk20a *c, bool add)
403{ 394{
404 return c->g->ops.fifo.update_runlist(c->g, 0, c->hw_chid, add, true); 395 return c->g->ops.fifo.update_runlist(c->g, c->runlist_id, c->hw_chid, add, true);
405} 396}
406 397
407void channel_gk20a_enable(struct channel_gk20a *ch) 398void channel_gk20a_enable(struct channel_gk20a *ch)
@@ -715,7 +706,7 @@ static int gk20a_channel_set_runlist_interleave(struct channel_gk20a *ch,
715 break; 706 break;
716 } 707 }
717 708
718 return ret ? ret : g->ops.fifo.update_runlist(g, 0, ~0, true, true); 709 return ret ? ret : g->ops.fifo.update_runlist(g, ch->runlist_id, ~0, true, true);
719} 710}
720 711
721static int gk20a_init_error_notifier(struct channel_gk20a *ch, 712static int gk20a_init_error_notifier(struct channel_gk20a *ch,
@@ -1102,7 +1093,7 @@ struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g,
1102 void (*update_fn)(struct channel_gk20a *, void *), 1093 void (*update_fn)(struct channel_gk20a *, void *),
1103 void *update_fn_data) 1094 void *update_fn_data)
1104{ 1095{
1105 struct channel_gk20a *ch = gk20a_open_new_channel(g); 1096 struct channel_gk20a *ch = gk20a_open_new_channel(g, -1);
1106 1097
1107 if (ch) { 1098 if (ch) {
1108 spin_lock(&ch->update_fn_lock); 1099 spin_lock(&ch->update_fn_lock);
@@ -1114,11 +1105,16 @@ struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g,
1114 return ch; 1105 return ch;
1115} 1106}
1116 1107
1117struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) 1108struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g, s32 runlist_id)
1118{ 1109{
1119 struct fifo_gk20a *f = &g->fifo; 1110 struct fifo_gk20a *f = &g->fifo;
1120 struct channel_gk20a *ch; 1111 struct channel_gk20a *ch;
1121 1112
1113 /* compatibility with existing code */
1114 if (!gk20a_fifo_is_valid_runlist_id(g, runlist_id)) {
1115 runlist_id = gk20a_fifo_get_gr_runlist_id(g);
1116 }
1117
1122 gk20a_dbg_fn(""); 1118 gk20a_dbg_fn("");
1123 1119
1124 ch = allocate_channel(f); 1120 ch = allocate_channel(f);
@@ -1133,6 +1129,9 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g)
1133 BUG_ON(ch->g); 1129 BUG_ON(ch->g);
1134 ch->g = g; 1130 ch->g = g;
1135 1131
1132 /* Runlist for the channel */
1133 ch->runlist_id = runlist_id;
1134
1136 if (g->ops.fifo.alloc_inst(g, ch)) { 1135 if (g->ops.fifo.alloc_inst(g, ch)) {
1137 ch->g = NULL; 1136 ch->g = NULL;
1138 free_channel(f, ch); 1137 free_channel(f, ch);
@@ -1184,7 +1183,8 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g)
1184 return ch; 1183 return ch;
1185} 1184}
1186 1185
1187static int __gk20a_channel_open(struct gk20a *g, struct file *filp) 1186/* note: runlist_id -1 is synonym for the ENGINE_GR_GK20A runlist id */
1187static int __gk20a_channel_open(struct gk20a *g, struct file *filp, s32 runlist_id)
1188{ 1188{
1189 int err; 1189 int err;
1190 struct channel_gk20a *ch; 1190 struct channel_gk20a *ch;
@@ -1198,7 +1198,7 @@ static int __gk20a_channel_open(struct gk20a *g, struct file *filp)
1198 gk20a_err(dev_from_gk20a(g), "failed to power on, %d", err); 1198 gk20a_err(dev_from_gk20a(g), "failed to power on, %d", err);
1199 return err; 1199 return err;
1200 } 1200 }
1201 ch = gk20a_open_new_channel(g); 1201 ch = gk20a_open_new_channel(g, runlist_id);
1202 gk20a_idle(g->dev); 1202 gk20a_idle(g->dev);
1203 if (!ch) { 1203 if (!ch) {
1204 gk20a_err(dev_from_gk20a(g), 1204 gk20a_err(dev_from_gk20a(g),
@@ -1220,7 +1220,7 @@ int gk20a_channel_open(struct inode *inode, struct file *filp)
1220 int ret; 1220 int ret;
1221 1221
1222 gk20a_dbg_fn("start"); 1222 gk20a_dbg_fn("start");
1223 ret = __gk20a_channel_open(g, filp); 1223 ret = __gk20a_channel_open(g, filp, -1);
1224 1224
1225 gk20a_dbg_fn("end"); 1225 gk20a_dbg_fn("end");
1226 return ret; 1226 return ret;
@@ -1233,6 +1233,7 @@ int gk20a_channel_open_ioctl(struct gk20a *g,
1233 int fd; 1233 int fd;
1234 struct file *file; 1234 struct file *file;
1235 char *name; 1235 char *name;
1236 s32 runlist_id = args->in.runlist_id;
1236 1237
1237 err = get_unused_fd_flags(O_RDWR); 1238 err = get_unused_fd_flags(O_RDWR);
1238 if (err < 0) 1239 if (err < 0)
@@ -1253,12 +1254,12 @@ int gk20a_channel_open_ioctl(struct gk20a *g,
1253 goto clean_up; 1254 goto clean_up;
1254 } 1255 }
1255 1256
1256 err = __gk20a_channel_open(g, file); 1257 err = __gk20a_channel_open(g, file, runlist_id);
1257 if (err) 1258 if (err)
1258 goto clean_up_file; 1259 goto clean_up_file;
1259 1260
1260 fd_install(fd, file); 1261 fd_install(fd, file);
1261 args->channel_fd = fd; 1262 args->out.channel_fd = fd;
1262 return 0; 1263 return 0;
1263 1264
1264clean_up_file: 1265clean_up_file:
@@ -2780,6 +2781,7 @@ int gk20a_channel_suspend(struct gk20a *g)
2780 u32 chid; 2781 u32 chid;
2781 bool channels_in_use = false; 2782 bool channels_in_use = false;
2782 int err; 2783 int err;
2784 u32 active_runlist_ids = 0;
2783 2785
2784 gk20a_dbg_fn(""); 2786 gk20a_dbg_fn("");
2785 2787
@@ -2803,12 +2805,14 @@ int gk20a_channel_suspend(struct gk20a *g)
2803 2805
2804 channels_in_use = true; 2806 channels_in_use = true;
2805 2807
2808 active_runlist_ids |= BIT(ch->runlist_id);
2809
2806 gk20a_channel_put(ch); 2810 gk20a_channel_put(ch);
2807 } 2811 }
2808 } 2812 }
2809 2813
2810 if (channels_in_use) { 2814 if (channels_in_use) {
2811 g->ops.fifo.update_runlist(g, 0, ~0, false, true); 2815 gk20a_fifo_update_runlist_ids(g, active_runlist_ids, ~0, false, true);
2812 2816
2813 for (chid = 0; chid < f->num_channels; chid++) { 2817 for (chid = 0; chid < f->num_channels; chid++) {
2814 if (gk20a_channel_get(&f->channel[chid])) { 2818 if (gk20a_channel_get(&f->channel[chid])) {
@@ -2827,6 +2831,7 @@ int gk20a_channel_resume(struct gk20a *g)
2827 struct fifo_gk20a *f = &g->fifo; 2831 struct fifo_gk20a *f = &g->fifo;
2828 u32 chid; 2832 u32 chid;
2829 bool channels_in_use = false; 2833 bool channels_in_use = false;
2834 u32 active_runlist_ids = 0;
2830 2835
2831 gk20a_dbg_fn(""); 2836 gk20a_dbg_fn("");
2832 2837
@@ -2835,12 +2840,13 @@ int gk20a_channel_resume(struct gk20a *g)
2835 gk20a_dbg_info("resume channel %d", chid); 2840 gk20a_dbg_info("resume channel %d", chid);
2836 g->ops.fifo.bind_channel(&f->channel[chid]); 2841 g->ops.fifo.bind_channel(&f->channel[chid]);
2837 channels_in_use = true; 2842 channels_in_use = true;
2843 active_runlist_ids |= BIT(f->channel[chid].runlist_id);
2838 gk20a_channel_put(&f->channel[chid]); 2844 gk20a_channel_put(&f->channel[chid]);
2839 } 2845 }
2840 } 2846 }
2841 2847
2842 if (channels_in_use) 2848 if (channels_in_use)
2843 g->ops.fifo.update_runlist(g, 0, ~0, true, true); 2849 gk20a_fifo_update_runlist_ids(g, active_runlist_ids, ~0, true, true);
2844 2850
2845 gk20a_dbg_fn("done"); 2851 gk20a_dbg_fn("done");
2846 return 0; 2852 return 0;