summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
diff options
context:
space:
mode:
authorBharat Nihalani <bnihalani@nvidia.com>2015-05-29 06:56:23 -0400
committerBharat Nihalani <bnihalani@nvidia.com>2015-06-02 23:18:55 -0400
commit1d8fdf56959240622073dd771dd9bfccf31b8f8e (patch)
tree5c670e604825ddc25d6b6b0cce32cb3e7dc6871a /drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
parent38cee4d7effe5a2079a08b3c9a216b3197893959 (diff)
Revert "Revert "Revert "gpu: nvgpu: New allocator for VA space"""
This reverts commit ce1cf06b9a8eb6314ba0ca294e8cb430e1e141c0 since it causes GPU pbdma interrupt to be generated. Bug 200106514 Change-Id: If3ed9a914c4e3e7f3f98c6609c6dbf57e1eb9aad Signed-off-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-on: http://git-master/r/749291
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a_allocator.h')
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_allocator.h213
1 files changed, 49 insertions, 164 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
index e86e053b..69a227bd 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. 2 * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
@@ -17,190 +17,75 @@
17#ifndef GK20A_ALLOCATOR_H 17#ifndef GK20A_ALLOCATOR_H
18#define GK20A_ALLOCATOR_H 18#define GK20A_ALLOCATOR_H
19 19
20#include <linux/list.h>
21#include <linux/rbtree.h> 20#include <linux/rbtree.h>
22#include <linux/debugfs.h> 21#include <linux/rwsem.h>
23#include <linux/platform_device.h> 22#include <linux/slab.h>
24 23
25/* #define ALLOCATOR_DEBUG */ 24/* #define ALLOCATOR_DEBUG */
26 25
27/* 26/* main struct */
28 * Each buddy is an element in a binary tree.
29 */
30struct gk20a_buddy {
31 struct gk20a_buddy *parent; /* Parent node. */
32 struct gk20a_buddy *buddy; /* This node's buddy. */
33 struct gk20a_buddy *left; /* Lower address sub-node. */
34 struct gk20a_buddy *right; /* Higher address sub-node. */
35
36 struct list_head buddy_entry; /* List entry for various lists. */
37 struct rb_node alloced_entry; /* RB tree of allocations. */
38
39 u64 start; /* Start address of this buddy. */
40 u64 end; /* End address of this buddy. */
41 u64 order; /* Buddy order. */
42
43#define BALLOC_BUDDY_ALLOCED 0x1
44#define BALLOC_BUDDY_SPLIT 0x2
45#define BALLOC_BUDDY_IN_LIST 0x4
46 int flags; /* List of associated flags. */
47
48 /*
49 * Size of the PDE this buddy is using. This allows for grouping like
50 * sized allocations into the same PDE.
51 */
52#define BALLOC_PTE_SIZE_ANY 0x0
53#define BALLOC_PTE_SIZE_SMALL 0x1
54#define BALLOC_PTE_SIZE_BIG 0x2
55 int pte_size;
56};
57
58#define __buddy_flag_ops(flag, flag_up) \
59 static inline int buddy_is_ ## flag(struct gk20a_buddy *b) \
60 { \
61 return b->flags & BALLOC_BUDDY_ ## flag_up; \
62 } \
63 static inline void buddy_set_ ## flag(struct gk20a_buddy *b) \
64 { \
65 b->flags |= BALLOC_BUDDY_ ## flag_up; \
66 } \
67 static inline void buddy_clr_ ## flag(struct gk20a_buddy *b) \
68 { \
69 b->flags &= ~BALLOC_BUDDY_ ## flag_up; \
70 }
71
72/*
73 * int buddy_is_alloced(struct gk20a_buddy *b);
74 * void buddy_set_alloced(struct gk20a_buddy *b);
75 * void buddy_clr_alloced(struct gk20a_buddy *b);
76 *
77 * int buddy_is_split(struct gk20a_buddy *b);
78 * void buddy_set_split(struct gk20a_buddy *b);
79 * void buddy_clr_split(struct gk20a_buddy *b);
80 *
81 * int buddy_is_in_list(struct gk20a_buddy *b);
82 * void buddy_set_in_list(struct gk20a_buddy *b);
83 * void buddy_clr_in_list(struct gk20a_buddy *b);
84 */
85__buddy_flag_ops(alloced, ALLOCED);
86__buddy_flag_ops(split, SPLIT);
87__buddy_flag_ops(in_list, IN_LIST);
88
89/*
90 * Keeps info for a fixed allocation.
91 */
92struct gk20a_fixed_alloc {
93 struct list_head buddies; /* List of buddies. */
94 struct rb_node alloced_entry; /* RB tree of fixed allocations. */
95
96 u64 start; /* Start of fixed block. */
97 u64 end; /* End address. */
98};
99
100struct vm_gk20a;
101
102/*
103 * GPU buddy allocator for the various GPU address spaces. Each addressable unit
104 * doesn't have to correspond to a byte. In some cases each unit is a more
105 * complex object such as a comp_tag line or the like.
106 *
107 * The max order is computed based on the size of the minimum order and the size
108 * of the address space.
109 *
110 * order_size is the size of an order 0 buddy.
111 */
112struct gk20a_allocator { 27struct gk20a_allocator {
113 28
114 struct vm_gk20a *vm; /* Parent VM - can be NULL. */ 29 char name[32]; /* name for allocator */
115 30 struct rb_root rb_root; /* rb tree root for blocks */
116 char name[32]; /* Name of allocator. */
117
118 u64 base; /* Base address of the space. */
119 u64 length; /* Length of the space. */
120 u64 blk_size; /* Size of order 0 allocation. */
121 u64 blk_shift; /* Shift to divide by blk_size. */
122
123 int init; /* Non-zero if initialized. */
124 31
125 /* Internal stuff. */ 32 u32 base; /* min value of this linear space */
126 u64 start; /* Real start (aligned to blk_size). */ 33 u32 limit; /* max value = limit - 1 */
127 u64 end; /* Real end, trimmed if needed. */
128 u64 count; /* Count of objects in space. */
129 u64 blks; /* Count of blks in the space. */
130 u64 max_order; /* Specific maximum order. */
131 34
132 struct rb_root alloced_buddies; /* Outstanding allocations. */ 35 unsigned long *bitmap; /* bitmap */
133 struct rb_root fixed_allocs; /* Outstanding fixed allocations. */
134 36
135 struct mutex lock; /* Protects buddy access. */ 37 struct gk20a_alloc_block *block_first; /* first block in list */
38 struct gk20a_alloc_block *block_recent; /* last visited block */
136 39
137#define GPU_BALLOC_GVA_SPACE 0x1 40 u32 first_free_addr; /* first free addr, non-contigous
138 u64 flags; 41 allocation preferred start,
42 in order to pick up small holes */
43 u32 last_free_addr; /* last free addr, contiguous
44 allocation preferred start */
45 u32 cached_hole_size; /* max free hole size up to
46 last_free_addr */
47 u32 block_count; /* number of blocks */
139 48
140 /* 49 struct rw_semaphore rw_sema; /* lock */
141 * Impose an upper bound on the maximum order. 50 struct kmem_cache *block_cache; /* slab cache */
142 */
143#define GPU_BALLOC_MAX_ORDER 31
144#define GPU_BALLOC_ORDER_LIST_LEN (GPU_BALLOC_MAX_ORDER + 1)
145 51
146 struct list_head buddy_list[GPU_BALLOC_ORDER_LIST_LEN]; 52 /* if enabled, constrain to [base, limit) */
147 u64 buddy_list_len[GPU_BALLOC_ORDER_LIST_LEN]; 53 struct {
148 u64 buddy_list_split[GPU_BALLOC_ORDER_LIST_LEN]; 54 bool enable;
149 u64 buddy_list_alloced[GPU_BALLOC_ORDER_LIST_LEN]; 55 u32 base;
56 u32 limit;
57 } constraint;
150 58
151 /* 59 int (*alloc)(struct gk20a_allocator *allocator,
152 * This is for when the allocator is managing a GVA space (the 60 u32 *addr, u32 len, u32 align);
153 * GPU_BALLOC_GVA_SPACE bit is set in @flags). This requires 61 int (*free)(struct gk20a_allocator *allocator,
154 * that we group like sized allocations into PDE blocks. 62 u32 addr, u32 len, u32 align);
155 */
156 u64 pte_blk_order;
157 63
158 struct dentry *debugfs_entry;
159
160 u64 bytes_alloced;
161 u64 bytes_alloced_real;
162 u64 bytes_freed;
163}; 64};
164 65
165#define balloc_lock(a) mutex_lock(&(a)->lock) 66int gk20a_allocator_init(struct gk20a_allocator *allocator,
166#define balloc_unlock(a) mutex_unlock(&(a)->lock) 67 const char *name, u32 base, u32 size);
68void gk20a_allocator_destroy(struct gk20a_allocator *allocator);
167 69
168#define balloc_get_order_list(a, order) (&(a)->buddy_list[(order)]) 70int gk20a_allocator_block_alloc(struct gk20a_allocator *allocator,
169#define balloc_order_to_len(a, order) ((1 << order) * (a)->blk_size) 71 u32 *addr, u32 len, u32 align);
170#define balloc_base_shift(a, base) ((base) - (a)->start)
171#define balloc_base_unshift(a, base) ((base) + (a)->start)
172 72
173int gk20a_allocator_init(struct gk20a_allocator *allocator, 73int gk20a_allocator_block_free(struct gk20a_allocator *allocator,
174 const char *name, u64 base, u64 size, u64 order0); 74 u32 addr, u32 len, u32 align);
175int __gk20a_allocator_init(struct gk20a_allocator *allocator,
176 struct vm_gk20a *vm, const char *name,
177 u64 base, u64 size, u64 order0,
178 u64 max_order, u64 flags);
179void gk20a_allocator_destroy(struct gk20a_allocator *allocator);
180 75
181/* 76#if defined(ALLOCATOR_DEBUG)
182 * Normal alloc/free operations for the buddy allocator.
183 */
184u64 gk20a_balloc(struct gk20a_allocator *allocator, u64 len);
185void gk20a_bfree(struct gk20a_allocator *allocator, u64 addr);
186 77
187/* 78#define allocator_dbg(alloctor, format, arg...) \
188 * Special interface to allocate a memory regions with a specific starting 79do { \
189 * address. Yikes. 80 if (1) \
190 */ 81 pr_debug("gk20a_allocator (%s) %s: " format "\n",\
191u64 gk20a_balloc_fixed(struct gk20a_allocator *allocator, u64 base, u64 len); 82 alloctor->name, __func__, ##arg);\
83} while (0)
192 84
193/* 85#else /* ALLOCATOR_DEBUG */
194 * Debugfs init.
195 */
196void gk20a_alloc_debugfs_init(struct platform_device *pdev);
197 86
198#if defined(ALLOCATOR_DEBUG) 87#define allocator_dbg(format, arg...)
199#define balloc_dbg(alloctor, format, arg...) \ 88
200 pr_info("%-25s %25s() " format, \ 89#endif /* ALLOCATOR_DEBUG */
201 alloctor->name, __func__, ##arg)
202#else
203#define balloc_dbg(allocator, format, arg...)
204#endif
205 90
206#endif /* GK20A_ALLOCATOR_H */ 91#endif /* GK20A_ALLOCATOR_H */