diff options
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; |