MALI: utgard: upgrade DDK to r6p1-01rel0
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / linux / mali_memory_virtual.c
1 /*\r
2  * Copyright (C) 2013-2016 ARM Limited. All rights reserved.
3  * 
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  * 
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */\r
10 \r
11 #include <linux/list.h>\r
12 #include <linux/mm.h>\r
13 #include <linux/mm_types.h>\r
14 #include <linux/fs.h>\r
15 #include <linux/dma-mapping.h>\r
16 #include <linux/slab.h>\r
17 #include <linux/platform_device.h>\r
18 \r
19 #include "mali_osk.h"\r
20 #include "mali_osk_mali.h"\r
21 #include "mali_kernel_linux.h"\r
22 #include "mali_scheduler.h"\r
23 #include "mali_memory_os_alloc.h"\r
24 #include "mali_memory_manager.h"\r
25 #include "mali_memory_virtual.h"\r
26 \r
27 \r
28 /**\r
29 *internal helper to link node into the rb-tree\r
30 */\r
31 static inline void _mali_vma_offset_add_rb(struct mali_allocation_manager *mgr,\r
32                 struct mali_vma_node *node)\r
33 {\r
34         struct rb_node **iter = &mgr->allocation_mgr_rb.rb_node;\r
35         struct rb_node *parent = NULL;\r
36         struct mali_vma_node *iter_node;\r
37 \r
38         while (likely(*iter)) {\r
39                 parent = *iter;\r
40                 iter_node = rb_entry(*iter, struct mali_vma_node, vm_rb);\r
41 \r
42                 if (node->vm_node.start < iter_node->vm_node.start)\r
43                         iter = &(*iter)->rb_left;\r
44                 else if (node->vm_node.start > iter_node->vm_node.start)\r
45                         iter = &(*iter)->rb_right;\r
46                 else\r
47                         MALI_DEBUG_ASSERT(0);\r
48         }\r
49 \r
50         rb_link_node(&node->vm_rb, parent, iter);\r
51         rb_insert_color(&node->vm_rb, &mgr->allocation_mgr_rb);\r
52 }\r
53 \r
54 /**\r
55  * mali_vma_offset_add() - Add offset node to RB Tree\r
56  */\r
57 int mali_vma_offset_add(struct mali_allocation_manager *mgr,\r
58                         struct mali_vma_node *node)\r
59 {\r
60         int ret = 0;\r
61         write_lock(&mgr->vm_lock);\r
62 \r
63         if (node->vm_node.allocated) {\r
64                 goto out;\r
65         }\r
66 \r
67         _mali_vma_offset_add_rb(mgr, node);\r
68         /* set to allocated */\r
69         node->vm_node.allocated = 1;\r
70 \r
71 out:\r
72         write_unlock(&mgr->vm_lock);\r
73         return ret;\r
74 }\r
75 \r
76 /**\r
77  * mali_vma_offset_remove() - Remove offset node from RB tree\r
78  */\r
79 void mali_vma_offset_remove(struct mali_allocation_manager *mgr,\r
80                             struct mali_vma_node *node)\r
81 {\r
82         write_lock(&mgr->vm_lock);\r
83 \r
84         if (node->vm_node.allocated) {\r
85                 rb_erase(&node->vm_rb, &mgr->allocation_mgr_rb);\r
86                 memset(&node->vm_node, 0, sizeof(node->vm_node));\r
87         }\r
88         write_unlock(&mgr->vm_lock);\r
89 }\r
90 \r
91 /**\r
92 * mali_vma_offset_search - Search the node in RB tree\r
93 */\r
94 struct mali_vma_node *mali_vma_offset_search(struct mali_allocation_manager *mgr,\r
95                 unsigned long start, unsigned long pages)\r
96 {\r
97         struct mali_vma_node *node, *best;\r
98         struct rb_node *iter;\r
99         unsigned long offset;\r
100         read_lock(&mgr->vm_lock);\r
101 \r
102         iter = mgr->allocation_mgr_rb.rb_node;\r
103         best = NULL;\r
104 \r
105         while (likely(iter)) {\r
106                 node = rb_entry(iter, struct mali_vma_node, vm_rb);\r
107                 offset = node->vm_node.start;\r
108                 if (start >= offset) {\r
109                         iter = iter->rb_right;\r
110                         best = node;\r
111                         if (start == offset)\r
112                                 break;\r
113                 } else {\r
114                         iter = iter->rb_left;\r
115                 }\r
116         }\r
117 \r
118         if (best) {\r
119                 offset = best->vm_node.start + best->vm_node.size;\r
120                 if (offset <= start + pages)\r
121                         best = NULL;\r
122         }\r
123         read_unlock(&mgr->vm_lock);\r
124 \r
125         return best;\r
126 }\r
127 \r