diff options
Diffstat (limited to 'drivers/isdn/gigaset/asyncdata.c')
-rw-r--r-- | drivers/isdn/gigaset/asyncdata.c | 124 |
1 files changed, 58 insertions, 66 deletions
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 44a58e6f8f65..a25216bf475e 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c | |||
@@ -119,10 +119,7 @@ static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, | |||
119 | int inputstate = bcs->inputstate; | 119 | int inputstate = bcs->inputstate; |
120 | __u16 fcs = bcs->fcs; | 120 | __u16 fcs = bcs->fcs; |
121 | struct sk_buff *skb = bcs->skb; | 121 | struct sk_buff *skb = bcs->skb; |
122 | unsigned char error; | ||
123 | struct sk_buff *compskb; | ||
124 | int startbytes = numbytes; | 122 | int startbytes = numbytes; |
125 | int l; | ||
126 | 123 | ||
127 | if (unlikely(inputstate & INS_byte_stuff)) { | 124 | if (unlikely(inputstate & INS_byte_stuff)) { |
128 | inputstate &= ~INS_byte_stuff; | 125 | inputstate &= ~INS_byte_stuff; |
@@ -158,8 +155,8 @@ byte_stuff: | |||
158 | #endif | 155 | #endif |
159 | 156 | ||
160 | /* end of frame */ | 157 | /* end of frame */ |
161 | error = 1; | 158 | gigaset_isdn_rcv_err(bcs); |
162 | gigaset_rcv_error(NULL, cs, bcs); | 159 | dev_kfree_skb(skb); |
163 | } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ | 160 | } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ |
164 | #ifdef CONFIG_GIGASET_DEBUG | 161 | #ifdef CONFIG_GIGASET_DEBUG |
165 | ++bcs->emptycount; | 162 | ++bcs->emptycount; |
@@ -170,54 +167,39 @@ byte_stuff: | |||
170 | "7e----------------------------"); | 167 | "7e----------------------------"); |
171 | 168 | ||
172 | /* end of frame */ | 169 | /* end of frame */ |
173 | error = 0; | ||
174 | |||
175 | if (unlikely(fcs != PPP_GOODFCS)) { | 170 | if (unlikely(fcs != PPP_GOODFCS)) { |
176 | dev_err(cs->dev, | 171 | dev_err(cs->dev, |
177 | "Checksum failed, %u bytes corrupted!\n", | 172 | "Checksum failed, %u bytes corrupted!\n", |
178 | skb->len); | 173 | skb->len); |
179 | compskb = NULL; | 174 | gigaset_isdn_rcv_err(bcs); |
180 | gigaset_rcv_error(compskb, cs, bcs); | 175 | dev_kfree_skb(skb); |
181 | error = 1; | 176 | } else if (likely(skb->len > 2)) { |
177 | __skb_trim(skb, skb->len - 2); | ||
178 | gigaset_skb_rcvd(bcs, skb); | ||
182 | } else { | 179 | } else { |
183 | if (likely((l = skb->len) > 2)) { | 180 | if (skb->len) { |
184 | skb->tail -= 2; | 181 | dev_err(cs->dev, |
185 | skb->len -= 2; | 182 | "invalid packet size (%d)\n", skb->len); |
186 | } else { | 183 | gigaset_isdn_rcv_err(bcs); |
187 | dev_kfree_skb(skb); | ||
188 | skb = NULL; | ||
189 | inputstate |= INS_skip_frame; | ||
190 | if (l == 1) { | ||
191 | dev_err(cs->dev, | ||
192 | "invalid packet size (1)!\n"); | ||
193 | error = 1; | ||
194 | gigaset_rcv_error(NULL, | ||
195 | cs, bcs); | ||
196 | } | ||
197 | } | ||
198 | if (likely(!(error || | ||
199 | (inputstate & | ||
200 | INS_skip_frame)))) { | ||
201 | gigaset_rcv_skb(skb, cs, bcs); | ||
202 | } | 184 | } |
185 | dev_kfree_skb(skb); | ||
203 | } | 186 | } |
204 | } | 187 | } |
205 | 188 | ||
206 | if (unlikely(error)) | ||
207 | if (skb) | ||
208 | dev_kfree_skb(skb); | ||
209 | |||
210 | fcs = PPP_INITFCS; | 189 | fcs = PPP_INITFCS; |
211 | inputstate &= ~(INS_have_data | INS_skip_frame); | 190 | inputstate &= ~(INS_have_data | INS_skip_frame); |
212 | if (unlikely(bcs->ignore)) { | 191 | if (unlikely(bcs->ignore)) { |
213 | inputstate |= INS_skip_frame; | 192 | inputstate |= INS_skip_frame; |
214 | skb = NULL; | 193 | skb = NULL; |
215 | } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) { | ||
216 | skb_reserve(skb, HW_HDR_LEN); | ||
217 | } else { | 194 | } else { |
218 | dev_warn(cs->dev, | 195 | skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); |
219 | "could not allocate new skb\n"); | 196 | if (skb != NULL) { |
220 | inputstate |= INS_skip_frame; | 197 | skb_reserve(skb, cs->hw_hdr_len); |
198 | } else { | ||
199 | dev_warn(cs->dev, | ||
200 | "could not allocate new skb\n"); | ||
201 | inputstate |= INS_skip_frame; | ||
202 | } | ||
221 | } | 203 | } |
222 | 204 | ||
223 | break; | 205 | break; |
@@ -314,18 +296,21 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, | |||
314 | /* pass data up */ | 296 | /* pass data up */ |
315 | if (likely(inputstate & INS_have_data)) { | 297 | if (likely(inputstate & INS_have_data)) { |
316 | if (likely(!(inputstate & INS_skip_frame))) { | 298 | if (likely(!(inputstate & INS_skip_frame))) { |
317 | gigaset_rcv_skb(skb, cs, bcs); | 299 | gigaset_skb_rcvd(bcs, skb); |
318 | } | 300 | } |
319 | inputstate &= ~(INS_have_data | INS_skip_frame); | 301 | inputstate &= ~(INS_have_data | INS_skip_frame); |
320 | if (unlikely(bcs->ignore)) { | 302 | if (unlikely(bcs->ignore)) { |
321 | inputstate |= INS_skip_frame; | 303 | inputstate |= INS_skip_frame; |
322 | skb = NULL; | 304 | skb = NULL; |
323 | } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) | ||
324 | != NULL)) { | ||
325 | skb_reserve(skb, HW_HDR_LEN); | ||
326 | } else { | 305 | } else { |
327 | dev_warn(cs->dev, "could not allocate new skb\n"); | 306 | skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); |
328 | inputstate |= INS_skip_frame; | 307 | if (skb != NULL) { |
308 | skb_reserve(skb, cs->hw_hdr_len); | ||
309 | } else { | ||
310 | dev_warn(cs->dev, | ||
311 | "could not allocate new skb\n"); | ||
312 | inputstate |= INS_skip_frame; | ||
313 | } | ||
329 | } | 314 | } |
330 | } | 315 | } |
331 | 316 | ||
@@ -383,7 +368,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) | |||
383 | /* FIXME use function pointers? */ | 368 | /* FIXME use function pointers? */ |
384 | if (inbuf->inputstate & INS_command) | 369 | if (inbuf->inputstate & INS_command) |
385 | procbytes = cmd_loop(c, src, numbytes, inbuf); | 370 | procbytes = cmd_loop(c, src, numbytes, inbuf); |
386 | else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC) | 371 | else if (inbuf->bcs->proto2 == L2_HDLC) |
387 | procbytes = hdlc_loop(c, src, numbytes, inbuf); | 372 | procbytes = hdlc_loop(c, src, numbytes, inbuf); |
388 | else | 373 | else |
389 | procbytes = iraw_loop(c, src, numbytes, inbuf); | 374 | procbytes = iraw_loop(c, src, numbytes, inbuf); |
@@ -440,16 +425,16 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input); | |||
440 | 425 | ||
441 | /* == data output ========================================================== */ | 426 | /* == data output ========================================================== */ |
442 | 427 | ||
443 | /* Encoding of a PPP packet into an octet stuffed HDLC frame | 428 | /* |
444 | * with FCS, opening and closing flags. | 429 | * Encode a data packet into an octet stuffed HDLC frame with FCS, |
430 | * opening and closing flags, preserving headroom data. | ||
445 | * parameters: | 431 | * parameters: |
446 | * skb skb containing original packet (freed upon return) | 432 | * skb skb containing original packet (freed upon return) |
447 | * head number of headroom bytes to allocate in result skb | 433 | * headroom number of headroom bytes to preserve |
448 | * tail number of tailroom bytes to allocate in result skb | ||
449 | * Return value: | 434 | * Return value: |
450 | * pointer to newly allocated skb containing the result frame | 435 | * pointer to newly allocated skb containing the result frame |
451 | */ | 436 | */ |
452 | static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) | 437 | static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) |
453 | { | 438 | { |
454 | struct sk_buff *hdlc_skb; | 439 | struct sk_buff *hdlc_skb; |
455 | __u16 fcs; | 440 | __u16 fcs; |
@@ -471,16 +456,17 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) | |||
471 | 456 | ||
472 | /* size of new buffer: original size + number of stuffing bytes | 457 | /* size of new buffer: original size + number of stuffing bytes |
473 | * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes | 458 | * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes |
459 | * + room for acknowledgement header | ||
474 | */ | 460 | */ |
475 | hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head); | 461 | hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + headroom); |
476 | if (!hdlc_skb) { | 462 | if (!hdlc_skb) { |
477 | dev_kfree_skb(skb); | 463 | dev_kfree_skb(skb); |
478 | return NULL; | 464 | return NULL; |
479 | } | 465 | } |
480 | skb_reserve(hdlc_skb, head); | ||
481 | 466 | ||
482 | /* Copy acknowledge request into new skb */ | 467 | /* Copy acknowledgement header into new skb */ |
483 | memcpy(hdlc_skb->head, skb->head, 2); | 468 | skb_reserve(hdlc_skb, headroom); |
469 | memcpy(hdlc_skb->head, skb->head, headroom); | ||
484 | 470 | ||
485 | /* Add flag sequence in front of everything.. */ | 471 | /* Add flag sequence in front of everything.. */ |
486 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; | 472 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; |
@@ -515,15 +501,16 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) | |||
515 | return hdlc_skb; | 501 | return hdlc_skb; |
516 | } | 502 | } |
517 | 503 | ||
518 | /* Encoding of a raw packet into an octet stuffed bit inverted frame | 504 | /* |
505 | * Encode a data packet into an octet stuffed raw bit inverted frame, | ||
506 | * preserving headroom data. | ||
519 | * parameters: | 507 | * parameters: |
520 | * skb skb containing original packet (freed upon return) | 508 | * skb skb containing original packet (freed upon return) |
521 | * head number of headroom bytes to allocate in result skb | 509 | * headroom number of headroom bytes to preserve |
522 | * tail number of tailroom bytes to allocate in result skb | ||
523 | * Return value: | 510 | * Return value: |
524 | * pointer to newly allocated skb containing the result frame | 511 | * pointer to newly allocated skb containing the result frame |
525 | */ | 512 | */ |
526 | static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | 513 | static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom) |
527 | { | 514 | { |
528 | struct sk_buff *iraw_skb; | 515 | struct sk_buff *iraw_skb; |
529 | unsigned char c; | 516 | unsigned char c; |
@@ -531,12 +518,15 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | |||
531 | int len; | 518 | int len; |
532 | 519 | ||
533 | /* worst case: every byte must be stuffed */ | 520 | /* worst case: every byte must be stuffed */ |
534 | iraw_skb = dev_alloc_skb(2*skb->len + tail + head); | 521 | iraw_skb = dev_alloc_skb(2*skb->len + headroom); |
535 | if (!iraw_skb) { | 522 | if (!iraw_skb) { |
536 | dev_kfree_skb(skb); | 523 | dev_kfree_skb(skb); |
537 | return NULL; | 524 | return NULL; |
538 | } | 525 | } |
539 | skb_reserve(iraw_skb, head); | 526 | |
527 | /* Copy acknowledgement header into new skb */ | ||
528 | skb_reserve(iraw_skb, headroom); | ||
529 | memcpy(iraw_skb->head, skb->head, headroom); | ||
540 | 530 | ||
541 | cp = skb->data; | 531 | cp = skb->data; |
542 | len = skb->len; | 532 | len = skb->len; |
@@ -555,8 +545,10 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | |||
555 | * @bcs: B channel descriptor structure. | 545 | * @bcs: B channel descriptor structure. |
556 | * @skb: data to send. | 546 | * @skb: data to send. |
557 | * | 547 | * |
558 | * Called by i4l.c to encode and queue an skb for sending, and start | 548 | * Called by LL to encode and queue an skb for sending, and start |
559 | * transmission if necessary. | 549 | * transmission if necessary. |
550 | * Once the payload data has been transmitted completely, gigaset_skb_sent() | ||
551 | * will be called with the first cs->hw_hdr_len bytes of skb->head preserved. | ||
560 | * | 552 | * |
561 | * Return value: | 553 | * Return value: |
562 | * number of bytes accepted for sending (skb->len) if ok, | 554 | * number of bytes accepted for sending (skb->len) if ok, |
@@ -567,10 +559,10 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) | |||
567 | unsigned len = skb->len; | 559 | unsigned len = skb->len; |
568 | unsigned long flags; | 560 | unsigned long flags; |
569 | 561 | ||
570 | if (bcs->proto2 == ISDN_PROTO_L2_HDLC) | 562 | if (bcs->proto2 == L2_HDLC) |
571 | skb = HDLC_Encode(skb, HW_HDR_LEN, 0); | 563 | skb = HDLC_Encode(skb, bcs->cs->hw_hdr_len); |
572 | else | 564 | else |
573 | skb = iraw_encode(skb, HW_HDR_LEN, 0); | 565 | skb = iraw_encode(skb, bcs->cs->hw_hdr_len); |
574 | if (!skb) { | 566 | if (!skb) { |
575 | dev_err(bcs->cs->dev, | 567 | dev_err(bcs->cs->dev, |
576 | "unable to allocate memory for encoding!\n"); | 568 | "unable to allocate memory for encoding!\n"); |