gpu: nvgpu: Protect sync by an own lock
[linux-3.10.git] / drivers / gpu / nvgpu / gk20a / channel_gk20a.h
index 8f7d2fa..6021c43 100644 (file)
 #define CHANNEL_GK20A_H
 
 #include <linux/log2.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
 #include <linux/mutex.h>
-#include <uapi/linux/nvgpu.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;
@@ -71,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;
 };
 
@@ -80,14 +83,28 @@ 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;
 
@@ -123,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. */
@@ -153,6 +172,7 @@ struct channel_gk20a {
        struct nvgpu_notification *error_notifier;
        void *error_notifier_va;
 
+       struct mutex sync_lock;
        struct gk20a_channel_sync *sync;
 
 #ifdef CONFIG_TEGRA_GR_VIRTUALIZATION
@@ -176,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);
@@ -207,6 +228,15 @@ 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,
@@ -216,10 +246,12 @@ void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a);
 
 int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
                                struct nvgpu_gpfifo *gpfifo,
+                               struct nvgpu_submit_gpfifo_args *args,
                                u32 num_entries,
                                u32 flags,
                                struct nvgpu_fence *fence,
-                               struct gk20a_fence **fence_out);
+                               struct gk20a_fence **fence_out,
+                               bool force_need_sync_fence);
 
 int gk20a_alloc_channel_gpfifo(struct channel_gk20a *c,
                               struct nvgpu_alloc_gpfifo_args *args);