blob: 116cabe0a0a68db02f5cf788898bfbce80289687 [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>
Holger Hans Peter Freyther34bd8bd2013-10-19 21:10:38 +020024#include <bts.h>
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +020025#include <tbf.h>
Jacob Erlbecke2e004e2015-06-18 17:16:26 +020026#include <gprs_ms.h>
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +020027
28#include <errno.h>
Jacob Erlbeckec478752015-06-19 16:35:38 +020029#include <values.h>
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +020030
31/* 3GPP TS 05.02 Annex B.1 */
32
33#define MS_NA 255 /* N/A */
34#define MS_A 254 /* 1 with hopping, 0 without */
35#define MS_B 253 /* 1 with hopping, 0 without (change Rx to Tx)*/
36#define MS_C 252 /* 1 with hopping, 0 without (change Tx to Rx)*/
37
38struct gprs_ms_multislot_class {
39 uint8_t rx, tx, sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
40 uint8_t ta, tb, ra, rb; /* Minimum Number of Slots */
41 uint8_t type; /* Type of Mobile */
42};
43
44static const struct gprs_ms_multislot_class gprs_ms_multislot_class[32] = {
45/* M-S Class Rx Tx Sum Tta Ttb Tra Trb Type */
46/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
47/* 1 */ { 1, 1, 2, 3, 2, 4, 2, 1 },
48/* 2 */ { 2, 1, 3, 3, 2, 3, 1, 1 },
49/* 3 */ { 2, 2, 3, 3, 2, 3, 1, 1 },
50/* 4 */ { 3, 1, 4, 3, 1, 3, 1, 1 },
51/* 5 */ { 2, 2, 4, 3, 1, 3, 1, 1 },
52/* 6 */ { 3, 2, 4, 3, 1, 3, 1, 1 },
53/* 7 */ { 3, 3, 4, 3, 1, 3, 1, 1 },
54/* 8 */ { 4, 1, 5, 3, 1, 2, 1, 1 },
55/* 9 */ { 3, 2, 5, 3, 1, 2, 1, 1 },
56/* 10 */ { 4, 2, 5, 3, 1, 2, 1, 1 },
57/* 11 */ { 4, 3, 5, 3, 1, 2, 1, 1 },
58/* 12 */ { 4, 4, 5, 2, 1, 2, 1, 1 },
59/* 13 */ { 3, 3, MS_NA, MS_NA, MS_A, 3, MS_A, 2 },
60/* 14 */ { 4, 4, MS_NA, MS_NA, MS_A, 3, MS_A, 2 },
61/* 15 */ { 5, 5, MS_NA, MS_NA, MS_A, 3, MS_A, 2 },
62/* 16 */ { 6, 6, MS_NA, MS_NA, MS_A, 2, MS_A, 2 },
63/* 17 */ { 7, 7, MS_NA, MS_NA, MS_A, 1, 0, 2 },
64/* 18 */ { 8, 8, MS_NA, MS_NA, 0, 0, 0, 2 },
65/* 19 */ { 6, 2, MS_NA, 3, MS_B, 2, MS_C, 1 },
66/* 20 */ { 6, 3, MS_NA, 3, MS_B, 2, MS_C, 1 },
67/* 21 */ { 6, 4, MS_NA, 3, MS_B, 2, MS_C, 1 },
68/* 22 */ { 6, 4, MS_NA, 2, MS_B, 2, MS_C, 1 },
69/* 23 */ { 6, 6, MS_NA, 2, MS_B, 2, MS_C, 1 },
70/* 24 */ { 8, 2, MS_NA, 3, MS_B, 2, MS_C, 1 },
71/* 25 */ { 8, 3, MS_NA, 3, MS_B, 2, MS_C, 1 },
72/* 26 */ { 8, 4, MS_NA, 3, MS_B, 2, MS_C, 1 },
73/* 27 */ { 8, 4, MS_NA, 2, MS_B, 2, MS_C, 1 },
74/* 28 */ { 8, 6, MS_NA, 2, MS_B, 2, MS_C, 1 },
75/* 29 */ { 8, 8, MS_NA, 2, MS_B, 2, MS_C, 1 },
76/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
77/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
78};
79
Holger Hans Peter Freyther6796ed22013-10-20 16:45:10 +020080static inline int8_t find_free_usf(struct gprs_rlcmac_pdch *pdch)
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +020081{
Daniel Willmanncd44ec42014-08-07 15:04:57 +020082 struct gprs_rlcmac_ul_tbf *tbf;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +020083 uint8_t usf_map = 0;
84 uint8_t tfi, usf;
85
86 /* make map of used USF */
87 for (tfi = 0; tfi < 32; tfi++) {
Daniel Willmann17a1d5e2014-05-30 20:21:30 +020088 tbf = pdch->ul_tbf_by_tfi(tfi);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +020089 if (!tbf)
90 continue;
Daniel Willmann7e994e32014-08-07 15:49:21 +020091 usf_map |= (1 << tbf->m_usf[pdch->ts_no]);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +020092 }
93
94 /* look for USF, don't use USF=7 */
95 for (usf = 0; usf < 7; usf++) {
96 if (!(usf_map & (1 << usf)))
97 return usf;
98 }
99
100 return -1;
101}
102
Jacob Erlbeckec478752015-06-19 16:35:38 +0200103static int find_possible_pdchs(struct gprs_rlcmac_trx *trx,
Jacob Erlbeck83426b22015-06-30 09:44:05 +0200104 size_t max_slots,
Jacob Erlbeckec478752015-06-19 16:35:38 +0200105 uint8_t mask, const char *mask_reason = NULL)
Holger Hans Peter Freytherb0a00752013-09-29 08:18:17 +0200106{
Jacob Erlbeckec478752015-06-19 16:35:38 +0200107 unsigned ts;
108 int valid_ts_set = 0;
Jacob Erlbeck83426b22015-06-30 09:44:05 +0200109 int8_t last_tsc = -1; /* must be signed */
Jacob Erlbeckec478752015-06-19 16:35:38 +0200110
111 for (ts = 0; ts < ARRAY_SIZE(trx->pdch); ts++) {
Holger Hans Peter Freytherb0a00752013-09-29 08:18:17 +0200112 struct gprs_rlcmac_pdch *pdch;
113
114 pdch = &trx->pdch[ts];
Holger Hans Peter Freyther17b0d832013-10-19 17:37:48 +0200115 if (!pdch->is_enabled()) {
Holger Hans Peter Freytherb0a00752013-09-29 08:18:17 +0200116 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
117 "not enabled\n", ts);
118 continue;
119 }
Jacob Erlbeckec478752015-06-19 16:35:38 +0200120
121 if (((1 << ts) & mask) == 0) {
122 if (mask_reason)
123 LOGP(DRLCMAC, LOGL_DEBUG,
124 "- Skipping TS %d, because %s\n",
125 ts, mask_reason);
126 continue;
127 }
128
Jacob Erlbeck83426b22015-06-30 09:44:05 +0200129 if (max_slots > 1) {
130 /* check if TSC changes, see TS 45.002, 6.4.2 */
131 if (last_tsc < 0)
132 last_tsc = pdch->tsc;
133 else if (last_tsc != pdch->tsc) {
134 LOGP(DRLCMAC, LOGL_ERROR,
135 "Skipping TS %d of TRX=%d, because it "
136 "has different TSC than lower TS of TRX. "
137 "In order to allow multislot, all "
138 "slots must be configured with the same "
139 "TSC!\n", ts, trx->trx_no);
140 continue;
141 }
142 }
143
Jacob Erlbeckec478752015-06-19 16:35:38 +0200144 valid_ts_set |= 1 << ts;
Holger Hans Peter Freytherb0a00752013-09-29 08:18:17 +0200145 }
146
Jacob Erlbeckec478752015-06-19 16:35:38 +0200147 return valid_ts_set;
148}
149
150static int find_least_busy_pdch(struct gprs_rlcmac_trx *trx,
151 enum gprs_rlcmac_tbf_direction dir,
152 uint8_t mask,
153 int *free_usf = 0)
154{
155 unsigned ts;
156 int min_used = INT_MAX;
157 int min_ts = -1;
158 int min_usf = -1;
159
160 for (ts = 0; ts < ARRAY_SIZE(trx->pdch); ts++) {
161 struct gprs_rlcmac_pdch *pdch = &trx->pdch[ts];
162 int num_tbfs;
163 int usf = -1; /* must be signed */
164
165 if (((1 << ts) & mask) == 0)
166 continue;
167
168 num_tbfs = pdch->num_tbfs(dir);
169 if (num_tbfs < min_used) {
170 /* We have found a candidate */
171 /* Make sure that an USF is available */
172 if (dir == GPRS_RLCMAC_UL_TBF) {
173 usf = find_free_usf(pdch);
174 if (usf < 0) {
175 LOGP(DRLCMAC, LOGL_DEBUG,
176 "- Skipping TS %d, because "
177 "no USF available\n", ts);
178 continue;
179 }
180 }
181 if (min_ts >= 0)
182 LOGP(DRLCMAC, LOGL_DEBUG,
183 "- Skipping TS %d, because "
184 "num TBFs %d > %d\n",
185 min_ts, min_used, num_tbfs);
186 min_used = num_tbfs;
187 min_ts = ts;
188 min_usf = usf;
189 } else {
190 LOGP(DRLCMAC, LOGL_DEBUG,
191 "- Skipping TS %d, because "
192 "num TBFs %d >= %d\n",
193 ts, num_tbfs, min_used);
194 }
195 }
196
197 if (min_ts < 0)
198 return -1;
199
200 if (free_usf)
201 *free_usf = min_usf;
202
203 return min_ts;
Holger Hans Peter Freytherb0a00752013-09-29 08:18:17 +0200204}
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200205
Jacob Erlbeckccc34e42015-06-29 13:45:05 +0200206static void attach_tbf_to_pdch(struct gprs_rlcmac_pdch *pdch,
207 struct gprs_rlcmac_tbf *tbf)
208{
209 if (tbf->pdch[pdch->ts_no])
210 tbf->pdch[pdch->ts_no]->detach_tbf(tbf);
211
212 tbf->pdch[pdch->ts_no] = pdch;
213 pdch->attach_tbf(tbf);
214}
215
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200216static void assign_uplink_tbf_usf(
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200217 struct gprs_rlcmac_pdch *pdch,
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200218 struct gprs_rlcmac_ul_tbf *tbf, int8_t usf)
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200219{
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100220 tbf->trx->ul_tbf[tbf->tfi()] = tbf;
Daniel Willmann7e994e32014-08-07 15:49:21 +0200221 tbf->m_usf[pdch->ts_no] = usf;
Jacob Erlbeckccc34e42015-06-29 13:45:05 +0200222 attach_tbf_to_pdch(pdch, tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200223}
224
Holger Hans Peter Freyther8481a052013-09-29 08:08:28 +0200225static void assign_dlink_tbf(
226 struct gprs_rlcmac_pdch *pdch,
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200227 struct gprs_rlcmac_dl_tbf *tbf)
Holger Hans Peter Freyther8481a052013-09-29 08:08:28 +0200228{
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100229 tbf->trx->dl_tbf[tbf->tfi()] = tbf;
Jacob Erlbeckccc34e42015-06-29 13:45:05 +0200230 attach_tbf_to_pdch(pdch, tbf);
Holger Hans Peter Freyther8481a052013-09-29 08:08:28 +0200231}
232
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200233
234/* Slot Allocation: Algorithm A
235 *
236 * Assign single slot for uplink and downlink
237 */
238int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200239 GprsMs *ms,
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200240 struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single)
241{
242 struct gprs_rlcmac_pdch *pdch;
Jacob Erlbeckec478752015-06-19 16:35:38 +0200243 int ts = -1;
244 int usf = -1;
245 int mask = 0xff;
246 const char *mask_reason = NULL;
247 struct gprs_rlcmac_tbf *ref_tbf;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200248
249 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm A) for class "
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200250 "%d\n", tbf->ms_class());
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200251
Jacob Erlbeckec478752015-06-19 16:35:38 +0200252 if ((ref_tbf = ms->tbf(tbf->direction)))
253 mask_reason = "need to reuse TS";
254 else if ((ref_tbf = ms->tbf(reverse(tbf->direction))))
255 mask_reason = ref_tbf->direction == GPRS_RLCMAC_UL_TBF ?
256 "not an uplink TBF" : "not a downlink TBF";
257
258 if (ref_tbf)
259 ts = ref_tbf->first_common_ts;
260
261 if (ts >= 0)
262 mask = 1 << ts;
263
Jacob Erlbeck83426b22015-06-30 09:44:05 +0200264 mask = find_possible_pdchs(tbf->trx, 1, mask, mask_reason);
Jacob Erlbeckec478752015-06-19 16:35:38 +0200265 if (!mask)
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200266 return -EINVAL;
267
Jacob Erlbeckec478752015-06-19 16:35:38 +0200268 ts = find_least_busy_pdch(tbf->trx, tbf->direction, mask, &usf);
269
270 if (ts < 0) {
271 LOGP(DRLCMAC, LOGL_NOTICE, "- Failed "
272 "to allocate a TS, no USF available\n");
273 return -EBUSY;
274 }
275
Holger Hans Peter Freytherb0a00752013-09-29 08:18:17 +0200276 pdch = &tbf->trx->pdch[ts];
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200277 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200278 struct gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
Holger Hans Peter Freyther948a3d62013-09-30 14:10:23 +0200279
Jacob Erlbeckec478752015-06-19 16:35:38 +0200280 if (usf < 0)
281 usf = find_free_usf(pdch);
282
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200283 if (usf < 0) {
284 LOGP(DRLCMAC, LOGL_NOTICE, "- Failed "
285 "allocating TS=%d, no USF available\n", ts);
286 return -EBUSY;
287 }
Jacob Erlbeckec478752015-06-19 16:35:38 +0200288
289 LOGP(DRLCMAC, LOGL_DEBUG, "- Assign uplink TS=%d USF=%d\n",
290 ts, usf);
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200291 assign_uplink_tbf_usf(pdch, ul_tbf, usf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200292 } else {
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200293 struct gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200294 LOGP(DRLCMAC, LOGL_DEBUG, "- Assign downlink TS=%d\n", ts);
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200295 assign_dlink_tbf(pdch, dl_tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200296 }
297 /* the only one TS is the common TS */
298 tbf->first_ts = tbf->first_common_ts = ts;
299
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200300 tbf->upgrade_to_multislot = 0;
301
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200302 return 0;
303}
304
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100305/*
306 * Select a window of Rx slots if available.
307 * The maximum allowed slots depend on RX or the window of available
308 * slots. This must be done for uplink TBF also, because it is the basis
309 * for calculating control slot and uplink slot(s).
310 */
311static uint8_t select_dl_slots(struct gprs_rlcmac_trx *trx,
312 const int ms_type, const int ms_max_rxslots,
313 uint8_t *out_rx_win_min, uint8_t *out_rx_win_max)
314
315{
316 uint8_t rx_window = 0;
317 int rx_window_size = 0;
318 int8_t last_tsc = -1; /* must be signed */
319 uint8_t rx_win_min = 0, rx_win_max = 0;
320
321 for (int ts_no = 0; ts_no < 8; ts_no++) {
322 struct gprs_rlcmac_pdch *pdch;
323 pdch = &trx->pdch[ts_no];
324
325 /* check if enabled */
326 if (!pdch->is_enabled()) {
327 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
328 "not enabled\n", ts_no);
329 if (ms_type == 1 && rx_window)
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100330 goto inc_window;
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100331 continue;
332 }
333 /* check if TSC changes */
334 if (last_tsc < 0)
335 last_tsc = pdch->tsc;
336 else if (last_tsc != pdch->tsc) {
337 LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS %d of TRX=%d, "
338 "because it has different TSC than lower TS "
339 "of TRX. In order to allow multislot, all "
340 "slots must be configured with the same "
341 "TSC!\n", ts_no, trx->trx_no);
342 if (ms_type == 1 && rx_window)
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100343 goto inc_window;
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100344 continue;
345 }
346
347 if (!rx_window)
348 rx_win_min = ts_no;
349
350 rx_window |= (1 << ts_no);
351 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected DL TS %d\n", ts_no);
352
353 /* range of window (required for Type 1) */
354 rx_win_max = ts_no;
355
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100356inc_window:
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100357 if (++rx_window_size == ms_max_rxslots) {
358 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because slots / "
359 "window reached maximum alowed Rx size\n");
360 break;
361 }
Andreas Eversbergccde4c42014-01-04 15:17:22 +0100362 if (ms_type == 1 && rx_window_size == 5) {
363 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because slots / "
364 "window reached maximum supported Rx size of "
365 "this algorithm\n");
366 break;
367 }
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100368 }
369
370 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected slots for RX: "
371 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
372 ((rx_window & 0x01)) ? 'D' : '.',
373 ((rx_window & 0x02)) ? 'D' : '.',
374 ((rx_window & 0x04)) ? 'D' : '.',
375 ((rx_window & 0x08)) ? 'D' : '.',
376 ((rx_window & 0x10)) ? 'D' : '.',
377 ((rx_window & 0x20)) ? 'D' : '.',
378 ((rx_window & 0x40)) ? 'D' : '.',
379 ((rx_window & 0x80)) ? 'D' : '.');
380
381 *out_rx_win_min = rx_win_min;
382 *out_rx_win_max = rx_win_max;
383 return rx_window;
384}
385
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200386static int reduce_rx_window(const int ms_type, const GprsMs *ms,
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100387 const int Tt, const int Tr,
388 int *rx_window,
389 uint8_t *rx_win_min, uint8_t *rx_win_max)
390{
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200391 gprs_rlcmac_ul_tbf *ul_tbf;
392
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100393 if (ms_type != 1)
394 return 0;
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200395 if (!ms)
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100396 return 0;
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200397
398 ul_tbf = ms->ul_tbf();
399
400 if (!ul_tbf)
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100401 return 0;
402
403 uint8_t collide = 0, ul_usage = 0;
404
405 /* calculate mask of colliding slots */
406 for (uint8_t ts_no = 0; ts_no < 8; ts_no++) {
407 int j;
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200408 if (!ul_tbf->pdch[ts_no])
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100409 continue;
410
411 ul_usage |= (1 << ts_no);
412 /* mark bits from TS-t .. TS+r */
Andreas Eversberg91670552014-05-29 11:08:58 +0200413 for (j = (ts_no - Tt) & 7; j != ((ts_no + Tr + 1) & 7); j = (j + 1) & 7)
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100414 collide |= (1 << j);
415 }
416
417 LOGP(DRLCMAC, LOGL_DEBUG, "- Not allowed slots due to existing "
418 "UL allocation: (TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7) "
419 " D=downlink x=not usable\n",
420 ((ul_usage & 0x01)) ? 'D' : ((collide & 0x01))?'x':'.',
421 ((ul_usage & 0x02)) ? 'D' : ((collide & 0x02))?'x':'.',
422 ((ul_usage & 0x04)) ? 'D' : ((collide & 0x04))?'x':'.',
423 ((ul_usage & 0x08)) ? 'D' : ((collide & 0x08))?'x':'.',
424 ((ul_usage & 0x10)) ? 'D' : ((collide & 0x10))?'x':'.',
425 ((ul_usage & 0x20)) ? 'D' : ((collide & 0x20))?'x':'.',
426 ((ul_usage & 0x40)) ? 'D' : ((collide & 0x40))?'x':'.',
427 ((ul_usage & 0x80)) ? 'D' : ((collide & 0x80))?'x':'.');
428
429 /*
430 * Uplink/Downlink in GSM is shifted by three timeslots. Make
431 * sure they don't collide.
432 */
433 *rx_window &= ~(collide << 3);
434 *rx_window &= ~(collide >> 5);
435 LOGP(DRLCMAC, LOGL_DEBUG, "- Remaining slots for RX: "
436 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
437 ((*rx_window & 0x01)) ? 'D' : '.',
438 ((*rx_window & 0x02)) ? 'D' : '.',
439 ((*rx_window & 0x04)) ? 'D' : '.',
440 ((*rx_window & 0x08)) ? 'D' : '.',
441 ((*rx_window & 0x10)) ? 'D' : '.',
442 ((*rx_window & 0x20)) ? 'D' : '.',
443 ((*rx_window & 0x40)) ? 'D' : '.',
444 ((*rx_window & 0x80)) ? 'D' : '.');
445
446 if (!*rx_window) {
447 LOGP(DRLCMAC, LOGL_NOTICE, "No suitable downlink slots "
448 "available with current uplink assignment\n");
449 return -EBUSY;
450 }
451
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100452 return 0;
453}
454
455/* shrink range of rx_win_min and rx_win_max */
456static void shrink_rx_window(uint8_t *rx_win_min, uint8_t *rx_win_max, int rx_window)
457{
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100458 /* calculate new min/max */
459 for (uint8_t ts_no = *rx_win_min; ts_no <= *rx_win_max; ts_no++) {
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100460 if ((rx_window & (1 << ts_no)))
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100461 break;
462 *rx_win_min = ts_no + 1;
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100463 LOGP(DRLCMAC, LOGL_DEBUG, "- TS is unused, so "
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100464 "raising start of DL window to %d\n",
465 *rx_win_min);
466 }
467 for (uint8_t ts_no = *rx_win_max; ts_no >= *rx_win_min; ts_no--) {
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100468 if ((rx_window & (1 << ts_no)))
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100469 break;
470 *rx_win_max = ts_no - 1;
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100471 LOGP(DRLCMAC, LOGL_DEBUG, "- TS is unused, so "
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100472 "lowering end of DL window to %d\n",
473 *rx_win_max);
474 }
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100475}
476
Holger Hans Peter Freytherdd4af802013-12-25 21:03:42 +0100477/*
478 * reduce window, to allow at least one uplink TX slot
479 * this is only required for Type 1
480 */
481static uint8_t update_rx_win_max(const int ms_type, const int Tt,
482 const int Tr, uint8_t rx_win_min, uint8_t rx_win_max)
483{
484 if (ms_type != 1)
485 return rx_win_max;
486
487 if (rx_win_max - rx_win_min + 1 + Tt + 1 + Tr > 8) {
488 rx_win_max = rx_win_min + 7 - Tt - 1 - Tr;
489 LOGP(DRLCMAC, LOGL_DEBUG, "- Reduce RX window due to time "
490 "contraints to %d slots\n", rx_win_max - rx_win_min + 1);
491 }
492
493 return rx_win_max;
494}
495
Holger Hans Peter Freyther3fd2ddf2013-12-25 21:11:20 +0100496static void tx_win_from_rx(const int ms_type,
497 uint8_t rx_win_min, uint8_t rx_win_max,
498 int Tt, int Tr,
499 uint8_t *tx_win_min, uint8_t *tx_win_max,
500 uint8_t *tx_range)
501{
502 if (ms_type == 1) {
503 /* calculate TX window (shifted by 3 timeslots)
504 * it uses the space between tx_win_max and tx_win_min */
505 *tx_win_min = (rx_win_max - 2 + Tt) & 7;
506 *tx_win_max = (rx_win_min + 4 - Tr) & 7;
507 } else {
508 /* TX and RX simultaniously */
509 *tx_win_min = rx_win_min;
510 *tx_win_max = 7;
511 }
512
513 *tx_range = (*tx_win_max - *tx_win_min + 1) & 7;
Andreas Eversberg7a16d462014-01-04 15:25:18 +0100514 /* if TX window fills complete range */
515 if (*tx_range == 0)
516 *tx_range = 8;
Holger Hans Peter Freyther3fd2ddf2013-12-25 21:11:20 +0100517 LOGP(DRLCMAC, LOGL_DEBUG, "- TX-Window is: %d..%d\n", *tx_win_min,
518 *tx_win_max);
519}
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100520
Holger Hans Peter Freyther1fe69322013-12-26 09:31:31 +0100521/*
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100522 * Select a window of Tx slots if available.
523 * The maximum allowed slots depend on TX or the window of available
524 * slots.
525 */
526static int select_ul_slots(gprs_rlcmac_trx *trx,
527 const int ms_type, const int ms_max_txslots,
528 uint8_t tx_win_min, uint8_t tx_range,
Andreas Eversberg765736d2014-01-04 15:27:31 +0100529 int8_t *usf, int8_t *first_common_ts, uint8_t rx_window)
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100530{
531 int tsc = -1;
532 uint8_t tx_window = 0;
533 int i;
534 uint8_t ts_no;
535
Andreas Eversbergfe2dcc82014-01-04 15:39:54 +0100536 for (ts_no = tx_win_min, i = 0; i < tx_range; ts_no = (ts_no + 1) & 7, i++) {
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100537 gprs_rlcmac_pdch *pdch = &trx->pdch[ts_no];
538
539 /* check if enabled */
540 if (!pdch->is_enabled()) {
541 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
542 "because not enabled\n", ts_no);
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100543 if (ms_type == 1 && tx_window)
544 goto inc_window;
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100545 continue;
546 }
Andreas Eversberg765736d2014-01-04 15:27:31 +0100547 /* check if used as downlink */
548 if (!(rx_window & (1 << ts_no))) {
549 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
550 "because not a downlink slot\n", ts_no);
551 if (ms_type == 1 && tx_window)
552 goto inc_window;
553 continue;
554 }
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100555 /* check if TSC changes */
556 if (tsc < 0)
557 tsc = pdch->tsc;
558 else if (tsc != pdch->tsc) {
559 LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS %d of "
560 "TRX=%d, because it has different TSC "
561 "than lower TS of TRX. In order to "
562 "allow multislot, all slots must be "
563 "configured with the same TSC!\n",
564 ts_no, trx->trx_no);
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100565 if (ms_type == 1)
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100566 goto inc_window;
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100567 continue;
568 }
569 /* check for free usf */
570 usf[ts_no] = find_free_usf(pdch);
571 if (usf[ts_no] < 0) {
572 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
573 "because no USF available\n", ts_no);
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100574 if (ms_type == 1)
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100575 goto inc_window;
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100576 continue;
577 }
578
579 if (!tx_window)
580 *first_common_ts = ts_no;
581
582 tx_window |= (1 << ts_no);
583 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected UL TS %d\n", ts_no);
584
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100585inc_window:
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100586 if (1 && ms_type == 1) { /* FIXME: multislot UL assignment */
587 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
588 "1 slot assigned\n");
589 break;
590 }
Andreas Eversberg0a940082014-01-15 13:53:43 +0100591 if (i+1 == ms_max_txslots) {
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100592 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
593 "slots / window reached maximum "
594 "allowed Tx size\n");
595 break;
596 }
597 }
598
599 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected TX window: "
600 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
601 ((tx_window & 0x01)) ? 'U' : '.',
602 ((tx_window & 0x02)) ? 'U' : '.',
603 ((tx_window & 0x04)) ? 'U' : '.',
604 ((tx_window & 0x08)) ? 'U' : '.',
605 ((tx_window & 0x10)) ? 'U' : '.',
606 ((tx_window & 0x20)) ? 'U' : '.',
607 ((tx_window & 0x40)) ? 'U' : '.',
608 ((tx_window & 0x80)) ? 'U' : '.');
609
610 if (!tx_window) {
611 LOGP(DRLCMAC, LOGL_NOTICE, "No suitable uplink slots "
612 "available\n");
613 return -EBUSY;
614 }
615
616 return tx_window;
617}
618
619/*
Holger Hans Peter Freyther1fe69322013-12-26 09:31:31 +0100620 * Assign the first common ts, which is used for control or
621 * single slot.
622 */
Andreas Eversberg765736d2014-01-04 15:27:31 +0100623static int select_first_ts(gprs_rlcmac_trx *trx, uint8_t tx_win_min,
624 uint8_t tx_range, uint8_t rx_window)
Holger Hans Peter Freyther1fe69322013-12-26 09:31:31 +0100625{
626 uint8_t ts_no;
627 int i;
Andreas Eversbergfe2dcc82014-01-04 15:39:54 +0100628 for (ts_no = tx_win_min, i = 0; i < tx_range; ts_no = (ts_no + 1) & 7, i++) {
Holger Hans Peter Freyther1fe69322013-12-26 09:31:31 +0100629 gprs_rlcmac_pdch *pdch = &trx->pdch[ts_no];
630 /* check if enabled */
631 if (!pdch->is_enabled()) {
632 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
633 "because not enabled\n", ts_no);
634 continue;
635 }
Andreas Eversberg765736d2014-01-04 15:27:31 +0100636 /* check if used as downlink */
637 if (!(rx_window & (1 << ts_no))) {
638 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
639 "because not a downlink slot\n", ts_no);
640 continue;
641 }
Holger Hans Peter Freyther1fe69322013-12-26 09:31:31 +0100642 return ts_no;
643 }
644
645 return -1;
646}
647
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200648/* Slot Allocation: Algorithm B
649 *
650 * Assign as many downlink slots as possible.
651 * Assign one uplink slot. (With free USF)
652 *
653 */
654int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200655 GprsMs *ms,
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200656 struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single)
657{
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200658 const struct gprs_ms_multislot_class *ms_class;
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100659 uint8_t Tx, Sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200660 uint8_t Tta, Ttb, Tra, Trb, Tt, Tr; /* Minimum Number of Slots */
661 uint8_t Type; /* Type of Mobile */
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100662 int rx_window;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200663 static const char *digit[10] = { "0","1","2","3","4","5","6","7","8","9" };
664 int8_t usf[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; /* must be signed */
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200665 int8_t first_common_ts = -1;
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100666 uint8_t ts;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200667 uint8_t slotcount = 0;
668
669
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200670 if (tbf->ms_class() >= 32) {
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200671 LOGP(DRLCMAC, LOGL_ERROR, "Multislot class %d out of range.\n",
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200672 tbf->ms_class());
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200673 return -EINVAL;
674 }
675
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200676 if (tbf->ms_class()) {
677 ms_class = &gprs_ms_multislot_class[tbf->ms_class()];
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200678 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm B) for "
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200679 "class %d\n", tbf->ms_class());
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200680 } else {
681 ms_class = &gprs_ms_multislot_class[12];
682 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm B) for "
683 "unknow class (assuming 12)\n");
684 }
685
686 if (ms_class->tx == MS_NA) {
687 LOGP(DRLCMAC, LOGL_NOTICE, "Multislot class %d not "
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200688 "applicable.\n", tbf->ms_class());
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200689 return -EINVAL;
690 }
691
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200692 Tx = ms_class->tx;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200693 Sum = ms_class->sum;
694 Tta = ms_class->ta;
695 Ttb = ms_class->tb;
696 Tra = ms_class->ra;
697 Trb = ms_class->rb;
698 Type = ms_class->type;
699
700 /* Tta and Ttb may depend on hopping or frequency change */
Holger Hans Peter Freytherf34f3442013-12-25 20:33:37 +0100701 if (Ttb == MS_A || Ttb == MS_B)
Holger Hans Peter Freyther11a74892013-09-29 08:13:42 +0200702 Ttb = 0;
Holger Hans Peter Freytherf34f3442013-12-25 20:33:37 +0100703 if (Trb == MS_A || Trb == MS_C)
Holger Hans Peter Freyther11a74892013-09-29 08:13:42 +0200704 Trb = 0;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200705
706 LOGP(DRLCMAC, LOGL_DEBUG, "- Rx=%d Tx=%d Sum Rx+Tx=%s Tta=%s Ttb=%d "
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100707 " Tra=%d Trb=%d Type=%d\n", ms_class->rx, Tx,
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200708 (Sum == MS_NA) ? "N/A" : digit[Sum],
709 (Tta == MS_NA) ? "N/A" : digit[Tta], Ttb, Tra, Trb, Type);
710
711 /* select the values for time contraints */
Holger Hans Peter Freyther11a74892013-09-29 08:13:42 +0200712 /* applicable to type 1 and type 2 */
713 Tt = Ttb;
714 Tr = Trb;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200715
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100716 uint8_t rx_win_min, rx_win_max;
717 rx_window = select_dl_slots(tbf->trx, ms_class->type, ms_class->rx,
718 &rx_win_min, &rx_win_max);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200719
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200720
721 /* reduce window, if existing uplink slots collide RX window */
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200722 int rc = reduce_rx_window(ms_class->type, ms, Tt, Tr,
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100723 &rx_window, &rx_win_min, &rx_win_max);
724 if (rc < 0)
725 return rc;
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100726 shrink_rx_window(&rx_win_min, &rx_win_max, rx_window);
Holger Hans Peter Freytherdd4af802013-12-25 21:03:42 +0100727 rx_win_max = update_rx_win_max(ms_class->type, Tt, Tr,
728 rx_win_min, rx_win_max);
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100729 shrink_rx_window(&rx_win_min, &rx_win_max, rx_window);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200730 LOGP(DRLCMAC, LOGL_DEBUG, "- RX-Window is: %d..%d\n", rx_win_min,
731 rx_win_max);
732
733 /* calculate TX window */
Holger Hans Peter Freyther3fd2ddf2013-12-25 21:11:20 +0100734 uint8_t tx_win_min, tx_win_max, tx_range;
735 tx_win_from_rx(ms_class->type, rx_win_min, rx_win_max, Tt, Tr,
736 &tx_win_min, &tx_win_max, &tx_range);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200737
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100738 /* select UL slots but in both cases assign first_common_ts */
739 uint8_t tx_window = 0;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200740 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100741 rc = select_ul_slots(tbf->trx, ms_class->type, ms_class->tx,
Andreas Eversberg765736d2014-01-04 15:27:31 +0100742 tx_win_min, tx_range, usf,
743 &first_common_ts, rx_window);
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100744 if (rc < 0)
745 return rc;
746 tx_window = rc;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200747 } else {
Andreas Eversberg765736d2014-01-04 15:27:31 +0100748 first_common_ts = select_first_ts(tbf->trx, tx_win_min,
749 tx_range, rx_window);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200750 }
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100751 #warning "first_common_ts might be different if there was no free USF for the new uplink assignment"
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200752
753 if (first_common_ts < 0) {
754 LOGP(DRLCMAC, LOGL_NOTICE, "No first common slots available\n");
755 return -EINVAL;
756 }
757
758 if (tbf->direction == GPRS_RLCMAC_DL_TBF) {
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200759 struct gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200760 /* assign downlink */
761 if (rx_window == 0) {
762 LOGP(DRLCMAC, LOGL_NOTICE, "No downlink slots "
763 "available\n");
764 return -EINVAL;
765 }
766 for (ts = 0; ts < 8; ts++) {
767 if ((rx_window & (1 << ts))) {
768 /* be sure to select a single downlink slots
769 * that can be used for uplink, if multiple
770 * slots are assigned later. */
771 if (single && first_common_ts != ts)
772 continue;
773 LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning DL TS "
774 "%d\n", ts);
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200775 assign_dlink_tbf(&tbf->trx->pdch[ts], dl_tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200776 slotcount++;
777 if (slotcount == 1)
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200778 dl_tbf->first_ts = ts;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200779 if (single)
780 break;
781 }
782 }
783 } else {
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200784 struct gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200785 for (ts = 0; ts < 8; ts++) {
786 if ((tx_window & (1 << ts))) {
787 LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning UL TS "
788 "%d\n", ts);
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200789 assign_uplink_tbf_usf(&tbf->trx->pdch[ts], ul_tbf, usf[ts]);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200790 slotcount++;
791 if (slotcount == 1)
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200792 ul_tbf->first_ts = ts;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200793 if (single)
794 break;
795 }
796 }
797 }
798 if (single && slotcount) {
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200799 uint8_t ts_count = 0;
800 for (ts = 0; ts < 8; ts++)
801 if ((tx_window & (1 << ts)))
802 ts_count++;
803
804 tbf->upgrade_to_multislot = (ts_count > 1);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200805 LOGP(DRLCMAC, LOGL_INFO, "Using single slot at TS %d for %s\n",
806 tbf->first_ts,
807 (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL");
808 } else {
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200809 tbf->upgrade_to_multislot = 0;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200810 LOGP(DRLCMAC, LOGL_INFO, "Using %d slots for %s\n", slotcount,
811 (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL");
812 }
813 if (slotcount == 0)
814 return -EBUSY;
815
816 tbf->first_common_ts = first_common_ts;
817
818 return 0;
819}