xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/mali400/mali/linux/mali_osk_bitmap.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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