diff options
author | Lakshmanan M <lm@nvidia.com> | 2016-06-09 01:00:16 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-06-13 10:45:19 -0400 |
commit | a295d90cac87949256b629e29f97fa5e28a1feb3 (patch) | |
tree | 7c1a104c0a0594869955074fe8abe86097cacae8 /drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |
parent | 987de665838f6b4aceadf52f076b91da4cc633ca (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.c | 48 |
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) | |||
328 | static void channel_gk20a_bind(struct channel_gk20a *c) | 328 | static 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 | ||
402 | static int channel_gk20a_update_runlist(struct channel_gk20a *c, bool add) | 393 | static 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 | ||
407 | void channel_gk20a_enable(struct channel_gk20a *ch) | 398 | void 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 | ||
721 | static int gk20a_init_error_notifier(struct channel_gk20a *ch, | 712 | static 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 | ||
1117 | struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) | 1108 | struct 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 | ||
1187 | static int __gk20a_channel_open(struct gk20a *g, struct file *filp) | 1186 | /* note: runlist_id -1 is synonym for the ENGINE_GR_GK20A runlist id */ |
1187 | static 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 | ||
1264 | clean_up_file: | 1265 | clean_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; |