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