gpu: nvgpu: create sync_fence only if needed
[linux-3.10.git] / drivers / gpu / nvgpu / gk20a / channel_sync_gk20a.c
index b0430bd..6c82653 100644 (file)
@@ -153,15 +153,20 @@ static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd,
 
 static void gk20a_channel_syncpt_update(void *priv, int nr_completed)
 {
-       struct channel_gk20a *ch20a = priv;
-       gk20a_channel_update(ch20a, nr_completed);
+       struct channel_gk20a *ch = priv;
+
+       gk20a_channel_update(ch, nr_completed);
+
+       /* note: channel_get() is in __gk20a_channel_syncpt_incr() */
+       gk20a_channel_put(ch);
 }
 
 static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s,
                                       bool wfi_cmd,
                                       bool register_irq,
                                       struct priv_cmd_entry **entry,
-                                      struct gk20a_fence **fence)
+                                      struct gk20a_fence **fence,
+                                      bool need_sync_fence)
 {
        u32 thresh;
        int incr_cmd_size;
@@ -208,18 +213,33 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s,
        thresh = nvhost_syncpt_incr_max_ext(sp->host1x_pdev, sp->id, 2);
 
        if (register_irq) {
-               err = nvhost_intr_register_notifier(sp->host1x_pdev,
+               struct channel_gk20a *referenced = gk20a_channel_get(c);
+
+               WARN_ON(!referenced);
+
+               if (referenced) {
+                       /* note: channel_put() is in
+                        * gk20a_channel_syncpt_update() */
+
+                       err = nvhost_intr_register_notifier(
+                               sp->host1x_pdev,
                                sp->id, thresh,
                                gk20a_channel_syncpt_update, c);
-
-               /* Adding interrupt action should never fail. A proper error
-                * handling here would require us to decrement the syncpt max
-                * back to its original value. */
-               WARN(err, "failed to set submit complete interrupt");
+                       if (err)
+                               gk20a_channel_put(referenced);
+
+                       /* Adding interrupt action should
+                        * never fail. A proper error handling
+                        * here would require us to decrement
+                        * the syncpt max back to its original
+                        * value. */
+                       WARN(err,
+                            "failed to set submit complete interrupt");
+               }
        }
 
        *fence = gk20a_fence_from_syncpt(sp->host1x_pdev, sp->id, thresh,
-                                        wfi_cmd);
+                                        wfi_cmd, need_sync_fence);
        *entry = incr_cmd;
        return 0;
 }
@@ -231,33 +251,35 @@ static int gk20a_channel_syncpt_incr_wfi(struct gk20a_channel_sync *s,
        return __gk20a_channel_syncpt_incr(s,
                        true /* wfi */,
                        false /* no irq handler */,
-                       entry, fence);
+                       entry, fence, true);
 }
 
 static int gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s,
                              struct priv_cmd_entry **entry,
-                             struct gk20a_fence **fence)
+                             struct gk20a_fence **fence,
+                             bool need_sync_fence)
 {
        /* Don't put wfi cmd to this one since we're not returning
         * a fence to user space. */
        return __gk20a_channel_syncpt_incr(s,
                        false /* no wfi */,
                        true /* register irq */,
-                       entry, fence);
+                       entry, fence, need_sync_fence);
 }
 
 static int gk20a_channel_syncpt_incr_user(struct gk20a_channel_sync *s,
                                   int wait_fence_fd,
                                   struct priv_cmd_entry **entry,
                                   struct gk20a_fence **fence,
-                                  bool wfi)
+                                  bool wfi,
+                                  bool need_sync_fence)
 {
        /* Need to do 'wfi + host incr' since we return the fence
         * to user space. */
        return __gk20a_channel_syncpt_incr(s,
                        wfi,
                        true /* register irq */,
-                       entry, fence);
+                       entry, fence, need_sync_fence);
 }
 
 static void gk20a_channel_syncpt_set_min_eq_max(struct gk20a_channel_sync *s)
@@ -293,7 +315,7 @@ static struct gk20a_channel_sync *
 gk20a_channel_syncpt_create(struct channel_gk20a *c)
 {
        struct gk20a_channel_syncpt *sp;
-       char syncpt_name[16];
+       char syncpt_name[32];
 
        sp = kzalloc(sizeof(*sp), GFP_KERNEL);
        if (!sp)
@@ -302,7 +324,8 @@ gk20a_channel_syncpt_create(struct channel_gk20a *c)
        sp->c = c;
        sp->host1x_pdev = c->g->host1x_dev;
 
-       sprintf(syncpt_name, "%s_%d", dev_name(&c->g->dev->dev), c->hw_chid);
+       snprintf(syncpt_name, sizeof(syncpt_name),
+               "%s_%d", dev_name(&c->g->dev->dev), c->hw_chid);
 
        sp->id = nvhost_get_syncpt_host_managed(sp->host1x_pdev,
                                                c->hw_chid, syncpt_name);
@@ -324,8 +347,6 @@ gk20a_channel_syncpt_create(struct channel_gk20a *c)
        sp->ops.syncpt_id               = gk20a_channel_syncpt_id;
        sp->ops.destroy                 = gk20a_channel_syncpt_destroy;
 
-       sp->ops.aggressive_destroy      = true;
-
        return &sp->ops;
 }
 #endif /* CONFIG_TEGRA_GK20A */
@@ -494,7 +515,8 @@ static int __gk20a_channel_semaphore_incr(
                struct gk20a_channel_sync *s, bool wfi_cmd,
                struct sync_fence *dependency,
                struct priv_cmd_entry **entry,
-               struct gk20a_fence **fence)
+               struct gk20a_fence **fence,
+               bool need_sync_fence)
 {
        u64 va;
        int incr_cmd_size;
@@ -541,18 +563,19 @@ static int gk20a_channel_semaphore_incr_wfi(
        return __gk20a_channel_semaphore_incr(s,
                        true /* wfi */,
                        NULL,
-                       entry, fence);
+                       entry, fence, true);
 }
 
 static int gk20a_channel_semaphore_incr(
                struct gk20a_channel_sync *s,
                struct priv_cmd_entry **entry,
-               struct gk20a_fence **fence)
+               struct gk20a_fence **fence,
+               bool need_sync_fence)
 {
        /* Don't put wfi cmd to this one since we're not returning
         * a fence to user space. */
        return __gk20a_channel_semaphore_incr(s, false /* no wfi */,
-                                             NULL, entry, fence);
+                                     NULL, entry, fence, need_sync_fence);
 }
 
 static int gk20a_channel_semaphore_incr_user(
@@ -560,7 +583,8 @@ static int gk20a_channel_semaphore_incr_user(
                int wait_fence_fd,
                struct priv_cmd_entry **entry,
                struct gk20a_fence **fence,
-               bool wfi)
+               bool wfi,
+               bool need_sync_fence)
 {
 #ifdef CONFIG_SYNC
        struct sync_fence *dependency = NULL;
@@ -573,7 +597,7 @@ static int gk20a_channel_semaphore_incr_user(
        }
 
        err = __gk20a_channel_semaphore_incr(s, wfi, dependency,
-                                            entry, fence);
+                                            entry, fence, need_sync_fence);
        if (err) {
                if (dependency)
                        sync_fence_put(dependency);
@@ -669,10 +693,6 @@ gk20a_channel_semaphore_create(struct channel_gk20a *c)
        sema->ops.syncpt_id     = gk20a_channel_semaphore_syncpt_id;
        sema->ops.destroy       = gk20a_channel_semaphore_destroy;
 
-       /* Aggressively destroying the semaphore sync would cause overhead
-        * since the pool needs to be mapped to GMMU. */
-       sema->ops.aggressive_destroy = false;
-
        return &sema->ops;
 clean_up:
        gk20a_channel_semaphore_destroy(&sema->ops);