~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/irda/qos.c

Version: ~ [ linux-5.4-rc3 ] ~ [ linux-5.3.6 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.79 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.149 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.196 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.196 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.75 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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, see <http://www.gnu.org/licenses/>.
 28  *
 29  ********************************************************************/
 30 
 31 #include <linux/export.h>
 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 int 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 int 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 int 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 const 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 const 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 const 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                 net_warn_ratelimited("%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         /*
346          * Make sure the mintt is sensible.
347          * Main culprit : Ericsson T39. - Jean II
348          */
349         if (sysctl_min_tx_turn_time > qos->min_turn_time.value) {
350                 int i;
351 
352                 net_warn_ratelimited("%s(), Detected buggy peer, adjust mtt to %dus!\n",
353                                      __func__, sysctl_min_tx_turn_time);
354 
355                 /* We don't really need bits, but easier this way */
356                 i = value_highest_bit(sysctl_min_tx_turn_time, min_turn_times,
357                                       8, &qos->min_turn_time.bits);
358                 sysctl_min_tx_turn_time = index_value(i, min_turn_times);
359                 qos->min_turn_time.value = sysctl_min_tx_turn_time;
360         }
361 
362         /*
363          * Not allowed to use a max turn time less than 500 ms if the baudrate
364          * is less than 115200
365          */
366         if ((qos->baud_rate.value < 115200) &&
367             (qos->max_turn_time.value < 500))
368         {
369                 pr_debug("%s(), adjusting max turn time from %d to 500 ms\n",
370                          __func__, qos->max_turn_time.value);
371                 qos->max_turn_time.value = 500;
372         }
373 
374         /*
375          * The data size must be adjusted according to the baud rate and max
376          * turn time
377          */
378         index = value_index(qos->data_size.value, data_sizes, 6);
379         line_capacity = irlap_max_line_capacity(qos->baud_rate.value,
380                                                 qos->max_turn_time.value);
381 
382 #ifdef CONFIG_IRDA_DYNAMIC_WINDOW
383         while ((qos->data_size.value > line_capacity) && (index > 0)) {
384                 qos->data_size.value = data_sizes[index--];
385                 pr_debug("%s(), reducing data size to %d\n",
386                          __func__, qos->data_size.value);
387         }
388 #else /* Use method described in section 6.6.11 of IrLAP */
389         while (irlap_requested_line_capacity(qos) > line_capacity) {
390                 IRDA_ASSERT(index != 0, return;);
391 
392                 /* Must be able to send at least one frame */
393                 if (qos->window_size.value > 1) {
394                         qos->window_size.value--;
395                         pr_debug("%s(), reducing window size to %d\n",
396                                  __func__, qos->window_size.value);
397                 } else if (index > 1) {
398                         qos->data_size.value = data_sizes[index--];
399                         pr_debug("%s(), reducing data size to %d\n",
400                                  __func__, qos->data_size.value);
401                 } else {
402                         net_warn_ratelimited("%s(), nothing more we can do!\n",
403                                              __func__);
404                 }
405         }
406 #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
407         /*
408          * Fix tx data size according to user limits - Jean II
409          */
410         if (qos->data_size.value > sysctl_max_tx_data_size)
411                 /* Allow non discrete adjustement to avoid losing capacity */
412                 qos->data_size.value = sysctl_max_tx_data_size;
413         /*
414          * Override Tx window if user request it. - Jean II
415          */
416         if (qos->window_size.value > sysctl_max_tx_window)
417                 qos->window_size.value = sysctl_max_tx_window;
418 }
419 
420 /*
421  * Function irlap_negotiate (qos_device, qos_session, skb)
422  *
423  *    Negotiate QoS values, not really that much negotiation :-)
424  *    We just set the QoS capabilities for the peer station
425  *
426  */
427 int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb)
428 {
429         int ret;
430 
431         ret = irda_param_extract_all(self, skb->data, skb->len,
432                                      &irlap_param_info);
433 
434         /* Convert the negotiated bits to values */
435         irda_qos_bits_to_value(&self->qos_tx);
436         irda_qos_bits_to_value(&self->qos_rx);
437 
438         irlap_adjust_qos_settings(&self->qos_tx);
439 
440         pr_debug("Setting BAUD_RATE to %d bps.\n",
441                  self->qos_tx.baud_rate.value);
442         pr_debug("Setting DATA_SIZE to %d bytes\n",
443                  self->qos_tx.data_size.value);
444         pr_debug("Setting WINDOW_SIZE to %d\n",
445                  self->qos_tx.window_size.value);
446         pr_debug("Setting XBOFS to %d\n",
447                  self->qos_tx.additional_bofs.value);
448         pr_debug("Setting MAX_TURN_TIME to %d ms.\n",
449                  self->qos_tx.max_turn_time.value);
450         pr_debug("Setting MIN_TURN_TIME to %d usecs.\n",
451                  self->qos_tx.min_turn_time.value);
452         pr_debug("Setting LINK_DISC to %d secs.\n",
453                  self->qos_tx.link_disc_time.value);
454         return ret;
455 }
456 
457 /*
458  * Function irlap_insert_negotiation_params (qos, fp)
459  *
460  *    Insert QoS negotiaion pararameters into frame
461  *
462  */
463 int irlap_insert_qos_negotiation_params(struct irlap_cb *self,
464                                         struct sk_buff *skb)
465 {
466         int ret;
467 
468         /* Insert data rate */
469         ret = irda_param_insert(self, PI_BAUD_RATE, skb_tail_pointer(skb),
470                                 skb_tailroom(skb), &irlap_param_info);
471         if (ret < 0)
472                 return ret;
473         skb_put(skb, ret);
474 
475         /* Insert max turnaround time */
476         ret = irda_param_insert(self, PI_MAX_TURN_TIME, skb_tail_pointer(skb),
477                                 skb_tailroom(skb), &irlap_param_info);
478         if (ret < 0)
479                 return ret;
480         skb_put(skb, ret);
481 
482         /* Insert data size */
483         ret = irda_param_insert(self, PI_DATA_SIZE, skb_tail_pointer(skb),
484                                 skb_tailroom(skb), &irlap_param_info);
485         if (ret < 0)
486                 return ret;
487         skb_put(skb, ret);
488 
489         /* Insert window size */
490         ret = irda_param_insert(self, PI_WINDOW_SIZE, skb_tail_pointer(skb),
491                                 skb_tailroom(skb), &irlap_param_info);
492         if (ret < 0)
493                 return ret;
494         skb_put(skb, ret);
495 
496         /* Insert additional BOFs */
497         ret = irda_param_insert(self, PI_ADD_BOFS, skb_tail_pointer(skb),
498                                 skb_tailroom(skb), &irlap_param_info);
499         if (ret < 0)
500                 return ret;
501         skb_put(skb, ret);
502 
503         /* Insert minimum turnaround time */
504         ret = irda_param_insert(self, PI_MIN_TURN_TIME, skb_tail_pointer(skb),
505                                 skb_tailroom(skb), &irlap_param_info);
506         if (ret < 0)
507                 return ret;
508         skb_put(skb, ret);
509 
510         /* Insert link disconnect/threshold time */
511         ret = irda_param_insert(self, PI_LINK_DISC, skb_tail_pointer(skb),
512                                 skb_tailroom(skb), &irlap_param_info);
513         if (ret < 0)
514                 return ret;
515         skb_put(skb, ret);
516 
517         return 0;
518 }
519 
520 /*
521  * Function irlap_param_baud_rate (instance, param, get)
522  *
523  *    Negotiate data-rate
524  *
525  */
526 static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get)
527 {
528         __u16 final;
529 
530         struct irlap_cb *self = (struct irlap_cb *) instance;
531 
532         IRDA_ASSERT(self != NULL, return -1;);
533         IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
534 
535         if (get) {
536                 param->pv.i = self->qos_rx.baud_rate.bits;
537                 pr_debug("%s(), baud rate = 0x%02x\n",
538                          __func__, param->pv.i);
539         } else {
540                 /*
541                  *  Stations must agree on baud rate, so calculate
542                  *  intersection
543                  */
544                 pr_debug("Requested BAUD_RATE: 0x%04x\n", (__u16)param->pv.i);
545                 final = (__u16) param->pv.i & self->qos_rx.baud_rate.bits;
546 
547                 pr_debug("Final BAUD_RATE: 0x%04x\n", final);
548                 self->qos_tx.baud_rate.bits = final;
549                 self->qos_rx.baud_rate.bits = final;
550         }
551 
552         return 0;
553 }
554 
555 /*
556  * Function irlap_param_link_disconnect (instance, param, get)
557  *
558  *    Negotiate link disconnect/threshold time.
559  *
560  */
561 static int irlap_param_link_disconnect(void *instance, irda_param_t *param,
562                                        int get)
563 {
564         __u16 final;
565 
566         struct irlap_cb *self = (struct irlap_cb *) instance;
567 
568         IRDA_ASSERT(self != NULL, return -1;);
569         IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
570 
571         if (get)
572                 param->pv.i = self->qos_rx.link_disc_time.bits;
573         else {
574                 /*
575                  *  Stations must agree on link disconnect/threshold
576                  *  time.
577                  */
578                 pr_debug("LINK_DISC: %02x\n", (__u8)param->pv.i);
579                 final = (__u8) param->pv.i & self->qos_rx.link_disc_time.bits;
580 
581                 pr_debug("Final LINK_DISC: %02x\n", final);
582                 self->qos_tx.link_disc_time.bits = final;
583                 self->qos_rx.link_disc_time.bits = final;
584         }
585         return 0;
586 }
587 
588 /*
589  * Function irlap_param_max_turn_time (instance, param, get)
590  *
591  *    Negotiate the maximum turnaround time. This is a type 1 parameter and
592  *    will be negotiated independently for each station
593  *
594  */
595 static int irlap_param_max_turn_time(void *instance, irda_param_t *param,
596                                      int get)
597 {
598         struct irlap_cb *self = (struct irlap_cb *) instance;
599 
600         IRDA_ASSERT(self != NULL, return -1;);
601         IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
602 
603         if (get)
604                 param->pv.i = self->qos_rx.max_turn_time.bits;
605         else
606                 self->qos_tx.max_turn_time.bits = (__u8) param->pv.i;
607 
608         return 0;
609 }
610 
611 /*
612  * Function irlap_param_data_size (instance, param, get)
613  *
614  *    Negotiate the data size. This is a type 1 parameter and
615  *    will be negotiated independently for each station
616  *
617  */
618 static int irlap_param_data_size(void *instance, irda_param_t *param, int get)
619 {
620         struct irlap_cb *self = (struct irlap_cb *) instance;
621 
622         IRDA_ASSERT(self != NULL, return -1;);
623         IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
624 
625         if (get)
626                 param->pv.i = self->qos_rx.data_size.bits;
627         else
628                 self->qos_tx.data_size.bits = (__u8) param->pv.i;
629 
630         return 0;
631 }
632 
633 /*
634  * Function irlap_param_window_size (instance, param, get)
635  *
636  *    Negotiate the window size. This is a type 1 parameter and
637  *    will be negotiated independently for each station
638  *
639  */
640 static int irlap_param_window_size(void *instance, irda_param_t *param,
641                                    int get)
642 {
643         struct irlap_cb *self = (struct irlap_cb *) instance;
644 
645         IRDA_ASSERT(self != NULL, return -1;);
646         IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
647 
648         if (get)
649                 param->pv.i = self->qos_rx.window_size.bits;
650         else
651                 self->qos_tx.window_size.bits = (__u8) param->pv.i;
652 
653         return 0;
654 }
655 
656 /*
657  * Function irlap_param_additional_bofs (instance, param, get)
658  *
659  *    Negotiate additional BOF characters. This is a type 1 parameter and
660  *    will be negotiated independently for each station.
661  */
662 static int irlap_param_additional_bofs(void *instance, irda_param_t *param, int get)
663 {
664         struct irlap_cb *self = (struct irlap_cb *) instance;
665 
666         IRDA_ASSERT(self != NULL, return -1;);
667         IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
668 
669         if (get)
670                 param->pv.i = self->qos_rx.additional_bofs.bits;
671         else
672                 self->qos_tx.additional_bofs.bits = (__u8) param->pv.i;
673 
674         return 0;
675 }
676 
677 /*
678  * Function irlap_param_min_turn_time (instance, param, get)
679  *
680  *    Negotiate the minimum turn around time. This is a type 1 parameter and
681  *    will be negotiated independently for each station
682  */
683 static int irlap_param_min_turn_time(void *instance, irda_param_t *param,
684                                      int get)
685 {
686         struct irlap_cb *self = (struct irlap_cb *) instance;
687 
688         IRDA_ASSERT(self != NULL, return -1;);
689         IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
690 
691         if (get)
692                 param->pv.i = self->qos_rx.min_turn_time.bits;
693         else
694                 self->qos_tx.min_turn_time.bits = (__u8) param->pv.i;
695 
696         return 0;
697 }
698 
699 /*
700  * Function irlap_max_line_capacity (speed, max_turn_time, min_turn_time)
701  *
702  *    Calculate the maximum line capacity
703  *
704  */
705 __u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
706 {
707         __u32 line_capacity;
708         int i,j;
709 
710         pr_debug("%s(), speed=%d, max_turn_time=%d\n",
711                  __func__, speed, max_turn_time);
712 
713         i = value_index(speed, baud_rates, 10);
714         j = value_index(max_turn_time, max_turn_times, 4);
715 
716         IRDA_ASSERT(((i >=0) && (i <10)), return 0;);
717         IRDA_ASSERT(((j >=0) && (j <4)), return 0;);
718 
719         line_capacity = max_line_capacities[i][j];
720 
721         pr_debug("%s(), line capacity=%d bytes\n",
722                  __func__, line_capacity);
723 
724         return line_capacity;
725 }
726 
727 #ifndef CONFIG_IRDA_DYNAMIC_WINDOW
728 static __u32 irlap_requested_line_capacity(struct qos_info *qos)
729 {
730         __u32 line_capacity;
731 
732         line_capacity = qos->window_size.value *
733                 (qos->data_size.value + 6 + qos->additional_bofs.value) +
734                 irlap_min_turn_time_in_bytes(qos->baud_rate.value,
735                                              qos->min_turn_time.value);
736 
737         pr_debug("%s(), requested line capacity=%d\n",
738                  __func__, line_capacity);
739 
740         return line_capacity;
741 }
742 #endif
743 
744 void irda_qos_bits_to_value(struct qos_info *qos)
745 {
746         int index;
747 
748         IRDA_ASSERT(qos != NULL, return;);
749 
750         index = msb_index(qos->baud_rate.bits);
751         qos->baud_rate.value = baud_rates[index];
752 
753         index = msb_index(qos->data_size.bits);
754         qos->data_size.value = data_sizes[index];
755 
756         index = msb_index(qos->window_size.bits);
757         qos->window_size.value = index+1;
758 
759         index = msb_index(qos->min_turn_time.bits);
760         qos->min_turn_time.value = min_turn_times[index];
761 
762         index = msb_index(qos->max_turn_time.bits);
763         qos->max_turn_time.value = max_turn_times[index];
764 
765         index = msb_index(qos->link_disc_time.bits);
766         qos->link_disc_time.value = link_disc_times[index];
767 
768         index = msb_index(qos->additional_bofs.bits);
769         qos->additional_bofs.value = add_bofs[index];
770 }
771 EXPORT_SYMBOL(irda_qos_bits_to_value);
772 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp