From d4586cc3ab132fd03dce731e1e053bd70d9122cf Mon Sep 17 00:00:00 2001 From: Arto Merilainen Date: Wed, 9 Apr 2014 14:50:43 +0300 Subject: gpu: nvgpu: Alloc physical mem for CBC in sim CBC frontdoor access works incorrectly in the simulator if CBC is allocated from IOVA. This patch makes CBC allocation to happen from physical memory if are running in simulator. Bug 1409151 Change-Id: Ia1d1ca35b5a0375f4707824df3ef06ad1b9117d4 Signed-off-by: Arto Merilainen --- drivers/gpu/nvgpu/gk20a/ltc_common.c | 94 ++++++++++++++++++++++++++++++++++-- drivers/gpu/nvgpu/gk20a/ltc_gk20a.c | 24 ++++----- drivers/gpu/nvgpu/gk20a/mm_gk20a.h | 2 +- 3 files changed, 100 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/ltc_common.c b/drivers/gpu/nvgpu/gk20a/ltc_common.c index 8af8c687..2d2516d9 100644 --- a/drivers/gpu/nvgpu/gk20a/ltc_common.c +++ b/drivers/gpu/nvgpu/gk20a/ltc_common.c @@ -180,6 +180,85 @@ static int gk20a_ltc_init_zbc(struct gk20a *g, struct gr_gk20a *gr) return 0; } +static int gk20a_ltc_alloc_phys_cbc(struct gk20a *g, + size_t compbit_backing_size) +{ + struct gr_gk20a *gr = &g->gr; + int order = ffs(compbit_backing_size >> PAGE_SHIFT); + struct page *pages; + struct sg_table *sgt; + int err = 0; + + /* allocate few pages */ + pages = alloc_pages(GFP_KERNEL, order); + if (!pages) { + gk20a_dbg(gpu_dbg_pte, "alloc_pages failed\n"); + err = -ENOMEM; + goto err_alloc_pages; + } + + /* clean up the pages */ + memset(page_address(pages), 0, compbit_backing_size); + + /* allocate room for placing the pages pointer.. */ + gr->compbit_store.pages = + kzalloc(sizeof(*gr->compbit_store.pages), GFP_KERNEL); + if (!gr->compbit_store.pages) { + gk20a_dbg(gpu_dbg_pte, "failed to allocate pages struct"); + err = -ENOMEM; + goto err_alloc_compbit_store; + } + + err = gk20a_get_sgtable_from_pages(&g->dev->dev, &sgt, &pages, 0, + compbit_backing_size); + if (err) { + gk20a_dbg(gpu_dbg_pte, "could not get sg table for pages\n"); + goto err_alloc_sg_table; + } + + /* store the parameters to gr structure */ + *gr->compbit_store.pages = pages; + gr->compbit_store.base_iova = sg_phys(sgt->sgl); + gr->compbit_store.size = compbit_backing_size; + + kfree(sgt); + + return 0; + +err_alloc_sg_table: + kfree(gr->compbit_store.pages); + gr->compbit_store.pages = NULL; +err_alloc_compbit_store: + __free_pages(pages, order); +err_alloc_pages: + return err; +} + +static int gk20a_ltc_alloc_virt_cbc(struct gk20a *g, + size_t compbit_backing_size) +{ + struct device *d = dev_from_gk20a(g); + struct gr_gk20a *gr = &g->gr; + DEFINE_DMA_ATTRS(attrs); + dma_addr_t iova; + + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); + + gr->compbit_store.pages = + dma_alloc_attrs(d, compbit_backing_size, &iova, + GFP_KERNEL, &attrs); + if (!gr->compbit_store.pages) { + gk20a_err(dev_from_gk20a(g), "failed to allocate backing store for compbit : size %zu", + compbit_backing_size); + return -ENOMEM; + } + + gr->compbit_store.base_iova = iova; + gr->compbit_store.size = compbit_backing_size; + + return 0; +} + static void gk20a_ltc_init_cbc(struct gk20a *g, struct gr_gk20a *gr) { u32 max_size = gr->max_comptag_mem; @@ -187,10 +266,17 @@ static void gk20a_ltc_init_cbc(struct gk20a *g, struct gr_gk20a *gr) u32 compbit_base_post_divide; u64 compbit_base_post_multiply64; - u64 compbit_store_base_iova = - NV_MC_SMMU_VADDR_TRANSLATE(gr->compbit_store.base_iova); - u64 compbit_base_post_divide64 = (compbit_store_base_iova >> - ltc_ltcs_ltss_cbc_base_alignment_shift_v()); + u64 compbit_store_base_iova; + u64 compbit_base_post_divide64; + + if (IS_ENABLED(CONFIG_GK20A_PHYS_PAGE_TABLES)) + compbit_store_base_iova = gr->compbit_store.base_iova; + else + compbit_store_base_iova = NV_MC_SMMU_VADDR_TRANSLATE( + gr->compbit_store.base_iova); + + compbit_base_post_divide64 = compbit_store_base_iova >> + ltc_ltcs_ltss_cbc_base_alignment_shift_v(); do_div(compbit_base_post_divide64, gr->num_fbps); compbit_base_post_divide = u64_lo32(compbit_base_post_divide64); diff --git a/drivers/gpu/nvgpu/gk20a/ltc_gk20a.c b/drivers/gpu/nvgpu/gk20a/ltc_gk20a.c index 74475d7a..f5c6d7e7 100644 --- a/drivers/gpu/nvgpu/gk20a/ltc_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ltc_gk20a.c @@ -27,10 +27,6 @@ static int gk20a_ltc_init_comptags(struct gk20a *g, struct gr_gk20a *gr) { - struct device *d = dev_from_gk20a(g); - DEFINE_DMA_ATTRS(attrs); - dma_addr_t iova; - /* max memory size (MB) to cover */ u32 max_size = gr->max_comptag_mem; /* one tag line covers 128KB */ @@ -50,6 +46,8 @@ static int gk20a_ltc_init_comptags(struct gk20a *g, struct gr_gk20a *gr) u32 compbit_backing_size; + int err; + gk20a_dbg_fn(""); if (max_comptag_lines == 0) { @@ -84,17 +82,13 @@ static int gk20a_ltc_init_comptags(struct gk20a *g, struct gr_gk20a *gr) gk20a_dbg_info("max comptag lines : %d", max_comptag_lines); - dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); - gr->compbit_store.size = compbit_backing_size; - gr->compbit_store.pages = dma_alloc_attrs(d, gr->compbit_store.size, - &iova, GFP_KERNEL, &attrs); - if (!gr->compbit_store.pages) { - gk20a_err(dev_from_gk20a(g), "failed to allocate" - "backing store for compbit : size %d", - compbit_backing_size); - return -ENOMEM; - } - gr->compbit_store.base_iova = iova; + if (IS_ENABLED(CONFIG_GK20A_PHYS_PAGE_TABLES)) + err = gk20a_ltc_alloc_phys_cbc(g, compbit_backing_size); + else + err = gk20a_ltc_alloc_virt_cbc(g, compbit_backing_size); + + if (err) + return err; gk20a_allocator_init(&gr->comp_tags, "comptag", 1, /* start */ diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h index cdbab138..d583849d 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h @@ -156,7 +156,7 @@ struct gr_ctx_desc { }; struct compbit_store_desc { - struct pages **pages; + struct page **pages; size_t size; u64 base_iova; }; -- cgit v1.2.2