gpu: nvgpu: Disable channel when updating SMPC WAR
Sandarbh Jain [Thu, 11 Jun 2015 19:15:02 +0000 (00:15 +0530)]
When updating SMPC WAR for channel, it needs to be kicked out. This
ensures that the updated information is re-read from context header.

Bug 1579548

Change-Id: Ieadc6b65b057d7f48dc16fbc786c881ab7e5fcd5
Signed-off-by: Sandarbh Jain <sanjain@nvidia.com>
Reviewed-on: http://git-master/r/756639
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>

drivers/gpu/nvgpu/gk20a/channel_gk20a.c
drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
drivers/gpu/nvgpu/gk20a/gk20a.h
drivers/gpu/nvgpu/gk20a/gr_gk20a.c

index 07137c2..755fcdd 100644 (file)
@@ -3,7 +3,7 @@
  *
  * GK20A Graphics channel
  *
- * 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,
@@ -418,6 +418,23 @@ void gk20a_disable_channel_no_update(struct channel_gk20a *ch)
                     ccsr_channel_enable_clr_true_f());
 }
 
+static void channel_gk20a_enable(struct channel_gk20a *ch)
+{
+       /* enable channel */
+       gk20a_writel(ch->g, ccsr_channel_r(ch->hw_chid),
+               gk20a_readl(ch->g, ccsr_channel_r(ch->hw_chid)) |
+               ccsr_channel_enable_set_true_f());
+}
+
+static void channel_gk20a_disable(struct channel_gk20a *ch)
+{
+       /* disable channel */
+       gk20a_writel(ch->g, ccsr_channel_r(ch->hw_chid),
+               gk20a_readl(ch->g,
+                       ccsr_channel_r(ch->hw_chid)) |
+                       ccsr_channel_enable_clr_true_f());
+}
+
 int gk20a_wait_channel_idle(struct channel_gk20a *ch)
 {
        bool channel_idle = false;
@@ -1939,6 +1956,8 @@ clean_up:
 void gk20a_init_channel(struct gpu_ops *gops)
 {
        gops->fifo.bind_channel = channel_gk20a_bind;
+       gops->fifo.disable_channel = channel_gk20a_disable;
+       gops->fifo.enable_channel = channel_gk20a_enable;
 }
 
 long gk20a_channel_ioctl(struct file *filp,
index f4d9a2d..fe29beb 100644 (file)
@@ -3,7 +3,7 @@
  *
  * GK20A Graphics FIFO (gr host)
  *
- * 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,
@@ -1898,4 +1898,5 @@ void gk20a_init_fifo(struct gpu_ops *gops)
 {
        gk20a_init_channel(gops);
        gops->fifo.trigger_mmu_fault = gk20a_fifo_trigger_mmu_fault;
+       gops->fifo.preempt_channel = gk20a_fifo_preempt_channel;
 }
index d8f902b..afab9fd 100644 (file)
@@ -3,7 +3,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,
@@ -136,6 +136,9 @@ struct gpu_ops {
                void (*bind_channel)(struct channel_gk20a *ch_gk20a);
                void (*trigger_mmu_fault)(struct gk20a *g,
                                unsigned long engine_ids);
+               void (*disable_channel)(struct channel_gk20a *ch);
+               void (*enable_channel)(struct channel_gk20a *ch);
+               int (*preempt_channel)(struct gk20a *g, u32 hw_chid);
        } fifo;
        struct pmu_v {
                /*used for change of enum zbc update cmd id from ver 0 to ver1*/
index 66ebfb9..9e032e0 100644 (file)
@@ -1629,6 +1629,15 @@ int gr_gk20a_update_smpc_ctxsw_mode(struct gk20a *g,
        struct channel_ctx_gk20a *ch_ctx = &c->ch_ctx;
        void *ctx_ptr = NULL;
        u32 data;
+       int ret;
+
+       c->g->ops.fifo.disable_channel(c);
+       ret = c->g->ops.fifo.preempt_channel(c->g, c->hw_chid);
+       if (ret) {
+               gk20a_err(dev_from_gk20a(g),
+                       "failed to preempt channel\n");
+               return ret;
+       }
 
        /* Channel gr_ctx buffer is gpu cacheable.
           Flush and invalidate before cpu update. */
@@ -1650,6 +1659,9 @@ int gr_gk20a_update_smpc_ctxsw_mode(struct gk20a *g,
 
        vunmap(ctx_ptr);
 
+       /* enable channel */
+       c->g->ops.fifo.enable_channel(c);
+
        return 0;
 }