2 * UWB reservation management.
4 * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include <linux/kernel.h>
19 #include <linux/uwb.h>
21 #include "uwb-internal.h"
23 static void uwb_rsv_fill_column_alloc(struct uwb_rsv_alloc_info
*ai
)
25 int col
, mas
, safe_mas
, unsafe_mas
;
26 unsigned char *bm
= ai
->bm
;
27 struct uwb_rsv_col_info
*ci
= ai
->ci
;
30 for (col
= ci
->csi
.start_col
; col
< UWB_NUM_ZONES
; col
+= ci
->csi
.interval
) {
32 safe_mas
= ci
->csi
.safe_mas_per_col
;
33 unsafe_mas
= ci
->csi
.unsafe_mas_per_col
;
35 for (mas
= 0; mas
< UWB_MAS_PER_ZONE
; mas
++ ) {
36 if (bm
[col
* UWB_MAS_PER_ZONE
+ mas
] == 0) {
41 } else if (unsafe_mas
> 0) {
43 c
= UWB_RSV_MAS_UNSAFE
;
47 bm
[col
* UWB_MAS_PER_ZONE
+ mas
] = c
;
53 static void uwb_rsv_fill_row_alloc(struct uwb_rsv_alloc_info
*ai
)
56 unsigned char *bm
= ai
->bm
;
57 struct uwb_rsv_row_info
*ri
= &ai
->ri
;
62 for (mas
= UWB_MAS_PER_ZONE
- 1; mas
>= 0; mas
--) {
63 if (ri
->avail
[mas
] == 1) {
65 if (rows
> ri
->used_rows
) {
67 } else if (rows
> 7) {
68 c
= UWB_RSV_MAS_UNSAFE
;
71 for (col
= 0; col
< UWB_NUM_ZONES
; col
++) {
72 if (bm
[col
* UWB_NUM_ZONES
+ mas
] != UWB_RSV_MAS_NOT_AVAIL
) {
73 bm
[col
* UWB_NUM_ZONES
+ mas
] = c
;
74 if(c
== UWB_RSV_MAS_SAFE
)
75 ai
->safe_allocated_mases
++;
77 ai
->unsafe_allocated_mases
++;
83 ai
->total_allocated_mases
= ai
->safe_allocated_mases
+ ai
->unsafe_allocated_mases
;
87 * Find the best column set for a given availability, interval, num safe mas and
90 * The different sets are tried in order as shown below, depending on the interval.
127 * set 1 -> { 2 6 10 14 }
129 * set 1 -> { 1 5 9 13 }
130 * set 2 -> { 3 7 11 15 }
134 * set 1 -> { 1 3 5 7 9 11 13 15 }
136 static int uwb_rsv_find_best_column_set(struct uwb_rsv_alloc_info
*ai
, int interval
,
137 int num_safe_mas
, int num_unsafe_mas
)
139 struct uwb_rsv_col_info
*ci
= ai
->ci
;
140 struct uwb_rsv_col_set_info
*csi
= &ci
->csi
;
141 struct uwb_rsv_col_set_info tmp_csi
;
142 int deep
, set
, col
, start_col_deep
, col_start_set
;
143 int start_col
, max_mas_in_set
, lowest_max_mas_in_deep
;
145 int found
= UWB_RSV_ALLOC_NOT_FOUND
;
147 tmp_csi
.start_col
= 0;
148 start_col_deep
= interval
;
149 n_mas
= num_unsafe_mas
+ num_safe_mas
;
151 for (deep
= 0; ((interval
>> deep
) & 0x1) == 0; deep
++) {
154 lowest_max_mas_in_deep
= UWB_MAS_PER_ZONE
;
156 for (set
= 1; set
<= (1 << deep
); set
++) {
158 start_col
= start_col_deep
+ col_start_set
;
159 for (col
= start_col
; col
< UWB_NUM_ZONES
; col
+= interval
) {
161 if (ci
[col
].max_avail_safe
>= num_safe_mas
&&
162 ci
[col
].max_avail_unsafe
>= n_mas
) {
163 if (ci
[col
].highest_mas
[n_mas
] > max_mas_in_set
)
164 max_mas_in_set
= ci
[col
].highest_mas
[n_mas
];
170 if ((lowest_max_mas_in_deep
> max_mas_in_set
) && max_mas_in_set
) {
171 lowest_max_mas_in_deep
= max_mas_in_set
;
173 tmp_csi
.start_col
= start_col
;
175 col_start_set
+= (interval
>> deep
);
178 if (lowest_max_mas_in_deep
< 8) {
179 csi
->start_col
= tmp_csi
.start_col
;
180 found
= UWB_RSV_ALLOC_FOUND
;
182 } else if ((lowest_max_mas_in_deep
> 8) &&
183 (lowest_max_mas_in_deep
!= UWB_MAS_PER_ZONE
) &&
184 (found
== UWB_RSV_ALLOC_NOT_FOUND
)) {
185 csi
->start_col
= tmp_csi
.start_col
;
186 found
= UWB_RSV_ALLOC_FOUND
;
190 if (found
== UWB_RSV_ALLOC_FOUND
) {
191 csi
->interval
= interval
;
192 csi
->safe_mas_per_col
= num_safe_mas
;
193 csi
->unsafe_mas_per_col
= num_unsafe_mas
;
195 ai
->safe_allocated_mases
= (UWB_NUM_ZONES
/ interval
) * num_safe_mas
;
196 ai
->unsafe_allocated_mases
= (UWB_NUM_ZONES
/ interval
) * num_unsafe_mas
;
197 ai
->total_allocated_mases
= ai
->safe_allocated_mases
+ ai
->unsafe_allocated_mases
;
198 ai
->interval
= interval
;
203 static void get_row_descriptors(struct uwb_rsv_alloc_info
*ai
)
205 unsigned char *bm
= ai
->bm
;
206 struct uwb_rsv_row_info
*ri
= &ai
->ri
;
210 for (mas
= 0; mas
< UWB_MAS_PER_ZONE
; mas
++) {
212 for (col
= 1; col
< UWB_NUM_ZONES
; col
++) {
213 if (bm
[col
* UWB_NUM_ZONES
+ mas
] == UWB_RSV_MAS_NOT_AVAIL
) {
222 static void uwb_rsv_fill_column_info(unsigned char *bm
, int column
, struct uwb_rsv_col_info
*rci
)
225 int block_count
= 0, start_block
= 0;
226 int previous_avail
= 0;
228 int safe_mas_in_row
[UWB_MAS_PER_ZONE
] = {
229 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1,
232 rci
->max_avail_safe
= 0;
234 for (mas
= 0; mas
< UWB_MAS_PER_ZONE
; mas
++) {
235 if (!bm
[column
* UWB_NUM_ZONES
+ mas
]) {
237 rci
->max_avail_unsafe
= available
;
239 rci
->highest_mas
[available
] = mas
;
241 if (previous_avail
) {
243 if ((block_count
> safe_mas_in_row
[start_block
]) &&
244 (!rci
->max_avail_safe
))
245 rci
->max_avail_safe
= available
- 1;
255 if (!rci
->max_avail_safe
)
256 rci
->max_avail_safe
= rci
->max_avail_unsafe
;
259 static void get_column_descriptors(struct uwb_rsv_alloc_info
*ai
)
261 unsigned char *bm
= ai
->bm
;
262 struct uwb_rsv_col_info
*ci
= ai
->ci
;
265 for (col
= 1; col
< UWB_NUM_ZONES
; col
++) {
266 uwb_rsv_fill_column_info(bm
, col
, &ci
[col
]);
270 static int uwb_rsv_find_best_row_alloc(struct uwb_rsv_alloc_info
*ai
)
273 int max_rows
= ai
->max_mas
/ UWB_USABLE_MAS_PER_ROW
;
274 int min_rows
= ai
->min_mas
/ UWB_USABLE_MAS_PER_ROW
;
275 if (ai
->min_mas
% UWB_USABLE_MAS_PER_ROW
)
277 for (n_rows
= max_rows
; n_rows
>= min_rows
; n_rows
--) {
278 if (n_rows
<= ai
->ri
.free_rows
) {
279 ai
->ri
.used_rows
= n_rows
;
280 ai
->interval
= 1; /* row reservation */
281 uwb_rsv_fill_row_alloc(ai
);
282 return UWB_RSV_ALLOC_FOUND
;
285 return UWB_RSV_ALLOC_NOT_FOUND
;
288 static int uwb_rsv_find_best_col_alloc(struct uwb_rsv_alloc_info
*ai
, int interval
)
290 int n_safe
, n_unsafe
, n_mas
;
291 int n_column
= UWB_NUM_ZONES
/ interval
;
292 int max_per_zone
= ai
->max_mas
/ n_column
;
293 int min_per_zone
= ai
->min_mas
/ n_column
;
295 if (ai
->min_mas
% n_column
)
298 if (min_per_zone
> UWB_MAS_PER_ZONE
) {
299 return UWB_RSV_ALLOC_NOT_FOUND
;
302 if (max_per_zone
> UWB_MAS_PER_ZONE
) {
303 max_per_zone
= UWB_MAS_PER_ZONE
;
306 for (n_mas
= max_per_zone
; n_mas
>= min_per_zone
; n_mas
--) {
307 if (uwb_rsv_find_best_column_set(ai
, interval
, 0, n_mas
) == UWB_RSV_ALLOC_NOT_FOUND
)
309 for (n_safe
= n_mas
; n_safe
>= 0; n_safe
--) {
310 n_unsafe
= n_mas
- n_safe
;
311 if (uwb_rsv_find_best_column_set(ai
, interval
, n_safe
, n_unsafe
) == UWB_RSV_ALLOC_FOUND
) {
312 uwb_rsv_fill_column_alloc(ai
);
313 return UWB_RSV_ALLOC_FOUND
;
317 return UWB_RSV_ALLOC_NOT_FOUND
;
320 int uwb_rsv_find_best_allocation(struct uwb_rsv
*rsv
, struct uwb_mas_bm
*available
,
321 struct uwb_mas_bm
*result
)
323 struct uwb_rsv_alloc_info
*ai
;
327 ai
= kzalloc(sizeof(struct uwb_rsv_alloc_info
), GFP_KERNEL
);
329 ai
->min_mas
= rsv
->min_mas
;
330 ai
->max_mas
= rsv
->max_mas
;
331 ai
->max_interval
= rsv
->max_interval
;
334 /* fill the not available vector from the available bm */
335 for (bit_index
= 0; bit_index
< UWB_NUM_MAS
; bit_index
++) {
336 if (!test_bit(bit_index
, available
->bm
))
337 ai
->bm
[bit_index
] = UWB_RSV_MAS_NOT_AVAIL
;
340 if (ai
->max_interval
== 1) {
341 get_row_descriptors(ai
);
342 if (uwb_rsv_find_best_row_alloc(ai
) == UWB_RSV_ALLOC_FOUND
)
345 goto alloc_not_found
;
348 get_column_descriptors(ai
);
350 for (interval
= 16; interval
>= 2; interval
>>=1) {
351 if (interval
> ai
->max_interval
)
353 if (uwb_rsv_find_best_col_alloc(ai
, interval
) == UWB_RSV_ALLOC_FOUND
)
357 /* try row reservation if no column is found */
358 get_row_descriptors(ai
);
359 if (uwb_rsv_find_best_row_alloc(ai
) == UWB_RSV_ALLOC_FOUND
)
362 goto alloc_not_found
;
365 bitmap_zero(result
->bm
, UWB_NUM_MAS
);
366 bitmap_zero(result
->unsafe_bm
, UWB_NUM_MAS
);
367 /* fill the safe and unsafe bitmaps */
368 for (bit_index
= 0; bit_index
< UWB_NUM_MAS
; bit_index
++) {
369 if (ai
->bm
[bit_index
] == UWB_RSV_MAS_SAFE
)
370 set_bit(bit_index
, result
->bm
);
371 else if (ai
->bm
[bit_index
] == UWB_RSV_MAS_UNSAFE
)
372 set_bit(bit_index
, result
->unsafe_bm
);
374 bitmap_or(result
->bm
, result
->bm
, result
->unsafe_bm
, UWB_NUM_MAS
);
376 result
->safe
= ai
->safe_allocated_mases
;
377 result
->unsafe
= ai
->unsafe_allocated_mases
;
380 return UWB_RSV_ALLOC_FOUND
;
384 return UWB_RSV_ALLOC_NOT_FOUND
;