gk20a: Moved bind fecs to init_gr_support
Mahantesh Kumbar [Tue, 14 Oct 2014 12:14:34 +0000 (17:14 +0530)]
-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
Bug 1570774

Change-Id: I01d6d7f61f5e3c0e788d9d77fcabe5a91fe86c84
Reviewed-on: http://git-master/r/559733
Signed-off-by: Naveen Kumar S <nkumars@nvidia.com>
(cherry picked from commit 1e63d8ae4056dbde82e1788decf7552f0b0af640)
Reviewed-on: http://git-master/r/666712
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Matthew Pedro <mapedro@nvidia.com>

drivers/gpu/nvgpu/gk20a/gr_gk20a.c
drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
drivers/gpu/nvgpu/gk20a/pmu_gk20a.h

index d6a8462..37b4786 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GK20A Graphics
  *
- * Copyright (c) 2011-2014, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2011-2015, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -54,6 +54,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 */
@@ -4538,6 +4539,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;
@@ -4563,6 +4649,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);
index 0e5d80a..f3d6e00 100644 (file)
@@ -1801,7 +1801,7 @@ static void pmu_setup_hw(struct work_struct *work)
                break;
        case PMU_STATE_ELPG_BOOTED:
                gk20a_dbg_pmu("elpg booted");
-               gk20a_init_pmu_bind_fecs(g);
+               gk20a_init_pmu_load_fecs(g);
                break;
        case PMU_STATE_LOADING_PG_BUF:
                gk20a_dbg_pmu("loaded pg buf");
@@ -1820,96 +1820,14 @@ static void pmu_setup_hw(struct work_struct *work)
        }
 }
 
-int gk20a_init_pmu_bind_fecs(struct gk20a *g)
+int gk20a_init_pmu_load_fecs(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);
        struct pmu_cmd cmd;
        u32 desc;
-       int err;
-       u32 size;
-       struct sg_table *sgt_pg_buf;
-       dma_addr_t iova;
-
+       int err = 0;
        gk20a_dbg_fn("");
 
-       size = 0;
-       err = gr_gk20a_fecs_get_reglist_img_size(g, &size);
-       if (err && (pmu->pmu_state == PMU_STATE_ELPG_BOOTED)) {
-               gk20a_err(dev_from_gk20a(g),
-                       "fail to query fecs pg buffer size");
-               return err;
-       }
-
-       if (err) {
-               gk20a_err(dev_from_gk20a(g),
-                       "fail to query fecs pg buffer size invalid boot state");
-               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 && (pmu->pmu_state == PMU_STATE_ELPG_BOOTED)) {
-               gk20a_err(dev_from_gk20a(g),
-                       "fail to bind pmu inst to gr");
-               return err;
-       }
-
-       if (err) {
-               gk20a_err(dev_from_gk20a(g),
-                       "fail to bind pmu inst to gr invalid boot state");
-               return err;
-       }
-
-       err = gr_gk20a_fecs_set_reglist_virtual_addr(g, pmu->pg_buf.pmu_va);
-       if (err && (pmu->pmu_state == PMU_STATE_ELPG_BOOTED)) {
-               gk20a_err(dev_from_gk20a(g),
-                       "fail to set pg buffer pmu va");
-               return err;
-       }
-
-       if (err) {
-               gk20a_err(dev_from_gk20a(g),
-                       "fail to set pg buffer pmu va invalid boot state");
-               return err;
-       }
-
        memset(&cmd, 0, sizeof(struct pmu_cmd));
        cmd.hdr.unit_id = PMU_UNIT_PG;
        cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_eng_buf_load);
@@ -1927,15 +1845,6 @@ int gk20a_init_pmu_bind_fecs(struct gk20a *g)
                        pmu_handle_pg_buf_config_msg, pmu, &desc, ~0);
        pmu->pmu_state = PMU_STATE_LOADING_PG_BUF;
        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;
 }
 
 static void pmu_setup_hw_load_zbc(struct gk20a *g)
index 153baf3..15fb82a 100644 (file)
@@ -1065,7 +1065,7 @@ struct pmu_gk20a {
 };
 
 int gk20a_init_pmu_support(struct gk20a *g);
-int gk20a_init_pmu_bind_fecs(struct gk20a *g);
+int gk20a_init_pmu_load_fecs(struct gk20a *g);
 
 void gk20a_pmu_isr(struct gk20a *g);