video: tegra: host: Add sparse texture support
[linux-3.10.git] / drivers / video / tegra / host / gk20a / mm_gk20a.h
index 2a9bdc0..b0fe0bd 100644 (file)
@@ -3,7 +3,7 @@
  *
  * GK20A memory management
  *
- * Copyright (c) 2011-2013, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2011-2014, 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,
@@ -22,6 +22,8 @@
 #define __MM_GK20A_H__
 
 #include <linux/scatterlist.h>
+#include <linux/iommu.h>
+#include <asm/dma-iommu.h>
 #include "../nvhost_allocator.h"
 
 /* This "address bit" in the gmmu ptes (and other gk20a accesses)
  */
 /* Hack, get this from manuals somehow... */
 #define NV_MC_SMMU_VADDR_TRANSLATION_BIT     34
+#define NV_MC_SMMU_VADDR_TRANSLATE(x) (x | \
+                               (1ULL << NV_MC_SMMU_VADDR_TRANSLATION_BIT))
 
+/* For now keep the size relatively small-ish compared to the full
+ * 40b va.  32GB for now. It consists of two 16GB spaces. */
+#define NV_GMMU_VA_RANGE       35ULL
+#define NV_GMMU_VA_IS_UPPER(x) ((x) >= ((u64)0x1 << (NV_GMMU_VA_RANGE-1)))
 
 struct mem_desc {
        struct mem_handle *ref;
@@ -44,7 +52,7 @@ struct mem_desc_sub {
 };
 
 struct gpfifo_desc {
-       struct mem_desc mem;
+       size_t size;
        u32 entry_num;
 
        u32 get;
@@ -52,6 +60,7 @@ struct gpfifo_desc {
 
        bool wrap;
 
+       u64 iova;
        struct gpfifo *cpu_va;
        u64 gpu_va;
 };
@@ -62,26 +71,51 @@ struct mmu_desc {
 };
 
 struct inst_desc {
-       struct mem_desc mem;
+       u64 iova;
+       void *cpuva;
+       phys_addr_t cpu_pa;
+       size_t size;
+};
+
+struct surface_mem_desc {
+       u64 iova;
+       void *cpuva;
+       struct sg_table *sgt;
+       size_t size;
 };
 
 struct userd_desc {
-       struct mem_desc mem;
-       void *cpu_va;
-       u64 cpu_pa;
+       struct sg_table *sgt;
+       u64 iova;
+       void *cpuva;
+       size_t size;
        u64 gpu_va;
 };
 
+struct runlist_mem_desc {
+       u64 iova;
+       void *cpuva;
+       size_t size;
+};
+
 struct patch_desc {
        struct mem_desc mem;
+       void *cpu_va;
        u64 gpu_va;
        u32 data_count;
 };
 
 struct pmu_mem_desc {
-       struct mem_desc mem;
-       phys_addr_t cpu_pa;
+       void *cpuva;
+       u64 iova;
        u64 pmu_va;
+       size_t size;
+};
+
+struct priv_cmd_queue_mem_desc {
+       u64 base_iova;
+       u32 *base_cpuva;
+       size_t size;
 };
 
 struct zcull_ctx_desc {
@@ -131,21 +165,38 @@ struct page_directory_gk20a {
        void *kv;
        /* Either a *page or a *mem_handle */
        void *ref;
-       bool dirty;
        struct sg_table *sgt;
        struct page_table_gk20a *ptes[gmmu_nr_page_sizes];
 };
 
 struct mapped_buffer_node {
+       struct vm_gk20a *vm;
        struct rb_node node;
+       struct list_head unmap_list;
+       struct list_head va_buffers_list;
+       struct vm_reserved_va_node *va_node;
        u64 addr;
        u64 size;
        struct mem_mgr *memmgr;
        struct mem_handle *handle_ref;
        struct sg_table *sgt;
+       struct kref ref;
+       u32 user_mapped;
+       bool own_mem_ref;
        u32 pgsz_idx;
        u32 ctag_offset;
        u32 ctag_lines;
+       u32 flags;
+       bool va_allocated;
+};
+
+struct vm_reserved_va_node {
+       struct list_head reserved_va_list;
+       struct list_head va_buffers_list;
+       u32 pgsz_idx;
+       u64 vaddr_start;
+       u64 size;
+       bool sparse;
 };
 
 struct vm_gk20a {
@@ -155,48 +206,27 @@ struct vm_gk20a {
        u64 va_start;
        u64 va_limit;
 
+       int num_user_mapped_buffers;
+
        bool big_pages;   /* enable large page support */
        bool enable_ctag;
        bool tlb_dirty;
+       bool mapped;
+
+       struct kref ref;
+
+       struct mutex update_gmmu_lock;
 
        struct page_directory_gk20a pdes;
 
        struct nvhost_allocator vma[gmmu_nr_page_sizes];
        struct rb_root mapped_buffers;
 
-       u64 (*alloc_va)(struct vm_gk20a *vm, u64 size,
-                       enum gmmu_pgsz_gk20a gmmu_pgsz_idx);
-
-       void (*free_va)(struct vm_gk20a *vm, u64 offset, u64 size,
-                       enum gmmu_pgsz_gk20a pgsz_idx);
+       struct list_head reserved_va_list;
 
-       u64 (*map)(struct vm_gk20a *vm,
-                  struct mem_mgr *memmgr,
-                  struct mem_handle *r,
-                  u64 offset_align,
-                  u32 flags /*NVHOST_MAP_BUFFER_FLAGS_*/,
-                  u32 kind,
-                  struct sg_table **sgt);
-
-       /* unmap handle from kernel */
-       void (*unmap)(struct vm_gk20a *vm,
-               u64 offset);
-
-       /* unmap handle from user */
-       void (*unmap_user)(struct vm_gk20a *vm,
-               u64 offset,
-               struct mem_mgr **memmgr,
-               struct mem_handle **r);
-
-       /* invalidate tlbs for the vm area */
-       void (*tlb_inval)(struct vm_gk20a *vm);
-
-       /* find buffer corresponding to va */
-       int (*find_buffer)(struct vm_gk20a *vm, u64 gpu_va,
-                       struct mem_mgr **memmgr, struct mem_handle **r,
-                       u64 *offset);
-
-       void (*remove_support)(struct vm_gk20a *vm);
+       dma_addr_t zero_page_iova;
+       void *zero_page_cpuva;
+       struct sg_table *zero_page_sgt;
 };
 
 struct gk20a;
@@ -209,6 +239,7 @@ int gk20a_init_pmu_vm(struct mm_gk20a *mm);
 
 void gk20a_mm_fb_flush(struct gk20a *g);
 void gk20a_mm_l2_flush(struct gk20a *g, bool invalidate);
+void gk20a_mm_l2_invalidate(struct gk20a *g);
 
 struct mm_gk20a {
        struct gk20a *g;
@@ -239,8 +270,15 @@ struct mm_gk20a {
                struct inst_desc inst_block;
        } pmu;
 
+       struct mutex tlb_lock;
+       struct mutex l2_op_lock;
+
        void (*remove_support)(struct mm_gk20a *mm);
        bool sw_ready;
+#ifdef CONFIG_DEBUG_FS
+       u32 ltc_enabled;
+       u32 ltc_enabled_debug;
+#endif
 };
 
 int gk20a_mm_init(struct mm_gk20a *mm);
@@ -287,15 +325,64 @@ void gk20a_mm_dump_vm(struct vm_gk20a *vm,
 
 int gk20a_mm_suspend(struct gk20a *g);
 
-static inline u64 gk20a_mm_iova_addr(struct scatterlist *sgl)
-{
-       u64 result = sg_phys(sgl);
-#ifdef CONFIG_TEGRA_IOMMU_SMMU
-       if (sg_dma_address(sgl))
-               result = sg_dma_address(sgl) |
-                       1ULL << NV_MC_SMMU_VADDR_TRANSLATION_BIT;
-#endif
-       return result;
-}
+phys_addr_t gk20a_get_phys_from_iova(struct device *d,
+                               u64 dma_addr);
+
+int gk20a_get_sgtable(struct device *d, struct sg_table **sgt,
+                       void *cpuva, u64 iova,
+                       size_t size);
+
+void gk20a_free_sgtable(struct sg_table **sgt);
+
+u64 gk20a_mm_iova_addr(struct scatterlist *sgl);
+
+void gk20a_mm_ltc_isr(struct gk20a *g);
+
+bool gk20a_mm_mmu_debug_mode_enabled(struct gk20a *g);
+
+u64 gk20a_gmmu_map(struct vm_gk20a *vm,
+               struct sg_table **sgt,
+               u64 size,
+               u32 flags,
+               int rw_flag);
+
+void gk20a_gmmu_unmap(struct vm_gk20a *vm,
+               u64 vaddr,
+               u64 size,
+               int rw_flag);
+
+u64 gk20a_vm_map(struct vm_gk20a *vm,
+                struct mem_mgr *memmgr,
+                struct mem_handle *r,
+                u64 offset_align,
+                u32 flags /*NVHOST_MAP_BUFFER_FLAGS_*/,
+                u32 kind,
+                struct sg_table **sgt,
+                bool user_mapped,
+                int rw_flag);
+
+/* unmap handle from kernel */
+void gk20a_vm_unmap(struct vm_gk20a *vm, u64 offset);
+
+/* get reference to all currently mapped buffers */
+int gk20a_vm_get_buffers(struct vm_gk20a *vm,
+                        struct mapped_buffer_node ***mapped_buffers,
+                        int *num_buffers);
+
+/* put references on the given buffers */
+void gk20a_vm_put_buffers(struct vm_gk20a *vm,
+                         struct mapped_buffer_node **mapped_buffers,
+                         int num_buffers);
+
+/* invalidate tlbs for the vm area */
+void gk20a_mm_tlb_invalidate(struct vm_gk20a *vm);
+
+/* find buffer corresponding to va */
+int gk20a_vm_find_buffer(struct vm_gk20a *vm, u64 gpu_va,
+                        struct mem_mgr **memmgr, struct mem_handle **r,
+                        u64 *offset);
+
+void gk20a_vm_get(struct vm_gk20a *vm);
+void gk20a_vm_put(struct vm_gk20a *vm);
 
 #endif /*_MM_GK20A_H_ */