diff options
author | Tilman Schmidt <tilman@imap.cc> | 2010-06-21 09:54:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-26 00:16:59 -0400 |
commit | e7752ee280608a24e27f163641121bdc2c68d6af (patch) | |
tree | a731b1d9b2c95732d2882a52bb20e4af7546de59 /drivers/isdn | |
parent | ed770f01360b392564650bf1553ce723fa46afec (diff) |
isdn/gigaset: honor CAPI application's buffer size request
Fix the Gigaset CAPI driver to limit the length of a connection's
payload data receive buffers to the corresponding CAPI application's
data buffer size, as some real-life CAPI applications tend to be
rather unhappy if they receive bigger data blocks than requested.
Impact: bugfix
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/gigaset/asyncdata.c | 44 | ||||
-rw-r--r-- | drivers/isdn/gigaset/capi.c | 8 | ||||
-rw-r--r-- | drivers/isdn/gigaset/common.c | 32 | ||||
-rw-r--r-- | drivers/isdn/gigaset/gigaset.h | 29 | ||||
-rw-r--r-- | drivers/isdn/gigaset/i4l.c | 21 | ||||
-rw-r--r-- | drivers/isdn/gigaset/isocdata.c | 72 |
6 files changed, 94 insertions, 112 deletions
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index c5016bd2d94f..c3b1dc3a13a0 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c | |||
@@ -126,26 +126,6 @@ static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf) | |||
126 | return numbytes; | 126 | return numbytes; |
127 | } | 127 | } |
128 | 128 | ||
129 | /* set up next receive skb for data mode | ||
130 | */ | ||
131 | static void new_rcv_skb(struct bc_state *bcs) | ||
132 | { | ||
133 | struct cardstate *cs = bcs->cs; | ||
134 | unsigned short hw_hdr_len = cs->hw_hdr_len; | ||
135 | |||
136 | if (bcs->ignore) { | ||
137 | bcs->skb = NULL; | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len); | ||
142 | if (bcs->skb == NULL) { | ||
143 | dev_warn(cs->dev, "could not allocate new skb\n"); | ||
144 | return; | ||
145 | } | ||
146 | skb_reserve(bcs->skb, hw_hdr_len); | ||
147 | } | ||
148 | |||
149 | /* process a block of received bytes in HDLC data mode | 129 | /* process a block of received bytes in HDLC data mode |
150 | * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) | 130 | * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) |
151 | * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. | 131 | * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. |
@@ -159,8 +139,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) | |||
159 | struct cardstate *cs = inbuf->cs; | 139 | struct cardstate *cs = inbuf->cs; |
160 | struct bc_state *bcs = cs->bcs; | 140 | struct bc_state *bcs = cs->bcs; |
161 | int inputstate = bcs->inputstate; | 141 | int inputstate = bcs->inputstate; |
162 | __u16 fcs = bcs->fcs; | 142 | __u16 fcs = bcs->rx_fcs; |
163 | struct sk_buff *skb = bcs->skb; | 143 | struct sk_buff *skb = bcs->rx_skb; |
164 | unsigned char *src = inbuf->data + inbuf->head; | 144 | unsigned char *src = inbuf->data + inbuf->head; |
165 | unsigned procbytes = 0; | 145 | unsigned procbytes = 0; |
166 | unsigned char c; | 146 | unsigned char c; |
@@ -245,8 +225,7 @@ byte_stuff: | |||
245 | 225 | ||
246 | /* prepare reception of next frame */ | 226 | /* prepare reception of next frame */ |
247 | inputstate &= ~INS_have_data; | 227 | inputstate &= ~INS_have_data; |
248 | new_rcv_skb(bcs); | 228 | skb = gigaset_new_rx_skb(bcs); |
249 | skb = bcs->skb; | ||
250 | } else { | 229 | } else { |
251 | /* empty frame (7E 7E) */ | 230 | /* empty frame (7E 7E) */ |
252 | #ifdef CONFIG_GIGASET_DEBUG | 231 | #ifdef CONFIG_GIGASET_DEBUG |
@@ -255,8 +234,7 @@ byte_stuff: | |||
255 | if (!skb) { | 234 | if (!skb) { |
256 | /* skipped (?) */ | 235 | /* skipped (?) */ |
257 | gigaset_isdn_rcv_err(bcs); | 236 | gigaset_isdn_rcv_err(bcs); |
258 | new_rcv_skb(bcs); | 237 | skb = gigaset_new_rx_skb(bcs); |
259 | skb = bcs->skb; | ||
260 | } | 238 | } |
261 | } | 239 | } |
262 | 240 | ||
@@ -279,11 +257,11 @@ byte_stuff: | |||
279 | #endif | 257 | #endif |
280 | inputstate |= INS_have_data; | 258 | inputstate |= INS_have_data; |
281 | if (skb) { | 259 | if (skb) { |
282 | if (skb->len == SBUFSIZE) { | 260 | if (skb->len >= bcs->rx_bufsize) { |
283 | dev_warn(cs->dev, "received packet too long\n"); | 261 | dev_warn(cs->dev, "received packet too long\n"); |
284 | dev_kfree_skb_any(skb); | 262 | dev_kfree_skb_any(skb); |
285 | /* skip remainder of packet */ | 263 | /* skip remainder of packet */ |
286 | bcs->skb = skb = NULL; | 264 | bcs->rx_skb = skb = NULL; |
287 | } else { | 265 | } else { |
288 | *__skb_put(skb, 1) = c; | 266 | *__skb_put(skb, 1) = c; |
289 | fcs = crc_ccitt_byte(fcs, c); | 267 | fcs = crc_ccitt_byte(fcs, c); |
@@ -292,7 +270,7 @@ byte_stuff: | |||
292 | } | 270 | } |
293 | 271 | ||
294 | bcs->inputstate = inputstate; | 272 | bcs->inputstate = inputstate; |
295 | bcs->fcs = fcs; | 273 | bcs->rx_fcs = fcs; |
296 | return procbytes; | 274 | return procbytes; |
297 | } | 275 | } |
298 | 276 | ||
@@ -308,18 +286,18 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) | |||
308 | struct cardstate *cs = inbuf->cs; | 286 | struct cardstate *cs = inbuf->cs; |
309 | struct bc_state *bcs = cs->bcs; | 287 | struct bc_state *bcs = cs->bcs; |
310 | int inputstate = bcs->inputstate; | 288 | int inputstate = bcs->inputstate; |
311 | struct sk_buff *skb = bcs->skb; | 289 | struct sk_buff *skb = bcs->rx_skb; |
312 | unsigned char *src = inbuf->data + inbuf->head; | 290 | unsigned char *src = inbuf->data + inbuf->head; |
313 | unsigned procbytes = 0; | 291 | unsigned procbytes = 0; |
314 | unsigned char c; | 292 | unsigned char c; |
315 | 293 | ||
316 | if (!skb) { | 294 | if (!skb) { |
317 | /* skip this block */ | 295 | /* skip this block */ |
318 | new_rcv_skb(bcs); | 296 | gigaset_new_rx_skb(bcs); |
319 | return numbytes; | 297 | return numbytes; |
320 | } | 298 | } |
321 | 299 | ||
322 | while (procbytes < numbytes && skb->len < SBUFSIZE) { | 300 | while (procbytes < numbytes && skb->len < bcs->rx_bufsize) { |
323 | c = *src++; | 301 | c = *src++; |
324 | procbytes++; | 302 | procbytes++; |
325 | 303 | ||
@@ -343,7 +321,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) | |||
343 | if (inputstate & INS_have_data) { | 321 | if (inputstate & INS_have_data) { |
344 | gigaset_skb_rcvd(bcs, skb); | 322 | gigaset_skb_rcvd(bcs, skb); |
345 | inputstate &= ~INS_have_data; | 323 | inputstate &= ~INS_have_data; |
346 | new_rcv_skb(bcs); | 324 | gigaset_new_rx_skb(bcs); |
347 | } | 325 | } |
348 | 326 | ||
349 | bcs->inputstate = inputstate; | 327 | bcs->inputstate = inputstate; |
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 8f78f15c8ef7..245a6083f79d 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c | |||
@@ -80,6 +80,7 @@ struct gigaset_capi_appl { | |||
80 | struct list_head ctrlist; | 80 | struct list_head ctrlist; |
81 | struct gigaset_capi_appl *bcnext; | 81 | struct gigaset_capi_appl *bcnext; |
82 | u16 id; | 82 | u16 id; |
83 | struct capi_register_params rp; | ||
83 | u16 nextMessageNumber; | 84 | u16 nextMessageNumber; |
84 | u32 listenInfoMask; | 85 | u32 listenInfoMask; |
85 | u32 listenCIPmask; | 86 | u32 listenCIPmask; |
@@ -945,6 +946,7 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, | |||
945 | return; | 946 | return; |
946 | } | 947 | } |
947 | ap->id = appl; | 948 | ap->id = appl; |
949 | ap->rp = *rp; | ||
948 | 950 | ||
949 | list_add(&ap->ctrlist, &iif->appls); | 951 | list_add(&ap->ctrlist, &iif->appls); |
950 | } | 952 | } |
@@ -1166,6 +1168,9 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, | |||
1166 | } | 1168 | } |
1167 | ap->bcnext = NULL; | 1169 | ap->bcnext = NULL; |
1168 | bcs->ap = ap; | 1170 | bcs->ap = ap; |
1171 | bcs->rx_bufsize = ap->rp.datablklen; | ||
1172 | dev_kfree_skb(bcs->rx_skb); | ||
1173 | gigaset_new_rx_skb(bcs); | ||
1169 | cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; | 1174 | cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; |
1170 | 1175 | ||
1171 | /* build command table */ | 1176 | /* build command table */ |
@@ -1435,6 +1440,9 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, | |||
1435 | CapiCallGivenToOtherApplication); | 1440 | CapiCallGivenToOtherApplication); |
1436 | ap->bcnext = NULL; | 1441 | ap->bcnext = NULL; |
1437 | bcs->ap = ap; | 1442 | bcs->ap = ap; |
1443 | bcs->rx_bufsize = ap->rp.datablklen; | ||
1444 | dev_kfree_skb(bcs->rx_skb); | ||
1445 | gigaset_new_rx_skb(bcs); | ||
1438 | bcs->chstate |= CHS_NOTIFY_LL; | 1446 | bcs->chstate |= CHS_NOTIFY_LL; |
1439 | 1447 | ||
1440 | /* check/encode B channel protocol */ | 1448 | /* check/encode B channel protocol */ |
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index f6f45f221920..9778fabbc488 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -399,8 +399,8 @@ static void gigaset_freebcs(struct bc_state *bcs) | |||
399 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); | 399 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); |
400 | clear_at_state(&bcs->at_state); | 400 | clear_at_state(&bcs->at_state); |
401 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); | 401 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); |
402 | dev_kfree_skb(bcs->skb); | 402 | dev_kfree_skb(bcs->rx_skb); |
403 | bcs->skb = NULL; | 403 | bcs->rx_skb = NULL; |
404 | 404 | ||
405 | for (i = 0; i < AT_NUM; ++i) { | 405 | for (i = 0; i < AT_NUM; ++i) { |
406 | kfree(bcs->commands[i]); | 406 | kfree(bcs->commands[i]); |
@@ -634,19 +634,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
634 | bcs->emptycount = 0; | 634 | bcs->emptycount = 0; |
635 | #endif | 635 | #endif |
636 | 636 | ||
637 | gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); | 637 | bcs->rx_bufsize = 0; |
638 | bcs->fcs = PPP_INITFCS; | 638 | bcs->rx_skb = NULL; |
639 | bcs->rx_fcs = PPP_INITFCS; | ||
639 | bcs->inputstate = 0; | 640 | bcs->inputstate = 0; |
640 | if (cs->ignoreframes) { | ||
641 | bcs->skb = NULL; | ||
642 | } else { | ||
643 | bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); | ||
644 | if (bcs->skb != NULL) | ||
645 | skb_reserve(bcs->skb, cs->hw_hdr_len); | ||
646 | else | ||
647 | pr_err("out of memory\n"); | ||
648 | } | ||
649 | |||
650 | bcs->channel = channel; | 641 | bcs->channel = channel; |
651 | bcs->cs = cs; | 642 | bcs->cs = cs; |
652 | 643 | ||
@@ -663,11 +654,6 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
663 | return bcs; | 654 | return bcs; |
664 | 655 | ||
665 | gig_dbg(DEBUG_INIT, " failed"); | 656 | gig_dbg(DEBUG_INIT, " failed"); |
666 | |||
667 | gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); | ||
668 | dev_kfree_skb(bcs->skb); | ||
669 | bcs->skb = NULL; | ||
670 | |||
671 | return NULL; | 657 | return NULL; |
672 | } | 658 | } |
673 | 659 | ||
@@ -839,14 +825,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs) | |||
839 | bcs->emptycount = 0; | 825 | bcs->emptycount = 0; |
840 | #endif | 826 | #endif |
841 | 827 | ||
842 | bcs->fcs = PPP_INITFCS; | 828 | bcs->rx_fcs = PPP_INITFCS; |
843 | bcs->chstate = 0; | 829 | bcs->chstate = 0; |
844 | 830 | ||
845 | bcs->ignore = cs->ignoreframes; | 831 | bcs->ignore = cs->ignoreframes; |
846 | if (bcs->ignore) { | 832 | dev_kfree_skb(bcs->rx_skb); |
847 | dev_kfree_skb(bcs->skb); | 833 | bcs->rx_skb = NULL; |
848 | bcs->skb = NULL; | ||
849 | } | ||
850 | 834 | ||
851 | cs->ops->reinitbcshw(bcs); | 835 | cs->ops->reinitbcshw(bcs); |
852 | } | 836 | } |
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 05947f9c1849..f77ec54eb07d 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h | |||
@@ -45,10 +45,6 @@ | |||
45 | #define MAX_EVENTS 64 /* size of event queue */ | 45 | #define MAX_EVENTS 64 /* size of event queue */ |
46 | 46 | ||
47 | #define RBUFSIZE 8192 | 47 | #define RBUFSIZE 8192 |
48 | #define SBUFSIZE 4096 /* sk_buff payload size */ | ||
49 | |||
50 | #define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */ | ||
51 | #define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */ | ||
52 | 48 | ||
53 | /* compile time options */ | 49 | /* compile time options */ |
54 | #define GIG_MAJOR 0 | 50 | #define GIG_MAJOR 0 |
@@ -380,8 +376,10 @@ struct bc_state { | |||
380 | 376 | ||
381 | struct at_state_t at_state; | 377 | struct at_state_t at_state; |
382 | 378 | ||
383 | __u16 fcs; | 379 | /* receive buffer */ |
384 | struct sk_buff *skb; | 380 | unsigned rx_bufsize; /* max size accepted by application */ |
381 | struct sk_buff *rx_skb; | ||
382 | __u16 rx_fcs; | ||
385 | int inputstate; /* see INS_XXXX */ | 383 | int inputstate; /* see INS_XXXX */ |
386 | 384 | ||
387 | int channel; | 385 | int channel; |
@@ -801,8 +799,23 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs) | |||
801 | gigaset_schedule_event(bcs->cs); | 799 | gigaset_schedule_event(bcs->cs); |
802 | } | 800 | } |
803 | 801 | ||
804 | /* handling routines for sk_buff */ | 802 | /* set up next receive skb for data mode */ |
805 | /* ============================= */ | 803 | static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs) |
804 | { | ||
805 | struct cardstate *cs = bcs->cs; | ||
806 | unsigned short hw_hdr_len = cs->hw_hdr_len; | ||
807 | |||
808 | if (bcs->ignore) { | ||
809 | bcs->rx_skb = NULL; | ||
810 | } else { | ||
811 | bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len); | ||
812 | if (bcs->rx_skb == NULL) | ||
813 | dev_warn(cs->dev, "could not allocate skb\n"); | ||
814 | else | ||
815 | skb_reserve(bcs->rx_skb, hw_hdr_len); | ||
816 | } | ||
817 | return bcs->rx_skb; | ||
818 | } | ||
806 | 819 | ||
807 | /* append received bytes to inbuf */ | 820 | /* append received bytes to inbuf */ |
808 | int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, | 821 | int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, |
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index c22e5ace8276..f01c3c2e2e46 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c | |||
@@ -16,7 +16,10 @@ | |||
16 | #include "gigaset.h" | 16 | #include "gigaset.h" |
17 | #include <linux/isdnif.h> | 17 | #include <linux/isdnif.h> |
18 | 18 | ||
19 | #define SBUFSIZE 4096 /* sk_buff payload size */ | ||
20 | #define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */ | ||
19 | #define HW_HDR_LEN 2 /* Header size used to store ack info */ | 21 | #define HW_HDR_LEN 2 /* Header size used to store ack info */ |
22 | #define MAX_BUF_SIZE (SBUFSIZE - HW_HDR_LEN) /* max data packet from LL */ | ||
20 | 23 | ||
21 | /* == Handling of I4L IO =====================================================*/ | 24 | /* == Handling of I4L IO =====================================================*/ |
22 | 25 | ||
@@ -231,6 +234,15 @@ static int command_from_LL(isdn_ctrl *cntrl) | |||
231 | dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); | 234 | dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); |
232 | return -EBUSY; | 235 | return -EBUSY; |
233 | } | 236 | } |
237 | switch (bcs->proto2) { | ||
238 | case L2_HDLC: | ||
239 | bcs->rx_bufsize = SBUFSIZE; | ||
240 | break; | ||
241 | default: /* assume transparent */ | ||
242 | bcs->rx_bufsize = TRANSBUFSIZE; | ||
243 | } | ||
244 | dev_kfree_skb(bcs->rx_skb); | ||
245 | gigaset_new_rx_skb(bcs); | ||
234 | 246 | ||
235 | commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC); | 247 | commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC); |
236 | if (!commands) { | 248 | if (!commands) { |
@@ -314,6 +326,15 @@ static int command_from_LL(isdn_ctrl *cntrl) | |||
314 | return -EINVAL; | 326 | return -EINVAL; |
315 | } | 327 | } |
316 | bcs = cs->bcs + ch; | 328 | bcs = cs->bcs + ch; |
329 | switch (bcs->proto2) { | ||
330 | case L2_HDLC: | ||
331 | bcs->rx_bufsize = SBUFSIZE; | ||
332 | break; | ||
333 | default: /* assume transparent */ | ||
334 | bcs->rx_bufsize = TRANSBUFSIZE; | ||
335 | } | ||
336 | dev_kfree_skb(bcs->rx_skb); | ||
337 | gigaset_new_rx_skb(bcs); | ||
317 | if (!gigaset_add_event(cs, &bcs->at_state, | 338 | if (!gigaset_add_event(cs, &bcs->at_state, |
318 | EV_ACCEPT, NULL, 0, NULL)) | 339 | EV_ACCEPT, NULL, 0, NULL)) |
319 | return -ENOMEM; | 340 | return -ENOMEM; |
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 16fd3bd48883..2dfd346fc889 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c | |||
@@ -500,19 +500,18 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) | |||
500 | */ | 500 | */ |
501 | static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) | 501 | static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) |
502 | { | 502 | { |
503 | bcs->fcs = crc_ccitt_byte(bcs->fcs, c); | 503 | bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c); |
504 | if (unlikely(bcs->skb == NULL)) { | 504 | if (bcs->rx_skb == NULL) |
505 | /* skipping */ | 505 | /* skipping */ |
506 | return; | 506 | return; |
507 | } | 507 | if (bcs->rx_skb->len >= bcs->rx_bufsize) { |
508 | if (unlikely(bcs->skb->len == SBUFSIZE)) { | ||
509 | dev_warn(bcs->cs->dev, "received oversized packet discarded\n"); | 508 | dev_warn(bcs->cs->dev, "received oversized packet discarded\n"); |
510 | bcs->hw.bas->giants++; | 509 | bcs->hw.bas->giants++; |
511 | dev_kfree_skb_any(bcs->skb); | 510 | dev_kfree_skb_any(bcs->rx_skb); |
512 | bcs->skb = NULL; | 511 | bcs->rx_skb = NULL; |
513 | return; | 512 | return; |
514 | } | 513 | } |
515 | *__skb_put(bcs->skb, 1) = c; | 514 | *__skb_put(bcs->rx_skb, 1) = c; |
516 | } | 515 | } |
517 | 516 | ||
518 | /* hdlc_flush | 517 | /* hdlc_flush |
@@ -521,18 +520,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) | |||
521 | static inline void hdlc_flush(struct bc_state *bcs) | 520 | static inline void hdlc_flush(struct bc_state *bcs) |
522 | { | 521 | { |
523 | /* clear skb or allocate new if not skipping */ | 522 | /* clear skb or allocate new if not skipping */ |
524 | if (likely(bcs->skb != NULL)) | 523 | if (bcs->rx_skb != NULL) |
525 | skb_trim(bcs->skb, 0); | 524 | skb_trim(bcs->rx_skb, 0); |
526 | else if (!bcs->ignore) { | 525 | else |
527 | bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len); | 526 | gigaset_new_rx_skb(bcs); |
528 | if (bcs->skb) | ||
529 | skb_reserve(bcs->skb, bcs->cs->hw_hdr_len); | ||
530 | else | ||
531 | dev_err(bcs->cs->dev, "could not allocate skb\n"); | ||
532 | } | ||
533 | 527 | ||
534 | /* reset packet state */ | 528 | /* reset packet state */ |
535 | bcs->fcs = PPP_INITFCS; | 529 | bcs->rx_fcs = PPP_INITFCS; |
536 | } | 530 | } |
537 | 531 | ||
538 | /* hdlc_done | 532 | /* hdlc_done |
@@ -549,7 +543,7 @@ static inline void hdlc_done(struct bc_state *bcs) | |||
549 | hdlc_flush(bcs); | 543 | hdlc_flush(bcs); |
550 | return; | 544 | return; |
551 | } | 545 | } |
552 | procskb = bcs->skb; | 546 | procskb = bcs->rx_skb; |
553 | if (procskb == NULL) { | 547 | if (procskb == NULL) { |
554 | /* previous error */ | 548 | /* previous error */ |
555 | gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); | 549 | gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); |
@@ -560,8 +554,8 @@ static inline void hdlc_done(struct bc_state *bcs) | |||
560 | bcs->hw.bas->runts++; | 554 | bcs->hw.bas->runts++; |
561 | dev_kfree_skb_any(procskb); | 555 | dev_kfree_skb_any(procskb); |
562 | gigaset_isdn_rcv_err(bcs); | 556 | gigaset_isdn_rcv_err(bcs); |
563 | } else if (bcs->fcs != PPP_GOODFCS) { | 557 | } else if (bcs->rx_fcs != PPP_GOODFCS) { |
564 | dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); | 558 | dev_notice(cs->dev, "frame check error\n"); |
565 | bcs->hw.bas->fcserrs++; | 559 | bcs->hw.bas->fcserrs++; |
566 | dev_kfree_skb_any(procskb); | 560 | dev_kfree_skb_any(procskb); |
567 | gigaset_isdn_rcv_err(bcs); | 561 | gigaset_isdn_rcv_err(bcs); |
@@ -574,13 +568,8 @@ static inline void hdlc_done(struct bc_state *bcs) | |||
574 | bcs->hw.bas->goodbytes += len; | 568 | bcs->hw.bas->goodbytes += len; |
575 | gigaset_skb_rcvd(bcs, procskb); | 569 | gigaset_skb_rcvd(bcs, procskb); |
576 | } | 570 | } |
577 | 571 | gigaset_new_rx_skb(bcs); | |
578 | bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); | 572 | bcs->rx_fcs = PPP_INITFCS; |
579 | if (bcs->skb) | ||
580 | skb_reserve(bcs->skb, cs->hw_hdr_len); | ||
581 | else | ||
582 | dev_err(cs->dev, "could not allocate skb\n"); | ||
583 | bcs->fcs = PPP_INITFCS; | ||
584 | } | 573 | } |
585 | 574 | ||
586 | /* hdlc_frag | 575 | /* hdlc_frag |
@@ -597,8 +586,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) | |||
597 | dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); | 586 | dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); |
598 | bcs->hw.bas->alignerrs++; | 587 | bcs->hw.bas->alignerrs++; |
599 | gigaset_isdn_rcv_err(bcs); | 588 | gigaset_isdn_rcv_err(bcs); |
600 | __skb_trim(bcs->skb, 0); | 589 | __skb_trim(bcs->rx_skb, 0); |
601 | bcs->fcs = PPP_INITFCS; | 590 | bcs->rx_fcs = PPP_INITFCS; |
602 | } | 591 | } |
603 | 592 | ||
604 | /* bit counts lookup table for HDLC bit unstuffing | 593 | /* bit counts lookup table for HDLC bit unstuffing |
@@ -847,7 +836,6 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
847 | static inline void trans_receive(unsigned char *src, unsigned count, | 836 | static inline void trans_receive(unsigned char *src, unsigned count, |
848 | struct bc_state *bcs) | 837 | struct bc_state *bcs) |
849 | { | 838 | { |
850 | struct cardstate *cs = bcs->cs; | ||
851 | struct sk_buff *skb; | 839 | struct sk_buff *skb; |
852 | int dobytes; | 840 | int dobytes; |
853 | unsigned char *dst; | 841 | unsigned char *dst; |
@@ -857,17 +845,11 @@ static inline void trans_receive(unsigned char *src, unsigned count, | |||
857 | hdlc_flush(bcs); | 845 | hdlc_flush(bcs); |
858 | return; | 846 | return; |
859 | } | 847 | } |
860 | skb = bcs->skb; | 848 | skb = bcs->rx_skb; |
861 | if (unlikely(skb == NULL)) { | 849 | if (skb == NULL) |
862 | bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); | 850 | skb = gigaset_new_rx_skb(bcs); |
863 | if (!skb) { | ||
864 | dev_err(cs->dev, "could not allocate skb\n"); | ||
865 | return; | ||
866 | } | ||
867 | skb_reserve(skb, cs->hw_hdr_len); | ||
868 | } | ||
869 | bcs->hw.bas->goodbytes += skb->len; | 851 | bcs->hw.bas->goodbytes += skb->len; |
870 | dobytes = TRANSBUFSIZE - skb->len; | 852 | dobytes = bcs->rx_bufsize - skb->len; |
871 | while (count > 0) { | 853 | while (count > 0) { |
872 | dst = skb_put(skb, count < dobytes ? count : dobytes); | 854 | dst = skb_put(skb, count < dobytes ? count : dobytes); |
873 | while (count > 0 && dobytes > 0) { | 855 | while (count > 0 && dobytes > 0) { |
@@ -879,14 +861,10 @@ static inline void trans_receive(unsigned char *src, unsigned count, | |||
879 | dump_bytes(DEBUG_STREAM_DUMP, | 861 | dump_bytes(DEBUG_STREAM_DUMP, |
880 | "rcv data", skb->data, skb->len); | 862 | "rcv data", skb->data, skb->len); |
881 | gigaset_skb_rcvd(bcs, skb); | 863 | gigaset_skb_rcvd(bcs, skb); |
882 | bcs->skb = skb = | 864 | skb = gigaset_new_rx_skb(bcs); |
883 | dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); | 865 | if (skb == NULL) |
884 | if (!skb) { | ||
885 | dev_err(cs->dev, "could not allocate skb\n"); | ||
886 | return; | 866 | return; |
887 | } | 867 | dobytes = bcs->rx_bufsize; |
888 | skb_reserve(skb, cs->hw_hdr_len); | ||
889 | dobytes = TRANSBUFSIZE; | ||
890 | } | 868 | } |
891 | } | 869 | } |
892 | } | 870 | } |