Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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