01ca38235b201fc03ef1e452d49f5dbd93ad7b0f
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / linux / mali_osk_bitmap.c
1 /*\r
2  * Copyright (C) 2010, 2013-2015 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 /**\r
12  * @file mali_osk_bitmap.c\r
13  * Implementation of the OS abstraction layer for the kernel device driver\r
14  */\r
15 \r
16 #include <linux/errno.h>\r
17 #include <linux/slab.h>\r
18 #include <linux/mm.h>\r
19 #include <linux/bitmap.h>\r
20 #include <linux/vmalloc.h>\r
21 #include "common/mali_kernel_common.h"\r
22 #include "mali_osk_types.h"\r
23 #include "mali_osk.h"\r
24 \r
25 u32 _mali_osk_bitmap_alloc(struct _mali_osk_bitmap *bitmap)\r
26 {\r
27         u32 obj;\r
28 \r
29         MALI_DEBUG_ASSERT_POINTER(bitmap);\r
30 \r
31         _mali_osk_spinlock_lock(bitmap->lock);\r
32 \r
33         obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->reserve);\r
34 \r
35         if (obj < bitmap->max) {\r
36                 set_bit(obj, bitmap->table);\r
37         } else {\r
38                 obj = -1;\r
39         }\r
40 \r
41         if (obj != -1)\r
42                 --bitmap->avail;\r
43         _mali_osk_spinlock_unlock(bitmap->lock);\r
44 \r
45         return obj;\r
46 }\r
47 \r
48 void _mali_osk_bitmap_free(struct _mali_osk_bitmap *bitmap, u32 obj)\r
49 {\r
50         MALI_DEBUG_ASSERT_POINTER(bitmap);\r
51 \r
52         _mali_osk_bitmap_free_range(bitmap, obj, 1);\r
53 }\r
54 \r
55 u32 _mali_osk_bitmap_alloc_range(struct _mali_osk_bitmap *bitmap, int cnt)\r
56 {\r
57         u32 obj;\r
58 \r
59         MALI_DEBUG_ASSERT_POINTER(bitmap);\r
60 \r
61         if (0 >= cnt) {\r
62                 return -1;\r
63         }\r
64 \r
65         if (1 == cnt) {\r
66                 return _mali_osk_bitmap_alloc(bitmap);\r
67         }\r
68 \r
69         _mali_osk_spinlock_lock(bitmap->lock);\r
70         obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max,\r
71                                          bitmap->last, cnt, 0);\r
72 \r
73         if (obj >= bitmap->max) {\r
74                 obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max,\r
75                                                  bitmap->reserve, cnt, 0);\r
76         }\r
77 \r
78         if (obj < bitmap->max) {\r
79                 bitmap_set(bitmap->table, obj, cnt);\r
80 \r
81                 bitmap->last = (obj + cnt);\r
82                 if (bitmap->last >= bitmap->max) {\r
83                         bitmap->last = bitmap->reserve;\r
84                 }\r
85         } else {\r
86                 obj = -1;\r
87         }\r
88 \r
89         if (obj != -1) {\r
90                 bitmap->avail -= cnt;\r
91         }\r
92 \r
93         _mali_osk_spinlock_unlock(bitmap->lock);\r
94 \r
95         return obj;\r
96 }\r
97 \r
98 u32 _mali_osk_bitmap_avail(struct _mali_osk_bitmap *bitmap)\r
99 {\r
100         MALI_DEBUG_ASSERT_POINTER(bitmap);\r
101 \r
102         return bitmap->avail;\r
103 }\r
104 \r
105 void _mali_osk_bitmap_free_range(struct _mali_osk_bitmap *bitmap, u32 obj, int cnt)\r
106 {\r
107         MALI_DEBUG_ASSERT_POINTER(bitmap);\r
108 \r
109         _mali_osk_spinlock_lock(bitmap->lock);\r
110         bitmap_clear(bitmap->table, obj, cnt);\r
111         bitmap->last = min(bitmap->last, obj);\r
112 \r
113         bitmap->avail += cnt;\r
114         _mali_osk_spinlock_unlock(bitmap->lock);\r
115 }\r
116 \r
117 int _mali_osk_bitmap_init(struct _mali_osk_bitmap *bitmap, u32 num, u32 reserve)\r
118 {\r
119         MALI_DEBUG_ASSERT_POINTER(bitmap);\r
120         MALI_DEBUG_ASSERT(reserve <= num);\r
121 \r
122         bitmap->reserve = reserve;\r
123         bitmap->last = reserve;\r
124         bitmap->max  = num;\r
125         bitmap->avail = num - reserve;\r
126         bitmap->lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_UNORDERED, _MALI_OSK_LOCK_ORDER_FIRST);\r
127         if (!bitmap->lock) {\r
128                 return _MALI_OSK_ERR_NOMEM;\r
129         }\r
130         bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) *\r
131                                 sizeof(long), GFP_KERNEL);\r
132         if (!bitmap->table) {\r
133                 _mali_osk_spinlock_term(bitmap->lock);\r
134                 return _MALI_OSK_ERR_NOMEM;\r
135         }\r
136 \r
137         return _MALI_OSK_ERR_OK;\r
138 }\r
139 \r
140 void _mali_osk_bitmap_term(struct _mali_osk_bitmap *bitmap)\r
141 {\r
142         MALI_DEBUG_ASSERT_POINTER(bitmap);\r
143 \r
144         if (NULL != bitmap->lock) {\r
145                 _mali_osk_spinlock_term(bitmap->lock);\r
146         }\r
147 \r
148         if (NULL != bitmap->table) {\r
149                 kfree(bitmap->table);\r
150         }\r
151 }\r
152 \r