Skip to content

Commit

Permalink
gigaset: prepare for CAPI implementation
Browse files Browse the repository at this point in the history
Reorganize the code of the Gigaset driver, moving all isdn4linux
dependencies to the source file i4l.c so that it can be replaced
by a file capi.c interfacing to Kernel CAPI instead.

Impact: refactoring, no functional change
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Tilman Schmidt authored and David S. Miller committed Oct 7, 2009
1 parent 7ecc59c commit 088ec0c
Show file tree
Hide file tree
Showing 7 changed files with 492 additions and 425 deletions.
124 changes: 58 additions & 66 deletions drivers/isdn/gigaset/asyncdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,7 @@ static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
int inputstate = bcs->inputstate;
__u16 fcs = bcs->fcs;
struct sk_buff *skb = bcs->skb;
unsigned char error;
struct sk_buff *compskb;
int startbytes = numbytes;
int l;

if (unlikely(inputstate & INS_byte_stuff)) {
inputstate &= ~INS_byte_stuff;
Expand Down Expand Up @@ -158,8 +155,8 @@ static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
#endif

/* end of frame */
error = 1;
gigaset_rcv_error(NULL, cs, bcs);
gigaset_isdn_rcv_err(bcs);
dev_kfree_skb(skb);
} else if (!(inputstate & INS_have_data)) { /* 7E 7E */
#ifdef CONFIG_GIGASET_DEBUG
++bcs->emptycount;
Expand All @@ -170,54 +167,39 @@ static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
"7e----------------------------");

/* end of frame */
error = 0;

if (unlikely(fcs != PPP_GOODFCS)) {
dev_err(cs->dev,
"Checksum failed, %u bytes corrupted!\n",
skb->len);
compskb = NULL;
gigaset_rcv_error(compskb, cs, bcs);
error = 1;
gigaset_isdn_rcv_err(bcs);
dev_kfree_skb(skb);
} else if (likely(skb->len > 2)) {
__skb_trim(skb, skb->len - 2);
gigaset_skb_rcvd(bcs, skb);
} else {
if (likely((l = skb->len) > 2)) {
skb->tail -= 2;
skb->len -= 2;
} else {
dev_kfree_skb(skb);
skb = NULL;
inputstate |= INS_skip_frame;
if (l == 1) {
dev_err(cs->dev,
"invalid packet size (1)!\n");
error = 1;
gigaset_rcv_error(NULL,
cs, bcs);
}
}
if (likely(!(error ||
(inputstate &
INS_skip_frame)))) {
gigaset_rcv_skb(skb, cs, bcs);
if (skb->len) {
dev_err(cs->dev,
"invalid packet size (%d)\n", skb->len);
gigaset_isdn_rcv_err(bcs);
}
dev_kfree_skb(skb);
}
}

if (unlikely(error))
if (skb)
dev_kfree_skb(skb);

fcs = PPP_INITFCS;
inputstate &= ~(INS_have_data | INS_skip_frame);
if (unlikely(bcs->ignore)) {
inputstate |= INS_skip_frame;
skb = NULL;
} else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
skb_reserve(skb, HW_HDR_LEN);
} else {
dev_warn(cs->dev,
"could not allocate new skb\n");
inputstate |= INS_skip_frame;
skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
if (skb != NULL) {
skb_reserve(skb, cs->hw_hdr_len);
} else {
dev_warn(cs->dev,
"could not allocate new skb\n");
inputstate |= INS_skip_frame;
}
}

break;
Expand Down Expand Up @@ -314,18 +296,21 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
/* pass data up */
if (likely(inputstate & INS_have_data)) {
if (likely(!(inputstate & INS_skip_frame))) {
gigaset_rcv_skb(skb, cs, bcs);
gigaset_skb_rcvd(bcs, skb);
}
inputstate &= ~(INS_have_data | INS_skip_frame);
if (unlikely(bcs->ignore)) {
inputstate |= INS_skip_frame;
skb = NULL;
} else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN))
!= NULL)) {
skb_reserve(skb, HW_HDR_LEN);
} else {
dev_warn(cs->dev, "could not allocate new skb\n");
inputstate |= INS_skip_frame;
skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
if (skb != NULL) {
skb_reserve(skb, cs->hw_hdr_len);
} else {
dev_warn(cs->dev,
"could not allocate new skb\n");
inputstate |= INS_skip_frame;
}
}
}

Expand Down Expand Up @@ -383,7 +368,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
/* FIXME use function pointers? */
if (inbuf->inputstate & INS_command)
procbytes = cmd_loop(c, src, numbytes, inbuf);
else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
else if (inbuf->bcs->proto2 == L2_HDLC)
procbytes = hdlc_loop(c, src, numbytes, inbuf);
else
procbytes = iraw_loop(c, src, numbytes, inbuf);
Expand Down Expand Up @@ -440,16 +425,16 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input);

/* == data output ========================================================== */

/* Encoding of a PPP packet into an octet stuffed HDLC frame
* with FCS, opening and closing flags.
/*
* Encode a data packet into an octet stuffed HDLC frame with FCS,
* opening and closing flags, preserving headroom data.
* parameters:
* skb skb containing original packet (freed upon return)
* head number of headroom bytes to allocate in result skb
* tail number of tailroom bytes to allocate in result skb
* skb skb containing original packet (freed upon return)
* headroom number of headroom bytes to preserve
* Return value:
* pointer to newly allocated skb containing the result frame
*/
static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom)
{
struct sk_buff *hdlc_skb;
__u16 fcs;
Expand All @@ -471,16 +456,17 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)

/* size of new buffer: original size + number of stuffing bytes
* + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
* + room for acknowledgement header
*/
hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + headroom);
if (!hdlc_skb) {
dev_kfree_skb(skb);
return NULL;
}
skb_reserve(hdlc_skb, head);

/* Copy acknowledge request into new skb */
memcpy(hdlc_skb->head, skb->head, 2);
/* Copy acknowledgement header into new skb */
skb_reserve(hdlc_skb, headroom);
memcpy(hdlc_skb->head, skb->head, headroom);

/* Add flag sequence in front of everything.. */
*(skb_put(hdlc_skb, 1)) = PPP_FLAG;
Expand Down Expand Up @@ -515,28 +501,32 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
return hdlc_skb;
}

/* Encoding of a raw packet into an octet stuffed bit inverted frame
/*
* Encode a data packet into an octet stuffed raw bit inverted frame,
* preserving headroom data.
* parameters:
* skb skb containing original packet (freed upon return)
* head number of headroom bytes to allocate in result skb
* tail number of tailroom bytes to allocate in result skb
* skb skb containing original packet (freed upon return)
* headroom number of headroom bytes to preserve
* Return value:
* pointer to newly allocated skb containing the result frame
*/
static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom)
{
struct sk_buff *iraw_skb;
unsigned char c;
unsigned char *cp;
int len;

/* worst case: every byte must be stuffed */
iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
iraw_skb = dev_alloc_skb(2*skb->len + headroom);
if (!iraw_skb) {
dev_kfree_skb(skb);
return NULL;
}
skb_reserve(iraw_skb, head);

/* Copy acknowledgement header into new skb */
skb_reserve(iraw_skb, headroom);
memcpy(iraw_skb->head, skb->head, headroom);

cp = skb->data;
len = skb->len;
Expand All @@ -555,8 +545,10 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
* @bcs: B channel descriptor structure.
* @skb: data to send.
*
* Called by i4l.c to encode and queue an skb for sending, and start
* Called by LL to encode and queue an skb for sending, and start
* transmission if necessary.
* Once the payload data has been transmitted completely, gigaset_skb_sent()
* will be called with the first cs->hw_hdr_len bytes of skb->head preserved.
*
* Return value:
* number of bytes accepted for sending (skb->len) if ok,
Expand All @@ -567,10 +559,10 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
unsigned len = skb->len;
unsigned long flags;

if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
if (bcs->proto2 == L2_HDLC)
skb = HDLC_Encode(skb, bcs->cs->hw_hdr_len);
else
skb = iraw_encode(skb, HW_HDR_LEN, 0);
skb = iraw_encode(skb, bcs->cs->hw_hdr_len);
if (!skb) {
dev_err(bcs->cs->dev,
"unable to allocate memory for encoding!\n");
Expand Down
4 changes: 2 additions & 2 deletions drivers/isdn/gigaset/bas-gigaset.c
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ static int starturbs(struct bc_state *bcs)
int rc;

/* initialize L2 reception */
if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
if (bcs->proto2 == L2_HDLC)
bcs->inputstate |= INS_flag_hunt;

/* submit all isochronous input URBs */
Expand Down Expand Up @@ -1064,7 +1064,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
"%s: buffer busy at frame %d",
__func__, nframe);
/* tasklet will be restarted from
gigaset_send_skb() */
gigaset_isoc_send_skb() */
} else {
dev_err(ucx->bcs->cs->dev,
"%s: buffer error %d at frame %d\n",
Expand Down
50 changes: 27 additions & 23 deletions drivers/isdn/gigaset/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,12 @@ void gigaset_freecs(struct cardstate *cs)

switch (cs->cs_init) {
default:
/* clear B channel structures */
for (i = 0; i < cs->channels; ++i) {
gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
gigaset_freebcs(cs->bcs + i);
}

/* clear device sysfs */
gigaset_free_dev_sysfs(cs);

Expand All @@ -477,22 +483,16 @@ void gigaset_freecs(struct cardstate *cs)
case 2: /* error in initcshw */
/* Deregister from LL */
make_invalid(cs, VALID_ID);
gig_dbg(DEBUG_INIT, "clearing iif");
gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
gigaset_isdn_unregister(cs);

/* fall through */
case 1: /* error when regestering to LL */
case 1: /* error when registering to LL */
gig_dbg(DEBUG_INIT, "clearing at_state");
clear_at_state(&cs->at_state);
dealloc_at_states(cs);

/* fall through */
case 0: /* error in one call to initbcs */
for (i = 0; i < cs->channels; ++i) {
gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
gigaset_freebcs(cs->bcs + i);
}

case 0: /* error in basic setup */
clear_events(cs);
gig_dbg(DEBUG_INIT, "freeing inbuf");
kfree(cs->inbuf);
Expand Down Expand Up @@ -620,11 +620,14 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
if (cs->ignoreframes) {
bcs->inputstate |= INS_skip_frame;
bcs->skb = NULL;
} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else {
pr_err("out of memory\n");
bcs->inputstate |= INS_skip_frame;
} 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->inputstate |= INS_skip_frame;
}
}

bcs->channel = channel;
Expand Down Expand Up @@ -726,14 +729,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->mode = M_UNKNOWN;
cs->mstate = MS_UNINITIALIZED;

for (i = 0; i < channels; ++i) {
gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
pr_err("could not allocate channel %d data\n", i);
goto error;
}
}

++cs->cs_init;

gig_dbg(DEBUG_INIT, "setting up at_state");
Expand All @@ -758,7 +753,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->cmdbytes = 0;

gig_dbg(DEBUG_INIT, "setting up iif");
if (!gigaset_register_to_LL(cs, modulename)) {
if (!gigaset_isdn_register(cs, modulename)) {
pr_err("error registering ISDN device\n");
goto error;
}
Expand All @@ -777,6 +772,15 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
/* set up device sysfs */
gigaset_init_dev_sysfs(cs);

/* set up channel data structures */
for (i = 0; i < channels; ++i) {
gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i);
if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
pr_err("could not allocate channel %d data\n", i);
goto error;
}
}

spin_lock_irqsave(&cs->lock, flags);
cs->running = 1;
spin_unlock_irqrestore(&cs->lock, flags);
Expand Down
Loading

0 comments on commit 088ec0c

Please sign in to comment.