diff options
-rw-r--r-- | drivers/gpu/nvgpu/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/hal_gk20a.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/tsg_gk20a.c | 48 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/tsg_gk20a.h | 6 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/fifo_gm20b.c | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/hal_gm20b.c | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/fifo_vgpu.c | 25 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/gr_vgpu.c | 82 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/tsg_vgpu.c | 85 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/vgpu.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/vgpu.h | 3 | ||||
-rw-r--r-- | include/linux/tegra_vgpu.h | 14 |
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 | ||
953 | unbind: | 953 | unbind: |
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 | ||
34 | static struct gpu_ops gk20a_ops = { | 35 | static 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 | ||
38 | int gk20a_enable_tsg(struct tsg_gk20a *tsg) | 38 | int 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 | ||
53 | int gk20a_disable_tsg(struct tsg_gk20a *tsg) | 52 | int 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 | /* | 81 | static 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 | */ | ||
88 | static 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 | */ | ||
100 | int 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 | |||
606 | void 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 | ||
30 | int gk20a_init_tsg_support(struct gk20a *g, u32 tsgid); | 30 | int gk20a_init_tsg_support(struct gk20a *g, u32 tsgid); |
31 | 31 | void gk20a_init_tsg_ops(struct gpu_ops *gops); | |
32 | int gk20a_tsg_unbind_channel(struct channel_gk20a *ch); | ||
33 | 32 | ||
34 | struct tsg_gk20a { | 33 | struct tsg_gk20a { |
35 | struct gk20a *g; | 34 | struct gk20a *g; |
@@ -59,6 +58,9 @@ struct tsg_gk20a { | |||
59 | 58 | ||
60 | int gk20a_enable_tsg(struct tsg_gk20a *tsg); | 59 | int gk20a_enable_tsg(struct tsg_gk20a *tsg); |
61 | int gk20a_disable_tsg(struct tsg_gk20a *tsg); | 60 | int gk20a_disable_tsg(struct tsg_gk20a *tsg); |
61 | int gk20a_tsg_bind_channel(struct tsg_gk20a *tsg, | ||
62 | struct channel_gk20a *ch); | ||
63 | int gk20a_tsg_unbind_channel(struct channel_gk20a *ch); | ||
62 | 64 | ||
63 | void gk20a_tsg_event_id_post_event(struct tsg_gk20a *tsg, | 65 | void 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 | ||
413 | static 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 | |||
413 | static int vgpu_submit_runlist(u64 handle, u8 runlist_id, u16 *runlist, | 437 | static 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 | ||
448 | static 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 | |||
448 | static int vgpu_gr_alloc_obj_ctx(struct channel_gk20a *c, | 468 | static 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 | |||
26 | static 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 | |||
57 | static 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 | |||
81 | void 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); | |||
47 | void vgpu_init_ltc_ops(struct gpu_ops *gops); | 47 | void vgpu_init_ltc_ops(struct gpu_ops *gops); |
48 | void vgpu_init_mm_ops(struct gpu_ops *gops); | 48 | void vgpu_init_mm_ops(struct gpu_ops *gops); |
49 | void vgpu_init_debug_ops(struct gpu_ops *gops); | 49 | void vgpu_init_debug_ops(struct gpu_ops *gops); |
50 | void vgpu_init_tsg_ops(struct gpu_ops *gops); | ||
50 | int vgpu_init_mm_support(struct gk20a *g); | 51 | int vgpu_init_mm_support(struct gk20a *g); |
51 | int vgpu_init_gr_support(struct gk20a *g); | 52 | int vgpu_init_gr_support(struct gk20a *g); |
52 | int vgpu_init_fifo_support(struct gk20a *g); | 53 | int 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 | ||
93 | struct tegra_vgpu_connect_params { | 96 | struct 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 | ||
367 | struct tegra_vgpu_tsg_bind_unbind_channel_params { | ||
368 | u32 tsg_id; | ||
369 | u64 ch_handle; | ||
370 | }; | ||
371 | |||
372 | struct tegra_vgpu_tsg_preempt_params { | ||
373 | u32 tsg_id; | ||
374 | }; | ||
375 | |||
364 | struct tegra_vgpu_cmd_msg { | 376 | struct 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 | }; |