]> git.karo-electronics.de Git - mv-sheeva.git/blob - net/irda/wrapper.c
[NET]: Avoid atomic xchg() for non-error case
[mv-sheeva.git] / net / irda / wrapper.c
1 /*********************************************************************
2  *
3  * Filename:      wrapper.c
4  * Version:       1.2
5  * Description:   IrDA SIR async wrapper layer
6  * Status:        Stable
7  * Author:        Dag Brattli <dagb@cs.uit.no>
8  * Created at:    Mon Aug  4 20:40:53 1997
9  * Modified at:   Fri Jan 28 13:21:09 2000
10  * Modified by:   Dag Brattli <dagb@cs.uit.no>
11  * Modified at:   Fri May 28  3:11 CST 1999
12  * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
13  *
14  *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
15  *     All Rights Reserved.
16  *     Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
17  *
18  *     This program is free software; you can redistribute it and/or
19  *     modify it under the terms of the GNU General Public License as
20  *     published by the Free Software Foundation; either version 2 of
21  *     the License, or (at your option) any later version.
22  *
23  *     Neither Dag Brattli nor University of Tromsø admit liability nor
24  *     provide warranty for any of this software. This material is
25  *     provided "AS-IS" and at no charge.
26  *
27  ********************************************************************/
28
29 #include <linux/skbuff.h>
30 #include <linux/string.h>
31 #include <linux/module.h>
32 #include <asm/byteorder.h>
33
34 #include <net/irda/irda.h>
35 #include <net/irda/wrapper.h>
36 #include <net/irda/crc.h>
37 #include <net/irda/irlap.h>
38 #include <net/irda/irlap_frame.h>
39 #include <net/irda/irda_device.h>
40
41 /************************** FRAME WRAPPING **************************/
42 /*
43  * Unwrap and unstuff SIR frames
44  *
45  * Note : at FIR and MIR, HDLC framing is used and usually handled
46  * by the controller, so we come here only for SIR... Jean II
47  */
48
49 /*
50  * Function stuff_byte (byte, buf)
51  *
52  *    Byte stuff one single byte and put the result in buffer pointed to by
53  *    buf. The buffer must at all times be able to have two bytes inserted.
54  *
55  * This is in a tight loop, better inline it, so need to be prior to callers.
56  * (2000 bytes on P6 200MHz, non-inlined ~370us, inline ~170us) - Jean II
57  */
58 static inline int stuff_byte(__u8 byte, __u8 *buf)
59 {
60         switch (byte) {
61         case BOF: /* FALLTHROUGH */
62         case EOF: /* FALLTHROUGH */
63         case CE:
64                 /* Insert transparently coded */
65                 buf[0] = CE;               /* Send link escape */
66                 buf[1] = byte^IRDA_TRANS;    /* Complement bit 5 */
67                 return 2;
68                 /* break; */
69         default:
70                  /* Non-special value, no transparency required */
71                 buf[0] = byte;
72                 return 1;
73                 /* break; */
74         }
75 }
76
77 /*
78  * Function async_wrap (skb, *tx_buff, buffsize)
79  *
80  *    Makes a new buffer with wrapping and stuffing, should check that
81  *    we don't get tx buffer overflow.
82  */
83 int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
84 {
85         struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
86         int xbofs;
87         int i;
88         int n;
89         union {
90                 __u16 value;
91                 __u8 bytes[2];
92         } fcs;
93
94         /* Initialize variables */
95         fcs.value = INIT_FCS;
96         n = 0;
97
98         /*
99          *  Send  XBOF's for required min. turn time and for the negotiated
100          *  additional XBOFS
101          */
102
103         if (cb->magic != LAP_MAGIC) {
104                 /*
105                  * This will happen for all frames sent from user-space.
106                  * Nothing to worry about, but we set the default number of
107                  * BOF's
108                  */
109                 IRDA_DEBUG(1, "%s(), wrong magic in skb!\n", __FUNCTION__);
110                 xbofs = 10;
111         } else
112                 xbofs = cb->xbofs + cb->xbofs_delay;
113
114         IRDA_DEBUG(4, "%s(), xbofs=%d\n", __FUNCTION__, xbofs);
115
116         /* Check that we never use more than 115 + 48 xbofs */
117         if (xbofs > 163) {
118                 IRDA_DEBUG(0, "%s(), too many xbofs (%d)\n", __FUNCTION__,
119                            xbofs);
120                 xbofs = 163;
121         }
122
123         memset(tx_buff + n, XBOF, xbofs);
124         n += xbofs;
125
126         /* Start of packet character BOF */
127         tx_buff[n++] = BOF;
128
129         /* Insert frame and calc CRC */
130         for (i=0; i < skb->len; i++) {
131                 /*
132                  *  Check for the possibility of tx buffer overflow. We use
133                  *  bufsize-5 since the maximum number of bytes that can be
134                  *  transmitted after this point is 5.
135                  */
136                 if(n >= (buffsize-5)) {
137                         IRDA_ERROR("%s(), tx buffer overflow (n=%d)\n",
138                                    __FUNCTION__, n);
139                         return n;
140                 }
141
142                 n += stuff_byte(skb->data[i], tx_buff+n);
143                 fcs.value = irda_fcs(fcs.value, skb->data[i]);
144         }
145
146         /* Insert CRC in little endian format (LSB first) */
147         fcs.value = ~fcs.value;
148 #ifdef __LITTLE_ENDIAN
149         n += stuff_byte(fcs.bytes[0], tx_buff+n);
150         n += stuff_byte(fcs.bytes[1], tx_buff+n);
151 #else /* ifdef __BIG_ENDIAN */
152         n += stuff_byte(fcs.bytes[1], tx_buff+n);
153         n += stuff_byte(fcs.bytes[0], tx_buff+n);
154 #endif
155         tx_buff[n++] = EOF;
156
157         return n;
158 }
159 EXPORT_SYMBOL(async_wrap_skb);
160
161 /************************* FRAME UNWRAPPING *************************/
162 /*
163  * Unwrap and unstuff SIR frames
164  *
165  * Complete rewrite by Jean II :
166  * More inline, faster, more compact, more logical. Jean II
167  * (16 bytes on P6 200MHz, old 5 to 7 us, new 4 to 6 us)
168  * (24 bytes on P6 200MHz, old 9 to 10 us, new 7 to 8 us)
169  * (for reference, 115200 b/s is 1 byte every 69 us)
170  * And reduce wrapper.o by ~900B in the process ;-)
171  *
172  * Then, we have the addition of ZeroCopy, which is optional
173  * (i.e. the driver must initiate it) and improve final processing.
174  * (2005 B frame + EOF on P6 200MHz, without 30 to 50 us, with 10 to 25 us)
175  *
176  * Note : at FIR and MIR, HDLC framing is used and usually handled
177  * by the controller, so we come here only for SIR... Jean II
178  */
179
180 /*
181  * We can also choose where we want to do the CRC calculation. We can
182  * do it "inline", as we receive the bytes, or "postponed", when
183  * receiving the End-Of-Frame.
184  * (16 bytes on P6 200MHz, inlined 4 to 6 us, postponed 4 to 5 us)
185  * (24 bytes on P6 200MHz, inlined 7 to 8 us, postponed 5 to 7 us)
186  * With ZeroCopy :
187  * (2005 B frame on P6 200MHz, inlined 10 to 25 us, postponed 140 to 180 us)
188  * Without ZeroCopy :
189  * (2005 B frame on P6 200MHz, inlined 30 to 50 us, postponed 150 to 180 us)
190  * (Note : numbers taken with irq disabled)
191  *
192  * From those numbers, it's not clear which is the best strategy, because
193  * we end up running through a lot of data one way or another (i.e. cache
194  * misses). I personally prefer to avoid the huge latency spike of the
195  * "postponed" solution, because it come just at the time when we have
196  * lot's of protocol processing to do and it will hurt our ability to
197  * reach low link turnaround times... Jean II
198  */
199 //#define POSTPONE_RX_CRC
200
201 /*
202  * Function async_bump (buf, len, stats)
203  *
204  *    Got a frame, make a copy of it, and pass it up the stack! We can try
205  *    to inline it since it's only called from state_inside_frame
206  */
207 static inline void
208 async_bump(struct net_device *dev,
209            struct net_device_stats *stats,
210            iobuff_t *rx_buff)
211 {
212         struct sk_buff *newskb;
213         struct sk_buff *dataskb;
214         int             docopy;
215
216         /* Check if we need to copy the data to a new skb or not.
217          * If the driver doesn't use ZeroCopy Rx, we have to do it.
218          * With ZeroCopy Rx, the rx_buff already point to a valid
219          * skb. But, if the frame is small, it is more efficient to
220          * copy it to save memory (copy will be fast anyway - that's
221          * called Rx-copy-break). Jean II */
222         docopy = ((rx_buff->skb == NULL) ||
223                   (rx_buff->len < IRDA_RX_COPY_THRESHOLD));
224
225         /* Allocate a new skb */
226         newskb = dev_alloc_skb(docopy ? rx_buff->len + 1 : rx_buff->truesize);
227         if (!newskb)  {
228                 stats->rx_dropped++;
229                 /* We could deliver the current skb if doing ZeroCopy Rx,
230                  * but this would stall the Rx path. Better drop the
231                  * packet... Jean II */
232                 return;
233         }
234
235         /* Align IP header to 20 bytes (i.e. increase skb->data)
236          * Note this is only useful with IrLAN, as PPP has a variable
237          * header size (2 or 1 bytes) - Jean II */
238         skb_reserve(newskb, 1);
239
240         if(docopy) {
241                 /* Copy data without CRC (lenght already checked) */
242                 memcpy(newskb->data, rx_buff->data, rx_buff->len - 2);
243                 /* Deliver this skb */
244                 dataskb = newskb;
245         } else {
246                 /* We are using ZeroCopy. Deliver old skb */
247                 dataskb = rx_buff->skb;
248                 /* And hook the new skb to the rx_buff */
249                 rx_buff->skb = newskb;
250                 rx_buff->head = newskb->data;   /* NOT newskb->head */
251                 //printk(KERN_DEBUG "ZeroCopy : len = %d, dataskb = %p, newskb = %p\n", rx_buff->len, dataskb, newskb);
252         }
253
254         /* Set proper length on skb (without CRC) */
255         skb_put(dataskb, rx_buff->len - 2);
256
257         /* Feed it to IrLAP layer */
258         dataskb->dev = dev;
259         dataskb->mac.raw  = dataskb->data;
260         dataskb->protocol = htons(ETH_P_IRDA);
261
262         netif_rx(dataskb);
263
264         stats->rx_packets++;
265         stats->rx_bytes += rx_buff->len;
266
267         /* Clean up rx_buff (redundant with async_unwrap_bof() ???) */
268         rx_buff->data = rx_buff->head;
269         rx_buff->len = 0;
270 }
271
272 /*
273  * Function async_unwrap_bof(dev, byte)
274  *
275  *    Handle Beginning Of Frame character received within a frame
276  *
277  */
278 static inline void
279 async_unwrap_bof(struct net_device *dev,
280                  struct net_device_stats *stats,
281                  iobuff_t *rx_buff, __u8 byte)
282 {
283         switch(rx_buff->state) {
284         case LINK_ESCAPE:
285         case INSIDE_FRAME:
286                 /* Not supposed to happen, the previous frame is not
287                  * finished - Jean II */
288                 IRDA_DEBUG(1, "%s(), Discarding incomplete frame\n",
289                            __FUNCTION__);
290                 stats->rx_errors++;
291                 stats->rx_missed_errors++;
292                 irda_device_set_media_busy(dev, TRUE);
293                 break;
294
295         case OUTSIDE_FRAME:
296         case BEGIN_FRAME:
297         default:
298                 /* We may receive multiple BOF at the start of frame */ 
299                 break;
300         }
301
302         /* Now receiving frame */
303         rx_buff->state = BEGIN_FRAME;
304         rx_buff->in_frame = TRUE;
305
306         /* Time to initialize receive buffer */
307         rx_buff->data = rx_buff->head;
308         rx_buff->len = 0;
309         rx_buff->fcs = INIT_FCS;
310 }
311
312 /*
313  * Function async_unwrap_eof(dev, byte)
314  *
315  *    Handle End Of Frame character received within a frame
316  *
317  */
318 static inline void
319 async_unwrap_eof(struct net_device *dev,
320                  struct net_device_stats *stats,
321                  iobuff_t *rx_buff, __u8 byte)
322 {
323 #ifdef POSTPONE_RX_CRC
324         int     i;
325 #endif
326
327         switch(rx_buff->state) {
328         case OUTSIDE_FRAME:
329                 /* Probably missed the BOF */
330                 stats->rx_errors++;
331                 stats->rx_missed_errors++;
332                 irda_device_set_media_busy(dev, TRUE);
333                 break;
334
335         case BEGIN_FRAME:
336         case LINK_ESCAPE:
337         case INSIDE_FRAME:
338         default:
339                 /* Note : in the case of BEGIN_FRAME and LINK_ESCAPE,
340                  * the fcs will most likely not match and generate an
341                  * error, as expected - Jean II */
342                 rx_buff->state = OUTSIDE_FRAME;
343                 rx_buff->in_frame = FALSE;
344
345 #ifdef POSTPONE_RX_CRC
346                 /* If we haven't done the CRC as we receive bytes, we
347                  * must do it now... Jean II */
348                 for(i = 0; i < rx_buff->len; i++)
349                         rx_buff->fcs = irda_fcs(rx_buff->fcs,
350                                                 rx_buff->data[i]);
351 #endif
352
353                 /* Test FCS and signal success if the frame is good */
354                 if (rx_buff->fcs == GOOD_FCS) {
355                         /* Deliver frame */
356                         async_bump(dev, stats, rx_buff);
357                         break;
358                 } else {
359                         /* Wrong CRC, discard frame!  */
360                         irda_device_set_media_busy(dev, TRUE);
361
362                         IRDA_DEBUG(1, "%s(), crc error\n", __FUNCTION__);
363                         stats->rx_errors++;
364                         stats->rx_crc_errors++;
365                 }
366                 break;
367         }
368 }
369
370 /*
371  * Function async_unwrap_ce(dev, byte)
372  *
373  *    Handle Character Escape character received within a frame
374  *
375  */
376 static inline void
377 async_unwrap_ce(struct net_device *dev,
378                  struct net_device_stats *stats,
379                  iobuff_t *rx_buff, __u8 byte)
380 {
381         switch(rx_buff->state) {
382         case OUTSIDE_FRAME:
383                 /* Activate carrier sense */
384                 irda_device_set_media_busy(dev, TRUE);
385                 break;
386
387         case LINK_ESCAPE:
388                 IRDA_WARNING("%s: state not defined\n", __FUNCTION__);
389                 break;
390
391         case BEGIN_FRAME:
392         case INSIDE_FRAME:
393         default:
394                 /* Stuffed byte coming */
395                 rx_buff->state = LINK_ESCAPE;
396                 break;
397         }
398 }
399
400 /*
401  * Function async_unwrap_other(dev, byte)
402  *
403  *    Handle other characters received within a frame
404  *
405  */
406 static inline void
407 async_unwrap_other(struct net_device *dev,
408                    struct net_device_stats *stats,
409                    iobuff_t *rx_buff, __u8 byte)
410 {
411         switch(rx_buff->state) {
412                 /* This is on the critical path, case are ordered by
413                  * probability (most frequent first) - Jean II */
414         case INSIDE_FRAME:
415                 /* Must be the next byte of the frame */
416                 if (rx_buff->len < rx_buff->truesize)  {
417                         rx_buff->data[rx_buff->len++] = byte;
418 #ifndef POSTPONE_RX_CRC
419                         rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
420 #endif
421                 } else {
422                         IRDA_DEBUG(1, "%s(), Rx buffer overflow, aborting\n",
423                                    __FUNCTION__);
424                         rx_buff->state = OUTSIDE_FRAME;
425                 }
426                 break;
427
428         case LINK_ESCAPE:
429                 /*
430                  *  Stuffed char, complement bit 5 of byte
431                  *  following CE, IrLAP p.114
432                  */
433                 byte ^= IRDA_TRANS;
434                 if (rx_buff->len < rx_buff->truesize)  {
435                         rx_buff->data[rx_buff->len++] = byte;
436 #ifndef POSTPONE_RX_CRC
437                         rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
438 #endif
439                         rx_buff->state = INSIDE_FRAME;
440                 } else {
441                         IRDA_DEBUG(1, "%s(), Rx buffer overflow, aborting\n",
442                                    __FUNCTION__);
443                         rx_buff->state = OUTSIDE_FRAME;
444                 }
445                 break;
446
447         case OUTSIDE_FRAME:
448                 /* Activate carrier sense */
449                 if(byte != XBOF)
450                         irda_device_set_media_busy(dev, TRUE);
451                 break;
452
453         case BEGIN_FRAME:
454         default:
455                 rx_buff->data[rx_buff->len++] = byte;
456 #ifndef POSTPONE_RX_CRC
457                 rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
458 #endif
459                 rx_buff->state = INSIDE_FRAME;
460                 break;
461         }
462 }
463
464 /*
465  * Function async_unwrap_char (dev, rx_buff, byte)
466  *
467  *    Parse and de-stuff frame received from the IrDA-port
468  *
469  * This is the main entry point for SIR drivers.
470  */
471 void async_unwrap_char(struct net_device *dev,
472                        struct net_device_stats *stats,
473                        iobuff_t *rx_buff, __u8 byte)
474 {
475         switch(byte) {
476         case CE:
477                 async_unwrap_ce(dev, stats, rx_buff, byte);
478                 break;
479         case BOF:
480                 async_unwrap_bof(dev, stats, rx_buff, byte);
481                 break;
482         case EOF:
483                 async_unwrap_eof(dev, stats, rx_buff, byte);
484                 break;
485         default:
486                 async_unwrap_other(dev, stats, rx_buff, byte);
487                 break;
488         }
489 }
490 EXPORT_SYMBOL(async_unwrap_char);
491