diff --git a/drivers/gpu/nvgpu/vgpu/gv11b/platform_gv11b_vgpu_tegra.c b/drivers/gpu/nvgpu/vgpu/gv11b/platform_gv11b_vgpu_tegra.c index 6adbd46be..d48d1308d 100644 --- a/drivers/gpu/nvgpu/vgpu/gv11b/platform_gv11b_vgpu_tegra.c +++ b/drivers/gpu/nvgpu/vgpu/gv11b/platform_gv11b_vgpu_tegra.c @@ -26,6 +26,8 @@ #include "common/linux/os_linux.h" #include +#include + #include static int gv11b_vgpu_probe(struct device *dev) @@ -35,6 +37,7 @@ static int gv11b_vgpu_probe(struct device *dev) struct resource *r; void __iomem *regs; struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(platform->g); + struct gk20a *g = platform->g; int ret; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usermode"); @@ -50,11 +53,22 @@ static int gv11b_vgpu_probe(struct device *dev) l->t19x.usermode_regs = regs; #ifdef CONFIG_TEGRA_GK20A_NVHOST - ret = nvgpu_get_nvhost_dev(platform->g); + ret = nvgpu_get_nvhost_dev(g); if (ret) { l->t19x.usermode_regs = NULL; return ret; } + + ret = nvgpu_nvhost_syncpt_unit_interface_get_aperture(g->nvhost_dev, + &g->syncpt_unit_base, + &g->syncpt_unit_size); + if (ret) { + dev_err(dev, "Failed to get syncpt interface"); + return -ENOSYS; + } + g->syncpt_size = nvgpu_nvhost_syncpt_unit_interface_get_byte_offset(1); + nvgpu_info(g, "syncpt_unit_base %llx syncpt_unit_size %zx size %x\n", + g->syncpt_unit_base, g->syncpt_unit_size, g->syncpt_size); #endif vgpu_init_clk_support(platform->g); @@ -62,7 +76,7 @@ static int gv11b_vgpu_probe(struct device *dev) } struct gk20a_platform gv11b_vgpu_tegra_platform = { - .has_syncpoints = false, + .has_syncpoints = true, .aggressive_sync_destroy_thresh = 64, /* power management configuration */ diff --git a/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_fifo_gv11b.c b/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_fifo_gv11b.c index 048a4c643..ae9d52a7a 100644 --- a/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_fifo_gv11b.c +++ b/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_fifo_gv11b.c @@ -23,6 +23,82 @@ #include #include "vgpu/vgpu.h" +#include "gv11b/fifo_gv11b.h" +#include + +#include + +#ifdef CONFIG_TEGRA_GK20A_NVHOST +int vgpu_gv11b_fifo_alloc_syncpt_buf(struct channel_gk20a *c, + u32 syncpt_id, struct nvgpu_mem *syncpt_buf) +{ + int err; + struct gk20a *g = c->g; + struct vm_gk20a *vm = c->vm; + struct tegra_vgpu_cmd_msg msg = {}; + struct tegra_vgpu_map_syncpt_params *p = &msg.params.t19x.map_syncpt; + + /* + * Add ro map for complete sync point shim range in vm. + * All channels sharing same vm will share same ro mapping. + * Create rw map for current channel sync point. + */ + if (!vm->syncpt_ro_map_gpu_va) { + vm->syncpt_ro_map_gpu_va = __nvgpu_vm_alloc_va(vm, + g->syncpt_unit_size, + gmmu_page_size_kernel); + if (!vm->syncpt_ro_map_gpu_va) { + nvgpu_err(g, "allocating read-only va space failed"); + return -ENOMEM; + } + + msg.cmd = TEGRA_VGPU_CMD_MAP_SYNCPT; + msg.handle = vgpu_get_handle(g); + p->as_handle = c->vm->handle; + p->gpu_va = vm->syncpt_ro_map_gpu_va; + p->len = g->syncpt_unit_size; + p->offset = 0; + p->prot = TEGRA_VGPU_MAP_PROT_READ_ONLY; + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + err = err ? err : msg.ret; + if (err) { + nvgpu_err(g, + "mapping read-only va space failed err %d", + err); + __nvgpu_vm_free_va(c->vm, vm->syncpt_ro_map_gpu_va, + gmmu_page_size_kernel); + vm->syncpt_ro_map_gpu_va = 0; + return err; + } + } + + syncpt_buf->gpu_va = __nvgpu_vm_alloc_va(c->vm, g->syncpt_size, + gmmu_page_size_kernel); + if (!syncpt_buf->gpu_va) { + nvgpu_err(g, "allocating syncpt va space failed"); + return -ENOMEM; + } + + msg.cmd = TEGRA_VGPU_CMD_MAP_SYNCPT; + msg.handle = vgpu_get_handle(g); + p->as_handle = c->vm->handle; + p->gpu_va = syncpt_buf->gpu_va; + p->len = g->syncpt_size; + p->offset = + nvgpu_nvhost_syncpt_unit_interface_get_byte_offset(syncpt_id); + p->prot = TEGRA_VGPU_MAP_PROT_NONE; + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + err = err ? err : msg.ret; + if (err) { + nvgpu_err(g, "mapping syncpt va space failed err %d", err); + __nvgpu_vm_free_va(c->vm, syncpt_buf->gpu_va, + gmmu_page_size_kernel); + return err; + } + + return 0; +} +#endif /* CONFIG_TEGRA_GK20A_NVHOST */ int vgpu_gv11b_init_fifo_setup_hw(struct gk20a *g) { diff --git a/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_fifo_gv11b.h b/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_fifo_gv11b.h index 034045420..bea935d32 100644 --- a/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_fifo_gv11b.h +++ b/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_fifo_gv11b.h @@ -26,4 +26,6 @@ struct gk20a; int vgpu_gv11b_init_fifo_setup_hw(struct gk20a *g); +int vgpu_gv11b_fifo_alloc_syncpt_buf(struct channel_gk20a *c, + u32 syncpt_id, struct nvgpu_mem *syncpt_buf); #endif diff --git a/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c b/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c index 9226206a6..2cd8018c8 100644 --- a/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c +++ b/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c @@ -378,7 +378,7 @@ static const struct gpu_ops vgpu_gv11b_ops = { .tsg_bind_channel = vgpu_tsg_bind_channel, .tsg_unbind_channel = vgpu_tsg_unbind_channel, #ifdef CONFIG_TEGRA_GK20A_NVHOST - .alloc_syncpt_buf = gv11b_fifo_alloc_syncpt_buf, + .alloc_syncpt_buf = vgpu_gv11b_fifo_alloc_syncpt_buf, .free_syncpt_buf = gv11b_fifo_free_syncpt_buf, .add_syncpt_wait_cmd = gv11b_fifo_add_syncpt_wait_cmd, .get_syncpt_wait_cmd_size = gv11b_fifo_get_syncpt_wait_cmd_size, diff --git a/include/linux/tegra_vgpu_t19x.h b/include/linux/tegra_vgpu_t19x.h index c2814f16c..fe39230e3 100644 --- a/include/linux/tegra_vgpu_t19x.h +++ b/include/linux/tegra_vgpu_t19x.h @@ -16,6 +16,7 @@ #define TEGRA_VGPU_CMD_ALLOC_CTX_HEADER 100 #define TEGRA_VGPU_CMD_FREE_CTX_HEADER 101 +#define TEGRA_VGPU_CMD_MAP_SYNCPT 102 struct tegra_vgpu_alloc_ctx_header_params { u64 ch_handle; @@ -26,9 +27,18 @@ struct tegra_vgpu_free_ctx_header_params { u64 ch_handle; }; +struct tegra_vgpu_map_syncpt_params { + u64 as_handle; + u64 gpu_va; + u64 len; + u64 offset; + u8 prot; +}; + union tegra_vgpu_t19x_params { struct tegra_vgpu_alloc_ctx_header_params alloc_ctx_header; struct tegra_vgpu_free_ctx_header_params free_ctx_header; + struct tegra_vgpu_map_syncpt_params map_syncpt; }; #define TEGRA_VGPU_ATTRIB_MAX_SUBCTX_COUNT 100