gpu: nvgpu: Protect sync by an own lock
[linux-3.10.git] / drivers / gpu / nvgpu / gk20a / channel_gk20a.h
index bb9f314..6021c43 100644 (file)
@@ -1,9 +1,7 @@
 /*
- * drivers/video/tegra/host/gk20a/channel_gk20a.h
- *
  * 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,
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#ifndef __CHANNEL_GK20A_H__
-#define __CHANNEL_GK20A_H__
+#ifndef CHANNEL_GK20A_H
+#define CHANNEL_GK20A_H
 
 #include <linux/log2.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
 #include <linux/mutex.h>
-#include <linux/nvhost_ioctl.h>
 #include <linux/poll.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <uapi/linux/nvgpu.h>
 
 struct gk20a;
 struct gr_gk20a;
@@ -37,6 +36,7 @@ struct gk20a_fence;
 
 #include "mm_gk20a.h"
 #include "gr_gk20a.h"
+#include "fence_gk20a.h"
 
 struct gpfifo {
        u32 entry0;
@@ -60,7 +60,6 @@ struct fence {
 /* contexts associated with a channel */
 struct channel_ctx_gk20a {
        struct gr_ctx_desc      *gr_ctx;
-       struct pm_ctx_desc      pm_ctx;
        struct patch_desc       patch_ctx;
        struct zcull_ctx_desc   zcull_ctx;
        u64     global_ctx_buffer_va[NR_GLOBAL_CTX_BUF_VA];
@@ -73,6 +72,8 @@ struct channel_gk20a_job {
        int num_mapped_buffers;
        struct gk20a_fence *pre_fence;
        struct gk20a_fence *post_fence;
+       struct priv_cmd_entry *wait_cmd;
+       struct priv_cmd_entry *incr_cmd;
        struct list_head list;
 };
 
@@ -82,15 +83,30 @@ struct channel_gk20a_poll_events {
        int num_pending_events;
 };
 
+struct channel_gk20a_clean_up {
+       struct mutex lock;
+       bool scheduled;
+       struct delayed_work wq;
+};
+
 /* this is the priv element of struct nvhost_channel */
 struct channel_gk20a {
-       struct gk20a *g;
-       bool in_use;
+       struct gk20a *g; /* set only when channel is active */
+
+       struct list_head free_chs;
+
+       spinlock_t ref_obtain_lock;
+       bool referenceable;
+       atomic_t ref_count;
+       wait_queue_head_t ref_count_dec_wq;
+
        int hw_chid;
        bool bound;
        bool first_init;
        bool vpr;
+       bool cde;
        pid_t pid;
+       struct mutex ioctl_lock;
 
        int tsgid;
        struct list_head ch_entry; /* channel's entry in TSG */
@@ -105,7 +121,7 @@ struct channel_gk20a {
 
        struct channel_ctx_gk20a ch_ctx;
 
-       struct inst_desc inst_block;
+       struct mem_desc inst_block;
        struct mem_desc_sub ramfc;
 
        void *userd_cpu_va;
@@ -124,6 +140,8 @@ struct channel_gk20a {
        u32 timeout_accumulated_ms;
        u32 timeout_gpfifo_get;
 
+       struct channel_gk20a_clean_up clean_up;
+
        bool cmds_pending;
        struct {
                /* These fences should be accessed with submit_lock held. */
@@ -139,6 +157,9 @@ struct channel_gk20a {
        struct dma_buf *cyclestate_buffer_handler;
        struct mutex cyclestate_buffer_mutex;
        } cyclestate;
+
+       struct mutex cs_client_mutex;
+       struct gk20a_cs_snapshot_client *cs_client;
 #endif
        struct mutex dbg_s_lock;
        struct list_head dbg_s_list;
@@ -148,9 +169,10 @@ struct channel_gk20a {
        bool timeout_debug_dump;
 
        struct dma_buf *error_notifier_ref;
-       struct nvhost_notification *error_notifier;
+       struct nvgpu_notification *error_notifier;
        void *error_notifier_va;
 
+       struct mutex sync_lock;
        struct gk20a_channel_sync *sync;
 
 #ifdef CONFIG_TEGRA_GR_VIRTUALIZATION
@@ -159,6 +181,13 @@ struct channel_gk20a {
 
        /* event support */
        struct channel_gk20a_poll_events poll_events;
+
+       /* signal channel owner via a callback, if set, in gk20a_channel_update
+        * via schedule_work */
+       void (*update_fn)(struct channel_gk20a *, void *);
+       void *update_fn_data;
+       spinlock_t update_fn_lock; /* make access to the two above atomic */
+       struct work_struct update_fn_work;
 };
 
 static inline bool gk20a_channel_as_bound(struct channel_gk20a *ch)
@@ -167,13 +196,14 @@ static inline bool gk20a_channel_as_bound(struct channel_gk20a *ch)
 }
 int channel_gk20a_commit_va(struct channel_gk20a *c);
 int gk20a_init_channel_support(struct gk20a *, u32 chid);
-void gk20a_free_channel(struct channel_gk20a *ch, bool finish);
+
+/* must be inside gk20a_busy()..gk20a_idle() */
+void gk20a_channel_close(struct channel_gk20a *ch);
+
 bool gk20a_channel_update_and_check_timeout(struct channel_gk20a *ch,
                                            u32 timeout_delta_ms);
-void gk20a_disable_channel(struct channel_gk20a *ch,
-                          bool wait_for_finish,
-                          unsigned long finish_timeout);
-void gk20a_channel_abort(struct channel_gk20a *ch);
+void gk20a_disable_channel(struct channel_gk20a *ch);
+void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt);
 int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout);
 void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error);
 void gk20a_channel_semaphore_wakeup(struct gk20a *g);
@@ -185,6 +215,8 @@ int gk20a_channel_resume(struct gk20a *g);
 
 /* Channel file operations */
 int gk20a_channel_open(struct inode *inode, struct file *filp);
+int gk20a_channel_open_ioctl(struct gk20a *g,
+               struct nvgpu_channel_open_args *args);
 long gk20a_channel_ioctl(struct file *filp,
                         unsigned int cmd,
                         unsigned long arg);
@@ -196,25 +228,39 @@ void gk20a_channel_event(struct channel_gk20a *ch);
 
 void gk20a_init_channel(struct gpu_ops *gops);
 
+/* returns ch if reference was obtained */
+struct channel_gk20a *__must_check _gk20a_channel_get(struct channel_gk20a *ch,
+                                                     const char *caller);
+#define gk20a_channel_get(ch) _gk20a_channel_get(ch, __func__)
+
+
+void _gk20a_channel_put(struct channel_gk20a *ch, const char *caller);
+#define gk20a_channel_put(ch) _gk20a_channel_put(ch, __func__)
+
 int gk20a_wait_channel_idle(struct channel_gk20a *ch);
 struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g);
+struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g,
+               void (*update_fn)(struct channel_gk20a *, void *),
+               void *update_fn_data);
 void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a);
 
 int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
-                               struct nvhost_gpfifo *gpfifo,
+                               struct nvgpu_gpfifo *gpfifo,
+                               struct nvgpu_submit_gpfifo_args *args,
                                u32 num_entries,
                                u32 flags,
-                               struct nvhost_fence *fence,
-                               struct gk20a_fence **fence_out);
+                               struct nvgpu_fence *fence,
+                               struct gk20a_fence **fence_out,
+                               bool force_need_sync_fence);
 
 int gk20a_alloc_channel_gpfifo(struct channel_gk20a *c,
-                              struct nvhost_alloc_gpfifo_args *args);
+                              struct nvgpu_alloc_gpfifo_args *args);
 
 void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a);
 void channel_gk20a_disable(struct channel_gk20a *ch);
 int channel_gk20a_alloc_inst(struct gk20a *g, struct channel_gk20a *ch);
 void channel_gk20a_free_inst(struct gk20a *g, struct channel_gk20a *ch);
 int channel_gk20a_setup_ramfc(struct channel_gk20a *c,
-                       u64 gpfifo_base, u32 gpfifo_entries);
-
-#endif /*__CHANNEL_GK20A_H__*/
+                       u64 gpfifo_base, u32 gpfifo_entries, u32 flags);
+void channel_gk20a_enable(struct channel_gk20a *ch);
+#endif /* CHANNEL_GK20A_H */