Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/irda/qos.c
15109 views
1
/*********************************************************************
2
*
3
* Filename: qos.c
4
* Version: 1.0
5
* Description: IrLAP QoS parameter negotiation
6
* Status: Stable
7
* Author: Dag Brattli <[email protected]>
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 <[email protected]>
11
*
12
* Copyright (c) 1998-2000 Dag Brattli <[email protected]>,
13
* All Rights Reserved.
14
* Copyright (c) 2000-2001 Jean Tourrilhes <[email protected]>
15
*
16
* This program is free software; you can redistribute it and/or
17
* modify it under the terms of the GNU General Public License as
18
* published by the Free Software Foundation; either version 2 of
19
* the License, or (at your option) any later version.
20
*
21
* This program is distributed in the hope that it will be useful,
22
* but WITHOUT ANY WARRANTY; without even the implied warranty of
23
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
* GNU General Public License for more details.
25
*
26
* You should have received a copy of the GNU General Public License
27
* along with this program; if not, write to the Free Software
28
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29
* MA 02111-1307 USA
30
*
31
********************************************************************/
32
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
#include <net/irda/irlap_frame.h>
40
41
/*
42
* Maximum values of the baud rate we negotiate with the other end.
43
* Most often, you don't have to change that, because Linux-IrDA will
44
* use the maximum offered by the link layer, which usually works fine.
45
* In some very rare cases, you may want to limit it to lower speeds...
46
*/
47
int sysctl_max_baud_rate = 16000000;
48
/*
49
* Maximum value of the lap disconnect timer we negotiate with the other end.
50
* Most often, the value below represent the best compromise, but some user
51
* may want to keep the LAP alive longer or shorter in case of link failure.
52
* Remember that the threshold time (early warning) is fixed to 3s...
53
*/
54
int sysctl_max_noreply_time = 12;
55
/*
56
* Minimum turn time to be applied before transmitting to the peer.
57
* Nonzero values (usec) are used as lower limit to the per-connection
58
* mtt value which was announced by the other end during negotiation.
59
* Might be helpful if the peer device provides too short mtt.
60
* Default is 10us which means using the unmodified value given by the
61
* peer except if it's 0 (0 is likely a bug in the other stack).
62
*/
63
unsigned sysctl_min_tx_turn_time = 10;
64
/*
65
* Maximum data size to be used in transmission in payload of LAP frame.
66
* There is a bit of confusion in the IrDA spec :
67
* The LAP spec defines the payload of a LAP frame (I field) to be
68
* 2048 bytes max (IrLAP 1.1, chapt 6.6.5, p40).
69
* On the other hand, the PHY mention frames of 2048 bytes max (IrPHY
70
* 1.2, chapt 5.3.2.1, p41). But, this number includes the LAP header
71
* (2 bytes), and CRC (32 bits at 4 Mb/s). So, for the I field (LAP
72
* payload), that's only 2042 bytes. Oups !
73
* My nsc-ircc hardware has troubles receiving 2048 bytes frames at 4 Mb/s,
74
* so adjust to 2042... I don't know if this bug applies only for 2048
75
* bytes frames or all negotiated frame sizes, but you can use the sysctl
76
* to play with this value anyway.
77
* Jean II */
78
unsigned sysctl_max_tx_data_size = 2042;
79
/*
80
* Maximum transmit window, i.e. number of LAP frames between turn-around.
81
* This allow to override what the peer told us. Some peers are buggy and
82
* don't always support what they tell us.
83
* Jean II */
84
unsigned sysctl_max_tx_window = 7;
85
86
static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get);
87
static int irlap_param_link_disconnect(void *instance, irda_param_t *parm,
88
int get);
89
static int irlap_param_max_turn_time(void *instance, irda_param_t *param,
90
int get);
91
static int irlap_param_data_size(void *instance, irda_param_t *param, int get);
92
static int irlap_param_window_size(void *instance, irda_param_t *param,
93
int get);
94
static int irlap_param_additional_bofs(void *instance, irda_param_t *parm,
95
int get);
96
static int irlap_param_min_turn_time(void *instance, irda_param_t *param,
97
int get);
98
99
#ifndef CONFIG_IRDA_DYNAMIC_WINDOW
100
static __u32 irlap_requested_line_capacity(struct qos_info *qos);
101
#endif
102
103
static __u32 min_turn_times[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
104
static __u32 baud_rates[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000,
105
1152000, 4000000, 16000000 }; /* bps */
106
static __u32 data_sizes[] = { 64, 128, 256, 512, 1024, 2048 }; /* bytes */
107
static __u32 add_bofs[] = { 48, 24, 12, 5, 3, 2, 1, 0 }; /* bytes */
108
static __u32 max_turn_times[] = { 500, 250, 100, 50 }; /* ms */
109
static __u32 link_disc_times[] = { 3, 8, 12, 16, 20, 25, 30, 40 }; /* secs */
110
111
static __u32 max_line_capacities[10][4] = {
112
/* 500 ms 250 ms 100 ms 50 ms (max turn time) */
113
{ 100, 0, 0, 0 }, /* 2400 bps */
114
{ 400, 0, 0, 0 }, /* 9600 bps */
115
{ 800, 0, 0, 0 }, /* 19200 bps */
116
{ 1600, 0, 0, 0 }, /* 38400 bps */
117
{ 2360, 0, 0, 0 }, /* 57600 bps */
118
{ 4800, 2400, 960, 480 }, /* 115200 bps */
119
{ 28800, 11520, 5760, 2880 }, /* 576000 bps */
120
{ 57600, 28800, 11520, 5760 }, /* 1152000 bps */
121
{ 200000, 100000, 40000, 20000 }, /* 4000000 bps */
122
{ 800000, 400000, 160000, 80000 }, /* 16000000 bps */
123
};
124
125
static pi_minor_info_t pi_minor_call_table_type_0[] = {
126
{ NULL, 0 },
127
/* 01 */{ irlap_param_baud_rate, PV_INTEGER | PV_LITTLE_ENDIAN },
128
{ NULL, 0 },
129
{ NULL, 0 },
130
{ NULL, 0 },
131
{ NULL, 0 },
132
{ NULL, 0 },
133
{ NULL, 0 },
134
/* 08 */{ irlap_param_link_disconnect, PV_INT_8_BITS }
135
};
136
137
static pi_minor_info_t pi_minor_call_table_type_1[] = {
138
{ NULL, 0 },
139
{ NULL, 0 },
140
/* 82 */{ irlap_param_max_turn_time, PV_INT_8_BITS },
141
/* 83 */{ irlap_param_data_size, PV_INT_8_BITS },
142
/* 84 */{ irlap_param_window_size, PV_INT_8_BITS },
143
/* 85 */{ irlap_param_additional_bofs, PV_INT_8_BITS },
144
/* 86 */{ irlap_param_min_turn_time, PV_INT_8_BITS },
145
};
146
147
static pi_major_info_t pi_major_call_table[] = {
148
{ pi_minor_call_table_type_0, 9 },
149
{ pi_minor_call_table_type_1, 7 },
150
};
151
152
static pi_param_info_t irlap_param_info = { pi_major_call_table, 2, 0x7f, 7 };
153
154
/* ---------------------- LOCAL SUBROUTINES ---------------------- */
155
/* Note : we start with a bunch of local subroutines.
156
* As the compiler is "one pass", this is the only way to get them to
157
* inline properly...
158
* Jean II
159
*/
160
/*
161
* Function value_index (value, array, size)
162
*
163
* Returns the index to the value in the specified array
164
*/
165
static inline int value_index(__u32 value, __u32 *array, int size)
166
{
167
int i;
168
169
for (i=0; i < size; i++)
170
if (array[i] == value)
171
break;
172
return i;
173
}
174
175
/*
176
* Function index_value (index, array)
177
*
178
* Returns value to index in array, easy!
179
*
180
*/
181
static inline __u32 index_value(int index, __u32 *array)
182
{
183
return array[index];
184
}
185
186
/*
187
* Function msb_index (word)
188
*
189
* Returns index to most significant bit (MSB) in word
190
*
191
*/
192
static int msb_index (__u16 word)
193
{
194
__u16 msb = 0x8000;
195
int index = 15; /* Current MSB */
196
197
/* Check for buggy peers.
198
* Note : there is a small probability that it could be us, but I
199
* would expect driver authors to catch that pretty early and be
200
* able to check precisely what's going on. If a end user sees this,
201
* it's very likely the peer. - Jean II */
202
if (word == 0) {
203
IRDA_WARNING("%s(), Detected buggy peer, adjust null PV to 0x1!\n",
204
__func__);
205
/* The only safe choice (we don't know the array size) */
206
word = 0x1;
207
}
208
209
while (msb) {
210
if (word & msb)
211
break; /* Found it! */
212
msb >>=1;
213
index--;
214
}
215
return index;
216
}
217
218
/*
219
* Function value_lower_bits (value, array)
220
*
221
* Returns a bit field marking all possibility lower than value.
222
*/
223
static inline int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field)
224
{
225
int i;
226
__u16 mask = 0x1;
227
__u16 result = 0x0;
228
229
for (i=0; i < size; i++) {
230
/* Add the current value to the bit field, shift mask */
231
result |= mask;
232
mask <<= 1;
233
/* Finished ? */
234
if (array[i] >= value)
235
break;
236
}
237
/* Send back a valid index */
238
if(i >= size)
239
i = size - 1; /* Last item */
240
*field = result;
241
return i;
242
}
243
244
/*
245
* Function value_highest_bit (value, array)
246
*
247
* Returns a bit field marking the highest possibility lower than value.
248
*/
249
static inline int value_highest_bit(__u32 value, __u32 *array, int size, __u16 *field)
250
{
251
int i;
252
__u16 mask = 0x1;
253
__u16 result = 0x0;
254
255
for (i=0; i < size; i++) {
256
/* Finished ? */
257
if (array[i] <= value)
258
break;
259
/* Shift mask */
260
mask <<= 1;
261
}
262
/* Set the current value to the bit field */
263
result |= mask;
264
/* Send back a valid index */
265
if(i >= size)
266
i = size - 1; /* Last item */
267
*field = result;
268
return i;
269
}
270
271
/* -------------------------- MAIN CALLS -------------------------- */
272
273
/*
274
* Function irda_qos_compute_intersection (qos, new)
275
*
276
* Compute the intersection of the old QoS capabilities with new ones
277
*
278
*/
279
void irda_qos_compute_intersection(struct qos_info *qos, struct qos_info *new)
280
{
281
IRDA_ASSERT(qos != NULL, return;);
282
IRDA_ASSERT(new != NULL, return;);
283
284
/* Apply */
285
qos->baud_rate.bits &= new->baud_rate.bits;
286
qos->window_size.bits &= new->window_size.bits;
287
qos->min_turn_time.bits &= new->min_turn_time.bits;
288
qos->max_turn_time.bits &= new->max_turn_time.bits;
289
qos->data_size.bits &= new->data_size.bits;
290
qos->link_disc_time.bits &= new->link_disc_time.bits;
291
qos->additional_bofs.bits &= new->additional_bofs.bits;
292
293
irda_qos_bits_to_value(qos);
294
}
295
296
/*
297
* Function irda_init_max_qos_capabilies (qos)
298
*
299
* The purpose of this function is for layers and drivers to be able to
300
* set the maximum QoS possible and then "and in" their own limitations
301
*
302
*/
303
void irda_init_max_qos_capabilies(struct qos_info *qos)
304
{
305
int i;
306
/*
307
* These are the maximum supported values as specified on pages
308
* 39-43 in IrLAP
309
*/
310
311
/* Use sysctl to set some configurable values... */
312
/* Set configured max speed */
313
i = value_lower_bits(sysctl_max_baud_rate, baud_rates, 10,
314
&qos->baud_rate.bits);
315
sysctl_max_baud_rate = index_value(i, baud_rates);
316
317
/* Set configured max disc time */
318
i = value_lower_bits(sysctl_max_noreply_time, link_disc_times, 8,
319
&qos->link_disc_time.bits);
320
sysctl_max_noreply_time = index_value(i, link_disc_times);
321
322
/* LSB is first byte, MSB is second byte */
323
qos->baud_rate.bits &= 0x03ff;
324
325
qos->window_size.bits = 0x7f;
326
qos->min_turn_time.bits = 0xff;
327
qos->max_turn_time.bits = 0x0f;
328
qos->data_size.bits = 0x3f;
329
qos->link_disc_time.bits &= 0xff;
330
qos->additional_bofs.bits = 0xff;
331
}
332
EXPORT_SYMBOL(irda_init_max_qos_capabilies);
333
334
/*
335
* Function irlap_adjust_qos_settings (qos)
336
*
337
* Adjust QoS settings in case some values are not possible to use because
338
* of other settings
339
*/
340
static void irlap_adjust_qos_settings(struct qos_info *qos)
341
{
342
__u32 line_capacity;
343
int index;
344
345
IRDA_DEBUG(2, "%s()\n", __func__);
346
347
/*
348
* Make sure the mintt is sensible.
349
* Main culprit : Ericsson T39. - Jean II
350
*/
351
if (sysctl_min_tx_turn_time > qos->min_turn_time.value) {
352
int i;
353
354
IRDA_WARNING("%s(), Detected buggy peer, adjust mtt to %dus!\n",
355
__func__, sysctl_min_tx_turn_time);
356
357
/* We don't really need bits, but easier this way */
358
i = value_highest_bit(sysctl_min_tx_turn_time, min_turn_times,
359
8, &qos->min_turn_time.bits);
360
sysctl_min_tx_turn_time = index_value(i, min_turn_times);
361
qos->min_turn_time.value = sysctl_min_tx_turn_time;
362
}
363
364
/*
365
* Not allowed to use a max turn time less than 500 ms if the baudrate
366
* is less than 115200
367
*/
368
if ((qos->baud_rate.value < 115200) &&
369
(qos->max_turn_time.value < 500))
370
{
371
IRDA_DEBUG(0,
372
"%s(), adjusting max turn time from %d to 500 ms\n",
373
__func__, qos->max_turn_time.value);
374
qos->max_turn_time.value = 500;
375
}
376
377
/*
378
* The data size must be adjusted according to the baud rate and max
379
* turn time
380
*/
381
index = value_index(qos->data_size.value, data_sizes, 6);
382
line_capacity = irlap_max_line_capacity(qos->baud_rate.value,
383
qos->max_turn_time.value);
384
385
#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
386
while ((qos->data_size.value > line_capacity) && (index > 0)) {
387
qos->data_size.value = data_sizes[index--];
388
IRDA_DEBUG(2, "%s(), reducing data size to %d\n",
389
__func__, qos->data_size.value);
390
}
391
#else /* Use method described in section 6.6.11 of IrLAP */
392
while (irlap_requested_line_capacity(qos) > line_capacity) {
393
IRDA_ASSERT(index != 0, return;);
394
395
/* Must be able to send at least one frame */
396
if (qos->window_size.value > 1) {
397
qos->window_size.value--;
398
IRDA_DEBUG(2, "%s(), reducing window size to %d\n",
399
__func__, qos->window_size.value);
400
} else if (index > 1) {
401
qos->data_size.value = data_sizes[index--];
402
IRDA_DEBUG(2, "%s(), reducing data size to %d\n",
403
__func__, qos->data_size.value);
404
} else {
405
IRDA_WARNING("%s(), nothing more we can do!\n",
406
__func__);
407
}
408
}
409
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
410
/*
411
* Fix tx data size according to user limits - Jean II
412
*/
413
if (qos->data_size.value > sysctl_max_tx_data_size)
414
/* Allow non discrete adjustement to avoid losing capacity */
415
qos->data_size.value = sysctl_max_tx_data_size;
416
/*
417
* Override Tx window if user request it. - Jean II
418
*/
419
if (qos->window_size.value > sysctl_max_tx_window)
420
qos->window_size.value = sysctl_max_tx_window;
421
}
422
423
/*
424
* Function irlap_negotiate (qos_device, qos_session, skb)
425
*
426
* Negotiate QoS values, not really that much negotiation :-)
427
* We just set the QoS capabilities for the peer station
428
*
429
*/
430
int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb)
431
{
432
int ret;
433
434
ret = irda_param_extract_all(self, skb->data, skb->len,
435
&irlap_param_info);
436
437
/* Convert the negotiated bits to values */
438
irda_qos_bits_to_value(&self->qos_tx);
439
irda_qos_bits_to_value(&self->qos_rx);
440
441
irlap_adjust_qos_settings(&self->qos_tx);
442
443
IRDA_DEBUG(2, "Setting BAUD_RATE to %d bps.\n",
444
self->qos_tx.baud_rate.value);
445
IRDA_DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
446
self->qos_tx.data_size.value);
447
IRDA_DEBUG(2, "Setting WINDOW_SIZE to %d\n",
448
self->qos_tx.window_size.value);
449
IRDA_DEBUG(2, "Setting XBOFS to %d\n",
450
self->qos_tx.additional_bofs.value);
451
IRDA_DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
452
self->qos_tx.max_turn_time.value);
453
IRDA_DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
454
self->qos_tx.min_turn_time.value);
455
IRDA_DEBUG(2, "Setting LINK_DISC to %d secs.\n",
456
self->qos_tx.link_disc_time.value);
457
return ret;
458
}
459
460
/*
461
* Function irlap_insert_negotiation_params (qos, fp)
462
*
463
* Insert QoS negotiaion pararameters into frame
464
*
465
*/
466
int irlap_insert_qos_negotiation_params(struct irlap_cb *self,
467
struct sk_buff *skb)
468
{
469
int ret;
470
471
/* Insert data rate */
472
ret = irda_param_insert(self, PI_BAUD_RATE, skb_tail_pointer(skb),
473
skb_tailroom(skb), &irlap_param_info);
474
if (ret < 0)
475
return ret;
476
skb_put(skb, ret);
477
478
/* Insert max turnaround time */
479
ret = irda_param_insert(self, PI_MAX_TURN_TIME, skb_tail_pointer(skb),
480
skb_tailroom(skb), &irlap_param_info);
481
if (ret < 0)
482
return ret;
483
skb_put(skb, ret);
484
485
/* Insert data size */
486
ret = irda_param_insert(self, PI_DATA_SIZE, skb_tail_pointer(skb),
487
skb_tailroom(skb), &irlap_param_info);
488
if (ret < 0)
489
return ret;
490
skb_put(skb, ret);
491
492
/* Insert window size */
493
ret = irda_param_insert(self, PI_WINDOW_SIZE, skb_tail_pointer(skb),
494
skb_tailroom(skb), &irlap_param_info);
495
if (ret < 0)
496
return ret;
497
skb_put(skb, ret);
498
499
/* Insert additional BOFs */
500
ret = irda_param_insert(self, PI_ADD_BOFS, skb_tail_pointer(skb),
501
skb_tailroom(skb), &irlap_param_info);
502
if (ret < 0)
503
return ret;
504
skb_put(skb, ret);
505
506
/* Insert minimum turnaround time */
507
ret = irda_param_insert(self, PI_MIN_TURN_TIME, skb_tail_pointer(skb),
508
skb_tailroom(skb), &irlap_param_info);
509
if (ret < 0)
510
return ret;
511
skb_put(skb, ret);
512
513
/* Insert link disconnect/threshold time */
514
ret = irda_param_insert(self, PI_LINK_DISC, skb_tail_pointer(skb),
515
skb_tailroom(skb), &irlap_param_info);
516
if (ret < 0)
517
return ret;
518
skb_put(skb, ret);
519
520
return 0;
521
}
522
523
/*
524
* Function irlap_param_baud_rate (instance, param, get)
525
*
526
* Negotiate data-rate
527
*
528
*/
529
static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get)
530
{
531
__u16 final;
532
533
struct irlap_cb *self = (struct irlap_cb *) instance;
534
535
IRDA_ASSERT(self != NULL, return -1;);
536
IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
537
538
if (get) {
539
param->pv.i = self->qos_rx.baud_rate.bits;
540
IRDA_DEBUG(2, "%s(), baud rate = 0x%02x\n",
541
__func__, param->pv.i);
542
} else {
543
/*
544
* Stations must agree on baud rate, so calculate
545
* intersection
546
*/
547
IRDA_DEBUG(2, "Requested BAUD_RATE: 0x%04x\n", (__u16) param->pv.i);
548
final = (__u16) param->pv.i & self->qos_rx.baud_rate.bits;
549
550
IRDA_DEBUG(2, "Final BAUD_RATE: 0x%04x\n", final);
551
self->qos_tx.baud_rate.bits = final;
552
self->qos_rx.baud_rate.bits = final;
553
}
554
555
return 0;
556
}
557
558
/*
559
* Function irlap_param_link_disconnect (instance, param, get)
560
*
561
* Negotiate link disconnect/threshold time.
562
*
563
*/
564
static int irlap_param_link_disconnect(void *instance, irda_param_t *param,
565
int get)
566
{
567
__u16 final;
568
569
struct irlap_cb *self = (struct irlap_cb *) instance;
570
571
IRDA_ASSERT(self != NULL, return -1;);
572
IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
573
574
if (get)
575
param->pv.i = self->qos_rx.link_disc_time.bits;
576
else {
577
/*
578
* Stations must agree on link disconnect/threshold
579
* time.
580
*/
581
IRDA_DEBUG(2, "LINK_DISC: %02x\n", (__u8) param->pv.i);
582
final = (__u8) param->pv.i & self->qos_rx.link_disc_time.bits;
583
584
IRDA_DEBUG(2, "Final LINK_DISC: %02x\n", final);
585
self->qos_tx.link_disc_time.bits = final;
586
self->qos_rx.link_disc_time.bits = final;
587
}
588
return 0;
589
}
590
591
/*
592
* Function irlap_param_max_turn_time (instance, param, get)
593
*
594
* Negotiate the maximum turnaround time. This is a type 1 parameter and
595
* will be negotiated independently for each station
596
*
597
*/
598
static int irlap_param_max_turn_time(void *instance, irda_param_t *param,
599
int get)
600
{
601
struct irlap_cb *self = (struct irlap_cb *) instance;
602
603
IRDA_ASSERT(self != NULL, return -1;);
604
IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
605
606
if (get)
607
param->pv.i = self->qos_rx.max_turn_time.bits;
608
else
609
self->qos_tx.max_turn_time.bits = (__u8) param->pv.i;
610
611
return 0;
612
}
613
614
/*
615
* Function irlap_param_data_size (instance, param, get)
616
*
617
* Negotiate the data size. This is a type 1 parameter and
618
* will be negotiated independently for each station
619
*
620
*/
621
static int irlap_param_data_size(void *instance, irda_param_t *param, int get)
622
{
623
struct irlap_cb *self = (struct irlap_cb *) instance;
624
625
IRDA_ASSERT(self != NULL, return -1;);
626
IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
627
628
if (get)
629
param->pv.i = self->qos_rx.data_size.bits;
630
else
631
self->qos_tx.data_size.bits = (__u8) param->pv.i;
632
633
return 0;
634
}
635
636
/*
637
* Function irlap_param_window_size (instance, param, get)
638
*
639
* Negotiate the window size. This is a type 1 parameter and
640
* will be negotiated independently for each station
641
*
642
*/
643
static int irlap_param_window_size(void *instance, irda_param_t *param,
644
int get)
645
{
646
struct irlap_cb *self = (struct irlap_cb *) instance;
647
648
IRDA_ASSERT(self != NULL, return -1;);
649
IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
650
651
if (get)
652
param->pv.i = self->qos_rx.window_size.bits;
653
else
654
self->qos_tx.window_size.bits = (__u8) param->pv.i;
655
656
return 0;
657
}
658
659
/*
660
* Function irlap_param_additional_bofs (instance, param, get)
661
*
662
* Negotiate additional BOF characters. This is a type 1 parameter and
663
* will be negotiated independently for each station.
664
*/
665
static int irlap_param_additional_bofs(void *instance, irda_param_t *param, int get)
666
{
667
struct irlap_cb *self = (struct irlap_cb *) instance;
668
669
IRDA_ASSERT(self != NULL, return -1;);
670
IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
671
672
if (get)
673
param->pv.i = self->qos_rx.additional_bofs.bits;
674
else
675
self->qos_tx.additional_bofs.bits = (__u8) param->pv.i;
676
677
return 0;
678
}
679
680
/*
681
* Function irlap_param_min_turn_time (instance, param, get)
682
*
683
* Negotiate the minimum turn around time. This is a type 1 parameter and
684
* will be negotiated independently for each station
685
*/
686
static int irlap_param_min_turn_time(void *instance, irda_param_t *param,
687
int get)
688
{
689
struct irlap_cb *self = (struct irlap_cb *) instance;
690
691
IRDA_ASSERT(self != NULL, return -1;);
692
IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
693
694
if (get)
695
param->pv.i = self->qos_rx.min_turn_time.bits;
696
else
697
self->qos_tx.min_turn_time.bits = (__u8) param->pv.i;
698
699
return 0;
700
}
701
702
/*
703
* Function irlap_max_line_capacity (speed, max_turn_time, min_turn_time)
704
*
705
* Calculate the maximum line capacity
706
*
707
*/
708
__u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
709
{
710
__u32 line_capacity;
711
int i,j;
712
713
IRDA_DEBUG(2, "%s(), speed=%d, max_turn_time=%d\n",
714
__func__, speed, max_turn_time);
715
716
i = value_index(speed, baud_rates, 10);
717
j = value_index(max_turn_time, max_turn_times, 4);
718
719
IRDA_ASSERT(((i >=0) && (i <10)), return 0;);
720
IRDA_ASSERT(((j >=0) && (j <4)), return 0;);
721
722
line_capacity = max_line_capacities[i][j];
723
724
IRDA_DEBUG(2, "%s(), line capacity=%d bytes\n",
725
__func__, line_capacity);
726
727
return line_capacity;
728
}
729
730
#ifndef CONFIG_IRDA_DYNAMIC_WINDOW
731
static __u32 irlap_requested_line_capacity(struct qos_info *qos)
732
{
733
__u32 line_capacity;
734
735
line_capacity = qos->window_size.value *
736
(qos->data_size.value + 6 + qos->additional_bofs.value) +
737
irlap_min_turn_time_in_bytes(qos->baud_rate.value,
738
qos->min_turn_time.value);
739
740
IRDA_DEBUG(2, "%s(), requested line capacity=%d\n",
741
__func__, line_capacity);
742
743
return line_capacity;
744
}
745
#endif
746
747
void irda_qos_bits_to_value(struct qos_info *qos)
748
{
749
int index;
750
751
IRDA_ASSERT(qos != NULL, return;);
752
753
index = msb_index(qos->baud_rate.bits);
754
qos->baud_rate.value = baud_rates[index];
755
756
index = msb_index(qos->data_size.bits);
757
qos->data_size.value = data_sizes[index];
758
759
index = msb_index(qos->window_size.bits);
760
qos->window_size.value = index+1;
761
762
index = msb_index(qos->min_turn_time.bits);
763
qos->min_turn_time.value = min_turn_times[index];
764
765
index = msb_index(qos->max_turn_time.bits);
766
qos->max_turn_time.value = max_turn_times[index];
767
768
index = msb_index(qos->link_disc_time.bits);
769
qos->link_disc_time.value = link_disc_times[index];
770
771
index = msb_index(qos->additional_bofs.bits);
772
qos->additional_bofs.value = add_bofs[index];
773
}
774
EXPORT_SYMBOL(irda_qos_bits_to_value);
775
776