allocator.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * UWB reservation management.
  3. *
  4. * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
  5. *
  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.
  9. *
  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.
  14. *
  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/>.
  17. */
  18. #include <linux/kernel.h>
  19. #include <linux/slab.h>
  20. #include <linux/uwb.h>
  21. #include "uwb-internal.h"
  22. static void uwb_rsv_fill_column_alloc(struct uwb_rsv_alloc_info *ai)
  23. {
  24. int col, mas, safe_mas, unsafe_mas;
  25. unsigned char *bm = ai->bm;
  26. struct uwb_rsv_col_info *ci = ai->ci;
  27. unsigned char c;
  28. for (col = ci->csi.start_col; col < UWB_NUM_ZONES; col += ci->csi.interval) {
  29. safe_mas = ci->csi.safe_mas_per_col;
  30. unsafe_mas = ci->csi.unsafe_mas_per_col;
  31. for (mas = 0; mas < UWB_MAS_PER_ZONE; mas++ ) {
  32. if (bm[col * UWB_MAS_PER_ZONE + mas] == 0) {
  33. if (safe_mas > 0) {
  34. safe_mas--;
  35. c = UWB_RSV_MAS_SAFE;
  36. } else if (unsafe_mas > 0) {
  37. unsafe_mas--;
  38. c = UWB_RSV_MAS_UNSAFE;
  39. } else {
  40. break;
  41. }
  42. bm[col * UWB_MAS_PER_ZONE + mas] = c;
  43. }
  44. }
  45. }
  46. }
  47. static void uwb_rsv_fill_row_alloc(struct uwb_rsv_alloc_info *ai)
  48. {
  49. int mas, col, rows;
  50. unsigned char *bm = ai->bm;
  51. struct uwb_rsv_row_info *ri = &ai->ri;
  52. unsigned char c;
  53. rows = 1;
  54. c = UWB_RSV_MAS_SAFE;
  55. for (mas = UWB_MAS_PER_ZONE - 1; mas >= 0; mas--) {
  56. if (ri->avail[mas] == 1) {
  57. if (rows > ri->used_rows) {
  58. break;
  59. } else if (rows > 7) {
  60. c = UWB_RSV_MAS_UNSAFE;
  61. }
  62. for (col = 0; col < UWB_NUM_ZONES; col++) {
  63. if (bm[col * UWB_NUM_ZONES + mas] != UWB_RSV_MAS_NOT_AVAIL) {
  64. bm[col * UWB_NUM_ZONES + mas] = c;
  65. if(c == UWB_RSV_MAS_SAFE)
  66. ai->safe_allocated_mases++;
  67. else
  68. ai->unsafe_allocated_mases++;
  69. }
  70. }
  71. rows++;
  72. }
  73. }
  74. ai->total_allocated_mases = ai->safe_allocated_mases + ai->unsafe_allocated_mases;
  75. }
  76. /*
  77. * Find the best column set for a given availability, interval, num safe mas and
  78. * num unsafe mas.
  79. *
  80. * The different sets are tried in order as shown below, depending on the interval.
  81. *
  82. * interval = 16
  83. * deep = 0
  84. * set 1 -> { 8 }
  85. * deep = 1
  86. * set 1 -> { 4 }
  87. * set 2 -> { 12 }
  88. * deep = 2
  89. * set 1 -> { 2 }
  90. * set 2 -> { 6 }
  91. * set 3 -> { 10 }
  92. * set 4 -> { 14 }
  93. * deep = 3
  94. * set 1 -> { 1 }
  95. * set 2 -> { 3 }
  96. * set 3 -> { 5 }
  97. * set 4 -> { 7 }
  98. * set 5 -> { 9 }
  99. * set 6 -> { 11 }
  100. * set 7 -> { 13 }
  101. * set 8 -> { 15 }
  102. *
  103. * interval = 8
  104. * deep = 0
  105. * set 1 -> { 4 12 }
  106. * deep = 1
  107. * set 1 -> { 2 10 }
  108. * set 2 -> { 6 14 }
  109. * deep = 2
  110. * set 1 -> { 1 9 }
  111. * set 2 -> { 3 11 }
  112. * set 3 -> { 5 13 }
  113. * set 4 -> { 7 15 }
  114. *
  115. * interval = 4
  116. * deep = 0
  117. * set 1 -> { 2 6 10 14 }
  118. * deep = 1
  119. * set 1 -> { 1 5 9 13 }
  120. * set 2 -> { 3 7 11 15 }
  121. *
  122. * interval = 2
  123. * deep = 0
  124. * set 1 -> { 1 3 5 7 9 11 13 15 }
  125. */
  126. static int uwb_rsv_find_best_column_set(struct uwb_rsv_alloc_info *ai, int interval,
  127. int num_safe_mas, int num_unsafe_mas)
  128. {
  129. struct uwb_rsv_col_info *ci = ai->ci;
  130. struct uwb_rsv_col_set_info *csi = &ci->csi;
  131. struct uwb_rsv_col_set_info tmp_csi;
  132. int deep, set, col, start_col_deep, col_start_set;
  133. int start_col, max_mas_in_set, lowest_max_mas_in_deep;
  134. int n_mas;
  135. int found = UWB_RSV_ALLOC_NOT_FOUND;
  136. tmp_csi.start_col = 0;
  137. start_col_deep = interval;
  138. n_mas = num_unsafe_mas + num_safe_mas;
  139. for (deep = 0; ((interval >> deep) & 0x1) == 0; deep++) {
  140. start_col_deep /= 2;
  141. col_start_set = 0;
  142. lowest_max_mas_in_deep = UWB_MAS_PER_ZONE;
  143. for (set = 1; set <= (1 << deep); set++) {
  144. max_mas_in_set = 0;
  145. start_col = start_col_deep + col_start_set;
  146. for (col = start_col; col < UWB_NUM_ZONES; col += interval) {
  147. if (ci[col].max_avail_safe >= num_safe_mas &&
  148. ci[col].max_avail_unsafe >= n_mas) {
  149. if (ci[col].highest_mas[n_mas] > max_mas_in_set)
  150. max_mas_in_set = ci[col].highest_mas[n_mas];
  151. } else {
  152. max_mas_in_set = 0;
  153. break;
  154. }
  155. }
  156. if ((lowest_max_mas_in_deep > max_mas_in_set) && max_mas_in_set) {
  157. lowest_max_mas_in_deep = max_mas_in_set;
  158. tmp_csi.start_col = start_col;
  159. }
  160. col_start_set += (interval >> deep);
  161. }
  162. if (lowest_max_mas_in_deep < 8) {
  163. csi->start_col = tmp_csi.start_col;
  164. found = UWB_RSV_ALLOC_FOUND;
  165. break;
  166. } else if ((lowest_max_mas_in_deep > 8) &&
  167. (lowest_max_mas_in_deep != UWB_MAS_PER_ZONE) &&
  168. (found == UWB_RSV_ALLOC_NOT_FOUND)) {
  169. csi->start_col = tmp_csi.start_col;
  170. found = UWB_RSV_ALLOC_FOUND;
  171. }
  172. }
  173. if (found == UWB_RSV_ALLOC_FOUND) {
  174. csi->interval = interval;
  175. csi->safe_mas_per_col = num_safe_mas;
  176. csi->unsafe_mas_per_col = num_unsafe_mas;
  177. ai->safe_allocated_mases = (UWB_NUM_ZONES / interval) * num_safe_mas;
  178. ai->unsafe_allocated_mases = (UWB_NUM_ZONES / interval) * num_unsafe_mas;
  179. ai->total_allocated_mases = ai->safe_allocated_mases + ai->unsafe_allocated_mases;
  180. ai->interval = interval;
  181. }
  182. return found;
  183. }
  184. static void get_row_descriptors(struct uwb_rsv_alloc_info *ai)
  185. {
  186. unsigned char *bm = ai->bm;
  187. struct uwb_rsv_row_info *ri = &ai->ri;
  188. int col, mas;
  189. ri->free_rows = 16;
  190. for (mas = 0; mas < UWB_MAS_PER_ZONE; mas ++) {
  191. ri->avail[mas] = 1;
  192. for (col = 1; col < UWB_NUM_ZONES; col++) {
  193. if (bm[col * UWB_NUM_ZONES + mas] == UWB_RSV_MAS_NOT_AVAIL) {
  194. ri->free_rows--;
  195. ri->avail[mas]=0;
  196. break;
  197. }
  198. }
  199. }
  200. }
  201. static void uwb_rsv_fill_column_info(unsigned char *bm, int column, struct uwb_rsv_col_info *rci)
  202. {
  203. int mas;
  204. int block_count = 0, start_block = 0;
  205. int previous_avail = 0;
  206. int available = 0;
  207. int safe_mas_in_row[UWB_MAS_PER_ZONE] = {
  208. 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1,
  209. };
  210. rci->max_avail_safe = 0;
  211. for (mas = 0; mas < UWB_MAS_PER_ZONE; mas ++) {
  212. if (!bm[column * UWB_NUM_ZONES + mas]) {
  213. available++;
  214. rci->max_avail_unsafe = available;
  215. rci->highest_mas[available] = mas;
  216. if (previous_avail) {
  217. block_count++;
  218. if ((block_count > safe_mas_in_row[start_block]) &&
  219. (!rci->max_avail_safe))
  220. rci->max_avail_safe = available - 1;
  221. } else {
  222. previous_avail = 1;
  223. start_block = mas;
  224. block_count = 1;
  225. }
  226. } else {
  227. previous_avail = 0;
  228. }
  229. }
  230. if (!rci->max_avail_safe)
  231. rci->max_avail_safe = rci->max_avail_unsafe;
  232. }
  233. static void get_column_descriptors(struct uwb_rsv_alloc_info *ai)
  234. {
  235. unsigned char *bm = ai->bm;
  236. struct uwb_rsv_col_info *ci = ai->ci;
  237. int col;
  238. for (col = 1; col < UWB_NUM_ZONES; col++) {
  239. uwb_rsv_fill_column_info(bm, col, &ci[col]);
  240. }
  241. }
  242. static int uwb_rsv_find_best_row_alloc(struct uwb_rsv_alloc_info *ai)
  243. {
  244. int n_rows;
  245. int max_rows = ai->max_mas / UWB_USABLE_MAS_PER_ROW;
  246. int min_rows = ai->min_mas / UWB_USABLE_MAS_PER_ROW;
  247. if (ai->min_mas % UWB_USABLE_MAS_PER_ROW)
  248. min_rows++;
  249. for (n_rows = max_rows; n_rows >= min_rows; n_rows--) {
  250. if (n_rows <= ai->ri.free_rows) {
  251. ai->ri.used_rows = n_rows;
  252. ai->interval = 1; /* row reservation */
  253. uwb_rsv_fill_row_alloc(ai);
  254. return UWB_RSV_ALLOC_FOUND;
  255. }
  256. }
  257. return UWB_RSV_ALLOC_NOT_FOUND;
  258. }
  259. static int uwb_rsv_find_best_col_alloc(struct uwb_rsv_alloc_info *ai, int interval)
  260. {
  261. int n_safe, n_unsafe, n_mas;
  262. int n_column = UWB_NUM_ZONES / interval;
  263. int max_per_zone = ai->max_mas / n_column;
  264. int min_per_zone = ai->min_mas / n_column;
  265. if (ai->min_mas % n_column)
  266. min_per_zone++;
  267. if (min_per_zone > UWB_MAS_PER_ZONE) {
  268. return UWB_RSV_ALLOC_NOT_FOUND;
  269. }
  270. if (max_per_zone > UWB_MAS_PER_ZONE) {
  271. max_per_zone = UWB_MAS_PER_ZONE;
  272. }
  273. for (n_mas = max_per_zone; n_mas >= min_per_zone; n_mas--) {
  274. if (uwb_rsv_find_best_column_set(ai, interval, 0, n_mas) == UWB_RSV_ALLOC_NOT_FOUND)
  275. continue;
  276. for (n_safe = n_mas; n_safe >= 0; n_safe--) {
  277. n_unsafe = n_mas - n_safe;
  278. if (uwb_rsv_find_best_column_set(ai, interval, n_safe, n_unsafe) == UWB_RSV_ALLOC_FOUND) {
  279. uwb_rsv_fill_column_alloc(ai);
  280. return UWB_RSV_ALLOC_FOUND;
  281. }
  282. }
  283. }
  284. return UWB_RSV_ALLOC_NOT_FOUND;
  285. }
  286. int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv, struct uwb_mas_bm *available,
  287. struct uwb_mas_bm *result)
  288. {
  289. struct uwb_rsv_alloc_info *ai;
  290. int interval;
  291. int bit_index;
  292. ai = kzalloc(sizeof(struct uwb_rsv_alloc_info), GFP_KERNEL);
  293. if (!ai)
  294. return UWB_RSV_ALLOC_NOT_FOUND;
  295. ai->min_mas = rsv->min_mas;
  296. ai->max_mas = rsv->max_mas;
  297. ai->max_interval = rsv->max_interval;
  298. /* fill the not available vector from the available bm */
  299. for_each_clear_bit(bit_index, available->bm, UWB_NUM_MAS)
  300. ai->bm[bit_index] = UWB_RSV_MAS_NOT_AVAIL;
  301. if (ai->max_interval == 1) {
  302. get_row_descriptors(ai);
  303. if (uwb_rsv_find_best_row_alloc(ai) == UWB_RSV_ALLOC_FOUND)
  304. goto alloc_found;
  305. else
  306. goto alloc_not_found;
  307. }
  308. get_column_descriptors(ai);
  309. for (interval = 16; interval >= 2; interval>>=1) {
  310. if (interval > ai->max_interval)
  311. continue;
  312. if (uwb_rsv_find_best_col_alloc(ai, interval) == UWB_RSV_ALLOC_FOUND)
  313. goto alloc_found;
  314. }
  315. /* try row reservation if no column is found */
  316. get_row_descriptors(ai);
  317. if (uwb_rsv_find_best_row_alloc(ai) == UWB_RSV_ALLOC_FOUND)
  318. goto alloc_found;
  319. else
  320. goto alloc_not_found;
  321. alloc_found:
  322. bitmap_zero(result->bm, UWB_NUM_MAS);
  323. bitmap_zero(result->unsafe_bm, UWB_NUM_MAS);
  324. /* fill the safe and unsafe bitmaps */
  325. for (bit_index = 0; bit_index < UWB_NUM_MAS; bit_index++) {
  326. if (ai->bm[bit_index] == UWB_RSV_MAS_SAFE)
  327. set_bit(bit_index, result->bm);
  328. else if (ai->bm[bit_index] == UWB_RSV_MAS_UNSAFE)
  329. set_bit(bit_index, result->unsafe_bm);
  330. }
  331. bitmap_or(result->bm, result->bm, result->unsafe_bm, UWB_NUM_MAS);
  332. result->safe = ai->safe_allocated_mases;
  333. result->unsafe = ai->unsafe_allocated_mases;
  334. kfree(ai);
  335. return UWB_RSV_ALLOC_FOUND;
  336. alloc_not_found:
  337. kfree(ai);
  338. return UWB_RSV_ALLOC_NOT_FOUND;
  339. }