From 1b6e655724d2cdfa441a34119ffe3c7d2acd9596 Mon Sep 17 00:00:00 2001 From: Mahantesh Kumbar Date: Tue, 14 Oct 2014 17:44:34 +0530 Subject: gk20a: Moved bind fecs to init_gr_support -Moved bind fecs from work queue to init_gr_support. -It makes all CPU->FECS communication to happen before booting PMU, and after we boot PMU, only PMU talks to FECS. So it removes possibility to race between CPU and PMU talking to FECS. Bug 200032923 Change-Id: I01d6d7f61f5e3c0e788d9d77fcabe5a91fe86c84 Signed-off-by: Mahantesh Kumbar Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/559733 --- drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'drivers/gpu/nvgpu/gk20a/gr_gk20a.c') diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index 1dc5603f..817cb98d 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c @@ -55,6 +55,7 @@ #define BLK_SIZE (256) +static int gk20a_init_gr_bind_fecs_elpg(struct gk20a *g); static int gr_gk20a_commit_inst(struct channel_gk20a *c, u64 gpu_va); /* global ctx buffer */ @@ -4560,6 +4561,91 @@ clean_up: return err; } +static int gk20a_init_gr_bind_fecs_elpg(struct gk20a *g) +{ + struct pmu_gk20a *pmu = &g->pmu; + struct mm_gk20a *mm = &g->mm; + struct vm_gk20a *vm = &mm->pmu.vm; + struct device *d = dev_from_gk20a(g); + int err = 0; + + u32 size; + struct sg_table *sgt_pg_buf; + dma_addr_t iova; + + gk20a_dbg_fn(""); + + size = 0; + + err = gr_gk20a_fecs_get_reglist_img_size(g, &size); + if (err) { + gk20a_err(dev_from_gk20a(g), + "fail to query fecs pg buffer size"); + return err; + } + + if (!pmu->pg_buf.cpuva) { + pmu->pg_buf.cpuva = dma_alloc_coherent(d, size, + &iova, + GFP_KERNEL); + if (!pmu->pg_buf.cpuva) { + gk20a_err(d, "failed to allocate memory\n"); + return -ENOMEM; + } + + pmu->pg_buf.iova = iova; + pmu->pg_buf.size = size; + + err = gk20a_get_sgtable(d, &sgt_pg_buf, + pmu->pg_buf.cpuva, + pmu->pg_buf.iova, + size); + if (err) { + gk20a_err(d, "failed to create sg table\n"); + goto err_free_pg_buf; + } + + pmu->pg_buf.pmu_va = gk20a_gmmu_map(vm, + &sgt_pg_buf, + size, + 0, /* flags */ + gk20a_mem_flag_none); + if (!pmu->pg_buf.pmu_va) { + gk20a_err(d, "failed to map fecs pg buffer"); + err = -ENOMEM; + goto err_free_sgtable; + } + + gk20a_free_sgtable(&sgt_pg_buf); + } + + + err = gr_gk20a_fecs_set_reglist_bind_inst(g, mm->pmu.inst_block.cpu_pa); + if (err) { + gk20a_err(dev_from_gk20a(g), + "fail to bind pmu inst to gr"); + return err; + } + + err = gr_gk20a_fecs_set_reglist_virtual_addr(g, pmu->pg_buf.pmu_va); + if (err) { + gk20a_err(dev_from_gk20a(g), + "fail to set pg buffer pmu va"); + return err; + } + + return err; + +err_free_sgtable: + gk20a_free_sgtable(&sgt_pg_buf); +err_free_pg_buf: + dma_free_coherent(d, size, + pmu->pg_buf.cpuva, pmu->pg_buf.iova); + pmu->pg_buf.cpuva = NULL; + pmu->pg_buf.iova = 0; + return err; +} + int gk20a_init_gr_support(struct gk20a *g) { u32 err; @@ -4581,6 +4667,10 @@ int gk20a_init_gr_support(struct gk20a *g) if (err) return err; + err = gk20a_init_gr_bind_fecs_elpg(g); + if (err) + return err; + /* GR is inialized, signal possible waiters */ g->gr.initialized = true; wake_up(&g->gr.init_wq); -- cgit v1.2.2