Commit e7752ee2 authored by Tilman Schmidt's avatar Tilman Schmidt Committed by David S. Miller

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: default avatarTilman Schmidt <tilman@imap.cc>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ed770f01
...@@ -126,26 +126,6 @@ static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf) ...@@ -126,26 +126,6 @@ static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
return numbytes; return numbytes;
} }
/* set up next receive skb for data mode
*/
static void new_rcv_skb(struct bc_state *bcs)
{
struct cardstate *cs = bcs->cs;
unsigned short hw_hdr_len = cs->hw_hdr_len;
if (bcs->ignore) {
bcs->skb = NULL;
return;
}
bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
if (bcs->skb == NULL) {
dev_warn(cs->dev, "could not allocate new skb\n");
return;
}
skb_reserve(bcs->skb, hw_hdr_len);
}
/* process a block of received bytes in HDLC data mode /* process a block of received bytes in HDLC data mode
* (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
* Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. * 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,8 +139,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
struct cardstate *cs = inbuf->cs; struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = cs->bcs; struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate; int inputstate = bcs->inputstate;
__u16 fcs = bcs->fcs; __u16 fcs = bcs->rx_fcs;
struct sk_buff *skb = bcs->skb; struct sk_buff *skb = bcs->rx_skb;
unsigned char *src = inbuf->data + inbuf->head; unsigned char *src = inbuf->data + inbuf->head;
unsigned procbytes = 0; unsigned procbytes = 0;
unsigned char c; unsigned char c;
...@@ -245,8 +225,7 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) ...@@ -245,8 +225,7 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
/* prepare reception of next frame */ /* prepare reception of next frame */
inputstate &= ~INS_have_data; inputstate &= ~INS_have_data;
new_rcv_skb(bcs); skb = gigaset_new_rx_skb(bcs);
skb = bcs->skb;
} else { } else {
/* empty frame (7E 7E) */ /* empty frame (7E 7E) */
#ifdef CONFIG_GIGASET_DEBUG #ifdef CONFIG_GIGASET_DEBUG
...@@ -255,8 +234,7 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) ...@@ -255,8 +234,7 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
if (!skb) { if (!skb) {
/* skipped (?) */ /* skipped (?) */
gigaset_isdn_rcv_err(bcs); gigaset_isdn_rcv_err(bcs);
new_rcv_skb(bcs); skb = gigaset_new_rx_skb(bcs);
skb = bcs->skb;
} }
} }
...@@ -279,11 +257,11 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) ...@@ -279,11 +257,11 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
#endif #endif
inputstate |= INS_have_data; inputstate |= INS_have_data;
if (skb) { if (skb) {
if (skb->len == SBUFSIZE) { if (skb->len >= bcs->rx_bufsize) {
dev_warn(cs->dev, "received packet too long\n"); dev_warn(cs->dev, "received packet too long\n");
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
/* skip remainder of packet */ /* skip remainder of packet */
bcs->skb = skb = NULL; bcs->rx_skb = skb = NULL;
} else { } else {
*__skb_put(skb, 1) = c; *__skb_put(skb, 1) = c;
fcs = crc_ccitt_byte(fcs, c); fcs = crc_ccitt_byte(fcs, c);
...@@ -292,7 +270,7 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) ...@@ -292,7 +270,7 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
} }
bcs->inputstate = inputstate; bcs->inputstate = inputstate;
bcs->fcs = fcs; bcs->rx_fcs = fcs;
return procbytes; return procbytes;
} }
...@@ -308,18 +286,18 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) ...@@ -308,18 +286,18 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
struct cardstate *cs = inbuf->cs; struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = cs->bcs; struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate; int inputstate = bcs->inputstate;
struct sk_buff *skb = bcs->skb; struct sk_buff *skb = bcs->rx_skb;
unsigned char *src = inbuf->data + inbuf->head; unsigned char *src = inbuf->data + inbuf->head;
unsigned procbytes = 0; unsigned procbytes = 0;
unsigned char c; unsigned char c;
if (!skb) { if (!skb) {
/* skip this block */ /* skip this block */
new_rcv_skb(bcs); gigaset_new_rx_skb(bcs);
return numbytes; return numbytes;
} }
while (procbytes < numbytes && skb->len < SBUFSIZE) { while (procbytes < numbytes && skb->len < bcs->rx_bufsize) {
c = *src++; c = *src++;
procbytes++; procbytes++;
...@@ -343,7 +321,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) ...@@ -343,7 +321,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
if (inputstate & INS_have_data) { if (inputstate & INS_have_data) {
gigaset_skb_rcvd(bcs, skb); gigaset_skb_rcvd(bcs, skb);
inputstate &= ~INS_have_data; inputstate &= ~INS_have_data;
new_rcv_skb(bcs); gigaset_new_rx_skb(bcs);
} }
bcs->inputstate = inputstate; bcs->inputstate = inputstate;
......
...@@ -80,6 +80,7 @@ struct gigaset_capi_appl { ...@@ -80,6 +80,7 @@ struct gigaset_capi_appl {
struct list_head ctrlist; struct list_head ctrlist;
struct gigaset_capi_appl *bcnext; struct gigaset_capi_appl *bcnext;
u16 id; u16 id;
struct capi_register_params rp;
u16 nextMessageNumber; u16 nextMessageNumber;
u32 listenInfoMask; u32 listenInfoMask;
u32 listenCIPmask; u32 listenCIPmask;
...@@ -945,6 +946,7 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, ...@@ -945,6 +946,7 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl,
return; return;
} }
ap->id = appl; ap->id = appl;
ap->rp = *rp;
list_add(&ap->ctrlist, &iif->appls); list_add(&ap->ctrlist, &iif->appls);
} }
...@@ -1166,6 +1168,9 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, ...@@ -1166,6 +1168,9 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
} }
ap->bcnext = NULL; ap->bcnext = NULL;
bcs->ap = ap; bcs->ap = ap;
bcs->rx_bufsize = ap->rp.datablklen;
dev_kfree_skb(bcs->rx_skb);
gigaset_new_rx_skb(bcs);
cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8;
/* build command table */ /* build command table */
...@@ -1435,6 +1440,9 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, ...@@ -1435,6 +1440,9 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
CapiCallGivenToOtherApplication); CapiCallGivenToOtherApplication);
ap->bcnext = NULL; ap->bcnext = NULL;
bcs->ap = ap; bcs->ap = ap;
bcs->rx_bufsize = ap->rp.datablklen;
dev_kfree_skb(bcs->rx_skb);
gigaset_new_rx_skb(bcs);
bcs->chstate |= CHS_NOTIFY_LL; bcs->chstate |= CHS_NOTIFY_LL;
/* check/encode B channel protocol */ /* check/encode B channel protocol */
......
...@@ -399,8 +399,8 @@ static void gigaset_freebcs(struct bc_state *bcs) ...@@ -399,8 +399,8 @@ static void gigaset_freebcs(struct bc_state *bcs)
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
clear_at_state(&bcs->at_state); clear_at_state(&bcs->at_state);
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
dev_kfree_skb(bcs->skb); dev_kfree_skb(bcs->rx_skb);
bcs->skb = NULL; bcs->rx_skb = NULL;
for (i = 0; i < AT_NUM; ++i) { for (i = 0; i < AT_NUM; ++i) {
kfree(bcs->commands[i]); kfree(bcs->commands[i]);
...@@ -634,19 +634,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, ...@@ -634,19 +634,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
bcs->emptycount = 0; bcs->emptycount = 0;
#endif #endif
gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); bcs->rx_bufsize = 0;
bcs->fcs = PPP_INITFCS; bcs->rx_skb = NULL;
bcs->rx_fcs = PPP_INITFCS;
bcs->inputstate = 0; bcs->inputstate = 0;
if (cs->ignoreframes) {
bcs->skb = NULL;
} else {
bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
if (bcs->skb != NULL)
skb_reserve(bcs->skb, cs->hw_hdr_len);
else
pr_err("out of memory\n");
}
bcs->channel = channel; bcs->channel = channel;
bcs->cs = cs; bcs->cs = cs;
...@@ -663,11 +654,6 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, ...@@ -663,11 +654,6 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
return bcs; return bcs;
gig_dbg(DEBUG_INIT, " failed"); gig_dbg(DEBUG_INIT, " failed");
gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
dev_kfree_skb(bcs->skb);
bcs->skb = NULL;
return NULL; return NULL;
} }
...@@ -839,14 +825,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs) ...@@ -839,14 +825,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
bcs->emptycount = 0; bcs->emptycount = 0;
#endif #endif
bcs->fcs = PPP_INITFCS; bcs->rx_fcs = PPP_INITFCS;
bcs->chstate = 0; bcs->chstate = 0;
bcs->ignore = cs->ignoreframes; bcs->ignore = cs->ignoreframes;
if (bcs->ignore) { dev_kfree_skb(bcs->rx_skb);
dev_kfree_skb(bcs->skb); bcs->rx_skb = NULL;
bcs->skb = NULL;
}
cs->ops->reinitbcshw(bcs); cs->ops->reinitbcshw(bcs);
} }
......
...@@ -45,10 +45,6 @@ ...@@ -45,10 +45,6 @@
#define MAX_EVENTS 64 /* size of event queue */ #define MAX_EVENTS 64 /* size of event queue */
#define RBUFSIZE 8192 #define RBUFSIZE 8192
#define SBUFSIZE 4096 /* sk_buff payload size */
#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */
/* compile time options */ /* compile time options */
#define GIG_MAJOR 0 #define GIG_MAJOR 0
...@@ -380,8 +376,10 @@ struct bc_state { ...@@ -380,8 +376,10 @@ struct bc_state {
struct at_state_t at_state; struct at_state_t at_state;
__u16 fcs; /* receive buffer */
struct sk_buff *skb; unsigned rx_bufsize; /* max size accepted by application */
struct sk_buff *rx_skb;
__u16 rx_fcs;
int inputstate; /* see INS_XXXX */ int inputstate; /* see INS_XXXX */
int channel; int channel;
...@@ -801,8 +799,23 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs) ...@@ -801,8 +799,23 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs)
gigaset_schedule_event(bcs->cs); gigaset_schedule_event(bcs->cs);
} }
/* handling routines for sk_buff */ /* set up next receive skb for data mode */
/* ============================= */ static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs)
{
struct cardstate *cs = bcs->cs;
unsigned short hw_hdr_len = cs->hw_hdr_len;
if (bcs->ignore) {
bcs->rx_skb = NULL;
} else {
bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len);
if (bcs->rx_skb == NULL)
dev_warn(cs->dev, "could not allocate skb\n");
else
skb_reserve(bcs->rx_skb, hw_hdr_len);
}
return bcs->rx_skb;
}
/* append received bytes to inbuf */ /* append received bytes to inbuf */
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
......
...@@ -16,7 +16,10 @@ ...@@ -16,7 +16,10 @@
#include "gigaset.h" #include "gigaset.h"
#include <linux/isdnif.h> #include <linux/isdnif.h>
#define SBUFSIZE 4096 /* sk_buff payload size */
#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
#define HW_HDR_LEN 2 /* Header size used to store ack info */ #define HW_HDR_LEN 2 /* Header size used to store ack info */
#define MAX_BUF_SIZE (SBUFSIZE - HW_HDR_LEN) /* max data packet from LL */
/* == Handling of I4L IO =====================================================*/ /* == Handling of I4L IO =====================================================*/
...@@ -231,6 +234,15 @@ static int command_from_LL(isdn_ctrl *cntrl) ...@@ -231,6 +234,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
return -EBUSY; return -EBUSY;
} }
switch (bcs->proto2) {
case L2_HDLC:
bcs->rx_bufsize = SBUFSIZE;
break;
default: /* assume transparent */
bcs->rx_bufsize = TRANSBUFSIZE;
}
dev_kfree_skb(bcs->rx_skb);
gigaset_new_rx_skb(bcs);
commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC); commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
if (!commands) { if (!commands) {
...@@ -314,6 +326,15 @@ static int command_from_LL(isdn_ctrl *cntrl) ...@@ -314,6 +326,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
return -EINVAL; return -EINVAL;
} }
bcs = cs->bcs + ch; bcs = cs->bcs + ch;
switch (bcs->proto2) {
case L2_HDLC:
bcs->rx_bufsize = SBUFSIZE;
break;
default: /* assume transparent */
bcs->rx_bufsize = TRANSBUFSIZE;
}
dev_kfree_skb(bcs->rx_skb);
gigaset_new_rx_skb(bcs);
if (!gigaset_add_event(cs, &bcs->at_state, if (!gigaset_add_event(cs, &bcs->at_state,
EV_ACCEPT, NULL, 0, NULL)) EV_ACCEPT, NULL, 0, NULL))
return -ENOMEM; return -ENOMEM;
......
...@@ -500,19 +500,18 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) ...@@ -500,19 +500,18 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
*/ */
static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
{ {
bcs->fcs = crc_ccitt_byte(bcs->fcs, c); bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c);
if (unlikely(bcs->skb == NULL)) { if (bcs->rx_skb == NULL)
/* skipping */ /* skipping */
return; return;
} if (bcs->rx_skb->len >= bcs->rx_bufsize) {
if (unlikely(bcs->skb->len == SBUFSIZE)) {
dev_warn(bcs->cs->dev, "received oversized packet discarded\n"); dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
bcs->hw.bas->giants++; bcs->hw.bas->giants++;
dev_kfree_skb_any(bcs->skb); dev_kfree_skb_any(bcs->rx_skb);
bcs->skb = NULL; bcs->rx_skb = NULL;
return; return;
} }
*__skb_put(bcs->skb, 1) = c; *__skb_put(bcs->rx_skb, 1) = c;
} }
/* hdlc_flush /* hdlc_flush
...@@ -521,18 +520,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) ...@@ -521,18 +520,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
static inline void hdlc_flush(struct bc_state *bcs) static inline void hdlc_flush(struct bc_state *bcs)
{ {
/* clear skb or allocate new if not skipping */ /* clear skb or allocate new if not skipping */
if (likely(bcs->skb != NULL)) if (bcs->rx_skb != NULL)
skb_trim(bcs->skb, 0); skb_trim(bcs->rx_skb, 0);
else if (!bcs->ignore) { else
bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len); gigaset_new_rx_skb(bcs);
if (bcs->skb)
skb_reserve(bcs->skb, bcs->cs->hw_hdr_len);
else
dev_err(bcs->cs->dev, "could not allocate skb\n");
}
/* reset packet state */ /* reset packet state */
bcs->fcs = PPP_INITFCS; bcs->rx_fcs = PPP_INITFCS;
} }
/* hdlc_done /* hdlc_done
...@@ -549,7 +543,7 @@ static inline void hdlc_done(struct bc_state *bcs) ...@@ -549,7 +543,7 @@ static inline void hdlc_done(struct bc_state *bcs)
hdlc_flush(bcs); hdlc_flush(bcs);
return; return;
} }
procskb = bcs->skb; procskb = bcs->rx_skb;
if (procskb == NULL) { if (procskb == NULL) {
/* previous error */ /* previous error */
gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
...@@ -560,8 +554,8 @@ static inline void hdlc_done(struct bc_state *bcs) ...@@ -560,8 +554,8 @@ static inline void hdlc_done(struct bc_state *bcs)
bcs->hw.bas->runts++; bcs->hw.bas->runts++;
dev_kfree_skb_any(procskb); dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs); gigaset_isdn_rcv_err(bcs);
} else if (bcs->fcs != PPP_GOODFCS) { } else if (bcs->rx_fcs != PPP_GOODFCS) {
dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); dev_notice(cs->dev, "frame check error\n");
bcs->hw.bas->fcserrs++; bcs->hw.bas->fcserrs++;
dev_kfree_skb_any(procskb); dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs); gigaset_isdn_rcv_err(bcs);
...@@ -574,13 +568,8 @@ static inline void hdlc_done(struct bc_state *bcs) ...@@ -574,13 +568,8 @@ static inline void hdlc_done(struct bc_state *bcs)
bcs->hw.bas->goodbytes += len; bcs->hw.bas->goodbytes += len;
gigaset_skb_rcvd(bcs, procskb); gigaset_skb_rcvd(bcs, procskb);
} }
gigaset_new_rx_skb(bcs);
bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); bcs->rx_fcs = PPP_INITFCS;
if (bcs->skb)
skb_reserve(bcs->skb, cs->hw_hdr_len);
else
dev_err(cs->dev, "could not allocate skb\n");
bcs->fcs = PPP_INITFCS;
} }
/* hdlc_frag /* hdlc_frag
...@@ -597,8 +586,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) ...@@ -597,8 +586,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
bcs->hw.bas->alignerrs++; bcs->hw.bas->alignerrs++;
gigaset_isdn_rcv_err(bcs); gigaset_isdn_rcv_err(bcs);
__skb_trim(bcs->skb, 0); __skb_trim(bcs->rx_skb, 0);
bcs->fcs = PPP_INITFCS; bcs->rx_fcs = PPP_INITFCS;
} }
/* bit counts lookup table for HDLC bit unstuffing /* bit counts lookup table for HDLC bit unstuffing
...@@ -847,7 +836,6 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, ...@@ -847,7 +836,6 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
static inline void trans_receive(unsigned char *src, unsigned count, static inline void trans_receive(unsigned char *src, unsigned count,
struct bc_state *bcs) struct bc_state *bcs)
{ {
struct cardstate *cs = bcs->cs;
struct sk_buff *skb; struct sk_buff *skb;
int dobytes; int dobytes;
unsigned char *dst; unsigned char *dst;
...@@ -857,17 +845,11 @@ static inline void trans_receive(unsigned char *src, unsigned count, ...@@ -857,17 +845,11 @@ static inline void trans_receive(unsigned char *src, unsigned count,
hdlc_flush(bcs); hdlc_flush(bcs);
return; return;
} }
skb = bcs->skb; skb = bcs->rx_skb;
if (unlikely(skb == NULL)) { if (skb == NULL)
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); skb = gigaset_new_rx_skb(bcs);
if (!skb) {
dev_err(cs->dev, "could not allocate skb\n");
return;
}
skb_reserve(skb, cs->hw_hdr_len);
}
bcs->hw.bas->goodbytes += skb->len; bcs->hw.bas->goodbytes += skb->len;
dobytes = TRANSBUFSIZE - skb->len; dobytes = bcs->rx_bufsize - skb->len;
while (count > 0) { while (count > 0) {
dst = skb_put(skb, count < dobytes ? count : dobytes); dst = skb_put(skb, count < dobytes ? count : dobytes);
while (count > 0 && dobytes > 0) { while (count > 0 && dobytes > 0) {
...@@ -879,14 +861,10 @@ static inline void trans_receive(unsigned char *src, unsigned count, ...@@ -879,14 +861,10 @@ static inline void trans_receive(unsigned char *src, unsigned count,
dump_bytes(DEBUG_STREAM_DUMP, dump_bytes(DEBUG_STREAM_DUMP,
"rcv data", skb->data, skb->len); "rcv data", skb->data, skb->len);
gigaset_skb_rcvd(bcs, skb); gigaset_skb_rcvd(bcs, skb);
bcs->skb = skb = skb = gigaset_new_rx_skb(bcs);
dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); if (skb == NULL)
if (!skb) {
dev_err(cs->dev, "could not allocate skb\n");
return; return;
} dobytes = bcs->rx_bufsize;
skb_reserve(skb, cs->hw_hdr_len);
dobytes = TRANSBUFSIZE;
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment