summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/Makefile1
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c2
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.c3
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h4
-rw-r--r--drivers/gpu/nvgpu/gk20a/hal_gk20a.c2
-rw-r--r--drivers/gpu/nvgpu/gk20a/tsg_gk20a.c48
-rw-r--r--drivers/gpu/nvgpu/gk20a/tsg_gk20a.h6
-rw-r--r--drivers/gpu/nvgpu/gm20b/fifo_gm20b.c1
-rw-r--r--drivers/gpu/nvgpu/gm20b/hal_gm20b.c1
-rw-r--r--drivers/gpu/nvgpu/vgpu/fifo_vgpu.c25
-rw-r--r--drivers/gpu/nvgpu/vgpu/gr_vgpu.c82
-rw-r--r--drivers/gpu/nvgpu/vgpu/tsg_vgpu.c85
-rw-r--r--drivers/gpu/nvgpu/vgpu/vgpu.c3
-rw-r--r--drivers/gpu/nvgpu/vgpu/vgpu.h3
-rw-r--r--include/linux/tegra_vgpu.h14
15 files changed, 235 insertions, 45 deletions
diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile
index 6b3c9e16..f7bbd744 100644
--- a/drivers/gpu/nvgpu/Makefile
+++ b/drivers/gpu/nvgpu/Makefile
@@ -95,6 +95,7 @@ nvgpu-$(CONFIG_TEGRA_GR_VIRTUALIZATION) += \
95 vgpu/vgpu.o \ 95 vgpu/vgpu.o \
96 vgpu/dbg_vgpu.o \ 96 vgpu/dbg_vgpu.o \
97 vgpu/fecs_trace_vgpu.o \ 97 vgpu/fecs_trace_vgpu.o \
98 vgpu/tsg_vgpu.o \
98 vgpu/gk20a/vgpu_hal_gk20a.o \ 99 vgpu/gk20a/vgpu_hal_gk20a.o \
99 vgpu/gk20a/vgpu_gr_gk20a.o \ 100 vgpu/gk20a/vgpu_gr_gk20a.o \
100 vgpu/gm20b/vgpu_hal_gm20b.o \ 101 vgpu/gm20b/vgpu_hal_gm20b.o \
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index a73a314c..02de1391 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -952,7 +952,7 @@ static void gk20a_free_channel(struct channel_gk20a *ch)
952 952
953unbind: 953unbind:
954 if (gk20a_is_channel_marked_as_tsg(ch)) 954 if (gk20a_is_channel_marked_as_tsg(ch))
955 gk20a_tsg_unbind_channel(ch); 955 g->ops.fifo.tsg_unbind_channel(ch);
956 956
957 g->ops.fifo.unbind_channel(ch); 957 g->ops.fifo.unbind_channel(ch);
958 g->ops.fifo.free_inst(g, ch); 958 g->ops.fifo.free_inst(g, ch);
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
index 92536b36..134a2480 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
@@ -2015,7 +2015,7 @@ int gk20a_fifo_preempt(struct gk20a *g, struct channel_gk20a *ch)
2015 int err; 2015 int err;
2016 2016
2017 if (gk20a_is_channel_marked_as_tsg(ch)) 2017 if (gk20a_is_channel_marked_as_tsg(ch))
2018 err = gk20a_fifo_preempt_tsg(ch->g, ch->tsgid); 2018 err = g->ops.fifo.preempt_tsg(ch->g, ch->tsgid);
2019 else 2019 else
2020 err = g->ops.fifo.preempt_channel(ch->g, ch->hw_chid); 2020 err = g->ops.fifo.preempt_channel(ch->g, ch->hw_chid);
2021 2021
@@ -2754,6 +2754,7 @@ void gk20a_init_fifo(struct gpu_ops *gops)
2754{ 2754{
2755 gk20a_init_channel(gops); 2755 gk20a_init_channel(gops);
2756 gops->fifo.preempt_channel = gk20a_fifo_preempt_channel; 2756 gops->fifo.preempt_channel = gk20a_fifo_preempt_channel;
2757 gops->fifo.preempt_tsg = gk20a_fifo_preempt_tsg;
2757 gops->fifo.update_runlist = gk20a_fifo_update_runlist; 2758 gops->fifo.update_runlist = gk20a_fifo_update_runlist;
2758 gops->fifo.trigger_mmu_fault = gk20a_fifo_trigger_mmu_fault; 2759 gops->fifo.trigger_mmu_fault = gk20a_fifo_trigger_mmu_fault;
2759 gops->fifo.apply_pb_timeout = gk20a_fifo_apply_pb_timeout; 2760 gops->fifo.apply_pb_timeout = gk20a_fifo_apply_pb_timeout;
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index 0e13fba3..6f47f228 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -324,6 +324,7 @@ struct gpu_ops {
324 u32 gpfifo_entries, u32 flags); 324 u32 gpfifo_entries, u32 flags);
325 int (*resetup_ramfc)(struct channel_gk20a *c); 325 int (*resetup_ramfc)(struct channel_gk20a *c);
326 int (*preempt_channel)(struct gk20a *g, u32 hw_chid); 326 int (*preempt_channel)(struct gk20a *g, u32 hw_chid);
327 int (*preempt_tsg)(struct gk20a *g, u32 tsgid);
327 int (*update_runlist)(struct gk20a *g, u32 runlist_id, 328 int (*update_runlist)(struct gk20a *g, u32 runlist_id,
328 u32 hw_chid, bool add, 329 u32 hw_chid, bool add,
329 bool wait_for_finish); 330 bool wait_for_finish);
@@ -345,6 +346,9 @@ struct gpu_ops {
345 void (*device_info_data_parse)(struct gk20a *g, 346 void (*device_info_data_parse)(struct gk20a *g,
346 u32 table_entry, u32 *inst_id, 347 u32 table_entry, u32 *inst_id,
347 u32 *pri_base, u32 *fault_id); 348 u32 *pri_base, u32 *fault_id);
349 int (*tsg_bind_channel)(struct tsg_gk20a *tsg,
350 struct channel_gk20a *ch);
351 int (*tsg_unbind_channel)(struct channel_gk20a *ch);
348 } fifo; 352 } fifo;
349 struct pmu_v { 353 struct pmu_v {
350 /*used for change of enum zbc update cmd id from ver 0 to ver1*/ 354 /*used for change of enum zbc update cmd id from ver 0 to ver1*/
diff --git a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c
index fb3b3e55..5112af55 100644
--- a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c
@@ -30,6 +30,7 @@
30#include "regops_gk20a.h" 30#include "regops_gk20a.h"
31#include "therm_gk20a.h" 31#include "therm_gk20a.h"
32#include "hw_proj_gk20a.h" 32#include "hw_proj_gk20a.h"
33#include "tsg_gk20a.h"
33 34
34static struct gpu_ops gk20a_ops = { 35static struct gpu_ops gk20a_ops = {
35 .clock_gating = { 36 .clock_gating = {
@@ -142,6 +143,7 @@ int gk20a_init_hal(struct gk20a *g)
142 gk20a_init_regops(gops); 143 gk20a_init_regops(gops);
143 gk20a_init_debug_ops(gops); 144 gk20a_init_debug_ops(gops);
144 gk20a_init_therm_ops(gops); 145 gk20a_init_therm_ops(gops);
146 gk20a_init_tsg_ops(gops);
145 gops->name = "gk20a"; 147 gops->name = "gk20a";
146 gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics; 148 gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics;
147 gops->get_litter_value = gk20a_get_litter_value; 149 gops->get_litter_value = gk20a_get_litter_value;
diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
index 5b77bf80..1e479395 100644
--- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
@@ -37,13 +37,12 @@ bool gk20a_is_channel_marked_as_tsg(struct channel_gk20a *ch)
37 37
38int gk20a_enable_tsg(struct tsg_gk20a *tsg) 38int gk20a_enable_tsg(struct tsg_gk20a *tsg)
39{ 39{
40 struct gk20a *g = tsg->g;
40 struct channel_gk20a *ch; 41 struct channel_gk20a *ch;
41 42
42 mutex_lock(&tsg->ch_list_lock); 43 mutex_lock(&tsg->ch_list_lock);
43 list_for_each_entry(ch, &tsg->ch_list, ch_entry) { 44 list_for_each_entry(ch, &tsg->ch_list, ch_entry) {
44 gk20a_writel(ch->g, ccsr_channel_r(ch->hw_chid), 45 g->ops.fifo.enable_channel(ch);
45 gk20a_readl(ch->g, ccsr_channel_r(ch->hw_chid))
46 | ccsr_channel_enable_set_true_f());
47 } 46 }
48 mutex_unlock(&tsg->ch_list_lock); 47 mutex_unlock(&tsg->ch_list_lock);
49 48
@@ -52,13 +51,12 @@ int gk20a_enable_tsg(struct tsg_gk20a *tsg)
52 51
53int gk20a_disable_tsg(struct tsg_gk20a *tsg) 52int gk20a_disable_tsg(struct tsg_gk20a *tsg)
54{ 53{
54 struct gk20a *g = tsg->g;
55 struct channel_gk20a *ch; 55 struct channel_gk20a *ch;
56 56
57 mutex_lock(&tsg->ch_list_lock); 57 mutex_lock(&tsg->ch_list_lock);
58 list_for_each_entry(ch, &tsg->ch_list, ch_entry) { 58 list_for_each_entry(ch, &tsg->ch_list, ch_entry) {
59 gk20a_writel(ch->g, ccsr_channel_r(ch->hw_chid), 59 g->ops.fifo.disable_channel(ch);
60 gk20a_readl(ch->g, ccsr_channel_r(ch->hw_chid))
61 | ccsr_channel_enable_clr_true_f());
62 } 60 }
63 mutex_unlock(&tsg->ch_list_lock); 61 mutex_unlock(&tsg->ch_list_lock);
64 62
@@ -80,31 +78,37 @@ static bool gk20a_is_channel_active(struct gk20a *g, struct channel_gk20a *ch)
80 return false; 78 return false;
81} 79}
82 80
83/* 81static int gk20a_tsg_bind_channel_fd(struct tsg_gk20a *tsg, int ch_fd)
84 * API to mark channel as part of TSG
85 *
86 * Note that channel is not runnable when we bind it to TSG
87 */
88static int gk20a_tsg_bind_channel(struct tsg_gk20a *tsg, int ch_fd)
89{ 82{
90 struct file *f = fget(ch_fd); 83 struct file *f = fget(ch_fd);
91 struct channel_gk20a *ch; 84 struct channel_gk20a *ch;
92 85 int err;
93 gk20a_dbg_fn("");
94 86
95 ch = gk20a_get_channel_from_file(ch_fd); 87 ch = gk20a_get_channel_from_file(ch_fd);
96 if (!ch) 88 if (!ch)
97 return -EINVAL; 89 return -EINVAL;
90 err = ch->g->ops.fifo.tsg_bind_channel(tsg, ch);
91 fput(f);
92 return err;
93}
94
95/*
96 * API to mark channel as part of TSG
97 *
98 * Note that channel is not runnable when we bind it to TSG
99 */
100int gk20a_tsg_bind_channel(struct tsg_gk20a *tsg,
101 struct channel_gk20a *ch)
102{
103 gk20a_dbg_fn("");
98 104
99 /* check if channel is already bound to some TSG */ 105 /* check if channel is already bound to some TSG */
100 if (gk20a_is_channel_marked_as_tsg(ch)) { 106 if (gk20a_is_channel_marked_as_tsg(ch)) {
101 fput(f);
102 return -EINVAL; 107 return -EINVAL;
103 } 108 }
104 109
105 /* channel cannot be bound to TSG if it is already active */ 110 /* channel cannot be bound to TSG if it is already active */
106 if (gk20a_is_channel_active(tsg->g, ch)) { 111 if (gk20a_is_channel_active(tsg->g, ch)) {
107 fput(f);
108 return -EINVAL; 112 return -EINVAL;
109 } 113 }
110 114
@@ -119,8 +123,6 @@ static int gk20a_tsg_bind_channel(struct tsg_gk20a *tsg, int ch_fd)
119 gk20a_dbg(gpu_dbg_fn, "BIND tsg:%d channel:%d\n", 123 gk20a_dbg(gpu_dbg_fn, "BIND tsg:%d channel:%d\n",
120 tsg->tsgid, ch->hw_chid); 124 tsg->tsgid, ch->hw_chid);
121 125
122 fput(f);
123
124 gk20a_dbg_fn("done"); 126 gk20a_dbg_fn("done");
125 return 0; 127 return 0;
126} 128}
@@ -494,7 +496,7 @@ long gk20a_tsg_dev_ioctl(struct file *filp, unsigned int cmd,
494 err = -EINVAL; 496 err = -EINVAL;
495 break; 497 break;
496 } 498 }
497 err = gk20a_tsg_bind_channel(tsg, ch_fd); 499 err = gk20a_tsg_bind_channel_fd(tsg, ch_fd);
498 break; 500 break;
499 } 501 }
500 502
@@ -539,7 +541,7 @@ long gk20a_tsg_dev_ioctl(struct file *filp, unsigned int cmd,
539 return err; 541 return err;
540 } 542 }
541 /* preempt TSG */ 543 /* preempt TSG */
542 err = gk20a_fifo_preempt_tsg(g, tsg->tsgid); 544 err = g->ops.fifo.preempt_tsg(g, tsg->tsgid);
543 gk20a_idle(g->dev); 545 gk20a_idle(g->dev);
544 break; 546 break;
545 } 547 }
@@ -600,3 +602,9 @@ long gk20a_tsg_dev_ioctl(struct file *filp, unsigned int cmd,
600 602
601 return err; 603 return err;
602} 604}
605
606void gk20a_init_tsg_ops(struct gpu_ops *gops)
607{
608 gops->fifo.tsg_bind_channel = gk20a_tsg_bind_channel;
609 gops->fifo.tsg_unbind_channel = gk20a_tsg_unbind_channel;
610}
diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h
index 9a8bfada..14ead5c0 100644
--- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h
@@ -28,8 +28,7 @@ long gk20a_tsg_dev_ioctl(struct file *filp,
28 unsigned int cmd, unsigned long arg); 28 unsigned int cmd, unsigned long arg);
29 29
30int gk20a_init_tsg_support(struct gk20a *g, u32 tsgid); 30int gk20a_init_tsg_support(struct gk20a *g, u32 tsgid);
31 31void gk20a_init_tsg_ops(struct gpu_ops *gops);
32int gk20a_tsg_unbind_channel(struct channel_gk20a *ch);
33 32
34struct tsg_gk20a { 33struct tsg_gk20a {
35 struct gk20a *g; 34 struct gk20a *g;
@@ -59,6 +58,9 @@ struct tsg_gk20a {
59 58
60int gk20a_enable_tsg(struct tsg_gk20a *tsg); 59int gk20a_enable_tsg(struct tsg_gk20a *tsg);
61int gk20a_disable_tsg(struct tsg_gk20a *tsg); 60int gk20a_disable_tsg(struct tsg_gk20a *tsg);
61int gk20a_tsg_bind_channel(struct tsg_gk20a *tsg,
62 struct channel_gk20a *ch);
63int gk20a_tsg_unbind_channel(struct channel_gk20a *ch);
62 64
63void gk20a_tsg_event_id_post_event(struct tsg_gk20a *tsg, 65void gk20a_tsg_event_id_post_event(struct tsg_gk20a *tsg,
64 int event_id); 66 int event_id);
diff --git a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c
index eaa22dc2..bb873bcc 100644
--- a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c
@@ -142,6 +142,7 @@ void gm20b_init_fifo(struct gpu_ops *gops)
142 gops->fifo.channel_set_timeslice = gk20a_channel_set_timeslice; 142 gops->fifo.channel_set_timeslice = gk20a_channel_set_timeslice;
143 143
144 gops->fifo.preempt_channel = gk20a_fifo_preempt_channel; 144 gops->fifo.preempt_channel = gk20a_fifo_preempt_channel;
145 gops->fifo.preempt_tsg = gk20a_fifo_preempt_tsg;
145 gops->fifo.update_runlist = gk20a_fifo_update_runlist; 146 gops->fifo.update_runlist = gk20a_fifo_update_runlist;
146 gops->fifo.trigger_mmu_fault = gm20b_fifo_trigger_mmu_fault; 147 gops->fifo.trigger_mmu_fault = gm20b_fifo_trigger_mmu_fault;
147 gops->fifo.wait_engine_idle = gk20a_fifo_wait_engine_idle; 148 gops->fifo.wait_engine_idle = gk20a_fifo_wait_engine_idle;
diff --git a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c
index df25be5e..c0113498 100644
--- a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c
@@ -211,6 +211,7 @@ int gm20b_init_hal(struct gk20a *g)
211 gm20b_init_debug_ops(gops); 211 gm20b_init_debug_ops(gops);
212 gm20b_init_cde_ops(gops); 212 gm20b_init_cde_ops(gops);
213 gm20b_init_therm_ops(gops); 213 gm20b_init_therm_ops(gops);
214 gk20a_init_tsg_ops(gops);
214 gops->name = "gm20b"; 215 gops->name = "gm20b";
215 gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics; 216 gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics;
216 gops->get_litter_value = gm20b_get_litter_value; 217 gops->get_litter_value = gm20b_get_litter_value;
diff --git a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c
index 8fcc7cc1..fb19db4a 100644
--- a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c
@@ -410,6 +410,30 @@ static int vgpu_fifo_preempt_channel(struct gk20a *g, u32 hw_chid)
410 return err; 410 return err;
411} 411}
412 412
413static int vgpu_fifo_preempt_tsg(struct gk20a *g, u32 tsgid)
414{
415 struct gk20a_platform *platform = gk20a_get_platform(g->dev);
416 struct tegra_vgpu_cmd_msg msg;
417 struct tegra_vgpu_tsg_preempt_params *p =
418 &msg.params.tsg_preempt;
419 int err;
420
421 gk20a_dbg_fn("");
422
423 msg.cmd = TEGRA_VGPU_CMD_TSG_PREEMPT;
424 msg.handle = platform->virt_handle;
425 p->tsg_id = tsgid;
426 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
427 err = err ? err : msg.ret;
428
429 if (err) {
430 gk20a_err(dev_from_gk20a(g),
431 "preempt tsg %u failed\n", tsgid);
432 }
433
434 return err;
435}
436
413static int vgpu_submit_runlist(u64 handle, u8 runlist_id, u16 *runlist, 437static int vgpu_submit_runlist(u64 handle, u8 runlist_id, u16 *runlist,
414 u32 num_entries) 438 u32 num_entries)
415{ 439{
@@ -680,6 +704,7 @@ void vgpu_init_fifo_ops(struct gpu_ops *gops)
680 gops->fifo.free_inst = vgpu_channel_free_inst; 704 gops->fifo.free_inst = vgpu_channel_free_inst;
681 gops->fifo.setup_ramfc = vgpu_channel_setup_ramfc; 705 gops->fifo.setup_ramfc = vgpu_channel_setup_ramfc;
682 gops->fifo.preempt_channel = vgpu_fifo_preempt_channel; 706 gops->fifo.preempt_channel = vgpu_fifo_preempt_channel;
707 gops->fifo.preempt_tsg = vgpu_fifo_preempt_tsg;
683 gops->fifo.update_runlist = vgpu_fifo_update_runlist; 708 gops->fifo.update_runlist = vgpu_fifo_update_runlist;
684 gops->fifo.wait_engine_idle = vgpu_fifo_wait_engine_idle; 709 gops->fifo.wait_engine_idle = vgpu_fifo_wait_engine_idle;
685 gops->fifo.channel_set_priority = vgpu_channel_set_priority; 710 gops->fifo.channel_set_priority = vgpu_channel_set_priority;
diff --git a/drivers/gpu/nvgpu/vgpu/gr_vgpu.c b/drivers/gpu/nvgpu/vgpu/gr_vgpu.c
index b9490ac9..f395ac1e 100644
--- a/drivers/gpu/nvgpu/vgpu/gr_vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/gr_vgpu.c
@@ -445,6 +445,26 @@ static int vgpu_gr_ch_bind_gr_ctx(struct channel_gk20a *c)
445 return err; 445 return err;
446} 446}
447 447
448static int vgpu_gr_tsg_bind_gr_ctx(struct tsg_gk20a *tsg)
449{
450 struct gk20a_platform *platform = gk20a_get_platform(tsg->g->dev);
451 struct gr_ctx_desc *gr_ctx = tsg->tsg_gr_ctx;
452 struct tegra_vgpu_cmd_msg msg = {0};
453 struct tegra_vgpu_tsg_bind_gr_ctx_params *p =
454 &msg.params.tsg_bind_gr_ctx;
455 int err;
456
457 msg.cmd = TEGRA_VGPU_CMD_TSG_BIND_GR_CTX;
458 msg.handle = platform->virt_handle;
459 p->tsg_id = tsg->tsgid;
460 p->gr_ctx_handle = gr_ctx->virt_ctx;
461 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
462 err = err ? err : msg.ret;
463 WARN_ON(err);
464
465 return err;
466}
467
448static int vgpu_gr_alloc_obj_ctx(struct channel_gk20a *c, 468static int vgpu_gr_alloc_obj_ctx(struct channel_gk20a *c,
449 struct nvgpu_alloc_obj_ctx_args *args) 469 struct nvgpu_alloc_obj_ctx_args *args)
450{ 470{
@@ -472,32 +492,58 @@ static int vgpu_gr_alloc_obj_ctx(struct channel_gk20a *c,
472 } 492 }
473 c->obj_class = args->class_num; 493 c->obj_class = args->class_num;
474 494
475 /* FIXME: add TSG support */
476 if (gk20a_is_channel_marked_as_tsg(c)) 495 if (gk20a_is_channel_marked_as_tsg(c))
477 tsg = &f->tsg[c->tsgid]; 496 tsg = &f->tsg[c->tsgid];
478 497
479 /* allocate gr ctx buffer */ 498 if (!tsg) {
480 if (!ch_ctx->gr_ctx) { 499 /* allocate gr ctx buffer */
481 err = g->ops.gr.alloc_gr_ctx(g, &c->ch_ctx.gr_ctx, 500 if (!ch_ctx->gr_ctx) {
482 c->vm, 501 err = g->ops.gr.alloc_gr_ctx(g, &c->ch_ctx.gr_ctx,
483 args->class_num, 502 c->vm,
484 args->flags); 503 args->class_num,
485 if (!err) 504 args->flags);
486 err = vgpu_gr_ch_bind_gr_ctx(c); 505 if (!err)
506 err = vgpu_gr_ch_bind_gr_ctx(c);
507 if (err) {
508 gk20a_err(dev_from_gk20a(g),
509 "fail to allocate gr ctx buffer");
510 goto out;
511 }
512 } else {
513 /*TBD: needs to be more subtle about which is
514 * being allocated as some are allowed to be
515 * allocated along same channel */
516 gk20a_err(dev_from_gk20a(g),
517 "too many classes alloc'd on same channel");
518 err = -EINVAL;
519 goto out;
520 }
521 } else {
522 if (!tsg->tsg_gr_ctx) {
523 tsg->vm = c->vm;
524 gk20a_vm_get(tsg->vm);
525 err = g->ops.gr.alloc_gr_ctx(g, &tsg->tsg_gr_ctx,
526 c->vm,
527 args->class_num,
528 args->flags);
529 if (!err)
530 err = vgpu_gr_tsg_bind_gr_ctx(tsg);
531 if (err) {
532 gk20a_err(dev_from_gk20a(g),
533 "fail to allocate TSG gr ctx buffer, err=%d", err);
534 gk20a_vm_put(tsg->vm);
535 tsg->vm = NULL;
536 goto out;
537 }
538 }
487 539
540 ch_ctx->gr_ctx = tsg->tsg_gr_ctx;
541 err = vgpu_gr_ch_bind_gr_ctx(c);
488 if (err) { 542 if (err) {
489 gk20a_err(dev_from_gk20a(g), 543 gk20a_err(dev_from_gk20a(g),
490 "fail to allocate gr ctx buffer"); 544 "fail to bind gr ctx buffer");
491 goto out; 545 goto out;
492 } 546 }
493 } else {
494 /*TBD: needs to be more subtle about which is
495 * being allocated as some are allowed to be
496 * allocated along same channel */
497 gk20a_err(dev_from_gk20a(g),
498 "too many classes alloc'd on same channel");
499 err = -EINVAL;
500 goto out;
501 } 547 }
502 548
503 /* commit gr ctx buffer */ 549 /* commit gr ctx buffer */
diff --git a/drivers/gpu/nvgpu/vgpu/tsg_vgpu.c b/drivers/gpu/nvgpu/vgpu/tsg_vgpu.c
new file mode 100644
index 00000000..9245693d
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/tsg_vgpu.c
@@ -0,0 +1,85 @@
1/*
2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/kernel.h>
18#include <linux/tegra_vgpu.h>
19
20#include "gk20a/gk20a.h"
21#include "gk20a/channel_gk20a.h"
22#include "gk20a/platform_gk20a.h"
23#include "gk20a/tsg_gk20a.h"
24#include "vgpu.h"
25
26static int vgpu_tsg_bind_channel(struct tsg_gk20a *tsg,
27 struct channel_gk20a *ch)
28{
29 struct gk20a_platform *platform = gk20a_get_platform(tsg->g->dev);
30 struct tegra_vgpu_cmd_msg msg = {};
31 struct tegra_vgpu_tsg_bind_unbind_channel_params *p =
32 &msg.params.tsg_bind_unbind_channel;
33 int err;
34
35 gk20a_dbg_fn("");
36
37 err = gk20a_tsg_bind_channel(tsg, ch);
38 if (err)
39 return err;
40
41 msg.cmd = TEGRA_VGPU_CMD_TSG_BIND_CHANNEL;
42 msg.handle = platform->virt_handle;
43 p->tsg_id = tsg->tsgid;
44 p->ch_handle = ch->virt_ctx;
45 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
46 err = err ? err : msg.ret;
47 if (err) {
48 gk20a_err(dev_from_gk20a(tsg->g),
49 "vgpu_tsg_bind_channel failed, ch %d tsgid %d",
50 ch->hw_chid, tsg->tsgid);
51 gk20a_tsg_unbind_channel(ch);
52 }
53
54 return err;
55}
56
57static int vgpu_tsg_unbind_channel(struct channel_gk20a *ch)
58{
59 struct gk20a_platform *platform = gk20a_get_platform(ch->g->dev);
60 struct tegra_vgpu_cmd_msg msg = {};
61 struct tegra_vgpu_tsg_bind_unbind_channel_params *p =
62 &msg.params.tsg_bind_unbind_channel;
63 int err;
64
65 gk20a_dbg_fn("");
66
67 err = gk20a_tsg_unbind_channel(ch);
68 if (err)
69 return err;
70
71 msg.cmd = TEGRA_VGPU_CMD_TSG_UNBIND_CHANNEL;
72 msg.handle = platform->virt_handle;
73 p->ch_handle = ch->virt_ctx;
74 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
75 err = err ? err : msg.ret;
76 WARN_ON(err);
77
78 return err;
79}
80
81void vgpu_init_tsg_ops(struct gpu_ops *gops)
82{
83 gops->fifo.tsg_bind_channel = vgpu_tsg_bind_channel;
84 gops->fifo.tsg_unbind_channel = vgpu_tsg_unbind_channel;
85}
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c
index 3c06652b..4948d246 100644
--- a/drivers/gpu/nvgpu/vgpu/vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/vgpu.c
@@ -268,6 +268,7 @@ void vgpu_init_hal_common(struct gk20a *g)
268 vgpu_init_mm_ops(gops); 268 vgpu_init_mm_ops(gops);
269 vgpu_init_debug_ops(gops); 269 vgpu_init_debug_ops(gops);
270 vgpu_init_fecs_trace_ops(gops); 270 vgpu_init_fecs_trace_ops(gops);
271 vgpu_init_tsg_ops(gops);
271 gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics; 272 gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics;
272} 273}
273 274
@@ -340,8 +341,6 @@ int vgpu_pm_finalize_poweron(struct device *dev)
340 goto done; 341 goto done;
341 } 342 }
342 343
343 g->gpu_characteristics.flags &= ~NVGPU_GPU_FLAGS_SUPPORT_TSG;
344
345 gk20a_ctxsw_trace_init(g); 344 gk20a_ctxsw_trace_init(g);
346 gk20a_channel_resume(g); 345 gk20a_channel_resume(g);
347 346
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.h b/drivers/gpu/nvgpu/vgpu/vgpu.h
index 32f4b110..fdd0a54c 100644
--- a/drivers/gpu/nvgpu/vgpu/vgpu.h
+++ b/drivers/gpu/nvgpu/vgpu/vgpu.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Virtualized GPU Interfaces 2 * Virtualized GPU Interfaces
3 * 3 *
4 * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -47,6 +47,7 @@ void vgpu_init_gr_ops(struct gpu_ops *gops);
47void vgpu_init_ltc_ops(struct gpu_ops *gops); 47void vgpu_init_ltc_ops(struct gpu_ops *gops);
48void vgpu_init_mm_ops(struct gpu_ops *gops); 48void vgpu_init_mm_ops(struct gpu_ops *gops);
49void vgpu_init_debug_ops(struct gpu_ops *gops); 49void vgpu_init_debug_ops(struct gpu_ops *gops);
50void vgpu_init_tsg_ops(struct gpu_ops *gops);
50int vgpu_init_mm_support(struct gk20a *g); 51int vgpu_init_mm_support(struct gk20a *g);
51int vgpu_init_gr_support(struct gk20a *g); 52int vgpu_init_gr_support(struct gk20a *g);
52int vgpu_init_fifo_support(struct gk20a *g); 53int vgpu_init_fifo_support(struct gk20a *g);
diff --git a/include/linux/tegra_vgpu.h b/include/linux/tegra_vgpu.h
index 1d195efd..bdaabf29 100644
--- a/include/linux/tegra_vgpu.h
+++ b/include/linux/tegra_vgpu.h
@@ -88,6 +88,9 @@ enum {
88 TEGRA_VGPU_CMD_GR_CTX_FREE, 88 TEGRA_VGPU_CMD_GR_CTX_FREE,
89 TEGRA_VGPU_CMD_CHANNEL_BIND_GR_CTX, 89 TEGRA_VGPU_CMD_CHANNEL_BIND_GR_CTX,
90 TEGRA_VGPU_CMD_TSG_BIND_GR_CTX, 90 TEGRA_VGPU_CMD_TSG_BIND_GR_CTX,
91 TEGRA_VGPU_CMD_TSG_BIND_CHANNEL,
92 TEGRA_VGPU_CMD_TSG_UNBIND_CHANNEL,
93 TEGRA_VGPU_CMD_TSG_PREEMPT,
91}; 94};
92 95
93struct tegra_vgpu_connect_params { 96struct tegra_vgpu_connect_params {
@@ -361,6 +364,15 @@ struct tegra_vgpu_tsg_bind_gr_ctx_params {
361 u64 gr_ctx_handle; 364 u64 gr_ctx_handle;
362}; 365};
363 366
367struct tegra_vgpu_tsg_bind_unbind_channel_params {
368 u32 tsg_id;
369 u64 ch_handle;
370};
371
372struct tegra_vgpu_tsg_preempt_params {
373 u32 tsg_id;
374};
375
364struct tegra_vgpu_cmd_msg { 376struct tegra_vgpu_cmd_msg {
365 u32 cmd; 377 u32 cmd;
366 int ret; 378 int ret;
@@ -397,6 +409,8 @@ struct tegra_vgpu_cmd_msg {
397 struct tegra_vgpu_gr_ctx_params gr_ctx; 409 struct tegra_vgpu_gr_ctx_params gr_ctx;
398 struct tegra_vgpu_channel_bind_gr_ctx_params ch_bind_gr_ctx; 410 struct tegra_vgpu_channel_bind_gr_ctx_params ch_bind_gr_ctx;
399 struct tegra_vgpu_tsg_bind_gr_ctx_params tsg_bind_gr_ctx; 411 struct tegra_vgpu_tsg_bind_gr_ctx_params tsg_bind_gr_ctx;
412 struct tegra_vgpu_tsg_bind_unbind_channel_params tsg_bind_unbind_channel;
413 struct tegra_vgpu_tsg_preempt_params tsg_preempt;
400 char padding[192]; 414 char padding[192];
401 } params; 415 } params;
402}; 416};