File: /usr/src/linux/net/irda/qos.c
1 /*********************************************************************
2 *
3 * Filename: qos.c
4 * Version: 1.0
5 * Description: IrLAP QoS parameter negotiation
6 * Status: Stable
7 * Author: Dag Brattli <dagb@cs.uit.no>
8 * Created at: Tue Sep 9 00:00:26 1997
9 * Modified at: Sun Jan 30 14:29:16 2000
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
11 *
12 * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
13 * All Rights Reserved.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 * MA 02111-1307 USA
29 *
30 ********************************************************************/
31
32 #include <linux/config.h>
33 #include <asm/byteorder.h>
34
35 #include <net/irda/irda.h>
36 #include <net/irda/parameters.h>
37 #include <net/irda/qos.h>
38 #include <net/irda/irlap.h>
39
40 /*
41 * Maximum values of the baud rate we negociate with the other end.
42 * Most often, you don't have to change that, because Linux-IrDA will
43 * use the maximum offered by the link layer, which usually works fine.
44 * In some very rare cases, you may want to limit it to lower speeds...
45 */
46 int sysctl_max_baud_rate = 16000000;
47 /*
48 * Maximum value of the lap disconnect timer we negociate with the other end.
49 * Most often, the value below represent the best compromise, but some user
50 * may want to keep the LAP alive longuer or shorter in case of link failure.
51 * Remember that the threshold time (early warning) is fixed to 3s...
52 */
53 int sysctl_max_inactive_time = 12;
54
55 static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get);
56 static int irlap_param_link_disconnect(void *instance, irda_param_t *parm,
57 int get);
58 static int irlap_param_max_turn_time(void *instance, irda_param_t *param,
59 int get);
60 static int irlap_param_data_size(void *instance, irda_param_t *param, int get);
61 static int irlap_param_window_size(void *instance, irda_param_t *param,
62 int get);
63 static int irlap_param_additional_bofs(void *instance, irda_param_t *parm,
64 int get);
65 static int irlap_param_min_turn_time(void *instance, irda_param_t *param,
66 int get);
67
68 __u32 min_turn_times[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
69 __u32 baud_rates[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000,
70 1152000, 4000000, 16000000 }; /* bps */
71 __u32 data_sizes[] = { 64, 128, 256, 512, 1024, 2048 }; /* bytes */
72 __u32 add_bofs[] = { 48, 24, 12, 5, 3, 2, 1, 0 }; /* bytes */
73 __u32 max_turn_times[] = { 500, 250, 100, 50 }; /* ms */
74 __u32 link_disc_times[] = { 3, 8, 12, 16, 20, 25, 30, 40 }; /* secs */
75
76 __u32 max_line_capacities[10][4] = {
77 /* 500 ms 250 ms 100 ms 50 ms (max turn time) */
78 { 100, 0, 0, 0 }, /* 2400 bps */
79 { 400, 0, 0, 0 }, /* 9600 bps */
80 { 800, 0, 0, 0 }, /* 19200 bps */
81 { 1600, 0, 0, 0 }, /* 38400 bps */
82 { 2360, 0, 0, 0 }, /* 57600 bps */
83 { 4800, 2400, 960, 480 }, /* 115200 bps */
84 { 28800, 11520, 5760, 2880 }, /* 576000 bps */
85 { 57600, 28800, 11520, 5760 }, /* 1152000 bps */
86 { 200000, 100000, 40000, 20000 }, /* 4000000 bps */
87 { 800000, 400000, 160000, 80000 }, /* 16000000 bps */
88 };
89
90 static pi_minor_info_t pi_minor_call_table_type_0[] = {
91 { NULL, 0 },
92 /* 01 */{ irlap_param_baud_rate, PV_INTEGER | PV_LITTLE_ENDIAN },
93 { NULL, 0 },
94 { NULL, 0 },
95 { NULL, 0 },
96 { NULL, 0 },
97 { NULL, 0 },
98 { NULL, 0 },
99 /* 08 */{ irlap_param_link_disconnect, PV_INT_8_BITS }
100 };
101
102 static pi_minor_info_t pi_minor_call_table_type_1[] = {
103 { NULL, 0 },
104 { NULL, 0 },
105 /* 82 */{ irlap_param_max_turn_time, PV_INT_8_BITS },
106 /* 83 */{ irlap_param_data_size, PV_INT_8_BITS },
107 /* 84 */{ irlap_param_window_size, PV_INT_8_BITS },
108 /* 85 */{ irlap_param_additional_bofs, PV_INT_8_BITS },
109 /* 86 */{ irlap_param_min_turn_time, PV_INT_8_BITS },
110 };
111
112 static pi_major_info_t pi_major_call_table[] = {
113 { pi_minor_call_table_type_0, 9 },
114 { pi_minor_call_table_type_1, 7 },
115 };
116
117 static pi_param_info_t irlap_param_info = { pi_major_call_table, 2, 0x7f, 7 };
118
119 /* ---------------------- LOCAL SUBROUTINES ---------------------- */
120 /* Note : we start with a bunch of local subroutines.
121 * As the compiler is "one pass", this is the only way to get them to
122 * inline properly...
123 * Jean II
124 */
125 /*
126 * Function value_index (value, array, size)
127 *
128 * Returns the index to the value in the specified array
129 */
130 static inline int value_index(__u32 value, __u32 *array, int size)
131 {
132 int i;
133
134 for (i=0; i < size; i++)
135 if (array[i] == value)
136 break;
137 return i;
138 }
139
140 /*
141 * Function index_value (index, array)
142 *
143 * Returns value to index in array, easy!
144 *
145 */
146 static inline __u32 index_value(int index, __u32 *array)
147 {
148 return array[index];
149 }
150
151 /*
152 * Function msb_index (word)
153 *
154 * Returns index to most significant bit (MSB) in word
155 *
156 */
157 int msb_index (__u16 word)
158 {
159 __u16 msb = 0x8000;
160 int index = 15; /* Current MSB */
161
162 while (msb) {
163 if (word & msb)
164 break; /* Found it! */
165 msb >>=1;
166 index--;
167 }
168 return index;
169 }
170
171 static inline __u32 byte_value(__u8 byte, __u32 *array)
172 {
173 int index;
174
175 ASSERT(array != NULL, return -1;);
176
177 index = msb_index(byte);
178
179 return index_value(index, array);
180 }
181
182 /*
183 * Function value_lower_bits (value, array)
184 *
185 * Returns a bit field marking all possibility lower than value.
186 * We may need a "value_higher_bits" in the future...
187 */
188 static inline int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field)
189 {
190 int i;
191 __u16 mask = 0x1;
192 __u16 result = 0x0;
193
194 for (i=0; i < size; i++) {
195 /* Add the current value to the bit field, shift mask */
196 result |= mask;
197 mask <<= 1;
198 /* Finished ? */
199 if (array[i] >= value)
200 break;
201 }
202 /* Send back a valid index */
203 if(i >= size)
204 i = size - 1; /* Last item */
205 *field = result;
206 return i;
207 }
208
209 /* -------------------------- MAIN CALLS -------------------------- */
210
211 /*
212 * Function irda_qos_compute_intersection (qos, new)
213 *
214 * Compute the intersection of the old QoS capabilites with new ones
215 *
216 */
217 void irda_qos_compute_intersection(struct qos_info *qos, struct qos_info *new)
218 {
219 ASSERT(qos != NULL, return;);
220 ASSERT(new != NULL, return;);
221
222 /* Apply */
223 qos->baud_rate.bits &= new->baud_rate.bits;
224 qos->window_size.bits &= new->window_size.bits;
225 qos->min_turn_time.bits &= new->min_turn_time.bits;
226 qos->max_turn_time.bits &= new->max_turn_time.bits;
227 qos->data_size.bits &= new->data_size.bits;
228 qos->link_disc_time.bits &= new->link_disc_time.bits;
229 qos->additional_bofs.bits &= new->additional_bofs.bits;
230
231 irda_qos_bits_to_value(qos);
232 }
233
234 /*
235 * Function irda_init_max_qos_capabilies (qos)
236 *
237 * The purpose of this function is for layers and drivers to be able to
238 * set the maximum QoS possible and then "and in" their own limitations
239 *
240 */
241 void irda_init_max_qos_capabilies(struct qos_info *qos)
242 {
243 int i;
244 /*
245 * These are the maximum supported values as specified on pages
246 * 39-43 in IrLAP
247 */
248
249 /* Use sysctl to set some configurable values... */
250 /* Set configured max speed */
251 i = value_lower_bits(sysctl_max_baud_rate, baud_rates, 10,
252 &qos->baud_rate.bits);
253 sysctl_max_baud_rate = index_value(i, baud_rates);
254
255 /* Set configured max disc time */
256 i = value_lower_bits(sysctl_max_inactive_time, link_disc_times, 8,
257 &qos->link_disc_time.bits);
258 sysctl_max_inactive_time = index_value(i, link_disc_times);
259
260 /* LSB is first byte, MSB is second byte */
261 qos->baud_rate.bits &= 0x03ff;
262
263 qos->window_size.bits = 0x7f;
264 qos->min_turn_time.bits = 0xff;
265 qos->max_turn_time.bits = 0x0f;
266 qos->data_size.bits = 0x3f;
267 qos->link_disc_time.bits &= 0xff;
268 qos->additional_bofs.bits = 0xff;
269 }
270
271 /*
272 * Function irlap_adjust_qos_settings (qos)
273 *
274 * Adjust QoS settings in case some values are not possible to use because
275 * of other settings
276 */
277 void irlap_adjust_qos_settings(struct qos_info *qos)
278 {
279 __u32 line_capacity;
280 int index;
281
282 IRDA_DEBUG(2, __FUNCTION__ "()\n");
283
284 /*
285 * Not allowed to use a max turn time less than 500 ms if the baudrate
286 * is less than 115200
287 */
288 if ((qos->baud_rate.value < 115200) &&
289 (qos->max_turn_time.value < 500))
290 {
291 IRDA_DEBUG(0, __FUNCTION__
292 "(), adjusting max turn time from %d to 500 ms\n",
293 qos->max_turn_time.value);
294 qos->max_turn_time.value = 500;
295 }
296
297 /*
298 * The data size must be adjusted according to the baud rate and max
299 * turn time
300 */
301 index = value_index(qos->data_size.value, data_sizes, 6);
302 line_capacity = irlap_max_line_capacity(qos->baud_rate.value,
303 qos->max_turn_time.value);
304
305 #ifdef CONFIG_IRDA_DYNAMIC_WINDOW
306 while ((qos->data_size.value > line_capacity) && (index > 0)) {
307 qos->data_size.value = data_sizes[index--];
308 IRDA_DEBUG(2, __FUNCTION__
309 "(), redusing data size to %d\n",
310 qos->data_size.value);
311 }
312 #else /* Use method descibed in section 6.6.11 of IrLAP */
313 while (irlap_requested_line_capacity(qos) > line_capacity) {
314 ASSERT(index != 0, return;);
315
316 /* Must be able to send at least one frame */
317 if (qos->window_size.value > 1) {
318 qos->window_size.value--;
319 IRDA_DEBUG(2, __FUNCTION__
320 "(), redusing window size to %d\n",
321 qos->window_size.value);
322 } else if (index > 1) {
323 qos->data_size.value = data_sizes[index--];
324 IRDA_DEBUG(2, __FUNCTION__
325 "(), redusing data size to %d\n",
326 qos->data_size.value);
327 } else {
328 WARNING(__FUNCTION__ "(), nothing more we can do!\n");
329 }
330 }
331 #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
332 }
333
334 /*
335 * Function irlap_negotiate (qos_device, qos_session, skb)
336 *
337 * Negotiate QoS values, not really that much negotiation :-)
338 * We just set the QoS capabilities for the peer station
339 *
340 */
341 int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb)
342 {
343 int ret;
344
345 ret = irda_param_extract_all(self, skb->data, skb->len,
346 &irlap_param_info);
347
348 /* Convert the negotiated bits to values */
349 irda_qos_bits_to_value(&self->qos_tx);
350 irda_qos_bits_to_value(&self->qos_rx);
351
352 irlap_adjust_qos_settings(&self->qos_tx);
353
354 IRDA_DEBUG(2, "Setting BAUD_RATE to %d bps.\n",
355 self->qos_tx.baud_rate.value);
356 IRDA_DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
357 self->qos_tx.data_size.value);
358 IRDA_DEBUG(2, "Setting WINDOW_SIZE to %d\n",
359 self->qos_tx.window_size.value);
360 IRDA_DEBUG(2, "Setting XBOFS to %d\n",
361 self->qos_tx.additional_bofs.value);
362 IRDA_DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
363 self->qos_tx.max_turn_time.value);
364 IRDA_DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
365 self->qos_tx.min_turn_time.value);
366 IRDA_DEBUG(2, "Setting LINK_DISC to %d secs.\n",
367 self->qos_tx.link_disc_time.value);
368 return ret;
369 }
370
371 /*
372 * Function irlap_insert_negotiation_params (qos, fp)
373 *
374 * Insert QoS negotiaion pararameters into frame
375 *
376 */
377 int irlap_insert_qos_negotiation_params(struct irlap_cb *self,
378 struct sk_buff *skb)
379 {
380 int ret;
381
382 /* Insert data rate */
383 ret = irda_param_insert(self, PI_BAUD_RATE, skb->tail,
384 skb_tailroom(skb), &irlap_param_info);
385 if (ret < 0)
386 return ret;
387 skb_put(skb, ret);
388
389 /* Insert max turnaround time */
390 ret = irda_param_insert(self, PI_MAX_TURN_TIME, skb->tail,
391 skb_tailroom(skb), &irlap_param_info);
392 if (ret < 0)
393 return ret;
394 skb_put(skb, ret);
395
396 /* Insert data size */
397 ret = irda_param_insert(self, PI_DATA_SIZE, skb->tail,
398 skb_tailroom(skb), &irlap_param_info);
399 if (ret < 0)
400 return ret;
401 skb_put(skb, ret);
402
403 /* Insert window size */
404 ret = irda_param_insert(self, PI_WINDOW_SIZE, skb->tail,
405 skb_tailroom(skb), &irlap_param_info);
406 if (ret < 0)
407 return ret;
408 skb_put(skb, ret);
409
410 /* Insert additional BOFs */
411 ret = irda_param_insert(self, PI_ADD_BOFS, skb->tail,
412 skb_tailroom(skb), &irlap_param_info);
413 if (ret < 0)
414 return ret;
415 skb_put(skb, ret);
416
417 /* Insert minimum turnaround time */
418 ret = irda_param_insert(self, PI_MIN_TURN_TIME, skb->tail,
419 skb_tailroom(skb), &irlap_param_info);
420 if (ret < 0)
421 return ret;
422 skb_put(skb, ret);
423
424 /* Insert link disconnect/threshold time */
425 ret = irda_param_insert(self, PI_LINK_DISC, skb->tail,
426 skb_tailroom(skb), &irlap_param_info);
427 if (ret < 0)
428 return ret;
429 skb_put(skb, ret);
430
431 return 0;
432 }
433
434 /*
435 * Function irlap_param_baud_rate (instance, param, get)
436 *
437 * Negotiate data-rate
438 *
439 */
440 static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get)
441 {
442 __u16 final;
443
444 struct irlap_cb *self = (struct irlap_cb *) instance;
445
446 ASSERT(self != NULL, return -1;);
447 ASSERT(self->magic == LAP_MAGIC, return -1;);
448
449 if (get) {
450 param->pv.i = self->qos_rx.baud_rate.bits;
451 IRDA_DEBUG(2, __FUNCTION__ "(), baud rate = 0x%02x\n",
452 param->pv.i);
453 } else {
454 /*
455 * Stations must agree on baud rate, so calculate
456 * intersection
457 */
458 IRDA_DEBUG(2, "Requested BAUD_RATE: 0x%04x\n", param->pv.s);
459 final = param->pv.s & self->qos_rx.baud_rate.bits;
460
461 IRDA_DEBUG(2, "Final BAUD_RATE: 0x%04x\n", final);
462 self->qos_tx.baud_rate.bits = final;
463 self->qos_rx.baud_rate.bits = final;
464 }
465
466 return 0;
467 }
468
469 /*
470 * Function irlap_param_link_disconnect (instance, param, get)
471 *
472 * Negotiate link disconnect/threshold time.
473 *
474 */
475 static int irlap_param_link_disconnect(void *instance, irda_param_t *param,
476 int get)
477 {
478 __u16 final;
479
480 struct irlap_cb *self = (struct irlap_cb *) instance;
481
482 ASSERT(self != NULL, return -1;);
483 ASSERT(self->magic == LAP_MAGIC, return -1;);
484
485 if (get)
486 param->pv.b = self->qos_rx.link_disc_time.bits;
487 else {
488 /*
489 * Stations must agree on link disconnect/threshold
490 * time.
491 */
492 IRDA_DEBUG(2, "LINK_DISC: %02x\n", param->pv.b);
493 final = param->pv.b & self->qos_rx.link_disc_time.bits;
494
495 IRDA_DEBUG(2, "Final LINK_DISC: %02x\n", final);
496 self->qos_tx.link_disc_time.bits = final;
497 self->qos_rx.link_disc_time.bits = final;
498 }
499 return 0;
500 }
501
502 /*
503 * Function irlap_param_max_turn_time (instance, param, get)
504 *
505 * Negotiate the maximum turnaround time. This is a type 1 parameter and
506 * will be negotiated independently for each station
507 *
508 */
509 static int irlap_param_max_turn_time(void *instance, irda_param_t *param,
510 int get)
511 {
512 struct irlap_cb *self = (struct irlap_cb *) instance;
513
514 ASSERT(self != NULL, return -1;);
515 ASSERT(self->magic == LAP_MAGIC, return -1;);
516
517 if (get)
518 param->pv.b = self->qos_rx.max_turn_time.bits;
519 else
520 self->qos_tx.max_turn_time.bits = param->pv.b;
521
522 return 0;
523 }
524
525 /*
526 * Function irlap_param_data_size (instance, param, get)
527 *
528 * Negotiate the data size. This is a type 1 parameter and
529 * will be negotiated independently for each station
530 *
531 */
532 static int irlap_param_data_size(void *instance, irda_param_t *param, int get)
533 {
534 struct irlap_cb *self = (struct irlap_cb *) instance;
535
536 ASSERT(self != NULL, return -1;);
537 ASSERT(self->magic == LAP_MAGIC, return -1;);
538
539 if (get)
540 param->pv.b = self->qos_rx.data_size.bits;
541 else
542 self->qos_tx.data_size.bits = param->pv.b;
543
544 return 0;
545 }
546
547 /*
548 * Function irlap_param_window_size (instance, param, get)
549 *
550 * Negotiate the window size. This is a type 1 parameter and
551 * will be negotiated independently for each station
552 *
553 */
554 static int irlap_param_window_size(void *instance, irda_param_t *param,
555 int get)
556 {
557 struct irlap_cb *self = (struct irlap_cb *) instance;
558
559 ASSERT(self != NULL, return -1;);
560 ASSERT(self->magic == LAP_MAGIC, return -1;);
561
562 if (get)
563 param->pv.b = self->qos_rx.window_size.bits;
564 else
565 self->qos_tx.window_size.bits = param->pv.b;
566
567 return 0;
568 }
569
570 /*
571 * Function irlap_param_additional_bofs (instance, param, get)
572 *
573 * Negotiate additional BOF characters. This is a type 1 parameter and
574 * will be negotiated independently for each station.
575 */
576 static int irlap_param_additional_bofs(void *instance, irda_param_t *param, int get)
577 {
578 struct irlap_cb *self = (struct irlap_cb *) instance;
579
580 ASSERT(self != NULL, return -1;);
581 ASSERT(self->magic == LAP_MAGIC, return -1;);
582
583 if (get)
584 param->pv.b = self->qos_rx.additional_bofs.bits;
585 else
586 self->qos_tx.additional_bofs.bits = param->pv.b;
587
588 return 0;
589 }
590
591 /*
592 * Function irlap_param_min_turn_time (instance, param, get)
593 *
594 * Negotiate the minimum turn around time. This is a type 1 parameter and
595 * will be negotiated independently for each station
596 */
597 static int irlap_param_min_turn_time(void *instance, irda_param_t *param,
598 int get)
599 {
600 struct irlap_cb *self = (struct irlap_cb *) instance;
601
602 ASSERT(self != NULL, return -1;);
603 ASSERT(self->magic == LAP_MAGIC, return -1;);
604
605 if (get)
606 param->pv.b = self->qos_rx.min_turn_time.bits;
607 else
608 self->qos_tx.min_turn_time.bits = param->pv.b;
609
610 return 0;
611 }
612
613 /*
614 * Function irlap_max_line_capacity (speed, max_turn_time, min_turn_time)
615 *
616 * Calculate the maximum line capacity
617 *
618 */
619 __u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
620 {
621 __u32 line_capacity;
622 int i,j;
623
624 IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, max_turn_time=%d\n",
625 speed, max_turn_time);
626
627 i = value_index(speed, baud_rates, 10);
628 j = value_index(max_turn_time, max_turn_times, 4);
629
630 ASSERT(((i >=0) && (i <=10)), return 0;);
631 ASSERT(((j >=0) && (j <=4)), return 0;);
632
633 line_capacity = max_line_capacities[i][j];
634
635 IRDA_DEBUG(2, __FUNCTION__ "(), line capacity=%d bytes\n",
636 line_capacity);
637
638 return line_capacity;
639 }
640
641 __u32 irlap_requested_line_capacity(struct qos_info *qos)
642 { __u32 line_capacity;
643
644 line_capacity = qos->window_size.value *
645 (qos->data_size.value + 6 + qos->additional_bofs.value) +
646 irlap_min_turn_time_in_bytes(qos->baud_rate.value,
647 qos->min_turn_time.value);
648
649 IRDA_DEBUG(2, __FUNCTION__ "(), requested line capacity=%d\n",
650 line_capacity);
651
652 return line_capacity;
653 }
654
655 void irda_qos_bits_to_value(struct qos_info *qos)
656 {
657 int index;
658
659 ASSERT(qos != NULL, return;);
660
661 index = msb_index(qos->baud_rate.bits);
662 qos->baud_rate.value = baud_rates[index];
663
664 index = msb_index(qos->data_size.bits);
665 qos->data_size.value = data_sizes[index];
666
667 index = msb_index(qos->window_size.bits);
668 qos->window_size.value = index+1;
669
670 index = msb_index(qos->min_turn_time.bits);
671 qos->min_turn_time.value = min_turn_times[index];
672
673 index = msb_index(qos->max_turn_time.bits);
674 qos->max_turn_time.value = max_turn_times[index];
675
676 index = msb_index(qos->link_disc_time.bits);
677 qos->link_disc_time.value = link_disc_times[index];
678
679 index = msb_index(qos->additional_bofs.bits);
680 qos->additional_bofs.value = add_bofs[index];
681 }
682