video: tegra: host: Add sparse texture support
[linux-3.10.git] / drivers / video / tegra / host / gk20a / mm_gk20a.h
index f2b3677..b0fe0bd 100644 (file)
@@ -3,7 +3,7 @@
  *
  * GK20A memory management
  *
- * Copyright (c) 2011, 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,
 #ifndef __MM_GK20A_H__
 #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)
+ * signals the address as presented should be translated by the SMMU.
+ * Without this bit present gk20a accesses are *not* translated.
+ */
+/* 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;
        struct sg_table *sgt;
@@ -35,7 +52,7 @@ struct mem_desc_sub {
 };
 
 struct gpfifo_desc {
-       struct mem_desc mem;
+       size_t size;
        u32 entry_num;
 
        u32 get;
@@ -43,6 +60,7 @@ struct gpfifo_desc {
 
        bool wrap;
 
+       u64 iova;
        struct gpfifo *cpu_va;
        u64 gpu_va;
 };
@@ -53,27 +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;
-       phys_addr_t 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 {
@@ -97,7 +139,7 @@ struct gr_ctx_desc {
 
 struct compbit_store_desc {
        struct mem_desc mem;
-       phys_addr_t base_pa;
+       u64 base_pa;
        u32 alignment;
 };
 
@@ -108,32 +150,53 @@ struct page_table_gk20a {
        /* track mapping cnt on this page table */
        u32 ref_cnt;
        struct sg_table *sgt;
-       /* 4k or 128k */
-       u32 page_size_idx;
 };
 
+enum gmmu_pgsz_gk20a {
+       gmmu_page_size_small = 0,
+       gmmu_page_size_big   = 1,
+       gmmu_nr_page_sizes   = 2
+};
+
+
 struct page_directory_gk20a {
        /* backing for */
        u32 num_pdes;
        void *kv;
-       phys_addr_t phys;
        /* Either a *page or a *mem_handle */
        void *ref;
-       bool dirty;
        struct sg_table *sgt;
-       struct page_table_gk20a *ptes;
+       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;
-       u32 page_size;
+       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 {
@@ -143,47 +206,40 @@ struct vm_gk20a {
        u64 va_start;
        u64 va_limit;
 
-       struct page_directory_gk20a pdes;
+       int num_user_mapped_buffers;
 
-       struct nvhost_allocator vma; /* page interval allocator */
-       struct rb_root mapped_buffers;
+       bool big_pages;   /* enable large page support */
+       bool enable_ctag;
+       bool tlb_dirty;
+       bool mapped;
 
-       u64 (*alloc_va)(struct vm_gk20a *vm,
-                       u64 size,
-                       u32 page_size);
+       struct kref ref;
 
-       void (*free_va)(struct vm_gk20a *vm, u64 offset, u64 size, u32 page_size);
+       struct mutex update_gmmu_lock;
 
-       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 page_directory_gk20a pdes;
 
-       /* unmap handle from kernel */
-       void (*unmap)(struct vm_gk20a *vm,
-               u64 offset);
+       struct nvhost_allocator vma[gmmu_nr_page_sizes];
+       struct rb_root mapped_buffers;
 
-       /* unmap handle from user */
-       void (*unmap_user)(struct vm_gk20a *vm,
-               u64 offset,
-               struct mem_mgr **memmgr,
-               struct mem_handle **r);
+       struct list_head reserved_va_list;
 
-       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;
 struct channel_gk20a;
 
-int gk20a_init_mm_support(struct gk20a *g, bool reinit);
+int gk20a_init_mm_support(struct gk20a *g);
+int gk20a_init_mm_setup_sw(struct gk20a *g);
 int gk20a_init_bar1_vm(struct mm_gk20a *mm);
 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_tlb_invalidate(struct gk20a *g, struct vm_gk20a *vm);
+void gk20a_mm_l2_invalidate(struct gk20a *g);
 
 struct mm_gk20a {
        struct gk20a *g;
@@ -195,7 +251,7 @@ struct mm_gk20a {
        struct {
                u32 order;
                u32 num_ptes;
-       } page_table_sizing[2];
+       } page_table_sizing[gmmu_nr_page_sizes];
 
 
        struct {
@@ -213,7 +269,18 @@ struct mm_gk20a {
                struct vm_gk20a vm;
                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);
 
 #define gk20a_from_mm(mm) ((mm)->g)
@@ -256,4 +323,66 @@ static inline int max_vaddr_bits_gk20a(void)
 void gk20a_mm_dump_vm(struct vm_gk20a *vm,
                u64 va_begin, u64 va_end, char *label);
 
+int gk20a_mm_suspend(struct gk20a *g);
+
+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_ */