blob: 8d4357e7996322d54bbb03b8d70ca74ead1c13cb [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;
Jacob Erlbeck5cd496d2015-06-30 10:24:37 +0200244 uint8_t ul_slots, dl_slots;
Jacob Erlbeckec478752015-06-19 16:35:38 +0200245 int usf = -1;
246 int mask = 0xff;
247 const char *mask_reason = NULL;
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 Erlbeck5cd496d2015-06-30 10:24:37 +0200252 dl_slots = ms->reserved_dl_slots();
253 ul_slots = ms->reserved_ul_slots();
254
255 ts = ms->first_common_ts();
256
257 if (ts >= 0) {
Jacob Erlbeckec478752015-06-19 16:35:38 +0200258 mask_reason = "need to reuse TS";
Jacob Erlbeckec478752015-06-19 16:35:38 +0200259 mask = 1 << ts;
Jacob Erlbeck5cd496d2015-06-30 10:24:37 +0200260 } else if (dl_slots || ul_slots) {
261 mask_reason = "need to use a reserved common TS";
262 mask = dl_slots & ul_slots;
263 }
Jacob Erlbeckec478752015-06-19 16:35:38 +0200264
Jacob Erlbeck83426b22015-06-30 09:44:05 +0200265 mask = find_possible_pdchs(tbf->trx, 1, mask, mask_reason);
Jacob Erlbeckec478752015-06-19 16:35:38 +0200266 if (!mask)
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200267 return -EINVAL;
268
Jacob Erlbeckec478752015-06-19 16:35:38 +0200269 ts = find_least_busy_pdch(tbf->trx, tbf->direction, mask, &usf);
270
271 if (ts < 0) {
272 LOGP(DRLCMAC, LOGL_NOTICE, "- Failed "
273 "to allocate a TS, no USF available\n");
274 return -EBUSY;
275 }
276
Holger Hans Peter Freytherb0a00752013-09-29 08:18:17 +0200277 pdch = &tbf->trx->pdch[ts];
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200278 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200279 struct gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
Holger Hans Peter Freyther948a3d62013-09-30 14:10:23 +0200280
Jacob Erlbeckec478752015-06-19 16:35:38 +0200281 if (usf < 0)
282 usf = find_free_usf(pdch);
283
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200284 if (usf < 0) {
285 LOGP(DRLCMAC, LOGL_NOTICE, "- Failed "
286 "allocating TS=%d, no USF available\n", ts);
287 return -EBUSY;
288 }
Jacob Erlbeckec478752015-06-19 16:35:38 +0200289
290 LOGP(DRLCMAC, LOGL_DEBUG, "- Assign uplink TS=%d USF=%d\n",
291 ts, usf);
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200292 assign_uplink_tbf_usf(pdch, ul_tbf, usf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200293 } else {
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200294 struct gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200295 LOGP(DRLCMAC, LOGL_DEBUG, "- Assign downlink TS=%d\n", ts);
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200296 assign_dlink_tbf(pdch, dl_tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200297 }
298 /* the only one TS is the common TS */
299 tbf->first_ts = tbf->first_common_ts = ts;
Jacob Erlbeck5cd496d2015-06-30 10:24:37 +0200300 ms->set_reserved_slots(tbf->trx, 1 << ts, 1 << ts);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200301
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200302 tbf->upgrade_to_multislot = 0;
303
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200304 return 0;
305}
306
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100307/*
308 * Select a window of Rx slots if available.
309 * The maximum allowed slots depend on RX or the window of available
310 * slots. This must be done for uplink TBF also, because it is the basis
311 * for calculating control slot and uplink slot(s).
312 */
313static uint8_t select_dl_slots(struct gprs_rlcmac_trx *trx,
314 const int ms_type, const int ms_max_rxslots,
315 uint8_t *out_rx_win_min, uint8_t *out_rx_win_max)
316
317{
318 uint8_t rx_window = 0;
319 int rx_window_size = 0;
320 int8_t last_tsc = -1; /* must be signed */
321 uint8_t rx_win_min = 0, rx_win_max = 0;
322
323 for (int ts_no = 0; ts_no < 8; ts_no++) {
324 struct gprs_rlcmac_pdch *pdch;
325 pdch = &trx->pdch[ts_no];
326
327 /* check if enabled */
328 if (!pdch->is_enabled()) {
329 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
330 "not enabled\n", ts_no);
331 if (ms_type == 1 && rx_window)
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100332 goto inc_window;
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100333 continue;
334 }
335 /* check if TSC changes */
336 if (last_tsc < 0)
337 last_tsc = pdch->tsc;
338 else if (last_tsc != pdch->tsc) {
339 LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS %d of TRX=%d, "
340 "because it has different TSC than lower TS "
341 "of TRX. In order to allow multislot, all "
342 "slots must be configured with the same "
343 "TSC!\n", ts_no, trx->trx_no);
344 if (ms_type == 1 && rx_window)
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100345 goto inc_window;
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100346 continue;
347 }
348
349 if (!rx_window)
350 rx_win_min = ts_no;
351
352 rx_window |= (1 << ts_no);
353 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected DL TS %d\n", ts_no);
354
355 /* range of window (required for Type 1) */
356 rx_win_max = ts_no;
357
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100358inc_window:
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100359 if (++rx_window_size == ms_max_rxslots) {
360 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because slots / "
361 "window reached maximum alowed Rx size\n");
362 break;
363 }
Andreas Eversbergccde4c42014-01-04 15:17:22 +0100364 if (ms_type == 1 && rx_window_size == 5) {
365 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because slots / "
366 "window reached maximum supported Rx size of "
367 "this algorithm\n");
368 break;
369 }
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100370 }
371
372 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected slots for RX: "
373 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
374 ((rx_window & 0x01)) ? 'D' : '.',
375 ((rx_window & 0x02)) ? 'D' : '.',
376 ((rx_window & 0x04)) ? 'D' : '.',
377 ((rx_window & 0x08)) ? 'D' : '.',
378 ((rx_window & 0x10)) ? 'D' : '.',
379 ((rx_window & 0x20)) ? 'D' : '.',
380 ((rx_window & 0x40)) ? 'D' : '.',
381 ((rx_window & 0x80)) ? 'D' : '.');
382
383 *out_rx_win_min = rx_win_min;
384 *out_rx_win_max = rx_win_max;
385 return rx_window;
386}
387
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200388static int reduce_rx_window(const int ms_type, const GprsMs *ms,
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100389 const int Tt, const int Tr,
390 int *rx_window,
391 uint8_t *rx_win_min, uint8_t *rx_win_max)
392{
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200393 gprs_rlcmac_ul_tbf *ul_tbf;
394
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100395 if (ms_type != 1)
396 return 0;
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200397 if (!ms)
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100398 return 0;
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200399
400 ul_tbf = ms->ul_tbf();
401
402 if (!ul_tbf)
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100403 return 0;
404
405 uint8_t collide = 0, ul_usage = 0;
406
407 /* calculate mask of colliding slots */
408 for (uint8_t ts_no = 0; ts_no < 8; ts_no++) {
409 int j;
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200410 if (!ul_tbf->pdch[ts_no])
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100411 continue;
412
413 ul_usage |= (1 << ts_no);
414 /* mark bits from TS-t .. TS+r */
Andreas Eversberg91670552014-05-29 11:08:58 +0200415 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 +0100416 collide |= (1 << j);
417 }
418
419 LOGP(DRLCMAC, LOGL_DEBUG, "- Not allowed slots due to existing "
420 "UL allocation: (TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7) "
421 " D=downlink x=not usable\n",
422 ((ul_usage & 0x01)) ? 'D' : ((collide & 0x01))?'x':'.',
423 ((ul_usage & 0x02)) ? 'D' : ((collide & 0x02))?'x':'.',
424 ((ul_usage & 0x04)) ? 'D' : ((collide & 0x04))?'x':'.',
425 ((ul_usage & 0x08)) ? 'D' : ((collide & 0x08))?'x':'.',
426 ((ul_usage & 0x10)) ? 'D' : ((collide & 0x10))?'x':'.',
427 ((ul_usage & 0x20)) ? 'D' : ((collide & 0x20))?'x':'.',
428 ((ul_usage & 0x40)) ? 'D' : ((collide & 0x40))?'x':'.',
429 ((ul_usage & 0x80)) ? 'D' : ((collide & 0x80))?'x':'.');
430
431 /*
432 * Uplink/Downlink in GSM is shifted by three timeslots. Make
433 * sure they don't collide.
434 */
435 *rx_window &= ~(collide << 3);
436 *rx_window &= ~(collide >> 5);
437 LOGP(DRLCMAC, LOGL_DEBUG, "- Remaining slots for RX: "
438 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
439 ((*rx_window & 0x01)) ? 'D' : '.',
440 ((*rx_window & 0x02)) ? 'D' : '.',
441 ((*rx_window & 0x04)) ? 'D' : '.',
442 ((*rx_window & 0x08)) ? 'D' : '.',
443 ((*rx_window & 0x10)) ? 'D' : '.',
444 ((*rx_window & 0x20)) ? 'D' : '.',
445 ((*rx_window & 0x40)) ? 'D' : '.',
446 ((*rx_window & 0x80)) ? 'D' : '.');
447
448 if (!*rx_window) {
449 LOGP(DRLCMAC, LOGL_NOTICE, "No suitable downlink slots "
450 "available with current uplink assignment\n");
451 return -EBUSY;
452 }
453
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100454 return 0;
455}
456
457/* shrink range of rx_win_min and rx_win_max */
458static void shrink_rx_window(uint8_t *rx_win_min, uint8_t *rx_win_max, int rx_window)
459{
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100460 /* calculate new min/max */
461 for (uint8_t ts_no = *rx_win_min; ts_no <= *rx_win_max; ts_no++) {
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100462 if ((rx_window & (1 << ts_no)))
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100463 break;
464 *rx_win_min = ts_no + 1;
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100465 LOGP(DRLCMAC, LOGL_DEBUG, "- TS is unused, so "
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100466 "raising start of DL window to %d\n",
467 *rx_win_min);
468 }
469 for (uint8_t ts_no = *rx_win_max; ts_no >= *rx_win_min; ts_no--) {
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100470 if ((rx_window & (1 << ts_no)))
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100471 break;
472 *rx_win_max = ts_no - 1;
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100473 LOGP(DRLCMAC, LOGL_DEBUG, "- TS is unused, so "
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100474 "lowering end of DL window to %d\n",
475 *rx_win_max);
476 }
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100477}
478
Holger Hans Peter Freytherdd4af802013-12-25 21:03:42 +0100479/*
480 * reduce window, to allow at least one uplink TX slot
481 * this is only required for Type 1
482 */
483static uint8_t update_rx_win_max(const int ms_type, const int Tt,
484 const int Tr, uint8_t rx_win_min, uint8_t rx_win_max)
485{
486 if (ms_type != 1)
487 return rx_win_max;
488
489 if (rx_win_max - rx_win_min + 1 + Tt + 1 + Tr > 8) {
490 rx_win_max = rx_win_min + 7 - Tt - 1 - Tr;
491 LOGP(DRLCMAC, LOGL_DEBUG, "- Reduce RX window due to time "
492 "contraints to %d slots\n", rx_win_max - rx_win_min + 1);
493 }
494
495 return rx_win_max;
496}
497
Holger Hans Peter Freyther3fd2ddf2013-12-25 21:11:20 +0100498static void tx_win_from_rx(const int ms_type,
499 uint8_t rx_win_min, uint8_t rx_win_max,
500 int Tt, int Tr,
501 uint8_t *tx_win_min, uint8_t *tx_win_max,
502 uint8_t *tx_range)
503{
504 if (ms_type == 1) {
505 /* calculate TX window (shifted by 3 timeslots)
506 * it uses the space between tx_win_max and tx_win_min */
507 *tx_win_min = (rx_win_max - 2 + Tt) & 7;
508 *tx_win_max = (rx_win_min + 4 - Tr) & 7;
509 } else {
510 /* TX and RX simultaniously */
511 *tx_win_min = rx_win_min;
512 *tx_win_max = 7;
513 }
514
515 *tx_range = (*tx_win_max - *tx_win_min + 1) & 7;
Andreas Eversberg7a16d462014-01-04 15:25:18 +0100516 /* if TX window fills complete range */
517 if (*tx_range == 0)
518 *tx_range = 8;
Holger Hans Peter Freyther3fd2ddf2013-12-25 21:11:20 +0100519 LOGP(DRLCMAC, LOGL_DEBUG, "- TX-Window is: %d..%d\n", *tx_win_min,
520 *tx_win_max);
521}
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100522
Holger Hans Peter Freyther1fe69322013-12-26 09:31:31 +0100523/*
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100524 * Select a window of Tx slots if available.
525 * The maximum allowed slots depend on TX or the window of available
526 * slots.
527 */
528static int select_ul_slots(gprs_rlcmac_trx *trx,
529 const int ms_type, const int ms_max_txslots,
530 uint8_t tx_win_min, uint8_t tx_range,
Andreas Eversberg765736d2014-01-04 15:27:31 +0100531 int8_t *usf, int8_t *first_common_ts, uint8_t rx_window)
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100532{
533 int tsc = -1;
534 uint8_t tx_window = 0;
535 int i;
536 uint8_t ts_no;
537
Andreas Eversbergfe2dcc82014-01-04 15:39:54 +0100538 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 +0100539 gprs_rlcmac_pdch *pdch = &trx->pdch[ts_no];
540
541 /* check if enabled */
542 if (!pdch->is_enabled()) {
543 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
544 "because not enabled\n", ts_no);
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100545 if (ms_type == 1 && tx_window)
546 goto inc_window;
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100547 continue;
548 }
Andreas Eversberg765736d2014-01-04 15:27:31 +0100549 /* check if used as downlink */
550 if (!(rx_window & (1 << ts_no))) {
551 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
552 "because not a downlink slot\n", ts_no);
553 if (ms_type == 1 && tx_window)
554 goto inc_window;
555 continue;
556 }
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100557 /* check if TSC changes */
558 if (tsc < 0)
559 tsc = pdch->tsc;
560 else if (tsc != pdch->tsc) {
561 LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS %d of "
562 "TRX=%d, because it has different TSC "
563 "than lower TS of TRX. In order to "
564 "allow multislot, all slots must be "
565 "configured with the same TSC!\n",
566 ts_no, trx->trx_no);
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100567 if (ms_type == 1)
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100568 goto inc_window;
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100569 continue;
570 }
571 /* check for free usf */
572 usf[ts_no] = find_free_usf(pdch);
573 if (usf[ts_no] < 0) {
574 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
575 "because no USF available\n", ts_no);
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100576 if (ms_type == 1)
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100577 goto inc_window;
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100578 continue;
579 }
580
581 if (!tx_window)
582 *first_common_ts = ts_no;
583
584 tx_window |= (1 << ts_no);
585 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected UL TS %d\n", ts_no);
586
Andreas Eversbergb03d4272014-01-04 15:14:19 +0100587inc_window:
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100588 if (1 && ms_type == 1) { /* FIXME: multislot UL assignment */
589 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
590 "1 slot assigned\n");
591 break;
592 }
Andreas Eversberg0a940082014-01-15 13:53:43 +0100593 if (i+1 == ms_max_txslots) {
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100594 LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
595 "slots / window reached maximum "
596 "allowed Tx size\n");
597 break;
598 }
599 }
600
601 LOGP(DRLCMAC, LOGL_DEBUG, "- Selected TX window: "
602 "(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
603 ((tx_window & 0x01)) ? 'U' : '.',
604 ((tx_window & 0x02)) ? 'U' : '.',
605 ((tx_window & 0x04)) ? 'U' : '.',
606 ((tx_window & 0x08)) ? 'U' : '.',
607 ((tx_window & 0x10)) ? 'U' : '.',
608 ((tx_window & 0x20)) ? 'U' : '.',
609 ((tx_window & 0x40)) ? 'U' : '.',
610 ((tx_window & 0x80)) ? 'U' : '.');
611
612 if (!tx_window) {
613 LOGP(DRLCMAC, LOGL_NOTICE, "No suitable uplink slots "
614 "available\n");
615 return -EBUSY;
616 }
617
618 return tx_window;
619}
620
621/*
Holger Hans Peter Freyther1fe69322013-12-26 09:31:31 +0100622 * Assign the first common ts, which is used for control or
623 * single slot.
624 */
Andreas Eversberg765736d2014-01-04 15:27:31 +0100625static int select_first_ts(gprs_rlcmac_trx *trx, uint8_t tx_win_min,
626 uint8_t tx_range, uint8_t rx_window)
Holger Hans Peter Freyther1fe69322013-12-26 09:31:31 +0100627{
628 uint8_t ts_no;
629 int i;
Andreas Eversbergfe2dcc82014-01-04 15:39:54 +0100630 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 +0100631 gprs_rlcmac_pdch *pdch = &trx->pdch[ts_no];
632 /* check if enabled */
633 if (!pdch->is_enabled()) {
634 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
635 "because not enabled\n", ts_no);
636 continue;
637 }
Andreas Eversberg765736d2014-01-04 15:27:31 +0100638 /* check if used as downlink */
639 if (!(rx_window & (1 << ts_no))) {
640 LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
641 "because not a downlink slot\n", ts_no);
642 continue;
643 }
Holger Hans Peter Freyther1fe69322013-12-26 09:31:31 +0100644 return ts_no;
645 }
646
647 return -1;
648}
649
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200650/* Slot Allocation: Algorithm B
651 *
652 * Assign as many downlink slots as possible.
653 * Assign one uplink slot. (With free USF)
654 *
655 */
656int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200657 GprsMs *ms,
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200658 struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single)
659{
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200660 const struct gprs_ms_multislot_class *ms_class;
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100661 uint8_t Tx, Sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200662 uint8_t Tta, Ttb, Tra, Trb, Tt, Tr; /* Minimum Number of Slots */
663 uint8_t Type; /* Type of Mobile */
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100664 int rx_window;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200665 static const char *digit[10] = { "0","1","2","3","4","5","6","7","8","9" };
666 int8_t usf[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; /* must be signed */
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200667 int8_t first_common_ts = -1;
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100668 uint8_t ts;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200669 uint8_t slotcount = 0;
670
671
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200672 if (tbf->ms_class() >= 32) {
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200673 LOGP(DRLCMAC, LOGL_ERROR, "Multislot class %d out of range.\n",
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200674 tbf->ms_class());
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200675 return -EINVAL;
676 }
677
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200678 if (tbf->ms_class()) {
679 ms_class = &gprs_ms_multislot_class[tbf->ms_class()];
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200680 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm B) for "
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200681 "class %d\n", tbf->ms_class());
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200682 } else {
683 ms_class = &gprs_ms_multislot_class[12];
684 LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm B) for "
685 "unknow class (assuming 12)\n");
686 }
687
688 if (ms_class->tx == MS_NA) {
689 LOGP(DRLCMAC, LOGL_NOTICE, "Multislot class %d not "
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200690 "applicable.\n", tbf->ms_class());
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200691 return -EINVAL;
692 }
693
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200694 Tx = ms_class->tx;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200695 Sum = ms_class->sum;
696 Tta = ms_class->ta;
697 Ttb = ms_class->tb;
698 Tra = ms_class->ra;
699 Trb = ms_class->rb;
700 Type = ms_class->type;
701
702 /* Tta and Ttb may depend on hopping or frequency change */
Holger Hans Peter Freytherf34f3442013-12-25 20:33:37 +0100703 if (Ttb == MS_A || Ttb == MS_B)
Holger Hans Peter Freyther11a74892013-09-29 08:13:42 +0200704 Ttb = 0;
Holger Hans Peter Freytherf34f3442013-12-25 20:33:37 +0100705 if (Trb == MS_A || Trb == MS_C)
Holger Hans Peter Freyther11a74892013-09-29 08:13:42 +0200706 Trb = 0;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200707
708 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 +0100709 " Tra=%d Trb=%d Type=%d\n", ms_class->rx, Tx,
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200710 (Sum == MS_NA) ? "N/A" : digit[Sum],
711 (Tta == MS_NA) ? "N/A" : digit[Tta], Ttb, Tra, Trb, Type);
712
713 /* select the values for time contraints */
Holger Hans Peter Freyther11a74892013-09-29 08:13:42 +0200714 /* applicable to type 1 and type 2 */
715 Tt = Ttb;
716 Tr = Trb;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200717
Holger Hans Peter Freyther882fc9b2013-12-25 20:34:26 +0100718 uint8_t rx_win_min, rx_win_max;
719 rx_window = select_dl_slots(tbf->trx, ms_class->type, ms_class->rx,
720 &rx_win_min, &rx_win_max);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200721
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200722
723 /* reduce window, if existing uplink slots collide RX window */
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200724 int rc = reduce_rx_window(ms_class->type, ms, Tt, Tr,
Holger Hans Peter Freythere45c19b2013-12-25 20:53:53 +0100725 &rx_window, &rx_win_min, &rx_win_max);
726 if (rc < 0)
727 return rc;
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100728 shrink_rx_window(&rx_win_min, &rx_win_max, rx_window);
Holger Hans Peter Freytherdd4af802013-12-25 21:03:42 +0100729 rx_win_max = update_rx_win_max(ms_class->type, Tt, Tr,
730 rx_win_min, rx_win_max);
Andreas Eversberg1cd9d882014-01-04 15:42:38 +0100731 shrink_rx_window(&rx_win_min, &rx_win_max, rx_window);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200732 LOGP(DRLCMAC, LOGL_DEBUG, "- RX-Window is: %d..%d\n", rx_win_min,
733 rx_win_max);
734
735 /* calculate TX window */
Holger Hans Peter Freyther3fd2ddf2013-12-25 21:11:20 +0100736 uint8_t tx_win_min, tx_win_max, tx_range;
737 tx_win_from_rx(ms_class->type, rx_win_min, rx_win_max, Tt, Tr,
738 &tx_win_min, &tx_win_max, &tx_range);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200739
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100740 /* select UL slots but in both cases assign first_common_ts */
741 uint8_t tx_window = 0;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200742 if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100743 rc = select_ul_slots(tbf->trx, ms_class->type, ms_class->tx,
Andreas Eversberg765736d2014-01-04 15:27:31 +0100744 tx_win_min, tx_range, usf,
745 &first_common_ts, rx_window);
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100746 if (rc < 0)
747 return rc;
748 tx_window = rc;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200749 } else {
Andreas Eversberg765736d2014-01-04 15:27:31 +0100750 first_common_ts = select_first_ts(tbf->trx, tx_win_min,
751 tx_range, rx_window);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200752 }
Holger Hans Peter Freyther73193112013-12-26 09:49:05 +0100753 #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 +0200754
755 if (first_common_ts < 0) {
756 LOGP(DRLCMAC, LOGL_NOTICE, "No first common slots available\n");
757 return -EINVAL;
758 }
759
760 if (tbf->direction == GPRS_RLCMAC_DL_TBF) {
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200761 struct gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200762 /* assign downlink */
763 if (rx_window == 0) {
764 LOGP(DRLCMAC, LOGL_NOTICE, "No downlink slots "
765 "available\n");
766 return -EINVAL;
767 }
768 for (ts = 0; ts < 8; ts++) {
769 if ((rx_window & (1 << ts))) {
770 /* be sure to select a single downlink slots
771 * that can be used for uplink, if multiple
772 * slots are assigned later. */
773 if (single && first_common_ts != ts)
774 continue;
775 LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning DL TS "
776 "%d\n", ts);
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200777 assign_dlink_tbf(&tbf->trx->pdch[ts], dl_tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200778 slotcount++;
779 if (slotcount == 1)
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200780 dl_tbf->first_ts = ts;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200781 if (single)
782 break;
783 }
784 }
785 } else {
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200786 struct gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200787 for (ts = 0; ts < 8; ts++) {
788 if ((tx_window & (1 << ts))) {
789 LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning UL TS "
790 "%d\n", ts);
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200791 assign_uplink_tbf_usf(&tbf->trx->pdch[ts], ul_tbf, usf[ts]);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200792 slotcount++;
793 if (slotcount == 1)
Daniel Willmanncd44ec42014-08-07 15:04:57 +0200794 ul_tbf->first_ts = ts;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200795 if (single)
796 break;
797 }
798 }
799 }
800 if (single && slotcount) {
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200801 uint8_t ts_count = 0;
802 for (ts = 0; ts < 8; ts++)
803 if ((tx_window & (1 << ts)))
804 ts_count++;
805
806 tbf->upgrade_to_multislot = (ts_count > 1);
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200807 LOGP(DRLCMAC, LOGL_INFO, "Using single slot at TS %d for %s\n",
808 tbf->first_ts,
809 (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL");
810 } else {
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200811 tbf->upgrade_to_multislot = 0;
Holger Hans Peter Freyther02ab4a82013-09-29 07:37:40 +0200812 LOGP(DRLCMAC, LOGL_INFO, "Using %d slots for %s\n", slotcount,
813 (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL");
814 }
815 if (slotcount == 0)
816 return -EBUSY;
817
818 tbf->first_common_ts = first_common_ts;
819
820 return 0;
821}