]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
gpu: nvgpu: Alloc physical mem for CBC in sim
authorArto Merilainen <amerilainen@nvidia.com>
Wed, 9 Apr 2014 11:50:43 +0000 (14:50 +0300)
committerGerrit Code Review <gerrit2@nvidia.com>
Fri, 11 Apr 2014 07:14:28 +0000 (00:14 -0700)
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 <amerilainen@nvidia.com>
drivers/gpu/nvgpu/gk20a/ltc_common.c
drivers/gpu/nvgpu/gk20a/ltc_gk20a.c
drivers/gpu/nvgpu/gk20a/mm_gk20a.h

index 8af8c6874296f1c9a59e61e398c0cc6dda4ff865..2d2516d98ce98803368285b7df3c7ac61f9483ea 100644 (file)
@@ -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);
index 74475d7af0115e914862274ed70b9f37449a9342..f5c6d7e764b8e728bb5e000d00e174479d3277ff 100644 (file)
 
 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 */
index cdbab13847e1fd0072c1045df7b76a7dc220abf7..d583849d90a5b899edd64b6acc6ee3505ac83535 100644 (file)
@@ -156,7 +156,7 @@ struct gr_ctx_desc {
 };
 
 struct compbit_store_desc {
-       struct pages **pages;
+       struct page **pages;
        size_t size;
        u64 base_iova;
 };