blob: ee3ec7990a1e6ec1376025259479692ae7e0ba1f [file] [log] [blame]
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +02001/* gprs_rlcmac.cpp
2 *
3 * Copyright (C) 2012 Ivan Klyuchnikov
4 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
5 * Copyright (C) 2013 by Holger Hans Peter Freyther
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <gprs_rlcmac.h>
23#include <gprs_debug.h>
24#include <tbf.h>
25
26#include <errno.h>
27
28/* 3GPP TS 05.02 Annex B.1 */
29
30#define MS_NA 255 /* N/A */
31#define MS_A 254 /* 1 with hopping, 0 without */
32#define MS_B 253 /* 1 with hopping, 0 without (change Rx to Tx)*/
33#define MS_C 252 /* 1 with hopping, 0 without (change Tx to Rx)*/
34
35struct gprs_ms_multislot_class {
36 uint8_t rx, tx, sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
37 uint8_t ta, tb, ra, rb; /* Minimum Number of Slots */
38 uint8_t type; /* Type of Mobile */
39};
40
41static const struct gprs_ms_multislot_class gprs_ms_multislot_class[32] = {
42/* M-S Class Rx Tx Sum Tta Ttb Tra Trb Type */
43/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
44/* 1 */ { 1, 1, 2, 3, 2, 4, 2, 1 },
45/* 2 */ { 2, 1, 3, 3, 2, 3, 1, 1 },
46/* 3 */ { 2, 2, 3, 3, 2, 3, 1, 1 },
47/* 4 */ { 3, 1, 4, 3, 1, 3, 1, 1 },
48/* 5 */ { 2, 2, 4, 3, 1, 3, 1, 1 },
49/* 6 */ { 3, 2, 4, 3, 1, 3, 1, 1 },
50/* 7 */ { 3, 3, 4, 3, 1, 3, 1, 1 },
51/* 8 */ { 4, 1, 5, 3, 1, 2, 1, 1 },
52/* 9 */ { 3, 2, 5, 3, 1, 2, 1, 1 },
53/* 10 */ { 4, 2, 5, 3, 1, 2, 1, 1 },
54/* 11 */ { 4, 3, 5, 3, 1, 2, 1, 1 },
55/* 12 */ { 4, 4, 5, 2, 1, 2, 1, 1 },
56/* 13 */ { 3, 3, MS_NA, MS_NA, MS_A, 3, MS_A, 2 },
57/* 14 */ { 4, 4, MS_NA, MS_NA, MS_A, 3, MS_A, 2 },
58/* 15 */ { 5, 5, MS_NA, MS_NA, MS_A, 3, MS_A, 2 },
59/* 16 */ { 6, 6, MS_NA, MS_NA, MS_A, 2, MS_A, 2 },
60/* 17 */ { 7, 7, MS_NA, MS_NA, MS_A, 1, 0, 2 },
61/* 18 */ { 8, 8, MS_NA, MS_NA, 0, 0, 0, 2 },
62/* 19 */ { 6, 2, MS_NA, 3, MS_B, 2, MS_C, 1 },
63/* 20 */ { 6, 3, MS_NA, 3, MS_B, 2, MS_C, 1 },
64/* 21 */ { 6, 4, MS_NA, 3, MS_B, 2, MS_C, 1 },
65/* 22 */ { 6, 4, MS_NA, 2, MS_B, 2, MS_C, 1 },
66/* 23 */ { 6, 6, MS_NA, 2, MS_B, 2, MS_C, 1 },
67/* 24 */ { 8, 2, MS_NA, 3, MS_B, 2, MS_C, 1 },
68/* 25 */ { 8, 3, MS_NA, 3, MS_B, 2, MS_C, 1 },
69/* 26 */ { 8, 4, MS_NA, 3, MS_B, 2, MS_C, 1 },
70/* 27 */ { 8, 4, MS_NA, 2, MS_B, 2, MS_C, 1 },
71/* 28 */ { 8, 6, MS_NA, 2, MS_B, 2, MS_C, 1 },
72/* 29 */ { 8, 8, MS_NA, 2, MS_B, 2, MS_C, 1 },
73/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
74/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
75};
76
77static inline int8_t find_free_usf(struct gprs_rlcmac_pdch *pdch, uint8_t ts)
78{
79 struct gprs_rlcmac_tbf *tbf;
80 uint8_t usf_map = 0;
81 uint8_t tfi, usf;
82
83 /* make map of used USF */
84 for (tfi = 0; tfi < 32; tfi++) {
85 tbf = pdch->ul_tbf[tfi];
86 if (!tbf)
87 continue;
88 usf_map |= (1 << tbf->dir.ul.usf[ts]);
89 }
90
91 /* look for USF, don't use USF=7 */
92 for (usf = 0; usf < 7; usf++) {
93 if (!(usf_map & (1 << usf)))
94 return usf;
95 }
96
97 return -1;
98}
99
100
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200101static void assign_uplink_tbf_usf(
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200102 struct gprs_rlcmac_pdch *pdch,
103 int ts,
104 struct gprs_rlcmac_tbf *tbf, int8_t usf)
105{
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200106 tbf->trx->ul_tbf[tbf->tfi] = tbf;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200107 pdch->ul_tbf[tbf->tfi] = tbf;
108 tbf->pdch[ts] = pdch;
109 tbf->dir.ul.usf[ts] = usf;
110}
111
Holger Hans Peter Freyther8481a052013-09-29 08:08:28 +0200112static void assign_dlink_tbf(
113 struct gprs_rlcmac_pdch *pdch,
114 int ts,
115 struct gprs_rlcmac_tbf *tbf)
116{
117 tbf->trx->dl_tbf[tbf->tfi] = tbf;
118 pdch->dl_tbf[tbf->tfi] = tbf;
119 tbf->pdch[ts] = pdch;
120}
121
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200122
123/* Slot Allocation: Algorithm A
124 *
125 * Assign single slot for uplink and downlink
126 */
127int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
128 struct gprs_rlcmac_tbf *old_tbf,
129 struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single)
130{
131 struct gprs_rlcmac_pdch *pdch;
132 uint8_t ts;
133 int8_t usf; /* must be signed */
134
135 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm A) for class "
136 "%d\n", tbf->ms_class);
137
138 for (ts = 0; ts < 8; ts++) {
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200139 pdch = &tbf->trx->pdch[ts];
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200140 if (!pdch->enable) {
141 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
142 "not enabled\n", ts);
143 continue;
144 }
145 break;
146 }
147 if (ts == 8)
148 return -EINVAL;
149
150 tbf->tsc = pdch->tsc;
151 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
152 /* if USF available */
153 usf = find_free_usf(pdch, ts);
154 if (usf < 0) {
155 LOGP(DRLCMAC, LOGL_NOTICE, "- Failed "
156 "allocating TS=%d, no USF available\n", ts);
157 return -EBUSY;
158 }
159 LOGP(DRLCMAC, LOGL_DEBUG, "- Assign uplink "
160 "TS=%d USF=%d\n", ts, usf);
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200161 assign_uplink_tbf_usf(pdch, ts, tbf, usf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200162 } else {
163 LOGP(DRLCMAC, LOGL_DEBUG, "- Assign downlink TS=%d\n", ts);
Holger Hans Peter Freyther8481a052013-09-29 08:08:28 +0200164 assign_dlink_tbf(pdch, ts, tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200165 }
166 /* the only one TS is the common TS */
167 tbf->first_ts = tbf->first_common_ts = ts;
168
169 return 0;
170}
171
172/* Slot Allocation: Algorithm B
173 *
174 * Assign as many downlink slots as possible.
175 * Assign one uplink slot. (With free USF)
176 *
177 */
178int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
179 struct gprs_rlcmac_tbf *old_tbf,
180 struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single)
181{
182 struct gprs_rlcmac_pdch *pdch;
183 const struct gprs_ms_multislot_class *ms_class;
184 uint8_t Rx, Tx, Sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
185 uint8_t Tta, Ttb, Tra, Trb, Tt, Tr; /* Minimum Number of Slots */
186 uint8_t Type; /* Type of Mobile */
187 uint8_t rx_win_min = 0, rx_win_max = 7;
188 uint8_t tx_win_min, tx_win_max, tx_range;
189 uint8_t rx_window = 0, tx_window = 0;
190 static const char *digit[10] = { "0","1","2","3","4","5","6","7","8","9" };
191 int8_t usf[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; /* must be signed */
192 int8_t tsc = -1; /* must be signed */
193 int8_t first_common_ts = -1;
194 uint8_t i, ts;
195 uint8_t slotcount = 0;
196
197
198 if (tbf->ms_class >= 32) {
199 LOGP(DRLCMAC, LOGL_ERROR, "Multislot class %d out of range.\n",
200 tbf->ms_class);
201 return -EINVAL;
202 }
203
204 if (tbf->ms_class) {
205 ms_class = &gprs_ms_multislot_class[tbf->ms_class];
206 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm B) for "
207 "class %d\n", tbf->ms_class);
208 } else {
209 ms_class = &gprs_ms_multislot_class[12];
210 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm B) for "
211 "unknow class (assuming 12)\n");
212 }
213
214 if (ms_class->tx == MS_NA) {
215 LOGP(DRLCMAC, LOGL_NOTICE, "Multislot class %d not "
216 "applicable.\n", tbf->ms_class);
217 return -EINVAL;
218 }
219
220 Rx = ms_class->rx;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200221 Tx = ms_class->tx;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200222 Sum = ms_class->sum;
223 Tta = ms_class->ta;
224 Ttb = ms_class->tb;
225 Tra = ms_class->ra;
226 Trb = ms_class->rb;
227 Type = ms_class->type;
228
229 /* Tta and Ttb may depend on hopping or frequency change */
Holger Hans Peter Freyther11a74892013-09-29 08:13:42 +0200230 if (Ttb == MS_A)
231 Ttb = 0;
232 if (Trb == MS_A)
233 Trb = 0;
234 if (Ttb == MS_B)
235 Ttb = 0;
236 if (Trb == MS_C)
237 Trb = 0;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200238
239 LOGP(DRLCMAC, LOGL_DEBUG, "- Rx=%d Tx=%d Sum Rx+Tx=%s Tta=%s Ttb=%d "
240 " Tra=%d Trb=%d Type=%d\n", Rx, Tx,
241 (Sum == MS_NA) ? "N/A" : digit[Sum],
242 (Tta == MS_NA) ? "N/A" : digit[Tta], Ttb, Tra, Trb, Type);
243
244 /* select the values for time contraints */
Holger Hans Peter Freyther11a74892013-09-29 08:13:42 +0200245 /* applicable to type 1 and type 2 */
246 Tt = Ttb;
247 Tr = Trb;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200248
249 /* select a window of Rx slots if available
250 * The maximum allowed slots depend on RX or the window of available
251 * slots.
252 * This must be done for uplink TBF also, because it is the basis
253 * for calculating control slot and uplink slot(s). */
254 for (ts = 0, i = 0; ts < 8; ts++) {
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200255 pdch = &tbf->trx->pdch[ts];
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200256 /* check if enabled */
257 if (!pdch->enable) {
258 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
259 "not enabled\n", ts);
260 /* increase window for Type 1 */
261 if (Type == 1 && rx_window)
262 i++;
263 continue;
264 }
265 /* check if TSC changes */
266 if (tsc < 0)
267 tbf->tsc = tsc = pdch->tsc;
268 else if (tsc != pdch->tsc) {
269 LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS %d of TRX=%d, "
270 "because it has different TSC than lower TS "
271 "of TRX. In order to allow multislot, all "
272 "slots must be configured with the same "
Holger Hans Peter Freyther96efa702013-09-29 07:44:39 +0200273 "TSC!\n", ts, tbf->trx_no);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200274 /* increase window for Type 1 */
275 if (Type == 1 && rx_window)
276 i++;
277 continue;
278 }
279
280 if (!rx_window)
281 rx_win_min = ts;
282
283 rx_window |= (1 << ts);
284 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected DL TS %d\n", ts);
285
286 /* range of window (required for Type 1) */
287 rx_win_max = ts;
288
289 if (++i == Rx) {
290 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because slots / "
291 "window reached maximum alowed Rx size\n");
292 break;
293 }
294 }
295
296 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected slots for RX: "
297 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
298 ((rx_window & 0x01)) ? 'D' : '.',
299 ((rx_window & 0x02)) ? 'D' : '.',
300 ((rx_window & 0x04)) ? 'D' : '.',
301 ((rx_window & 0x08)) ? 'D' : '.',
302 ((rx_window & 0x10)) ? 'D' : '.',
303 ((rx_window & 0x20)) ? 'D' : '.',
304 ((rx_window & 0x40)) ? 'D' : '.',
305 ((rx_window & 0x80)) ? 'D' : '.');
306
307 /* reduce window, if existing uplink slots collide RX window */
308 if (Type == 1 && old_tbf && old_tbf->direction == GPRS_RLCMAC_UL_TBF) {
309 uint8_t collide = 0, ul_usage = 0;
310 int j;
311
312 /* calculate mask of colliding slots */
313 for (ts = 0; ts < 8; ts++) {
314 if (old_tbf->pdch[ts]) {
315 ul_usage |= (1 << ts);
316 /* mark bits from TS-t .. TS+r */
317 for (j = ts - Tt; j != ((ts + Tr + 1) & 7);
318 j = (j + 1) & 7)
319 collide |= (1 << j);
320 }
321 }
322 LOGP(DRLCMAC, LOGL_DEBUG, "- Not allowed slots due to existing "
323 "UL allocation: (TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7) "
324 " D=downlink x=not usable\n",
325 ((ul_usage & 0x01)) ? 'D' : ((collide & 0x01))?'x':'.',
326 ((ul_usage & 0x02)) ? 'D' : ((collide & 0x02))?'x':'.',
327 ((ul_usage & 0x04)) ? 'D' : ((collide & 0x04))?'x':'.',
328 ((ul_usage & 0x08)) ? 'D' : ((collide & 0x08))?'x':'.',
329 ((ul_usage & 0x10)) ? 'D' : ((collide & 0x10))?'x':'.',
330 ((ul_usage & 0x20)) ? 'D' : ((collide & 0x20))?'x':'.',
331 ((ul_usage & 0x40)) ? 'D' : ((collide & 0x40))?'x':'.',
332 ((ul_usage & 0x80)) ? 'D' : ((collide & 0x80))?'x':'.');
333
334 /* apply mask to reduce tx_window (shifted by 3 slots) */
335 rx_window &= ~(collide << 3);
336 rx_window &= ~(collide >> 5);
337 LOGP(DRLCMAC, LOGL_DEBUG, "- Remaining slots for RX: "
338 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
339 ((rx_window & 0x01)) ? 'D' : '.',
340 ((rx_window & 0x02)) ? 'D' : '.',
341 ((rx_window & 0x04)) ? 'D' : '.',
342 ((rx_window & 0x08)) ? 'D' : '.',
343 ((rx_window & 0x10)) ? 'D' : '.',
344 ((rx_window & 0x20)) ? 'D' : '.',
345 ((rx_window & 0x40)) ? 'D' : '.',
346 ((rx_window & 0x80)) ? 'D' : '.');
347 if (!rx_window) {
348 LOGP(DRLCMAC, LOGL_NOTICE, "No suitable downlink slots "
349 "available with current uplink assignment\n");
350 return -EBUSY;
351 }
352
353 /* calculate new min/max */
354 for (ts = rx_win_min; ts <= rx_win_max; ts++) {
355 if ((rx_window & (1 << ts)))
356 break;
357 rx_win_min = ts + 1;
358 LOGP(DRLCMAC, LOGL_DEBUG, "- TS has been deleted, so "
359 "raising start of DL window to %d\n",
360 rx_win_min);
361 }
362 for (ts = rx_win_max; ts >= rx_win_min; ts--) {
363 if ((rx_window & (1 << ts)))
364 break;
365 rx_win_max = ts - 1;
366 LOGP(DRLCMAC, LOGL_DEBUG, "- TS has been deleted, so "
367 "lowering end of DL window to %d\n",
368 rx_win_max);
369 }
370 }
371
372 /* reduce window, to allow at least one uplink TX slot
373 * this is only required for Type 1 */
374 if (Type == 1 && rx_win_max - rx_win_min + 1 + Tt + 1 + Tr > 8) {
375 rx_win_max = rx_win_min + 7 - Tt - 1 - Tr;
376 LOGP(DRLCMAC, LOGL_DEBUG, "- Reduce RX window due to time "
377 "contraints to %d slots\n",
378 rx_win_max - rx_win_min + 1);
379 }
380
381 LOGP(DRLCMAC, LOGL_DEBUG, "- RX-Window is: %d..%d\n", rx_win_min,
382 rx_win_max);
383
384 /* calculate TX window */
385 if (Type == 1) {
386 /* calculate TX window (shifted by 3 timeslots)
387 * it uses the space between tx_win_max and tx_win_min */
388 tx_win_min = (rx_win_max - 2 + Tt) & 7;
389 tx_win_max = (rx_win_min + 4 - Tr) & 7;
390 /* calculate the TX window size (might be larger than Tx) */
391 tx_range = (tx_win_max - tx_win_min + 1) & 7;
392 } else {
393 /* TX and RX simultaniously */
394 tx_win_min = rx_win_min;
395 tx_win_max = 7;
396 /* TX window size (might be larger than Tx) */
397 tx_range = tx_win_max - tx_win_min + 1;
398 }
399
400 LOGP(DRLCMAC, LOGL_DEBUG, "- TX-Window is: %d..%d\n", tx_win_min,
401 tx_win_max);
402
403 /* select a window of Tx slots if available
404 * The maximum allowed slots depend on TX or the window of available
405 * slots.
406 *
407 * also assign the first common ts, which is used for control or single
408 * slot. */
409 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
410 for (ts = tx_win_min, i = 0; i < tx_range; ts = (ts + 1) & 7) {
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200411 pdch = &tbf->trx->pdch[ts];
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200412 /* check if enabled */
413 if (!pdch->enable) {
414 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
415 "because not enabled\n", ts);
416 continue;
417 }
418 /* check if TSC changes */
419 if (tsc < 0)
420 tbf->tsc = tsc = pdch->tsc;
421 else if (tsc != pdch->tsc) {
422 LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS %d of "
423 "TRX=%d, because it has different TSC "
424 "than lower TS of TRX. In order to "
425 "allow multislot, all slots must be "
426 "configured with the same TSC!\n",
Holger Hans Peter Freyther96efa702013-09-29 07:44:39 +0200427 ts, tbf->trx_no);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200428 /* increase window for Type 1 */
429 if (Type == 1)
430 i++;
431 continue;
432 }
433 /* check for free usf */
434 usf[ts] = find_free_usf(pdch, ts);
435 if (usf[ts] < 0) {
436 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
437 "because no USF available\n", ts);
438 /* increase window for Type 1 */
439 if (Type == 1)
440 i++;
441 continue;
442 }
443
444 if (!tx_window)
445 first_common_ts = ts;
446
447 tx_window |= (1 << ts);
448 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected UL TS %d\n", ts);
449
450 if (1 && Type == 1) { /* FIXME: multislot UL assignment */
451 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
452 "1 slot assigned\n");
453 break;
454 }
455 if (++i == Tx) {
456 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
457 "slots / window reached maximum "
458 "allowed Tx size\n");
459 break;
460 }
461 }
462
463 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected TX window: "
464 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
465 ((tx_window & 0x01)) ? 'U' : '.',
466 ((tx_window & 0x02)) ? 'U' : '.',
467 ((tx_window & 0x04)) ? 'U' : '.',
468 ((tx_window & 0x08)) ? 'U' : '.',
469 ((tx_window & 0x10)) ? 'U' : '.',
470 ((tx_window & 0x20)) ? 'U' : '.',
471 ((tx_window & 0x40)) ? 'U' : '.',
472 ((tx_window & 0x80)) ? 'U' : '.');
473
474 if (!tx_window) {
475 LOGP(DRLCMAC, LOGL_NOTICE, "No suitable uplink slots "
476 "available\n");
477 return -EBUSY;
478 }
479 } else {
480 /* assign the first common ts, which is used for control or
481 * single slot. */
482 for (ts = tx_win_min, i = 0; i < tx_range; ts = (ts + 1) & 7) {
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200483 pdch = &tbf->trx->pdch[ts];
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200484 /* check if enabled */
485 if (!pdch->enable) {
486 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
487 "because not enabled\n", ts);
488 continue;
489 }
490 first_common_ts = ts;
491 break;
492 }
493 }
494
495 if (first_common_ts < 0) {
496 LOGP(DRLCMAC, LOGL_NOTICE, "No first common slots available\n");
497 return -EINVAL;
498 }
499
500 if (tbf->direction == GPRS_RLCMAC_DL_TBF) {
501 /* assign downlink */
502 if (rx_window == 0) {
503 LOGP(DRLCMAC, LOGL_NOTICE, "No downlink slots "
504 "available\n");
505 return -EINVAL;
506 }
507 for (ts = 0; ts < 8; ts++) {
508 if ((rx_window & (1 << ts))) {
509 /* be sure to select a single downlink slots
510 * that can be used for uplink, if multiple
511 * slots are assigned later. */
512 if (single && first_common_ts != ts)
513 continue;
514 LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning DL TS "
515 "%d\n", ts);
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200516 pdch = &tbf->trx->pdch[ts];
Holger Hans Peter Freyther8481a052013-09-29 08:08:28 +0200517 assign_dlink_tbf(pdch, ts, tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200518 slotcount++;
519 if (slotcount == 1)
520 tbf->first_ts = ts;
521 if (single)
522 break;
523 }
524 }
525 } else {
526 /* assign uplink */
527 if (tx_window == 0) {
528 LOGP(DRLCMAC, LOGL_NOTICE, "No uplink slots "
529 "available\n");
530 return -EINVAL;
531 }
532 for (ts = 0; ts < 8; ts++) {
533 if ((tx_window & (1 << ts))) {
534 LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning UL TS "
535 "%d\n", ts);
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200536 pdch = &tbf->trx->pdch[ts];
537 assign_uplink_tbf_usf(pdch, ts, tbf, usf[ts]);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200538 slotcount++;
539 if (slotcount == 1)
540 tbf->first_ts = ts;
541 if (single)
542 break;
543 }
544 }
545 }
546 if (single && slotcount) {
547 LOGP(DRLCMAC, LOGL_INFO, "Using single slot at TS %d for %s\n",
548 tbf->first_ts,
549 (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL");
550 } else {
551 LOGP(DRLCMAC, LOGL_INFO, "Using %d slots for %s\n", slotcount,
552 (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL");
553 }
554 if (slotcount == 0)
555 return -EBUSY;
556
557 tbf->first_common_ts = first_common_ts;
558
559 return 0;
560}